Feature Request: Managed Objects

51 views
Skip to first unread message

ollym

unread,
Dec 17, 2010, 10:39:21 AM12/17/10
to nodejs
Would it be possible to add something like this:
It would obviously need some C++ implementation, but would be useful
for clever OEM/datastore implementations.

var ManagedObject = require('util').ManagedObject;

var obj = new ManagedObject({
get: function(key) { console.log('GET: ' + key); return true; }
set: function(key, value) { console.log('SET: ' + key + '=' +
value }
});

obj.value; // returns true
// Output:
// GET: value

obj.value = false;
// Output:
// SET: value=false

obj.value; // returns true (still)
// Output:
// GET: value

anders conbere

unread,
Dec 17, 2010, 12:30:50 PM12/17/10
to nod...@googlegroups.com
You can use __defineGetter__ and __defineSetter__ to accomplish this
on specific properties. Though personally I'm not sure how to make
that true for all properties (it wouldn't be hard to set up as part of
object initialization, as long as you never added any properties to
the object and expected them to be protected).

~ Anders

> --
> You received this message because you are subscribed to the Google Groups "nodejs" group.
> To post to this group, send email to nod...@googlegroups.com.
> To unsubscribe from this group, send email to nodejs+un...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/nodejs?hl=en.
>
>

Shimon Doodkin

unread,
Dec 17, 2010, 1:37:49 PM12/17/10
to nodejs

Tom Robinson

unread,
Dec 17, 2010, 2:28:20 PM12/17/10
to nod...@googlegroups.com
Hopefully we'll get proxies one of these days: http://wiki.ecmascript.org/doku.php?id=harmony:proxies

Nick Husher

unread,
Dec 17, 2010, 3:00:49 PM12/17/10
to nod...@googlegroups.com
I believe ECMAScript5 object and property descriptors API is the desired way to do what you're after:

http://ejohn.org/blog/ecmascript-5-objects-and-properties/

As far as I know, v8 has reasonably good ES5 object and property support. Last time I checked, though, they had one bug that may or may not apply to you:

Let's say you have a native object (say a DOM element in a web browser) and it has a property on it with an internal setter. For example, "innerHTML."

As you may know, you can do myDomElement.innerHTML = someString, and it will update the innards of the element with the browser-evaluated string. Clearly there's magic happening here beyond just setting a property. The problem is that if you try to get a pointer that getter or setter method in v8, it will return undefined:

var d = Object.getOwnPropertyDescriptor(myDomElement, "innerHTML");

d.getter // undefined
d.setter // undefined

This makes it impossible to intercept native property assignments. If you wanted to toss an event any time content was assigned to innerHTML, you would be unable in v8.

Testing in firefox indicates that its JS engine *does* hand back a pointer to a native function. In that browser it's possible to shim property assignments.

Last I checked, bugs filed about this get flagged as "not a bug."


Nick
____________________

Nicholas Husher
nhu...@gmail.com
http://nickol.us

Isaac Schlueter

unread,
Dec 17, 2010, 3:40:51 PM12/17/10
to nod...@googlegroups.com
No, getter/setter properties cannot provide this.

What he's asking for is a generic "any time I write or read any random
property, run this code" kind of thing. That's proxies. You can't do
that with Object.defineProperty, because you don't know what
properties you're going to be defining ahead of time.

It is my sincere hope that such a thing never makes it into JavaScript
proper. You can, of course, implement it as a userland module if you
do some C++ hacking, and the programs that use it will likely not be
portable to any other platform. But, your ORMs and such can be really
cool.

I investigated doing something like this as a way to have an object
that looks just like a regular object, but in fact saves all its data
to a redis or couchdb datastore. I abandoned it eventually, in favor
of explicit .get(k) and .set(k,v) functions because:

1. it's not so bad.
2. o.set("foo", "bar") looks like it's calling a function.
3. o.foo = "bar" doesn't look like it's calling a function.
4. code should look like what it is.

I'm ok with mild to moderate use of getter/setters. But proxies go
too far, imo, and this kind of thing is what has ruined ruby. That's
my esthetic preference, YMMV.

If you DO implement such a thing, I'd recommend sticking to the
Harmony Proxies API strawman. Some thought and planning has gone into
it, and it's somewhat well known.

--i

Isaac Schlueter

unread,
Dec 17, 2010, 3:43:04 PM12/17/10
to nod...@googlegroups.com
Sorry, there's a typo.

On Fri, Dec 17, 2010 at 12:40, Isaac Schlueter <i...@izs.me> wrote:
> portable to any other platform.  But, your ORMs and such can be really
> cool.

That should read:

"But, your ORMs and such can be really cool-looking douchebags."

My bad. Premature send and all that.

--i

Nick Husher

unread,
Dec 17, 2010, 5:31:31 PM12/17/10
to nod...@googlegroups.com
It wouldn't work with an arbitrary property, but what if did something like this:

var obj = MGR.manageObject(myUnmanagedClassInstanceOrObjectLiteral, { getter: ... setter: ... });

The managedObject would seal (Object.seal) the object handed to it, preventing arbitrary extensions and then shim in the getters and setters as appropriate. You either need to plan your managed properties carefully, or devise a strategy to clone the original unmanaged object and copy the values of the managed object into it, plus the properties you needed to add.

Proxies seem like an interesting idea, but I can't even begin to think through the expressive implications of having them in the language, though. I think I'd rather build something like that on top of the language (through explicit getters/setters as you describe) than have it shoved into the language underneath me. It seems like debugging a rogue proxy would be challenging.


Nick
____________________

anders conbere

unread,
Dec 17, 2010, 5:52:06 PM12/17/10
to nod...@googlegroups.com
On Fri, Dec 17, 2010 at 2:31 PM, Nick Husher <nhu...@gmail.com> wrote:
> It wouldn't work with an arbitrary property, but what if did something like this:
>
> var obj = MGR.manageObject(myUnmanagedClassInstanceOrObjectLiteral, { getter: ... setter: ... });
>
> The managedObject would seal (Object.seal) the object handed to it, preventing arbitrary extensions and then shim in the getters and setters as appropriate. You either need to plan your managed properties carefully, or devise a strategy to clone the original unmanaged object and copy the values of the managed object into it, plus the properties you needed to add.

This is exactly the kind of behavior I was eluding to in my first post.

You could also do this at some stage in a constructor, pulling all
instantiated properties into the managed state.

~ Anders

Olly

unread,
Dec 18, 2010, 5:46:35 PM12/18/10
to nodejs
Isaacs was right. I am totally aware of the new ECMA5 object features
that are available to the V8 VM, but i am also aware that there is
currently absolutely no way to do what i was suggesting. For those who
don't understand, i'm looking for functionality similar to that of
PHP's __get and __set magic methods. Obviously as an ORM it would be
nice, simply working with objects and saving their state without
having to use any ORM specific functionality. get()/set() methods are
just as good, but i was just wondering if it were easy to do, it would
be a nice touch to just stash away in the util module somewhere. But i
guess not! ha

On Dec 17, 10:52 pm, anders conbere <aconb...@gmail.com> wrote:
> On Fri, Dec 17, 2010 at 2:31 PM, Nick Husher <nhus...@gmail.com> wrote:
> > It wouldn't work with an arbitrary property, but what if did something like this:
>
> > var obj = MGR.manageObject(myUnmanagedClassInstanceOrObjectLiteral, { getter: ... setter: ... });
>
> > The managedObject would seal (Object.seal) the object handed to it, preventing arbitrary extensions and then shim in the getters and setters as appropriate. You either need to plan your managed properties carefully, or devise a strategy to clone the original unmanaged object and copy the values of the managed object into it, plus the properties you needed to add.
>
> This is exactly the kind of behavior I was eluding to in my first post.
>
> You could also do this at some stage in a constructor, pulling all
> instantiated properties into the managed state.
>
> ~ Anders
>
>
>
>
>
> > Proxies seem like an interesting idea, but I can't even begin to think through the expressive implications of having them in the language, though. I think I'd rather build something like that on top of the language (through explicit getters/setters as you describe) than have it shoved into the language underneath me. It seems like debugging a rogue proxy would be challenging.
>
> > Nick
> > ____________________
>
> > Nicholas Husher
> > nhus...@gmail.com
> >> For more options, visit this group athttp://groups.google.com/group/nodejs?hl=en.

Jacob Rothstein

unread,
Dec 18, 2010, 7:31:38 PM12/18/10
to nod...@googlegroups.com
I don't know if the author announced it anywhere, but
https://github.com/brickysam26/node-proxy is an implementation of the
harmony proxy stick man for node.

–Jacob

Olly

unread,
Dec 19, 2010, 6:27:15 AM12/19/10
to nodejs
Hi Jacob,

That URL doesn't work.

On Dec 19, 12:31 am, Jacob Rothstein <jacob.rothst...@gmail.com>
wrote:
> I don't know if the author announced it anywhere, buthttps://github.com/brickysam26/node-proxyis an implementation of the

Jacob Rothstein

unread,
Dec 19, 2010, 4:55:33 PM12/19/10
to nod...@googlegroups.com
Hunh. It seems brickysam26 left github. You can still `npm install
node-proxy`.

–Jacob

Reply all
Reply to author
Forward
0 new messages