Re: libseed-list Hooking into the imports system



Here's an updated seed-autoprop.c, since I needed it to set 'this' in the callbacks to the calling context global object instead of the autoprop.Object object (to be able to do the . -> __script_path__ trick)

One can still reach the autoprop object from the callbacks by using a function closure, but beware of infinite recursion if accessing own properties..

/Jonatan

Jonatan Liljedahl wrote:
Yes, this was a nice solution. See attached 'autoprop' module. (Feel free to include it in the main distro, I think it can be very useful for all sorts of special objects. Perhaps one should also add callbacks for CallAsFunction, CallAsConstructor, GetPropertyNames, etc..)
...snip...
/* Seed module: Autoprop object class
by Jonatan Liljedahl <lijon kymatica com> 2010

Usage:

    o = new imports.autoprop.Object;
    o.get_property = function(name) {
        return some_value; // or null to forward to normal props
    }
    o.set_property = function(name, value) {
        do_something(name,value);
        return true; // or false to allow normal props to be set
    }

    o.foobar = 42;      // will call o.set_property('foobar',42)
    print(o.something); // will call o.get_property('something)


'this' inside the callback is set to the calling contexts global object, not the autoprop object.
Use a function closure if you need to access the autoprop object inside the callbacks,
but beware of infinite recursion if you access own properties there.

Compile with:

gcc -shared -fPIC seed-autoprop.c -I/usr/local/include/seed \
    `pkg-config --cflags --libs glib-2.0 gmodule-2.0 gobject-introspection-1.0` \
    -o libseed_autoprop.so
    
*/

#include <seed.h>

SeedClass dynamic_object_class;

static SeedObject
seed_construct_dynamic_object (SeedContext ctx,
                               SeedObject constructor,
                               size_t argument_count,
                               const SeedValue arguments[],
                               SeedException * exception)
{
    return seed_make_object (ctx, dynamic_object_class, NULL);
}

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

    if (!g_strcmp0 (prop, "toString"))
        return NULL;
    if (!g_strcmp0 (prop, "valueOf"))
        return NULL;
    if (!g_strcmp0 (prop, "get_property"))
        return NULL;
    if (!g_strcmp0 (prop, "set_property"))
        return NULL;

    SeedValue handler = seed_object_get_property (ctx, object, "get_property");
    SeedValue ret = NULL;
    if (seed_value_is_object (ctx, handler)) {
        SeedValue args[1] = { seed_value_from_string (ctx, prop, exception) };
        ret = (SeedValue) seed_object_call (ctx, (SeedObject)handler, NULL, 1, args, exception);
        if(seed_value_is_null(ctx,ret)) ret = NULL;
    }

    return ret;
}

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, "set_property");
    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;
}

SeedObject
seed_module_init (SeedEngine * eng)
{
    SeedObject constructor;
    SeedObject namespace_ref = seed_make_object (eng->context, NULL, NULL);
    seed_class_definition class_def = seed_empty_class;

    class_def.class_name = "Object";
    class_def.get_property = seed_dynamic_object_get_property;
    class_def.set_property = seed_dynamic_object_set_property;
 
    dynamic_object_class = seed_create_class (&class_def);

    constructor = seed_make_constructor(eng->context, dynamic_object_class, seed_construct_dynamic_object);
    seed_object_set_property (eng->context, namespace_ref, "Object", constructor);

    return namespace_ref;
}



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