[seed] Dynamic Object module - a module to expose internal object callback properties



commit d31acaad673eecd97e3f70720af81c9ef34ab4cd
Author: Jonatan Liljedahl <lijon kymatica com>
Date:   Tue Jul 13 15:58:32 2010 +0800

    Dynamic Object module - a module to expose internal object callback properties
    
    Usage:
    
        o = imports.DynamicObject.create({
            getProperty: function(name) {
                return some_value; // or null to forward to normal props
            },
            SetProperty: function(name, value) {
                do_something(name,value);
                return true; // or false to allow normal props to be set
            },
            deleteProperty: function(name) {
                return true; // or false to forward to normal property deletion
            },
            callAsFunction: function() {
                print("called with args: "+Array.prototype.slice.call(arguments));
            },
            callAsConstructor: function() {
                return {foo:123};
            },
            getPropertyNames: function(){} // not implemented yet...
        });
    
        o.foobar = 42;      // will call o.set_property('foobar',42)
        print(o.something); // will call o.get_property('something)

 configure.ac                               |   14 ++
 modules/DynamicObject/Makefile.am          |   25 ++++
 modules/DynamicObject/seed-DynamicObject.c |  205 ++++++++++++++++++++++++++++
 modules/Makefile.am                        |    2 +-
 4 files changed, 245 insertions(+), 1 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 7fb8980..a4b63a8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -248,6 +248,18 @@ AC_ARG_ENABLE(os-module,
 AM_CONDITIONAL(BUILD_OS_MODULE, test "x$want_os_module" = "xyes")
 AC_SUBST(BUILD_OS_MODULE)
 
+
+dnl ==== DynamicObject ====
+AC_ARG_ENABLE(dynamicobject-module,
+                          AC_HELP_STRING([--enable-dynamicobject-module],
+                                     [enable the DynamicObject Seed module. [default=yes]]),
+ 		[want_dynamicobject_module=$enableval],[want_dynamicobject_module="yes"])
+
+
+AM_CONDITIONAL(BUILD_DYNAMICOBJECT_MODULE, test "x$want_dynamicobject_module" = "xyes")
+AC_SUBST(BUILD_DYNAMICOBJECT_MODULE)
+
+ 
 dnl ==== gtkbuilder ====
 AC_ARG_ENABLE(gtkbuilder-module,
 			  AC_HELP_STRING([--enable-gtkbuilder-module],
@@ -429,6 +441,7 @@ modules/gtkbuilder/Makefile
 modules/gettext/Makefile
 modules/mpfr/Makefile
 modules/ffi/Makefile
+modules/DynamicObject/Makefile
 
 libseed/seed-path.h
 ])
@@ -457,6 +470,7 @@ Modules:
    gettext....................$want_gettext_module
    mpfr.......................$want_mpfr_module
    ffi........................$want_ffi_module
+   Dynamic Object.............$want_dynamicobject_module
 "
 
 if test "x$want_readline_module" != "xyes"; then
diff --git a/modules/DynamicObject/Makefile.am b/modules/DynamicObject/Makefile.am
new file mode 100644
index 0000000..6eb7814
--- /dev/null
+++ b/modules/DynamicObject/Makefile.am
@@ -0,0 +1,25 @@
+if BUILD_DYNAMICOBJECT_MODULE
+
+seedlibdir = ${libdir}/seed
+
+seedlib_LTLIBRARIES = \
+	libseed_DynamicObject.la
+
+libseed_DynamicObject_la_SOURCES = \
+	seed-DynamicObject.c
+
+AM_CPPFLAGS = \
+	-I top_srcdir@/libseed/ \
+	$(GOBJECT_INTROSPECTION_CFLAGS) \
+	$(SEED_DEBUG_CFLAGS) \
+	$(SEED_PROFILE_CFLAGS)
+
+libseed_DynamicObject_la_LDFLAGS = \
+	-module -avoid-version \
+	$(GOBJECT_INTROSPECTION_LDFLAGS) \
+	$(SEED_PROFILE_LIBS)
+
+endif
+
+
+
diff --git a/modules/DynamicObject/seed-DynamicObject.c b/modules/DynamicObject/seed-DynamicObject.c
new file mode 100644
index 0000000..cf8afdf
--- /dev/null
+++ b/modules/DynamicObject/seed-DynamicObject.c
@@ -0,0 +1,205 @@
+/*
+DynamicObject Seed module
+
+this free software: you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation, either version 3 of
+the License, or (at your option) any later version.
+ 
+Copyright (C) 2010 Jonatan Liljedahl <lijon kymatica com>
+
+--------------------------------------------------------------------------------
+
+Compile with:
+
+gcc -shared -fPIC seed-DynamicObject.c -I/usr/local/include/seed \
+    `pkg-config --cflags --libs glib-2.0 gmodule-2.0 gobject-introspection-1.0` \
+    -o libseed_DynamicObject.so
+
+Usage:
+
+    o = imports.DynamicObject.create({
+        getProperty: function(name) {
+            return some_value; // or null to forward to normal props
+        },
+        SetProperty: function(name, value) {
+            do_something(name,value);
+            return true; // or false to allow normal props to be set
+        },
+        deleteProperty: function(name) {
+            return true; // or false to forward to normal property deletion
+        },
+        callAsFunction: function() {
+            print("called with args: "+Array.prototype.slice.call(arguments));
+        },
+        callAsConstructor: function() {
+            return {foo:123};
+        },
+        getPropertyNames: function(){} // not implemented yet...
+    });
+
+    o.foobar = 42;      // will call o.set_property('foobar',42)
+    print(o.something); // will call o.get_property('something)
+    // etc..
+
+'this' inside the callback is set to the calling contexts global object,
+not the dynamic object.
+
+You can also create the object first and set the callbacks later:
+
+    o = imports.DynamicObject.create();
+    o.callAsFunction = function() { return o.something; }
+
+*/
+
+#include <seed.h>
+
+static SeedClass dynamic_object_class;
+
+static SeedValue
+seed_dynamic_object_create (SeedContext ctx,
+                            SeedObject function,
+                            SeedObject this_object,
+                            gsize argument_count,
+                            const SeedValue arguments[],
+                            SeedException *exception)
+{
+    SeedObject obj = seed_make_object (ctx, dynamic_object_class, NULL);
+    if (argument_count > 0)
+        seed_object_set_property (ctx, obj, "__proto__", arguments[0]);
+
+    return (SeedValue)obj;
+}
+
+static SeedValue
+seed_dynamic_object_get_property (SeedContext ctx,
+                                  SeedObject object,
+                                  SeedString property_name,
+                                  SeedException *exception)
+{
+    guint len = seed_string_get_maximum_size (property_name);
+    gchar *prop = g_alloca (len * sizeof (gchar));
+    seed_string_to_utf8_buffer (property_name, prop, len);
+
+    // forward these to ordinary property lookup
+    if (!g_strcmp0 (prop, "toString"))
+        return NULL;
+    if (!g_strcmp0 (prop, "valueOf"))
+        return NULL;
+    if (!g_strcmp0 (prop, "getProperty"))
+        return NULL;
+    if (!g_strcmp0 (prop, "setProperty"))
+        return NULL;
+    if (!g_strcmp0 (prop, "deleteProperty"))
+        return NULL;
+    if (!g_strcmp0 (prop, "callAsFunction"))
+        return NULL;
+    if (!g_strcmp0 (prop, "callAsConstructor"))
+        return NULL;
+
+    SeedValue handler = seed_object_get_property (ctx, object, "getProperty");
+    if (seed_value_is_object (ctx, handler)) {
+        SeedValue args[1] = { seed_value_from_string (ctx, prop, exception) };
+        SeedValue ret = (SeedValue) seed_object_call (ctx, (SeedObject)handler, NULL, 1, args, exception);
+        return seed_value_is_null(ctx,ret)?NULL:ret;
+    }
+
+    return NULL;
+}
+
+static gboolean
+seed_dynamic_object_set_property (SeedContext ctx,
+                                  SeedObject object,
+                                  SeedString property_name,
+                                  SeedValue value,
+                                  SeedException *exception)
+{
+    guint len = seed_string_get_maximum_size (property_name);
+    gchar *prop = g_alloca (len * sizeof (gchar));
+    seed_string_to_utf8_buffer (property_name, prop, len);
+
+    SeedValue handler = seed_object_get_property (ctx, object, "setProperty");
+    if (seed_value_is_object (ctx, handler)) {
+        SeedValue args[2] = {
+            seed_value_from_string (ctx, prop, exception),
+            value};
+        SeedValue ret = seed_object_call (ctx, (SeedObject)handler, NULL, 2, args, exception);
+        return seed_value_to_boolean (ctx, ret, exception);
+    }
+
+    return FALSE;
+}
+
+static gboolean 
+seed_dynamic_object_delete_property (SeedContext ctx,
+                                     SeedObject object,
+                                     SeedString property_name,
+                                     SeedException *exception)
+{
+    guint len = seed_string_get_maximum_size (property_name);
+    gchar *prop = g_alloca (len * sizeof (gchar));
+    seed_string_to_utf8_buffer (property_name, prop, len);
+
+    SeedValue handler = seed_object_get_property (ctx, object, "deleteProperty");
+    if (seed_value_is_object (ctx, handler)) {
+        SeedValue args[1] = { seed_value_from_string (ctx, prop, exception) };
+        SeedValue ret = (SeedValue) seed_object_call (ctx, (SeedObject)handler, NULL, 1, args, exception);
+        return seed_value_to_boolean (ctx, ret, exception);
+    }
+    return FALSE;
+
+}
+
+static SeedValue
+seed_dynamic_object_call_as_function (SeedContext ctx,
+                                      SeedObject function,
+                                      SeedObject this_object,
+                                      size_t argument_count,
+                                      const SeedValue arguments[],
+                                      SeedException *exception)
+{
+    SeedValue handler = seed_object_get_property (ctx, function, "callAsFunction");
+    if (seed_value_is_object (ctx, handler)) {
+        return (SeedValue) seed_object_call (ctx, (SeedObject)handler, NULL, argument_count, arguments, exception);
+    }
+    return NULL;
+}
+
+static SeedValue
+seed_dynamic_object_call_as_constructor (SeedContext ctx,
+                                         SeedObject function,
+                                         size_t argument_count,
+                                         const SeedValue arguments[],
+                                         SeedException *exception)
+{
+    SeedValue handler = seed_object_get_property (ctx, function, "callAsConstructor");
+    if (seed_value_is_object (ctx, handler)) {
+        return (SeedValue) seed_object_call (ctx, (SeedObject)handler, NULL, argument_count, arguments, exception);
+    }
+    return NULL;
+}
+
+//static void
+//seed_dynamic_object_get_property_names (SeedContext ctx,
+//                                        SeedObject object,
+//                                        /*wait for API*/ propertyNames)
+
+SeedObject
+seed_module_init (SeedEngine * eng)
+{
+    SeedObject namespace_ref = seed_make_object (eng->context, NULL, NULL);
+    seed_class_definition class_def = seed_empty_class;
+
+    class_def.class_name = "DynamicObject";
+    class_def.get_property = seed_dynamic_object_get_property;
+    class_def.set_property = seed_dynamic_object_set_property;
+    class_def.delete_property = seed_dynamic_object_delete_property;
+    class_def.call_as_function = seed_dynamic_object_call_as_function;
+    class_def.call_as_constructor = seed_dynamic_object_call_as_constructor;
+     
+    dynamic_object_class = seed_create_class (&class_def);
+
+    seed_create_function(eng->context, "create", (SeedFunctionCallback)seed_dynamic_object_create, namespace_ref);
+    return namespace_ref;
+}
+
diff --git a/modules/Makefile.am b/modules/Makefile.am
index 150e2e2..ebaaad9 100644
--- a/modules/Makefile.am
+++ b/modules/Makefile.am
@@ -1 +1 @@
-SUBDIRS = example sqlite canvas multiprocessing readline os sandbox dbus libxml cairo gtkbuilder gettext mpfr ffi
+SUBDIRS = example sqlite canvas multiprocessing readline os sandbox dbus libxml cairo gtkbuilder gettext mpfr ffi DynamicObject



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]