Re: libseed-list Hooking into the imports system



Here's the new one.

/Jonatan

Alan Knowles wrote:
imports.DynamicObject.define(....)


could not think of anything else of the top of my head..
Regards
Alan

--- On 11/Jul/2010, Jonatan Liljedahl wrote:
Yes, that makes sense. But perhaps the module should be named something else than autoprop. Any ideas? Perhaps it should go into the Seed module (if you guys want to include it) or some other module for similar future stuff?

/Jonatan

Alan Knowles wrote:
yes, that does sound good, I guess following the internal API as well makes some sense..

var o = imports.autoprop.defineObject({
    getProperty : function (name) {
      ..
    },
    setProperty : function (name, value) {
      ..
    },
    deleteProperty: function(name) {
      ..
    },
    hasProperty: function(name) {
      ..
    },
    callAsFunction: function(args) {} ,
    callAsConstructor: function(args) {} ,
    finalize : function() { }
    ...
});


/* Parent Class */
  NULL,				/* Static Values */
  NULL,				/* Static Functions */
  NULL,
  NULL,				/* Finalize */
  NULL,				/* Has Property */
  NULL,				/* Get Property */
  NULL,				/* Set Property */
  NULL,				/* Delete Property */
  NULL,				/* Get Property Names */
  NULL,				/* Call As Function */
  NULL,	                        /* Call As Constructor */
  NULL,				/* Has Instance */
  NULL				/* Convert To Type */

Regards
Alan
...snip...
/*
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);
    }

}

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;
}



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