static GjsForeignInfo * gjs_struct_foreign_lookup(JSContext *context, GIBaseInfo *interface_info) { GjsForeignInfo *retval = NULL; GHashTable *hash_table; char *key; key = g_strdup_printf("%s.%s", g_base_info_get_namespace(interface_info), g_base_info_get_name(interface_info)); hash_table = get_foreign_structs(); retval = (GjsForeignInfo*)g_hash_table_lookup(hash_table, key); if (!retval) { if (gjs_foreign_load_foreign_module(context, g_base_info_get_namespace(interface_info))) { retval = (GjsForeignInfo*)g_hash_table_lookup(hash_table, key); } } if (!retval) { gjs_throw(context, "Unable to find module implementing foreign type %s.%s", g_base_info_get_namespace(interface_info), g_base_info_get_name(interface_info)); } g_free(key); return retval; }
static JSBool error_to_string(JSContext *context, uintN argc, jsval *vp) { jsval v_self; JSObject *self; Error *priv; jsval v_out; gchar *descr; JSBool retval; v_self = JS_THIS(context, vp); if (!JSVAL_IS_OBJECT(v_self)) { /* Lie a bit here... */ gjs_throw(context, "GLib.Error.prototype.toString() called on a non object"); return JS_FALSE; } self = JSVAL_TO_OBJECT(v_self); priv = priv_from_js(context, self); if (priv == NULL) return JS_FALSE; v_out = JSVAL_VOID; retval = JS_FALSE; /* We follow the same pattern as standard JS errors, at the expense of hiding some useful information */ if (priv->gerror == NULL) { descr = g_strdup_printf("%s.%s", g_base_info_get_namespace(priv->info), g_base_info_get_name(priv->info)); if (!gjs_string_from_utf8(context, descr, -1, &v_out)) goto out; } else { descr = g_strdup_printf("%s.%s: %s", g_base_info_get_namespace(priv->info), g_base_info_get_name(priv->info), priv->gerror->message); if (!gjs_string_from_utf8(context, descr, -1, &v_out)) goto out; } JS_SET_RVAL(context, vp, v_out); retval = JS_TRUE; out: g_free(descr); return retval; }
JSBool gjs_typecheck_fundamental(JSContext *context, JSObject *object, GType expected_gtype, JSBool throw_error) { FundamentalInstance *priv; JSBool result; if (!do_base_typecheck(context, object, throw_error)) return JS_FALSE; priv = priv_from_js(context, object); g_assert(priv != NULL); if (priv->gfundamental == NULL) { if (throw_error) { Fundamental *proto_priv = (Fundamental *) priv; gjs_throw(context, "Object is %s.%s.prototype, not an fundamental instance - cannot convert to void*", proto_priv->info ? g_base_info_get_namespace((GIBaseInfo *) proto_priv->info) : "", proto_priv->info ? g_base_info_get_name((GIBaseInfo *) proto_priv->info) : g_type_name(proto_priv->gtype)); } return JS_FALSE; } if (expected_gtype != G_TYPE_NONE) result = g_type_is_a(priv->prototype->gtype, expected_gtype); else result = JS_TRUE; if (!result && throw_error) { if (priv->prototype->info) { gjs_throw_custom(context, "TypeError", "Object is of type %s.%s - cannot convert to %s", g_base_info_get_namespace((GIBaseInfo *) priv->prototype->info), g_base_info_get_name((GIBaseInfo *) priv->prototype->info), g_type_name(expected_gtype)); } else { gjs_throw_custom(context, "TypeError", "Object is of type %s - cannot convert to %s", g_type_name(priv->prototype->gtype), g_type_name(expected_gtype)); } } return result; }
int lgi_type_get_name (lua_State *L, GIBaseInfo *info) { GSList *list = NULL, *i; int n = 1; lua_pushstring (L, g_base_info_get_namespace (info)); if (g_base_info_get_type (info) == GI_INFO_TYPE_CALLBACK) /* Avoid duplicate name for callbacks. */ info = g_base_info_get_container (info); /* Add names on the whole path, but in reverse order. */ for (; info != NULL; info = g_base_info_get_container (info)) if (!GI_IS_TYPE_INFO (info)) list = g_slist_prepend (list, info); for (i = list; i != NULL; i = g_slist_next (i)) { if (g_base_info_get_type (i->data) != GI_INFO_TYPE_TYPE) { lua_pushstring (L, "."); lua_pushstring (L, g_base_info_get_name (i->data)); n += 2; } } g_slist_free (list); return n; }
GError* gjs_gerror_from_error(JSContext *context, JSObject *obj) { Error *priv; if (obj == NULL) return NULL; /* If this is a plain GBoxed (i.e. a GError without metadata), delegate marshalling. */ if (gjs_typecheck_boxed (context, obj, NULL, G_TYPE_ERROR, JS_FALSE)) return gjs_c_struct_from_boxed (context, obj); priv = priv_from_js(context, obj); if (priv == NULL) return NULL; if (priv->gerror == NULL) { gjs_throw(context, "Object is %s.%s.prototype, not an object instance - cannot convert to a boxed instance", g_base_info_get_namespace( (GIBaseInfo*) priv->info), g_base_info_get_name( (GIBaseInfo*) priv->info)); return NULL; } return priv->gerror; }
void* gjs_g_fundamental_from_object(JSContext *context, JSObject *obj) { FundamentalInstance *priv; if (obj == NULL) return NULL; priv = priv_from_js(context, obj); if (priv == NULL) { gjs_throw(context, "No introspection information for %p", obj); return NULL; } if (priv->gfundamental == NULL) { gjs_throw(context, "Object is %s.%s.prototype, not an object instance - cannot convert to a fundamental instance", g_base_info_get_namespace((GIBaseInfo *) priv->prototype->info), g_base_info_get_name((GIBaseInfo *) priv->prototype->info)); return NULL; } return priv->gfundamental; }
void gjs_define_error_class(JSContext *context, JSObject *in_object, GIEnumInfo *info) { const char *constructor_name; GIBoxedInfo *glib_error_info; JSObject *prototype, *parent_proto; JSObject *constructor; Error *priv; /* See the comment in gjs_define_boxed_class() for an * explanation of how this all works; Error is pretty much the * same as Boxed (except that we inherit from GLib.Error). */ constructor_name = g_base_info_get_name( (GIBaseInfo*) info); g_irepository_require(NULL, "GLib", "2.0", (GIRepositoryLoadFlags) 0, NULL); glib_error_info = (GIBoxedInfo*) g_irepository_find_by_name(NULL, "GLib", "Error"); parent_proto = gjs_lookup_generic_prototype(context, glib_error_info); g_base_info_unref((GIBaseInfo*)glib_error_info); if (!gjs_init_class_dynamic(context, in_object, parent_proto, g_base_info_get_namespace( (GIBaseInfo*) info), constructor_name, &gjs_error_class, gjs_error_constructor, 1, /* props of prototype */ &gjs_error_proto_props[0], /* funcs of prototype */ &gjs_error_proto_funcs[0], /* props of constructor, MyConstructor.myprop */ NULL, /* funcs of constructor, MyConstructor.myfunc() */ &gjs_error_constructor_funcs[0], &prototype, &constructor)) { gjs_log_exception(context); g_error("Can't init class %s", constructor_name); } GJS_INC_COUNTER(gerror); priv = g_slice_new0(Error); priv->info = info; g_base_info_ref( (GIBaseInfo*) priv->info); priv->domain = g_quark_from_string (g_enum_info_get_error_domain(priv->info)); JS_SetPrivate(prototype, priv); gjs_debug(GJS_DEBUG_GBOXED, "Defined class %s prototype is %p class %p in object %p", constructor_name, prototype, JS_GetClass(prototype), in_object); gjs_define_enum_values(context, constructor, priv->info); gjs_define_enum_static_methods(context, constructor, priv->info); }
static gchar * get_struct_package (GIBaseInfo* info) { const gchar *basename, *package, *name; basename = g_base_info_get_namespace (info); package = get_package_for_basename (basename); if (!package) return NULL; name = g_base_info_get_name (info); return g_strconcat (package, "::", name, NULL); }
void lgi_type_get_repotype (lua_State *L, GType gtype, GIBaseInfo *info) { luaL_checkstack (L, 4, ""); /* Get repo-index table. */ lua_pushlightuserdata (L, &repo_index); lua_rawget (L, LUA_REGISTRYINDEX); /* Prepare gtype, if not given directly. */ if (gtype == G_TYPE_INVALID && info && GI_IS_REGISTERED_TYPE_INFO (info)) { gtype = g_registered_type_info_get_g_type (info); if (gtype == G_TYPE_NONE) gtype = G_TYPE_INVALID; } /* First of all, check direct indexing of repo-index by gtype, should be fastest. */ if (gtype != G_TYPE_INVALID) { lua_pushlightuserdata (L, (gpointer) gtype); lua_rawget (L, -2); } else lua_pushnil (L); if (lua_isnil (L, -1)) { /* Not indexed yet. Try to lookup by name - this works when lazy-loaded repo tables are not loaded yet. */ if (!info && gtype != G_TYPE_INVALID) { info = g_irepository_find_by_gtype (NULL, gtype); lgi_gi_info_new (L, info); } else /* Keep stack balanced as in the previous 'if' branch. */ lua_pushnil (L); if (info) { lua_pushlightuserdata (L, &repo); lua_rawget (L, LUA_REGISTRYINDEX); lua_getfield (L, -1, g_base_info_get_namespace (info)); lua_getfield (L, -1, g_base_info_get_name (info)); lua_replace (L, -5); lua_pop (L, 3); } else lua_pop (L, 1); } lua_replace (L, -2); }
static JSBool fundamental_invoke_constructor(FundamentalInstance *priv, JSContext *context, JSObject *obj, unsigned argc, jsval *argv, GArgument *rvalue) { jsval js_constructor, js_constructor_func; jsid constructor_const; JSBool ret = JS_FALSE; constructor_const = gjs_context_get_const_string(context, GJS_STRING_CONSTRUCTOR); if (!gjs_object_require_property(context, obj, NULL, constructor_const, &js_constructor) || priv->prototype->constructor_name == JSID_VOID) { gjs_throw (context, "Couldn't find a constructor for type %s.%s", g_base_info_get_namespace((GIBaseInfo*) priv->prototype->info), g_base_info_get_name((GIBaseInfo*) priv->prototype->info)); goto end; } if (!gjs_object_require_property(context, JSVAL_TO_OBJECT(js_constructor), NULL, priv->prototype->constructor_name, &js_constructor_func)) { gjs_throw (context, "Couldn't find a constructor for type %s.%s", g_base_info_get_namespace((GIBaseInfo*) priv->prototype->info), g_base_info_get_name((GIBaseInfo*) priv->prototype->info)); goto end; } ret = gjs_invoke_constructor_from_c(context, JSVAL_TO_OBJECT(js_constructor_func), obj, argc, argv, rvalue); end: return ret; }
gchar * _pygi_g_base_info_get_fullname (GIBaseInfo *info) { GIBaseInfo *container_info; gchar *fullname; container_info = g_base_info_get_container (info); if (container_info != NULL) { fullname = g_strdup_printf ("%s.%s.%s", g_base_info_get_namespace (container_info), g_base_info_get_name (container_info), g_base_info_get_name (info)); } else { fullname = g_strdup_printf ("%s.%s", g_base_info_get_namespace (info), g_base_info_get_name (info)); } if (fullname == NULL) { PyErr_NoMemory(); } return fullname; }
static PyObject * _struct_new (PyTypeObject *type, PyObject *args, PyObject *kwargs) { static char *kwlist[] = { NULL }; GIBaseInfo *info; gsize size; gpointer pointer; PyObject *self = NULL; if (!PyArg_ParseTupleAndKeywords (args, kwargs, "", kwlist)) { return NULL; } info = _pygi_object_get_gi_info ( (PyObject *) type, &PyGIStructInfo_Type); if (info == NULL) { if (PyErr_ExceptionMatches (PyExc_AttributeError)) { PyErr_Format (PyExc_TypeError, "missing introspection information"); } return NULL; } size = g_struct_info_get_size ( (GIStructInfo *) info); if (size == 0) { PyErr_Format (PyExc_TypeError, "cannot allocate disguised struct %s.%s; consider adding a constructor to the library or to the overrides", g_base_info_get_namespace (info), g_base_info_get_name (info)); goto out; } pointer = g_try_malloc0 (size); if (pointer == NULL) { PyErr_NoMemory(); goto out; } self = _pygi_struct_new (type, pointer, TRUE); if (self == NULL) { g_free (pointer); } out: g_base_info_unref (info); return (PyObject *) self; }
static PyObject * struct_new (PyTypeObject *type, PyObject *args, PyObject *kwargs) { static char *kwlist[] = { NULL }; GIBaseInfo *info; gsize size; gpointer pointer; PyObject *self = NULL; if (!PyArg_ParseTupleAndKeywords (args, kwargs, "", kwlist)) { return NULL; } info = struct_get_info ( type ); if (info == NULL) { if (PyErr_ExceptionMatches (PyExc_AttributeError)) { PyErr_Format (PyExc_TypeError, "missing introspection information"); } return NULL; } size = g_struct_info_get_size ( (GIStructInfo *) info); if (size == 0) { PyErr_Format (PyExc_TypeError, "struct cannot be created directly; try using a constructor, see: help(%s.%s)", g_base_info_get_namespace (info), g_base_info_get_name (info)); goto out; } pointer = g_try_malloc0 (size); if (pointer == NULL) { PyErr_NoMemory(); goto out; } self = pygi_struct_new (type, pointer, TRUE); if (self == NULL) { g_free (pointer); } out: g_base_info_unref (info); return (PyObject *) self; }
/* Default spidermonkey toString is worthless. Replace it * with something that gives us both the introspection name * and a memory address. */ JSBool _gwkjs_proxy_to_string_func(JSContextRef context, JSObjectRef this_obj, const char *objtype, GIBaseInfo *info, GType gtype, gpointer native_address, jsval *rval) { GString *buf; JSBool ret = JS_FALSE; buf = g_string_new(""); g_string_append_c(buf, '['); g_string_append(buf, objtype); if (native_address == NULL) g_string_append(buf, " prototype of"); else g_string_append(buf, " instance proxy"); if (info != NULL) { g_string_append_printf(buf, " GIName:%s.%s", g_base_info_get_namespace(info), g_base_info_get_name(info)); } else { g_string_append(buf, " GType:"); g_string_append(buf, g_type_name(gtype)); } g_string_append_printf(buf, " jsobj@%p", this_obj); if (native_address != NULL) g_string_append_printf(buf, " native@%p", native_address); g_string_append_c(buf, ']'); if (!gwkjs_string_from_utf8 (context, buf->str, -1, rval)) goto out; ret = JS_TRUE; out: g_string_free (buf, TRUE); return ret; }
static PyObject * struct_repr(PyGIStruct *self) { PyObject* repr; GIBaseInfo *info; PyGPointer *pointer = (PyGPointer *)self; info = struct_get_info (Py_TYPE (self)); if (info == NULL) return NULL; repr = PYGLIB_PyUnicode_FromFormat ("<%s.%s object at %p (%s at %p)>", g_base_info_get_namespace (info), g_base_info_get_name (info), self, g_type_name (pointer->gtype), pointer->pointer); g_base_info_unref (info); return repr; }
JSObject* gjs_object_from_g_fundamental(JSContext *context, GIObjectInfo *info, void *gfundamental) { JSObject *proto; JSObject *object; if (gfundamental == NULL) return NULL; object = _fundamental_lookup_object(gfundamental); if (object) return object; gjs_debug_marshal(GJS_DEBUG_GFUNDAMENTAL, "Wrapping fundamental %s.%s %p with JSObject", g_base_info_get_namespace((GIBaseInfo *) info), g_base_info_get_name((GIBaseInfo *) info), gfundamental); proto = gjs_lookup_fundamental_prototype_from_gtype(context, G_TYPE_FROM_INSTANCE(gfundamental)); object = JS_NewObjectWithGivenProto(context, JS_GetClass(proto), proto, gjs_get_import_global(context)); if (object == NULL) goto out; init_fundamental_instance(context, object); associate_js_instance_to_fundamental(context, object, gfundamental, FALSE); out: return object; }
GError* gjs_gerror_from_error(JSContext *context, JSObject *obj) { Error *priv; if (obj == NULL) return NULL; priv = priv_from_js(context, obj); if (priv == NULL) return NULL; if (priv->gerror == NULL) { gjs_throw(context, "Object is %s.%s.prototype, not an object instance - cannot convert to a boxed instance", g_base_info_get_namespace( (GIBaseInfo*) priv->info), g_base_info_get_name( (GIBaseInfo*) priv->info)); return NULL; } return priv->gerror; }
static void out_argument_to_raw_data_interface(GICallableInfo *callable_info, GIArgument *argument, gpointer result, GITypeInfo *type_info, G_GNUC_UNUSED GITransfer transfer /* TODO */, gboolean is_return_value) { GIBaseInfo *interface_info; GIInfoType interface_type; GIFFIReturnValue *ffi_return_value = result; interface_info = g_type_info_get_interface(type_info); interface_type = g_base_info_get_type(interface_info); switch (interface_type) { case GI_INFO_TYPE_INVALID: case GI_INFO_TYPE_FUNCTION: case GI_INFO_TYPE_CALLBACK: case GI_INFO_TYPE_STRUCT: case GI_INFO_TYPE_BOXED: rb_raise(rb_eNotImpError, "TODO: %s::%s: out raw data(interface)[%s]: <%s>", g_base_info_get_namespace(callable_info), g_base_info_get_name(callable_info), g_info_type_to_string(interface_type), g_base_info_get_name(interface_info)); break; case GI_INFO_TYPE_ENUM: if (is_return_value) { ffi_return_value->v_ulong = argument->v_int; } else { *((gint *)result) = argument->v_int; } break; case GI_INFO_TYPE_FLAGS: case GI_INFO_TYPE_OBJECT: case GI_INFO_TYPE_INTERFACE: case GI_INFO_TYPE_CONSTANT: rb_raise(rb_eNotImpError, "TODO: %s::%s: out raw data(interface)[%s]: <%s>", g_base_info_get_namespace(callable_info), g_base_info_get_name(callable_info), g_info_type_to_string(interface_type), g_base_info_get_name(interface_info)); break; case GI_INFO_TYPE_INVALID_0: g_assert_not_reached(); break; case GI_INFO_TYPE_UNION: case GI_INFO_TYPE_VALUE: case GI_INFO_TYPE_SIGNAL: case GI_INFO_TYPE_VFUNC: case GI_INFO_TYPE_PROPERTY: case GI_INFO_TYPE_FIELD: case GI_INFO_TYPE_ARG: case GI_INFO_TYPE_TYPE: case GI_INFO_TYPE_UNRESOLVED: default: rb_raise(rb_eNotImpError, "TODO: %s::%s: out raw data(interface)[%s]: <%s>", g_base_info_get_namespace(callable_info), g_base_info_get_name(callable_info), g_info_type_to_string(interface_type), g_base_info_get_name(interface_info)); break; } g_base_info_unref(interface_info); }
static void argument_from_raw_data_interface(GICallableInfo *callable_info, void *raw_arg, GIArgument *argument, GITypeInfo *type_info) { GIBaseInfo *interface_info; GIInfoType interface_type; interface_info = g_type_info_get_interface(type_info); interface_type = g_base_info_get_type(interface_info); switch (interface_type) { case GI_INFO_TYPE_INVALID: case GI_INFO_TYPE_FUNCTION: case GI_INFO_TYPE_CALLBACK: rb_raise(rb_eNotImpError, "TODO: %s::%s: raw data -> GIArgument(interface)[%s]: <%s>", g_base_info_get_namespace(callable_info), g_base_info_get_name(callable_info), g_info_type_to_string(interface_type), g_base_info_get_name(interface_info)); break; case GI_INFO_TYPE_STRUCT: argument->v_pointer = *((gpointer *)(raw_arg)); break; case GI_INFO_TYPE_BOXED: case GI_INFO_TYPE_ENUM: rb_raise(rb_eNotImpError, "TODO: %s::%s: raw data -> GIArgument(interface)[%s]: <%s>", g_base_info_get_namespace(callable_info), g_base_info_get_name(callable_info), g_info_type_to_string(interface_type), g_base_info_get_name(interface_info)); break; case GI_INFO_TYPE_FLAGS: argument->v_int32= *((gint32 *)(raw_arg)); break; case GI_INFO_TYPE_OBJECT: case GI_INFO_TYPE_INTERFACE: argument->v_pointer = *((gpointer *)(raw_arg)); break; case GI_INFO_TYPE_CONSTANT: rb_raise(rb_eNotImpError, "TODO: %s::%s: raw data -> GIArgument(interface)[%s]: <%s>", g_base_info_get_namespace(callable_info), g_base_info_get_name(callable_info), g_info_type_to_string(interface_type), g_base_info_get_name(interface_info)); break; case GI_INFO_TYPE_INVALID_0: g_assert_not_reached(); break; case GI_INFO_TYPE_UNION: case GI_INFO_TYPE_VALUE: case GI_INFO_TYPE_SIGNAL: case GI_INFO_TYPE_VFUNC: case GI_INFO_TYPE_PROPERTY: case GI_INFO_TYPE_FIELD: case GI_INFO_TYPE_ARG: case GI_INFO_TYPE_TYPE: case GI_INFO_TYPE_UNRESOLVED: default: rb_raise(rb_eNotImpError, "TODO: %s::%s: raw data -> GIArgument(interface)[%s]: <%s>", g_base_info_get_namespace(callable_info), g_base_info_get_name(callable_info), g_info_type_to_string(interface_type), g_base_info_get_name(interface_info)); break; } g_base_info_unref(interface_info); }
/* * Like JSResolveOp, but flags provide contextual information as follows: * * JSRESOLVE_QUALIFIED a qualified property id: obj.id or obj[id], not id * JSRESOLVE_ASSIGNING obj[id] is on the left-hand side of an assignment * JSRESOLVE_DETECTING 'if (o.p)...' or similar detection opcode sequence * JSRESOLVE_DECLARING var, const, or boxed prolog declaration opcode * JSRESOLVE_CLASSNAME class name used when constructing * * The *objp out parameter, on success, should be null to indicate that id * was not resolved; and non-null, referring to obj or one of its prototypes, * if id was resolved. */ static JSBool union_new_resolve(JSContext *context, JS::HandleObject obj, JS::HandleId id, unsigned flags, JS::MutableHandleObject objp) { Union *priv; char *name; JSBool ret = JS_TRUE; if (!gjs_get_string_id(context, id, &name)) return JS_TRUE; /* not resolved, but no error */ priv = priv_from_js(context, obj); gjs_debug_jsprop(GJS_DEBUG_GBOXED, "Resolve prop '%s' hook obj %p priv %p", name, *obj, priv); if (priv == NULL) { ret = JS_FALSE; /* wrong class */ goto out; } if (priv->gboxed == NULL) { /* We are the prototype, so look for methods and other class properties */ GIFunctionInfo *method_info; method_info = g_union_info_find_method((GIUnionInfo*) priv->info, name); if (method_info != NULL) { JSObject *union_proto; const char *method_name; #if GJS_VERBOSE_ENABLE_GI_USAGE _gjs_log_info_usage((GIBaseInfo*) method_info); #endif if (g_function_info_get_flags (method_info) & GI_FUNCTION_IS_METHOD) { method_name = g_base_info_get_name( (GIBaseInfo*) method_info); gjs_debug(GJS_DEBUG_GBOXED, "Defining method %s in prototype for %s.%s", method_name, g_base_info_get_namespace( (GIBaseInfo*) priv->info), g_base_info_get_name( (GIBaseInfo*) priv->info)); union_proto = obj; if (gjs_define_function(context, union_proto, g_registered_type_info_get_g_type(priv->info), method_info) == NULL) { g_base_info_unref( (GIBaseInfo*) method_info); ret = JS_FALSE; goto out; } objp.set(union_proto); /* we defined the prop in object_proto */ } g_base_info_unref( (GIBaseInfo*) method_info); } } else { /* We are an instance, not a prototype, so look for * per-instance props that we want to define on the * JSObject. Generally we do not want to cache these in JS, we * want to always pull them from the C object, or JS would not * see any changes made from C. So we use the get/set prop * hooks, not this resolve hook. */ } out: g_free(name); return ret; }
gboolean _pygi_create_callback (GIBaseInfo *function_info, gboolean is_method, gboolean is_constructor, int n_args, Py_ssize_t py_argc, PyObject *py_argv, guint8 callback_index, guint8 user_data_index, guint8 destroy_notify_index, PyGICClosure **closure_out) { GIArgInfo *callback_arg; GITypeInfo *callback_type; GICallbackInfo *callback_info; GIScopeType scope; gboolean found_py_function; PyObject *py_function; guint8 i, py_argv_pos; PyObject *py_user_data; gboolean allow_none; callback_arg = g_callable_info_get_arg ( (GICallableInfo*) function_info, callback_index); scope = g_arg_info_get_scope (callback_arg); allow_none = g_arg_info_may_be_null (callback_arg); callback_type = g_arg_info_get_type (callback_arg); g_assert (g_type_info_get_tag (callback_type) == GI_TYPE_TAG_INTERFACE); callback_info = (GICallbackInfo*) g_type_info_get_interface (callback_type); g_assert (g_base_info_get_type ( (GIBaseInfo*) callback_info) == GI_INFO_TYPE_CALLBACK); /* Find the Python function passed for the callback */ found_py_function = FALSE; py_function = Py_None; py_user_data = NULL; /* if its a method then we need to skip over 'self' */ if (is_method || is_constructor) py_argv_pos = 1; else py_argv_pos = 0; for (i = 0; i < n_args && i < py_argc; i++) { if (i == callback_index) { py_function = PyTuple_GetItem (py_argv, py_argv_pos); /* if we allow none then set the closure to NULL and return */ if (allow_none && py_function == Py_None) { *closure_out = NULL; goto out; } found_py_function = TRUE; } else if (i == user_data_index) { py_user_data = PyTuple_GetItem (py_argv, py_argv_pos); } py_argv_pos++; } if (!found_py_function || (py_function == Py_None || !PyCallable_Check (py_function))) { PyErr_Format (PyExc_TypeError, "Error invoking %s.%s: Unexpected value " "for argument '%s'", g_base_info_get_namespace ( (GIBaseInfo*) function_info), g_base_info_get_name ( (GIBaseInfo*) function_info), g_base_info_get_name ( (GIBaseInfo*) callback_arg)); g_base_info_unref ( (GIBaseInfo*) callback_info); g_base_info_unref ( (GIBaseInfo*) callback_type); return FALSE; } /** Now actually build the closure **/ *closure_out = _pygi_make_native_closure ( (GICallableInfo *) callback_info, g_arg_info_get_scope (callback_arg), py_function, py_user_data); out: g_base_info_unref ( (GIBaseInfo*) callback_info); g_base_info_unref ( (GIBaseInfo*) callback_type); return TRUE; }
JSBool gjs_define_fundamental_class(JSContext *context, JSObject *in_object, GIObjectInfo *info, JSObject **constructor_p, JSObject **prototype_p) { const char *constructor_name; JSObject *prototype; jsval value; jsid js_constructor_name = JSID_VOID; JSObject *parent_proto; Fundamental *priv; JSObject *constructor; GType parent_gtype; GType gtype; GIFunctionInfo *constructor_info; /* See the comment in gjs_define_object_class() for an explanation * of how this all works; Fundamental is pretty much the same as * Object. */ constructor_name = g_base_info_get_name((GIBaseInfo *) info); constructor_info = find_fundamental_constructor(context, info, &js_constructor_name); gtype = g_registered_type_info_get_g_type (info); parent_gtype = g_type_parent(gtype); parent_proto = NULL; if (parent_gtype != G_TYPE_INVALID) parent_proto = gjs_lookup_fundamental_prototype_from_gtype(context, parent_gtype); if (!gjs_init_class_dynamic(context, in_object, /* parent prototype JSObject* for * prototype; NULL for * Object.prototype */ parent_proto, g_base_info_get_namespace((GIBaseInfo *) info), constructor_name, &gjs_fundamental_instance_class, gjs_fundamental_instance_constructor, /* number of constructor args (less can be passed) */ constructor_info != NULL ? g_callable_info_get_n_args((GICallableInfo *) constructor_info) : 0, /* props of prototype */ parent_proto ? NULL : &gjs_fundamental_instance_proto_props[0], /* funcs of prototype */ parent_proto ? NULL : &gjs_fundamental_instance_proto_funcs[0], /* props of constructor, MyConstructor.myprop */ NULL, /* funcs of constructor, MyConstructor.myfunc() */ NULL, &prototype, &constructor)) { gjs_log_exception(context); g_error("Can't init class %s", constructor_name); } /* Put the info in the prototype */ priv = g_slice_new0(Fundamental); g_assert(priv != NULL); g_assert(priv->info == NULL); priv->info = g_base_info_ref((GIBaseInfo *) info); priv->gtype = gtype; priv->constructor_name = js_constructor_name; priv->constructor_info = constructor_info; priv->ref_function = g_object_info_get_ref_function_pointer(info); g_assert(priv->ref_function != NULL); priv->unref_function = g_object_info_get_unref_function_pointer(info); g_assert(priv->unref_function != NULL); priv->set_value_function = g_object_info_get_set_value_function_pointer(info); g_assert(priv->set_value_function != NULL); priv->get_value_function = g_object_info_get_get_value_function_pointer(info); g_assert(priv->get_value_function != NULL); JS_SetPrivate(prototype, priv); gjs_debug(GJS_DEBUG_GFUNDAMENTAL, "Defined class %s prototype is %p class %p in object %p constructor %s.%s.%s", constructor_name, prototype, JS_GetClass(prototype), in_object, constructor_info != NULL ? g_base_info_get_namespace(constructor_info) : "unknown", constructor_info != NULL ? g_base_info_get_name(g_base_info_get_container(constructor_info)) : "unknown", constructor_info != NULL ? g_base_info_get_name(constructor_info) : "unknown"); if (g_object_info_get_n_fields(priv->info) > 0) { gjs_debug(GJS_DEBUG_GFUNDAMENTAL, "Fundamental type '%s.%s' apparently has accessible fields. " "Gjs has no support for this yet, ignoring these.", g_base_info_get_namespace((GIBaseInfo *)priv->info), g_base_info_get_name ((GIBaseInfo *)priv->info)); } gjs_object_define_static_methods(context, constructor, gtype, info); value = OBJECT_TO_JSVAL(gjs_gtype_create_gtype_wrapper(context, gtype)); JS_DefineProperty(context, constructor, "$gtype", value, NULL, NULL, JSPROP_PERMANENT); if (constructor_p) *constructor_p = constructor; if (prototype_p) *prototype_p = prototype; return JS_TRUE; }
gboolean _pygi_scan_for_callbacks (GIFunctionInfo *function_info, gboolean is_method, guint8 *callback_index, guint8 *user_data_index, guint8 *destroy_notify_index) { guint i, n_args; *callback_index = G_MAXUINT8; *user_data_index = G_MAXUINT8; *destroy_notify_index = G_MAXUINT8; n_args = g_callable_info_get_n_args ( (GICallableInfo *) function_info); for (i = 0; i < n_args; i++) { GIDirection direction; GIArgInfo *arg_info; GITypeInfo *type_info; guint8 destroy, closure; GITypeTag type_tag; arg_info = g_callable_info_get_arg ( (GICallableInfo*) function_info, i); type_info = g_arg_info_get_type (arg_info); type_tag = g_type_info_get_tag (type_info); if (type_tag == GI_TYPE_TAG_INTERFACE) { GIBaseInfo* interface_info; GIInfoType interface_type; interface_info = g_type_info_get_interface (type_info); interface_type = g_base_info_get_type (interface_info); if (interface_type == GI_INFO_TYPE_CALLBACK && ! (strcmp (g_base_info_get_namespace ( (GIBaseInfo*) interface_info), "GLib") == 0 && (strcmp (g_base_info_get_name ( (GIBaseInfo*) interface_info), "DestroyNotify") == 0 || (strcmp (g_base_info_get_name ( (GIBaseInfo*) interface_info), "FreeFunc") == 0)))) { if (*callback_index != G_MAXUINT8) { PyErr_Format (PyExc_TypeError, "Function %s.%s has multiple callbacks, not supported", g_base_info_get_namespace ( (GIBaseInfo*) function_info), g_base_info_get_name ( (GIBaseInfo*) function_info)); g_base_info_unref (interface_info); return FALSE; } *callback_index = i; } g_base_info_unref (interface_info); } destroy = g_arg_info_get_destroy (arg_info); closure = g_arg_info_get_closure (arg_info); direction = g_arg_info_get_direction (arg_info); if (destroy > 0 && destroy < n_args) { if (*destroy_notify_index != G_MAXUINT8) { PyErr_Format (PyExc_TypeError, "Function %s has multiple GDestroyNotify, not supported", g_base_info_get_name ( (GIBaseInfo*) function_info)); return FALSE; } *destroy_notify_index = destroy; } if (closure > 0 && closure < n_args) { if (*user_data_index != G_MAXUINT8) { PyErr_Format (PyExc_TypeError, "Function %s has multiple user_data arguments, not supported", g_base_info_get_name ( (GIBaseInfo*) function_info)); return FALSE; } *user_data_index = closure; } g_base_info_unref ( (GIBaseInfo*) arg_info); g_base_info_unref ( (GIBaseInfo*) type_info); } return TRUE; }
/* * Like JSResolveOp, but flags provide contextual information as follows: * * JSRESOLVE_QUALIFIED a qualified property id: obj.id or obj[id], not id * JSRESOLVE_ASSIGNING obj[id] is on the left-hand side of an assignment * JSRESOLVE_DETECTING 'if (o.p)...' or similar detection opcode sequence * JSRESOLVE_DECLARING var, const, or fundamental prolog declaration opcode * JSRESOLVE_CLASSNAME class name used when constructing * * The *objp out parameter, on success, should be null to indicate that id * was not resolved; and non-null, referring to obj or one of its prototypes, * if id was resolved. */ static JSBool fundamental_instance_new_resolve(JSContext *context, JS::HandleObject obj, JS::HandleId id, unsigned flags, JS::MutableHandleObject objp) { FundamentalInstance *priv; char *name; JSBool ret = JS_FALSE; if (!gjs_get_string_id(context, id, &name)) return JS_TRUE; /* not resolved, but no error */ priv = priv_from_js(context, obj); gjs_debug_jsprop(GJS_DEBUG_GFUNDAMENTAL, "Resolve prop '%s' hook obj %p priv %p", name, *obj, priv); if (priv == NULL) goto out; /* wrong class */ if (priv->prototype == NULL) { /* We are the prototype, so look for methods and other class properties */ Fundamental *proto_priv = (Fundamental *) priv; GIFunctionInfo *method_info; method_info = g_object_info_find_method((GIStructInfo*) proto_priv->info, name); if (method_info != NULL) { const char *method_name; #if GJS_VERBOSE_ENABLE_GI_USAGE _gjs_log_info_usage((GIBaseInfo *) method_info); #endif if (g_function_info_get_flags (method_info) & GI_FUNCTION_IS_METHOD) { method_name = g_base_info_get_name((GIBaseInfo *) method_info); /* we do not define deprecated methods in the prototype */ if (g_base_info_is_deprecated((GIBaseInfo *) method_info)) { gjs_debug(GJS_DEBUG_GFUNDAMENTAL, "Ignoring definition of deprecated method %s in prototype %s.%s", method_name, g_base_info_get_namespace((GIBaseInfo *) proto_priv->info), g_base_info_get_name((GIBaseInfo *) proto_priv->info)); g_base_info_unref((GIBaseInfo *) method_info); ret = JS_TRUE; goto out; } gjs_debug(GJS_DEBUG_GFUNDAMENTAL, "Defining method %s in prototype for %s.%s", method_name, g_base_info_get_namespace((GIBaseInfo *) proto_priv->info), g_base_info_get_name((GIBaseInfo *) proto_priv->info)); if (gjs_define_function(context, obj, proto_priv->gtype, method_info) == NULL) { g_base_info_unref((GIBaseInfo *) method_info); goto out; } objp.set(obj); } g_base_info_unref((GIBaseInfo *) method_info); } ret = fundamental_instance_new_resolve_interface(context, obj, objp, proto_priv, name); } else { /* We are an instance, not a prototype, so look for * per-instance props that we want to define on the * JSObject. Generally we do not want to cache these in JS, we * want to always pull them from the C object, or JS would not * see any changes made from C. So we use the get/set prop * hooks, not this resolve hook. */ } ret = JS_TRUE; out: g_free(name); return ret; }
JSBool gjs_define_error_class(JSContext *context, JSObject *in_object, GIEnumInfo *info, JSObject **constructor_p, JSObject **prototype_p) { const char *constructor_name; GIBoxedInfo *glib_error_info; JSObject *prototype, *parent_proto; JSObject *constructor; jsval value; Error *priv; /* See the comment in gjs_define_boxed_class() for an * explanation of how this all works; Error is pretty much the * same as Boxed (except that we inherit from GLib.Error). */ constructor_name = g_base_info_get_name( (GIBaseInfo*) info); if (gjs_object_get_property(context, in_object, constructor_name, &value)) { JSObject *constructor; if (!JSVAL_IS_OBJECT(value)) { gjs_throw(context, "Existing property '%s' does not look like a constructor", constructor_name); return JS_FALSE; } constructor = JSVAL_TO_OBJECT(value); gjs_object_get_property(context, constructor, "prototype", &value); if (!JSVAL_IS_OBJECT(value)) { gjs_throw(context, "error %s prototype property does not appear to exist or has wrong type", constructor_name); return JS_FALSE; } else { if (prototype_p) *prototype_p = JSVAL_TO_OBJECT(value); if (constructor_p) *constructor_p = constructor; return JS_TRUE; } } g_irepository_require(NULL, "GLib", "2.0", 0, NULL); glib_error_info = (GIBoxedInfo*) g_irepository_find_by_name(NULL, "GLib", "Error"); parent_proto = gjs_lookup_boxed_prototype(context, glib_error_info); g_base_info_unref((GIBaseInfo*)glib_error_info); prototype = gjs_init_class_dynamic(context, in_object, parent_proto, g_base_info_get_namespace( (GIBaseInfo*) info), constructor_name, &gjs_error_class, gjs_error_constructor, /* number of constructor args (less can be passed) */ 1, /* props of prototype */ &gjs_error_proto_props[0], /* funcs of prototype */ &gjs_error_proto_funcs[0], /* props of constructor, MyConstructor.myprop */ NULL, /* funcs of constructor, MyConstructor.myfunc() */ &gjs_error_constructor_funcs[0]); if (prototype == NULL) { gjs_log_exception(context, NULL); gjs_fatal("Can't init class %s", constructor_name); } g_assert(gjs_object_has_property(context, in_object, constructor_name)); GJS_INC_COUNTER(gerror); priv = g_slice_new0(Error); priv->info = info; g_base_info_ref( (GIBaseInfo*) priv->info); priv->domain = g_quark_from_string (g_enum_info_get_error_domain(priv->info)); JS_SetPrivate(context, prototype, priv); gjs_debug(GJS_DEBUG_GBOXED, "Defined class %s prototype is %p class %p in object %p", constructor_name, prototype, JS_GET_CLASS(context, prototype), in_object); constructor = NULL; gjs_object_get_property(context, in_object, constructor_name, &value); if (!JSVAL_IS_VOID(value)) { if (!JSVAL_IS_OBJECT(value)) { gjs_throw(context, "Property '%s' does not look like a constructor", constructor_name); return JS_FALSE; } } constructor = JSVAL_TO_OBJECT(value); gjs_define_enum_values(context, constructor, priv->info); if (constructor_p) *constructor_p = constructor; if (prototype_p) *prototype_p = prototype; return JS_TRUE; }
static JSValueRef ns_get_property(JSContextRef context, JSObjectRef obj, JSStringRef property_name, JSValueRef* exception) { Ns *priv = NULL; char *name = NULL; GIRepository *repo = NULL; GIBaseInfo *info; JSValueRef ret = NULL; gboolean defined; name = gwkjs_jsstring_to_cstring(property_name); /* let Object.prototype resolve these */ if (strcmp(name, "valueOf") == 0 || strcmp(name, "toString") == 0) { goto out; } priv = priv_from_js(obj); gwkjs_debug_jsprop(GWKJS_DEBUG_GNAMESPACE, "Resolve prop '%s' hook obj %p priv %p", name, (void *)obj, priv); if (priv == NULL) { goto out; } // If the module was already included, the default proto system // should return the property, not this method. if (g_hash_table_contains(priv->modules, name)) goto out; repo = g_irepository_get_default(); info = g_irepository_find_by_name(repo, priv->gi_namespace, name); if (info == NULL) { /* No property defined, but no error either, so return TRUE */ goto out; } gwkjs_debug(GWKJS_DEBUG_GNAMESPACE, "Found info type %s for '%s' in namespace '%s'", gwkjs_info_type_name(g_base_info_get_type(info)), g_base_info_get_name(info), g_base_info_get_namespace(info)); g_hash_table_replace(priv->modules, g_strdup(name), NULL); if ((ret = gwkjs_define_info(context, obj, info, &defined))) { g_base_info_unref(info); //XXX: Does it return THIS?! // if (defined) // objp.set(obj); /* we defined the property in this object */ } else { g_hash_table_remove(priv->modules, name); gwkjs_debug(GWKJS_DEBUG_GNAMESPACE, "Failed to define info '%s'", g_base_info_get_name(info)); g_base_info_unref(info); } out: g_free(name); return ret; }
JSBool gjs_define_interface_class(JSContext *context, JSObject *in_object, GIInterfaceInfo *info, JSObject **prototype_p) { Interface *priv; const char *constructor_name; JSObject *constructor; JSObject *prototype; jsval value; constructor_name = g_base_info_get_name((GIBaseInfo*)info); gjs_object_get_property(context, in_object, constructor_name, &value); if (!JSVAL_IS_VOID(value)) { JSObject *constructor; if (!JSVAL_IS_OBJECT(value)) { gjs_throw(context, "Existing property '%s' does not look like a constructor", constructor_name); return JS_FALSE; } constructor = JSVAL_TO_OBJECT(value); gjs_object_get_property(context, constructor, "prototype", &value); if (!JSVAL_IS_OBJECT(value)) { gjs_throw(context, "prototype property does not appear to exist or has wrong type"); return JS_FALSE; } else { if (prototype_p) *prototype_p = JSVAL_TO_OBJECT(value); return JS_TRUE; } return JS_TRUE; } if (!gjs_init_class_dynamic(context, in_object, NULL, g_base_info_get_namespace((GIBaseInfo*)info), constructor_name, &gjs_interface_class, gjs_interface_constructor, 0, /* props of prototype */ &gjs_interface_proto_props[0], /* funcs of prototype */ &gjs_interface_proto_funcs[0], /* props of constructor, MyConstructor.myprop */ NULL, /* funcs of constructor, MyConstructor.myfunc() */ NULL, &prototype, &constructor)) { gjs_fatal("Can't init class %s", constructor_name); } GJS_INC_COUNTER(interface); priv = g_slice_new0(Interface); priv->info = info; priv->gtype = g_registered_type_info_get_g_type(priv->info); g_base_info_ref((GIBaseInfo*)priv->info); JS_SetPrivate(context, prototype, priv); gjs_define_static_methods(context, constructor, priv->gtype, priv->info); value = OBJECT_TO_JSVAL(gjs_gtype_create_gtype_wrapper(context, priv->gtype)); JS_DefineProperty(context, constructor, "$gtype", value, NULL, NULL, JSPROP_PERMANENT); if (prototype_p) *prototype_p = prototype; return JS_TRUE; }
/* * Like JSResolveOp, but flags provide contextual information as follows: * * JSRESOLVE_QUALIFIED a qualified property id: obj.id or obj[id], not id * JSRESOLVE_ASSIGNING obj[id] is on the left-hand side of an assignment * JSRESOLVE_DETECTING 'if (o.p)...' or similar detection opcode sequence * JSRESOLVE_DECLARING var, const, or boxed prolog declaration opcode * JSRESOLVE_CLASSNAME class name used when constructing * * The *objp out parameter, on success, should be null to indicate that id * was not resolved; and non-null, referring to obj or one of its prototypes, * if id was resolved. */ static JSBool boxed_new_resolve(JSContext *context, JSObject *obj, jsid id, unsigned flags, JSObject **objp) { Boxed *priv; char *name; JSBool ret = JS_FALSE; *objp = NULL; if (!gjs_get_string_id(context, id, &name)) return JS_TRUE; /* not resolved, but no error */ priv = priv_from_js(context, obj); gjs_debug_jsprop(GJS_DEBUG_GBOXED, "Resolve prop '%s' hook obj %p priv %p", name, obj, priv); if (priv == NULL) goto out; /* wrong class */ if (priv->gboxed == NULL) { /* We are the prototype, so look for methods and other class properties */ GIFunctionInfo *method_info; method_info = g_struct_info_find_method((GIStructInfo*) priv->info, name); if (method_info != NULL) { JSObject *boxed_proto; const char *method_name; #if GJS_VERBOSE_ENABLE_GI_USAGE _gjs_log_info_usage((GIBaseInfo*) method_info); #endif method_name = g_base_info_get_name( (GIBaseInfo*) method_info); gjs_debug(GJS_DEBUG_GBOXED, "Defining method %s in prototype for %s.%s", method_name, g_base_info_get_namespace( (GIBaseInfo*) priv->info), g_base_info_get_name( (GIBaseInfo*) priv->info)); boxed_proto = obj; if (gjs_define_function(context, boxed_proto, priv->gtype, (GICallableInfo *)method_info) == NULL) { g_base_info_unref( (GIBaseInfo*) method_info); goto out; } *objp = boxed_proto; /* we defined the prop in object_proto */ g_base_info_unref( (GIBaseInfo*) method_info); } } else { /* We are an instance, not a prototype, so look for * per-instance props that we want to define on the * JSObject. Generally we do not want to cache these in JS, we * want to always pull them from the C object, or JS would not * see any changes made from C. So we use the get/set prop * hooks, not this resolve hook. */ } ret = JS_TRUE; out: g_free(name); return ret; }
JSBool gjs_define_boxed_class(JSContext *context, JSObject *in_object, GIBoxedInfo *info, JSObject **constructor_p, JSObject **prototype_p) { const char *constructor_name; JSObject *prototype; JSObject *constructor; jsval value; Boxed *priv; /* See the comment in gjs_define_object_class() for an * explanation of how this all works; Boxed is pretty much the * same as Object. */ constructor_name = g_base_info_get_name( (GIBaseInfo*) info); if (gjs_object_get_property(context, in_object, constructor_name, &value)) { JSObject *constructor; if (!JSVAL_IS_OBJECT(value)) { gjs_throw(context, "Existing property '%s' does not look like a constructor", constructor_name); return JS_FALSE; } constructor = JSVAL_TO_OBJECT(value); gjs_object_get_property(context, constructor, "prototype", &value); if (!JSVAL_IS_OBJECT(value)) { gjs_throw(context, "boxed %s prototype property does not appear to exist or has wrong type", constructor_name); return JS_FALSE; } else { if (prototype_p) *prototype_p = JSVAL_TO_OBJECT(value); if (constructor_p) *constructor_p = constructor; return JS_TRUE; } } if (!gjs_init_class_dynamic(context, in_object, NULL, /* parent prototype */ g_base_info_get_namespace( (GIBaseInfo*) info), constructor_name, &gjs_boxed_class, gjs_boxed_constructor, 1, /* props of prototype */ &gjs_boxed_proto_props[0], /* funcs of prototype */ &gjs_boxed_proto_funcs[0], /* props of constructor, MyConstructor.myprop */ NULL, /* funcs of constructor, MyConstructor.myfunc() */ NULL, &prototype, &constructor)) { gjs_log_exception(context, NULL); gjs_fatal("Can't init class %s", constructor_name); } GJS_INC_COUNTER(boxed); priv = g_slice_new0(Boxed); priv->info = info; boxed_fill_prototype_info(priv); g_base_info_ref( (GIBaseInfo*) priv->info); priv->gtype = g_registered_type_info_get_g_type ((GIRegisteredTypeInfo*) priv->info); JS_SetPrivate(context, prototype, priv); gjs_debug(GJS_DEBUG_GBOXED, "Defined class %s prototype is %p class %p in object %p", constructor_name, prototype, JS_GET_CLASS(context, prototype), in_object); priv->can_allocate_directly = struct_is_simple (priv->info); define_boxed_class_fields (context, priv, prototype); gjs_define_static_methods (context, constructor, priv->gtype, priv->info); value = OBJECT_TO_JSVAL(gjs_gtype_create_gtype_wrapper(context, priv->gtype)); JS_DefineProperty(context, constructor, "$gtype", value, NULL, NULL, JSPROP_PERMANENT); if (constructor_p) *constructor_p = constructor; if (prototype_p) *prototype_p = prototype; return JS_TRUE; }
static PyObject * _wrap_g_base_info_get_namespace (PyGIBaseInfo *self) { return PYGLIB_PyUnicode_FromString (g_base_info_get_namespace (self->info)); }