gjs r112 - in trunk: . gi test/js
- From: otaylor svn gnome org
- To: svn-commits-list gnome org
- Subject: gjs r112 - in trunk: . gi test/js
- Date: Wed, 19 Nov 2008 22:30:35 +0000 (UTC)
Author: otaylor
Date: Wed Nov 19 22:30:35 2008
New Revision: 112
URL: http://svn.gnome.org/viewvc/gjs?rev=112&view=rev
Log:
Bug 560808 - Simple field supported for boxed types
* gi/boxed.c: Define properties for the fields defined in the
introspection information.
* test/js/testEverythingEncapsulated.js: New field for tests of
boxed types and structures.
Added:
trunk/test/js/testEverythingEncapsulated.js
Modified:
trunk/Makefile-test.am
trunk/gi/boxed.c
Modified: trunk/Makefile-test.am
==============================================================================
--- trunk/Makefile-test.am (original)
+++ trunk/Makefile-test.am Wed Nov 19 22:30:35 2008
@@ -107,6 +107,7 @@
test/js/modules/jsUnit.js \
test/js/testself.js \
test/js/testEverythingBasic.js \
+ test/js/testEverythingEncapulated.js \
test/js/testGI.js \
test/js/testImporter.js \
test/js/testLang.js \
Modified: trunk/gi/boxed.c
==============================================================================
--- trunk/gi/boxed.c (original)
+++ trunk/gi/boxed.c Wed Nov 19 22:30:35 2008
@@ -331,6 +331,194 @@
g_slice_free(Boxed, priv);
}
+static GIFieldInfo *
+get_field_info (JSContext *context,
+ Boxed *priv,
+ jsval id)
+{
+ int field_index;
+
+ if (!JSVAL_IS_INT (id)) {
+ gjs_throw(context, "Field index for %s is not an integer",
+ g_base_info_get_name ((GIBaseInfo *)priv->info));
+ return NULL;
+ }
+
+ field_index = JSVAL_TO_INT(id);
+ if (field_index < 0 || field_index >= g_struct_info_get_n_fields (priv->info)) {
+ gjs_throw(context, "Bad field index %d for %s", field_index,
+ g_base_info_get_name ((GIBaseInfo *)priv->info));
+ return NULL;
+ }
+
+ return g_struct_info_get_field (priv->info, field_index);
+}
+
+static JSBool
+boxed_field_getter (JSContext *context,
+ JSObject *obj,
+ jsval id,
+ jsval *value)
+{
+ Boxed *priv;
+ GIFieldInfo *field_info;
+ GITypeInfo *type_info;
+ GArgument arg;
+ gboolean success = FALSE;
+
+ priv = priv_from_js(context, obj);
+ if (!priv)
+ return JS_FALSE;
+
+ field_info = get_field_info(context, priv, id);
+ if (!field_info)
+ return JS_FALSE;
+
+ type_info = g_field_info_get_type (field_info);
+
+ if (priv->gboxed == NULL) { /* direct access to proto field */
+ gjs_throw(context, "Can't get field %s.%s from a prototype",
+ g_base_info_get_name ((GIBaseInfo *)priv->info),
+ g_base_info_get_name ((GIBaseInfo *)field_info));
+ goto out;
+ }
+
+ if (!g_field_info_get_field (field_info, priv->gboxed, &arg)) {
+ gjs_throw(context, "Reading field %s.%s is not supported",
+ g_base_info_get_name ((GIBaseInfo *)priv->info),
+ g_base_info_get_name ((GIBaseInfo *)field_info));
+ goto out;
+ }
+
+ if (!gjs_value_from_g_argument (context, value,
+ type_info,
+ &arg))
+ goto out;
+
+ success = TRUE;
+
+out:
+ g_base_info_unref ((GIBaseInfo *)field_info);
+ g_base_info_unref ((GIBaseInfo *)type_info);
+
+ return success;
+}
+
+static JSBool
+boxed_field_setter (JSContext *context,
+ JSObject *obj,
+ jsval id,
+ jsval *value)
+{
+ Boxed *priv;
+ GIFieldInfo *field_info;
+ GITypeInfo *type_info;
+ GArgument arg;
+ gboolean success = FALSE;
+ gboolean need_release = FALSE;
+
+ priv = priv_from_js(context, obj);
+ if (!priv)
+ return JS_FALSE;
+
+ field_info = get_field_info(context, priv, id);
+ if (!field_info)
+ return JS_FALSE;
+
+ type_info = g_field_info_get_type (field_info);
+
+ if (priv->gboxed == NULL) { /* direct access to proto field */
+ gjs_throw(context, "Can't set field %s.%s on prototype",
+ g_base_info_get_name ((GIBaseInfo *)priv->info),
+ g_base_info_get_name ((GIBaseInfo *)field_info));
+ goto out;
+ }
+
+ if (!gjs_value_to_g_argument(context, *value,
+ type_info,
+ g_base_info_get_name ((GIBaseInfo *)field_info),
+ GJS_ARGUMENT_FIELD,
+ TRUE, &arg))
+ goto out;
+
+ need_release = TRUE;
+
+ if (!g_field_info_set_field (field_info, priv->gboxed, &arg)) {
+ gjs_throw(context, "Writing field %s.%s is not supported",
+ g_base_info_get_name ((GIBaseInfo *)priv->info),
+ g_base_info_get_name ((GIBaseInfo *)field_info));
+ goto out;
+ }
+
+ success = TRUE;
+
+out:
+ if (need_release)
+ gjs_g_argument_release (context, GI_TRANSFER_NOTHING,
+ type_info,
+ &arg);
+
+ g_base_info_unref ((GIBaseInfo *)field_info);
+ g_base_info_unref ((GIBaseInfo *)type_info);
+
+ return success;
+}
+
+static JSBool
+define_boxed_class_fields (JSContext *context,
+ Boxed *priv,
+ JSObject *proto)
+{
+ int n_fields = g_struct_info_get_n_fields (priv->info);
+ int i;
+
+ /* We identify properties with a 'TinyId': a 8-bit numeric value
+ * that can be retrieved in the property getter/setter. Using it
+ * allows us to avoid a hash-table lookup or linear search.
+ * It does restrict us to a maximum of 256 fields per type.
+ *
+ * We define all fields as read/write so that the user gets an
+ * error message. If we omitted fields or defined them read-only
+ * we'd:
+ *
+ * - Storing a new property for a non-accessible field
+ * - Silently do nothing when writing a read-only field
+ *
+ * Which is pretty confusing if the only reason a field isn't
+ * writable is language binding or memory-management restrictions.
+ *
+ * We just go ahead and define the fields immediately for the
+ * class; doing it lazily in boxed_new_resolve() would be possible
+ * as well if doing it ahead of time caused to much start-up
+ * memory overhead.
+ */
+ if (n_fields > 256) {
+ gjs_debug(GJS_DEBUG_ERROR,
+ "Only defining the first 256 fields in boxed type '%s'",
+ g_base_info_get_name ((GIBaseInfo *)priv->info));
+ n_fields = 256;
+ }
+
+ for (i = 0; i < n_fields; i++) {
+ GIFieldInfo *field = g_struct_info_get_field (priv->info, i);
+ const char *field_name = g_base_info_get_name ((GIBaseInfo *)field);
+ gboolean result;
+
+ result = JS_DefinePropertyWithTinyId(context, proto, field_name, i,
+ JSVAL_NULL,
+ boxed_field_getter, boxed_field_setter,
+ JSPROP_PERMANENT | JSPROP_SHARED);
+
+ g_base_info_unref ((GIBaseInfo *)field);
+
+ if (!result)
+ return JS_FALSE;
+ }
+
+ return JS_TRUE;
+}
+
+
/* The bizarre thing about this vtable is that it applies to both
* instances of the object, and to the prototype that instances of the
* class have.
@@ -501,6 +689,8 @@
gjs_debug(GJS_DEBUG_GBOXED, "Defined class %s prototype is %p class %p in object %p",
constructor_name, prototype, JS_GetClass(context, prototype), in_object);
+ define_boxed_class_fields (context, priv, prototype);
+
if (constructor_p) {
*constructor_p = NULL;
gjs_object_get_property(context, in_object, constructor_name, &value);
Added: trunk/test/js/testEverythingEncapsulated.js
==============================================================================
--- (empty file)
+++ trunk/test/js/testEverythingEncapsulated.js Wed Nov 19 22:30:35 2008
@@ -0,0 +1,9 @@
+const Everything = imports.gi.Everything;
+
+function testBoxed() {
+ boxed = new Everything.TestBoxed();
+ boxed.some_int8 = 42;
+ assertEquals(42, boxed.some_int8);
+}
+
+gjstestRun();
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]