[gjs/wip/gobj-kitchen-sink: 17/23] boxed: Introduce support for complex constructors
- From: Jasper St. Pierre <jstpierre src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs/wip/gobj-kitchen-sink: 17/23] boxed: Introduce support for complex constructors
- Date: Thu, 2 Feb 2012 22:09:25 +0000 (UTC)
commit 6904ffe10f4e248b5dbc69468108de0ab3edf998
Author: Giovanni Campagna <gcampagna src gnome org>
Date: Sun Dec 11 18:43:12 2011 +0100
boxed: Introduce support for complex constructors
For types that don't have a zero-args constructor, but have a
default constructor (called new), we can now invoke it directly
with "new BoxedType", instead of "BoxedType.new", by delegating
inside the native constructor.
This affects also GVariant, which is made to delegate to an internal
JS function, and thus can be packed with new GLib.Variant()
gi/boxed.c | 318 ++++++++++++++++++++------------
modules/overrides/GLib.js | 13 +-
modules/overrides/Gio.js | 16 +-
test/js/testEverythingEncapsulated.js | 31 ++++
test/js/testGDBus.js | 12 +-
5 files changed, 253 insertions(+), 137 deletions(-)
---
diff --git a/gi/boxed.c b/gi/boxed.c
index 99b778d..0c45f63 100644
--- a/gi/boxed.c
+++ b/gi/boxed.c
@@ -40,8 +40,15 @@
#include <girepository.h>
typedef struct {
+ /* prototype info */
GIBoxedInfo *info;
+ GType gtype;
+ gint zero_args_constructor; /* -1 if none */
+ gint default_constructor; /* -1 if none */
+
+ /* instance info */
void *gboxed; /* NULL if we are the prototype and not an instance */
+
guint can_allocate_directly : 1;
guint allocated_directly : 1;
guint not_owning_gboxed : 1; /* if set, the JS wrapper does not own
@@ -208,10 +215,8 @@ boxed_get_copy_source(JSContext *context,
return JS_TRUE;
}
-static JSBool
-boxed_new_direct(JSContext *context,
- JSObject *obj, /* "this" for constructor */
- Boxed *priv)
+static void
+boxed_new_direct(Boxed *priv)
{
g_assert(priv->can_allocate_directly);
@@ -221,72 +226,6 @@ boxed_new_direct(JSContext *context,
gjs_debug_lifecycle(GJS_DEBUG_GBOXED,
"JSObject created by directly allocating %s",
g_base_info_get_name ((GIBaseInfo *)priv->info));
-
- return JS_TRUE;
-}
-
-static JSBool
-boxed_new(JSContext *context,
- JSObject *obj, /* "this" for constructor */
- Boxed *priv)
-{
- GType gtype;
- int n_methods;
- int i;
-
- gtype = g_registered_type_info_get_g_type( (GIRegisteredTypeInfo*) priv->info);
-
- if (gtype != G_TYPE_NONE) {
- /* If the structure is registered as a boxed, we can create a new instance by
- * looking for a zero-args constructor and calling it; constructors don't
- * really make sense for non-boxed types, since there is no memory management
- * for the return value; those are handled below along with simple boxed
- * structures without constructor.
- */
- n_methods = g_struct_info_get_n_methods(priv->info);
-
- for (i = 0; i < n_methods; ++i) {
- GIFunctionInfo *func_info;
- GIFunctionInfoFlags flags;
-
- func_info = g_struct_info_get_method(priv->info, i);
-
- flags = g_function_info_get_flags(func_info);
- if ((flags & GI_FUNCTION_IS_CONSTRUCTOR) != 0 &&
- g_callable_info_get_n_args((GICallableInfo*) func_info) == 0) {
-
- GIArgument rval;
- GError *error = NULL;
-
- if (!g_function_info_invoke(func_info, NULL, 0, NULL, 0, &rval, &error)) {
- gjs_throw(context, "Failed to invoke boxed constructor: %s", error->message);
- g_clear_error(&error);
- g_base_info_unref((GIBaseInfo*) func_info);
- return JS_FALSE;
- }
-
- g_base_info_unref((GIBaseInfo*) func_info);
-
- priv->gboxed = rval.v_pointer;
-
- gjs_debug_lifecycle(GJS_DEBUG_GBOXED,
- "JSObject created with boxed instance %p type %s",
- priv->gboxed, g_type_name(gtype));
-
- return JS_TRUE;
- }
-
- g_base_info_unref((GIBaseInfo*) func_info);
- }
- }
-
- if (priv->can_allocate_directly)
- return boxed_new_direct(context, obj, priv);
-
- gjs_throw(context, "Unable to construct boxed type %s since it has no zero-args <constructor>, can only wrap an existing one",
- g_base_info_get_name((GIBaseInfo*) priv->info));
-
- return JS_FALSE;
}
/* When initializing a boxed object from a hash of properties, we don't want
@@ -387,39 +326,121 @@ boxed_init_from_props(JSContext *context,
return success;
}
-/* Do any initialization of a newly constructed object from the arguments passed
- * in from Javascript.
- */
static JSBool
-boxed_init(JSContext *context,
- JSObject *obj, /* "this" for constructor */
- Boxed *priv,
- uintN argc,
- jsval *argv)
+boxed_invoke_constructor(JSContext *context,
+ JSObject *obj,
+ const gchar *constructor_name,
+ uintN argc,
+ jsval *argv,
+ jsval *rval)
{
- if (argc == 0)
- return JS_TRUE;
+ jsval js_constructor, js_constructor_func;
- if (argc == 1) {
- Boxed *source_priv;
+ if (!gjs_object_require_property (context, obj, NULL, "constructor", &js_constructor))
+ return JS_FALSE;
- /* Short-cut to memcpy when possible */
- if (priv->can_allocate_directly &&
- boxed_get_copy_source (context, priv, argv[0], &source_priv)) {
+ if (!gjs_object_require_property (context, JSVAL_TO_OBJECT(js_constructor), NULL,
+ constructor_name, &js_constructor_func))
+ return JS_FALSE;
- memcpy(priv->gboxed, source_priv->gboxed,
- g_struct_info_get_size (priv->info));
+ return gjs_call_function_value (context, NULL, js_constructor_func, argc, argv, rval);
+}
- return JS_TRUE;
- }
+static JSBool
+boxed_new(JSContext *context,
+ JSObject *obj, /* "this" for constructor */
+ Boxed *priv,
+ uintN argc,
+ jsval *argv,
+ jsval *rval)
+{
+ if (g_type_is_a (priv->gtype, G_TYPE_VARIANT)) {
+ /* Short-circuit construction for GVariants by calling into the JS packing
+ function */
+ return boxed_invoke_constructor (context, obj, "_new_internal", argc, argv, rval);
+
+ } else if (g_type_is_a (priv->gtype, G_TYPE_BOXED)) {
+ /* If the structure is registered as a boxed, we can create a new instance by
+ * looking for a zero-args constructor and calling it; constructors don't
+ * really make sense for non-boxed types, since there is no memory management
+ * for the return value; those are handled below along with simple boxed
+ * structures without constructor.
+ */
+
+ /* for backward compatibility, we choose the zero args constructor if one
+ exists, otherwise we choose the default constructor
+ (the one called new, if one exists, otherwise the first) */
+ if (priv->zero_args_constructor >= 0) {
+ GIFunctionInfo *func_info = g_struct_info_get_method (priv->info, priv->zero_args_constructor);
+
+ GIArgument rval;
+ GError *error = NULL;
+
+ if (!g_function_info_invoke(func_info, NULL, 0, NULL, 0, &rval, &error)) {
+ gjs_throw(context, "Failed to invoke boxed constructor: %s", error->message);
+ g_clear_error(&error);
+ g_base_info_unref((GIBaseInfo*) func_info);
+ return JS_FALSE;
+ }
+
+ g_base_info_unref((GIBaseInfo*) func_info);
- return boxed_init_from_props(context, obj, priv, argv[0]);
+ priv->gboxed = rval.v_pointer;
+
+ gjs_debug_lifecycle(GJS_DEBUG_GBOXED,
+ "JSObject created with boxed instance %p type %s",
+ priv->gboxed, g_type_name(gtype));
+
+ if (argc == 0) /* done */
+ return JS_TRUE;
+
+ } else if (argc != 0 && priv->default_constructor >= 0) {
+ /* a boxed can have both a default constructor and still be directly allocatable;
+ in that case, we allocate directly if called with 0 args (as that would fail the
+ constructor, that has at least one argument) and invoke the constructor otherwise
+ */
+
+ GIFunctionInfo *constructor;
+ const gchar *constructor_name;
+ JSBool retval;
+
+ /* for simplicity, we simply delegate all the work to the actual JS constructor
+ function (which we retrieve from the JS constructor, that is, Namespace.BoxedType,
+ or object.constructor, given that object was created with the right prototype */
+
+ constructor = g_struct_info_get_method(priv->info, priv->default_constructor);
+ constructor_name = g_base_info_get_name((GIBaseInfo*)constructor);
+
+ retval = boxed_invoke_constructor(context, obj, constructor_name, argc, argv, rval);
+
+ g_base_info_unref((GIBaseInfo*)constructor);
+ return retval;
+
+ }
}
- gjs_throw(context, "Constructor with multiple arguments not supported for %s",
- g_base_info_get_name((GIBaseInfo *)priv->info));
+ if (priv->gboxed == NULL) {
+ /* nothing gained from constructors, fallback on direct allocation or throw */
+ if (priv->can_allocate_directly) {
+ boxed_new_direct(priv);
+
+ if (argc > 1) {
+ gjs_throw(context, "Constructor with multiple arguments not supported for %s",
+ g_base_info_get_name((GIBaseInfo *)priv->info));
+ return JS_FALSE;
+ }
+
+ if (argc == 0) /* done */
+ return JS_TRUE;
+ } else {
+ gjs_throw(context, "Unable to construct struct type %s since it has no default constructor and cannot be allocated directly",
+ g_base_info_get_name((GIBaseInfo*) priv->info));
+ return JS_FALSE;
+ }
+ }
- return JS_FALSE;
+ /* if we reach this point, we need to init from a map of fields */
+ return boxed_init_from_props (context, obj, priv, argv[0]);
}
GJS_NATIVE_CONSTRUCTOR_DECLARE(boxed)
@@ -429,7 +450,8 @@ GJS_NATIVE_CONSTRUCTOR_DECLARE(boxed)
Boxed *proto_priv;
JSObject *proto;
Boxed *source_priv;
- GType gtype;
+ jsval actual_rval;
+ JSBool retval;
GJS_NATIVE_CONSTRUCTOR_PRELUDE(boxed);
@@ -457,39 +479,48 @@ GJS_NATIVE_CONSTRUCTOR_DECLARE(boxed)
return JS_FALSE;
}
- priv->info = proto_priv->info;
- priv->can_allocate_directly = proto_priv->can_allocate_directly;
+ *priv = *proto_priv;
g_base_info_ref( (GIBaseInfo*) priv->info);
- gtype = g_registered_type_info_get_g_type( (GIRegisteredTypeInfo*) priv->info);
- /* Short-circuit copy-construction in the case where we can use g_boxed_copy */
+ /* Short-circuit copy-construction in the case where we can use g_boxed_copy or memcpy */
if (argc == 1 &&
boxed_get_copy_source(context, priv, argv[0], &source_priv)) {
- if (gtype != G_TYPE_NONE && g_type_is_a (gtype, G_TYPE_BOXED)) {
- priv->gboxed = g_boxed_copy(gtype, source_priv->gboxed);
+ if (g_type_is_a (priv->gtype, G_TYPE_BOXED)) {
+ priv->gboxed = g_boxed_copy(priv->gtype, source_priv->gboxed);
+
+ GJS_NATIVE_CONSTRUCTOR_FINISH(boxed);
+ return JS_TRUE;
+ } else if (priv->can_allocate_directly) {
+ boxed_new_direct (priv);
+ memcpy(priv->gboxed, source_priv->gboxed,
+ g_struct_info_get_size (priv->info));
+
GJS_NATIVE_CONSTRUCTOR_FINISH(boxed);
return JS_TRUE;
}
}
- /* Short-circuit construction for GVariants (simply cannot construct here,
- the constructor should be overridden) */
- if (g_type_is_a(gtype, G_TYPE_VARIANT)) {
- gjs_throw(context,
- "Can't create instance of GVariant directly, use GVariant.new_*");
- return JS_FALSE;
- }
+ /* we may need to return a value different from object
+ (for example because we delegate to another constructor)
+ prepare the location for that
+ */
- if (!boxed_new(context, object, priv))
- return JS_FALSE;
+ actual_rval = JSVAL_VOID;
+ JS_AddValueRoot(context, &actual_rval);
- if (!boxed_init(context, object, priv, argc, argv))
- return JS_FALSE;
+ retval = boxed_new(context, object, priv, argc, argv, &actual_rval);
- GJS_NATIVE_CONSTRUCTOR_FINISH(boxed);
+ if (retval) {
+ if (!JSVAL_IS_VOID (actual_rval))
+ JS_SET_RVAL(context, vp, actual_rval);
+ else
+ GJS_NATIVE_CONSTRUCTOR_FINISH(boxed);
+ }
- return JS_TRUE;
+ JS_RemoveValueRoot(context, &actual_rval);
+
+ return retval;
}
static void
@@ -1080,6 +1111,54 @@ struct_is_simple(GIStructInfo *info)
return is_simple;
}
+static void
+boxed_fill_prototype_info(Boxed *priv)
+{
+ int i, n_methods;
+ int first_constructor = -1;
+
+ priv->gtype = g_registered_type_info_get_g_type( (GIRegisteredTypeInfo*) priv->info);
+ priv->zero_args_constructor = -1;
+ priv->default_constructor = -1;
+
+ if (priv->gtype != G_TYPE_NONE) {
+ /* If the structure is registered as a boxed, we can create a new instance by
+ * looking for a zero-args constructor and calling it; constructors don't
+ * really make sense for non-boxed types, since there is no memory management
+ * for the return value.
+ */
+ n_methods = g_struct_info_get_n_methods(priv->info);
+
+ for (i = 0; i < n_methods; ++i) {
+ GIFunctionInfo *func_info;
+ GIFunctionInfoFlags flags;
+
+ func_info = g_struct_info_get_method(priv->info, i);
+
+ flags = g_function_info_get_flags(func_info);
+ if ((flags & GI_FUNCTION_IS_CONSTRUCTOR) != 0) {
+ if (first_constructor < 0)
+ first_constructor = i;
+
+ if (priv->zero_args_constructor < 0 &&
+ g_callable_info_get_n_args((GICallableInfo*) func_info) == 0)
+ priv->zero_args_constructor = i;
+
+ if (priv->default_constructor < 0 &&
+ strcmp(g_base_info_get_name ((GIBaseInfo*) func_info), "new") == 0)
+ priv->default_constructor = i;
+ }
+
+ g_base_info_unref((GIBaseInfo*) func_info);
+ }
+
+ if (priv->default_constructor < 0)
+ priv->default_constructor = priv->zero_args_constructor;
+ if (priv->default_constructor < 0)
+ priv->default_constructor = first_constructor;
+ }
+}
+
JSBool
gjs_define_boxed_class(JSContext *context,
JSObject *in_object,
@@ -1158,6 +1237,8 @@ gjs_define_boxed_class(JSContext *context,
priv = g_slice_new0(Boxed);
priv->info = info;
+ boxed_fill_prototype_info(priv);
+
g_base_info_ref( (GIBaseInfo*) priv->info);
JS_SetPrivate(context, prototype, priv);
@@ -1218,10 +1299,11 @@ gjs_boxed_from_c_struct(JSContext *context,
gjs_get_import_global (context));
priv = g_slice_new0(Boxed);
- JS_SetPrivate(context, obj, priv);
- priv->info = info;
+
+ *priv = *proto_priv;
g_base_info_ref( (GIBaseInfo*) priv->info);
- priv->can_allocate_directly = proto_priv->can_allocate_directly;
+
+ JS_SetPrivate(context, obj, priv);
if ((flags & GJS_BOXED_CREATION_NO_COPY) != 0) {
/* we need to create a JS Boxed which references the
@@ -1238,9 +1320,7 @@ gjs_boxed_from_c_struct(JSContext *context,
} else if (g_type_is_a(gtype, G_TYPE_VARIANT)) {
priv->gboxed = g_variant_ref_sink (gboxed);
} else if (priv->can_allocate_directly) {
- if (!boxed_new_direct(context, obj, priv))
- return JS_FALSE;
-
+ boxed_new_direct(priv);
memcpy(priv->gboxed, gboxed, g_struct_info_get_size (priv->info));
} else {
gjs_throw(context,
diff --git a/modules/overrides/GLib.js b/modules/overrides/GLib.js
index bfbcf63..252be1f 100644
--- a/modules/overrides/GLib.js
+++ b/modules/overrides/GLib.js
@@ -105,7 +105,7 @@ function _pack_variant(signature, value) {
if (value != null)
return GLib.Variant.new_maybe(null, _pack_variant(signature, value))
else
- return GLib.Variant.new_maybe(GLib.VariantType.new(_read_single_type(signature, false).join('')), null);
+ return GLib.Variant.new_maybe(new GLib.VariantType(_read_single_type(signature, false).join('')), null);
case 'a':
let arrayType = _read_single_type(signature, false);
if (arrayType[0] == 's') {
@@ -136,7 +136,7 @@ function _pack_variant(signature, value) {
arrayValue.push(child);
}
}
- return GLib.Variant.new_array(GLib.VariantType.new(arrayType.join('')), arrayValue, arrayValue.length);
+ return GLib.Variant.new_array(new GLib.VariantType(arrayType.join('')), arrayValue, arrayValue.length);
case '(':
let children = [ ];
for (let i = 0; i < value.length; i++) {
@@ -200,7 +200,7 @@ function _unpack_variant(variant, deep) {
else
return val;
case 'a':
- if (variant.is_of_type(GLib.VariantType.new('a{?*}'))) {
+ if (variant.is_of_type(new GLib.VariantType('a{?*}'))) {
// special case containers
let ret = { };
let nElements = variant.n_children();
@@ -240,7 +240,7 @@ function _init() {
GLib = this;
- this.Variant.new = function (sig, value) {
+ this.Variant._new_internal = function(sig, value) {
let signature = Array.prototype.slice.call(sig);
let variant = _pack_variant(signature, value);
@@ -249,6 +249,11 @@ function _init() {
return variant;
}
+ this.Variant.new = function(sig, value) {
+ log('WARNING: GLib.Variant.new is deprecated, use new GLib.Variant instead');
+
+ return new GLib.Variant(sig, value);
+ }
this.Variant.prototype.unpack = function() {
return _unpack_variant(this, false);
}
diff --git a/modules/overrides/Gio.js b/modules/overrides/Gio.js
index 114c3d6..0098832 100644
--- a/modules/overrides/Gio.js
+++ b/modules/overrides/Gio.js
@@ -76,7 +76,7 @@ function _proxyInvoker(methodName, sync, inSignature, arg_array) {
}
}
- var inVariant = GLib.Variant.new('(' + inSignature.join('') + ')', arg_array);
+ var inVariant = new GLib.Variant('(' + inSignature.join('') + ')', arg_array);
var asyncCallback = function (proxy, result) {
try {
@@ -117,11 +117,11 @@ function _propertyGetter(name) {
}
function _propertySetter(name, value, signature) {
- let variant = GLib.Variant.new(signature, value);
+ let variant = new GLib.Variant(signature, value);
this.set_cached_property(name, variant);
this.call('org.freedesktop.DBus.Properties.Set',
- GLib.Variant.new('(ssv)',
+ new GLib.Variant('(ssv)',
[this.g_interface_name,
name, variant]),
Gio.DBusCallFlags.NONE, -1, null,
@@ -339,7 +339,7 @@ const DBusImplementerBase = new Lang.Class({
}
if (retval === undefined) {
// undefined (no return value) is the empty tuple
- retval = GLib.Variant.new_tuple([], 0);
+ retval = new GLib.Variant('()', []);
}
try {
if (!(retval instanceof GLib.Variant)) {
@@ -354,7 +354,7 @@ const DBusImplementerBase = new Lang.Class({
// into an Array
retval = [retval];
}
- retval = GLib.Variant.new(outSignature, retval);
+ retval = new GLib.Variant(outSignature, retval);
}
invocation.return_value(retval);
} catch(e) {
@@ -377,7 +377,7 @@ const DBusImplementerBase = new Lang.Class({
let propInfo = klass.Interface.lookup_property(property_name);
let jsval = this[property_name];
if (jsval != undefined)
- return GLib.Variant.new(propInfo.signature, jsval);
+ return new GLib.Variant(propInfo.signature, jsval);
else
return null;
},
@@ -406,7 +406,7 @@ const DBusImplementerBase = new Lang.Class({
if (argArray.length == 0)
this._dbusImpl.emit_signal(signal_name, null);
else
- this._dbusImpl.emit_signal(signal_name, GLib.Variant.new(signalType, argArray));
+ this._dbusImpl.emit_signal(signal_name, new GLib.Variant(signalType, argArray));
},
emit_property_changed: function(property_name, new_value) {
@@ -414,7 +414,7 @@ const DBusImplementerBase = new Lang.Class({
let propertyInfo = klass.Inteface.lookup_property(property_name);
if (new_value != undefined)
- new_value = GLib.Variant.new(propertyInfo.signature, new_value);
+ new_value = new GLib.Variant(propertyInfo.signature, new_value);
this._dbusImpl.emit_property_changed(property_name, new_value);
},
diff --git a/test/js/testEverythingEncapsulated.js b/test/js/testEverythingEncapsulated.js
index 69c6eca..7b8ff97 100644
--- a/test/js/testEverythingEncapsulated.js
+++ b/test/js/testEverythingEncapsulated.js
@@ -1,6 +1,8 @@
// application/javascript;version=1.8
// This used to be called "Everything"
const Everything = imports.gi.Regress;
+const GLib = imports.gi.GLib;
+
if (!('assertEquals' in this)) { /* allow running this test standalone */
imports.lang.copyPublicProperties(imports.jsUnit, this);
gjstestRun = function() { return imports.jsUnit.gjstestRun(window); };
@@ -146,4 +148,33 @@ function testTestStructFixedArray() {
assertEquals(51, struct.array[9]);
}
+function testComplexConstructor() {
+ let boxed = new Everything.TestBoxedB(7, 5);
+
+ assertEquals(7, boxed.some_int8);
+ assertEquals(5, boxed.some_long);
+
+ let str_variant = new GLib.Variant('s', 'mystring');
+ assertEquals('mystring', str_variant.get_string()[0]);
+ assertEquals('mystring', str_variant.deep_unpack());
+
+ let struct_variant = new GLib.Variant('(sogvau)',
+ [ 'a string',
+ '/a/object/path',
+ 'asig', //nature
+ new GLib.Variant('s', 'variant'),
+ [ 7, 3 ]
+ ]);
+ assertEquals(5, struct_variant.n_children());
+
+ let unpacked = struct_variant.deep_unpack();
+ assertEquals('a string', unpacked[0]);
+ assertEquals('/a/object/path', unpacked[1]);
+ assertEquals('asig', unpacked[2]);
+ assertTrue(unpacked[3] instanceof GLib.Variant);
+ assertEquals('variant', unpacked[3].deep_unpack());
+ assertTrue(unpacked[4] instanceof Array);
+ assertEquals(2, unpacked[4].length);
+}
+
gjstestRun();
diff --git a/test/js/testGDBus.js b/test/js/testGDBus.js
index 0a503e9..9a03e52 100644
--- a/test/js/testGDBus.js
+++ b/test/js/testGDBus.js
@@ -97,7 +97,7 @@ const Test = new Gio.DBusImplementerClass({
},
frobateStuff: function(args) {
- return { hello: GLib.Variant.new('s', 'world') };
+ return { hello: new GLib.Variant('s', 'world') };
},
nonJsonFrobateStuff: function(i) {
@@ -172,7 +172,7 @@ const Test = new Gio.DBusImplementerClass({
echoAsync: function(parameters, invocation) {
var [someString, someInt] = parameters;
Mainloop.idle_add(function() {
- invocation.return_value(GLib.Variant.new('(si)', [someString, someInt]));
+ invocation.return_value(new GLib.Variant('(si)', [someString, someInt]));
return false;
});
},
@@ -189,7 +189,7 @@ const Test = new Gio.DBusImplementerClass({
// variant
get PropReadWrite() {
- return GLib.Variant.new('u', this._propReadWrite);
+ return new GLib.Variant('u', this._propReadWrite);
},
set PropReadWrite(value) {
@@ -532,11 +532,11 @@ function testStructArray() {
function testDictSignatures() {
let someDict = {
- aDouble: GLib.Variant.new('d', 10),
+ aDouble: new GLib.Variant('d', 10),
// should be an integer after round trip
- anInteger: GLib.Variant.new('i', 10.5),
+ anInteger: new GLib.Variant('i', 10.5),
// should remain a double
- aDoubleBeforeAndAfter: GLib.Variant.new('d', 10.5),
+ aDoubleBeforeAndAfter: new GLib.Variant('d', 10.5),
};
let theResult, theExcp;
proxy.dictEchoRemote(someDict, function(result, excp) {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]