Event properties on objects, a proxy experiment
From: David Bruant bruan...@gmail.com Subject: Event properties on objects, a proxy experiment Date: October 12, 2011 15:38:02 GMT+02:00 To: es-discuss es-discuss@mozilla.org […] So I wondered what if events were part of an object and exposed as such?. What if an object, instead of being attributes+methods was attributes+methods+events? (as I learned later having that thought, what I'm describing is actually what some people call component in the software engineering literature) Great idea! Discoverability is very important. I also like Erik’s syntactic sugar. Thinking of events as methods helps greatly with understanding them. There is a rough similarity between overriding (in subclassing/inheritance) and subscribing to an event. Similar to method combinations in Common Lisp, it makes sense to define event listeners that are invoked before the even fires (compare: before methods) or after an event fires (compare: after methods). [1] http://clhs.lisp.se/Body/07_ffb.htm -- Dr. Axel Rauschmayer a...@rauschma.de twitter.com/rauschma home: rauschma.de blog: 2ality.com ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Event properties on objects, a proxy experiment
Le 16/10/2011 22:16, Axel Rauschmayer a écrit : *From: *David Bruant bruan...@gmail.com mailto:bruan...@gmail.com *Subject: **Event properties on objects, a proxy experiment* *Date: *October 12, 2011 15:38:02 GMT+02:00 *To: *es-discuss es-discuss@mozilla.org mailto:es-discuss@mozilla.org […] So I wondered what if events were part of an object and exposed as such?. What if an object, instead of being attributes+methods was attributes+methods+events? (as I learned later having that thought, what I'm describing is actually what some people call component in the software engineering literature) Great idea! Discoverability is very important. I also like Erik’s syntactic sugar. Thinking of events as methods helps greatly with understanding them. I really think events as something different than methods, no a particular sort of methods. fire as [[Call]] is a convenience rather than considering the event as a method. There is a rough similarity between overriding (in subclassing/inheritance) and subscribing to an event. Similar to method combinations in Common Lisp, it makes sense to define event listeners that are invoked before the even fires (compare: before methods) or after an event fires (compare: after methods). [1] http://clhs.lisp.se/Body/07_ffb.htm Interesting reading. Thanks for sharing :-) David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Event properties on objects, a proxy experiment
Thinking of events as methods helps greatly with understanding them. I really think events as something different than methods, no a particular sort of methods. fire as [[Call]] is a convenience rather than considering the event as a method. But what does “firing an event” really mean? If it *was* a method, then a button would have it: Button.prototype.clicked() If the user clicks the button, the browser invokes the clicked() method. Thus, the method invocation would *be* the event. And if you want to be informed of it, you would intercept the method invocation. Erik Arvidsson’s syntactic sugar points in a similar direction: var obj = { onfoo: event(a, b, c) { ... } }; // addListener obj.onfoo.add(function(a, b, c) { assertEquals(this, obj); ... }); With event(a,b,c) being an “interceptable method”. This is merely a different way of thinking about your proposal (it doesn’t influence an implementation), but I find that Erik’s proposal complements it perfectly. -- Dr. Axel Rauschmayer a...@rauschma.de twitter.com/rauschma home: rauschma.de blog: 2ality.com ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Event properties on objects, a proxy experiment
something like this ? ... (function () { function dispatch(callback) { callback.call(this.r, this.e); } function add(callback) { this.handlers.indexOf(callback) 0 this.handlers.push(callback); } function remove(callback) { var i = this.handlers.indexOf(callback); -1 i this.handlers.splice(i, 1); } function createListener(self, listeners, name) { function listener(evt) { handlers.forEach(dispatch, {r: self, e: evt}); } var handlers = []; listener.handlers = handlers; listener.add = add; listener.remove = remove; listener.fire = listener; // redundant return listeners[name] = listener; } function Event(self, listeners) { return Proxy.create({ delete: function (receiver, name) { delete listeners[name]; }, get: function (receiver, name) { return listeners.hasOwnProperty(name) ? listeners[name] : createListener(self, listeners, name) ; } }); } var event = event; Object.defineProperty(Object.prototype, on, { enumerable: false, configurable: false, get: function () { return this[event] || Object.defineProperty( this, event, { enumerable: false, configurable: false, writable: false, value: Event(this, {}) } )[event]; } }); }()); // generic clalback function click(e) { alert(e.type); } // generic object var object = {}; // magic on object.on.click.add(click); // add object.on.click({type: click}); // fire object.on.click.remove(click); // remove object.on.click({type: click}); // nothing delete object.on.click; gisted already: https://gist.github.com/1289809 best regards ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Event properties on objects, a proxy experiment
Le 15/10/2011 18:26, Andrea Giammarchi a écrit : something like this ? ... My email client says that you're responding to my initial message, but you may as well be responding to my concern about |this| binding. I'll assume the former. (...) gisted already: https://gist.github.com/1289809 best regards Unfortunately, it doesn't work with any sort of object. It works with objects inheriting from Object.prototype and which do not have an own 'on' property (which would shadow yours) or an own 'event' property (because you create one). As I stated in my initial e-mail, my goal was to support having the ability to list events in order to potentially have doc and IDE support or at least analysis. I agree that you could easily support enumeration of events (with the getOwnPropertyNames trap for your event property), but it would require actually running the code (JavaScript static analysis or rather abstract interpretation is very hard, but I haven't even started to think about how proxies makes this even harder!) Unlike if you can just (semi-)syntactically declare that your property is an event with the event attribute of the property descriptor or with an addition to the object literal syntax as Erik suggested. Thanks, David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Event properties on objects, a proxy experiment
naaa, event is just a placeholder ... most likely is gonna be var event = @__event__ + Math.random(); and most likely that code should be on top with all other native prototypes shims or improvements. the correct this is bound as expected, the click function will have this === object indeed When I wrote any sort of object, i implicity meant any that inherits from Object.prototype ... are other objects ? I don't think so ... I would never do something like alert.on.alert(callback); you know what I mean ;-) br P.S. I just pressed reply but I think I removed your text through selection ... apologies On Sat, Oct 15, 2011 at 7:44 PM, David Bruant bruan...@gmail.com wrote: Le 15/10/2011 18:26, Andrea Giammarchi a écrit : something like this ? ... My email client says that you're responding to my initial message, but you may as well be responding to my concern about |this| binding. I'll assume the former. (...) gisted already: https://gist.github.com/1289809 best regards Unfortunately, it doesn't work with any sort of object. It works with objects inheriting from Object.prototype and which do not have an own 'on' property (which would shadow yours) or an own 'event' property (because you create one). As I stated in my initial e-mail, my goal was to support having the ability to list events in order to potentially have doc and IDE support or at least analysis. I agree that you could easily support enumeration of events (with the getOwnPropertyNames trap for your event property), but it would require actually running the code (JavaScript static analysis or rather abstract interpretation is very hard, but I haven't even started to think about how proxies makes this even harder!) Unlike if you can just (semi-)syntactically declare that your property is an event with the event attribute of the property descriptor or with an addition to the object literal syntax as Erik suggested. Thanks, David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Event properties on objects, a proxy experiment
Le 15/10/2011 19:52, Andrea Giammarchi a écrit : naaa, event is just a placeholder ... most likely is gonna be var event = @__event__ + Math.random(); Or rather a private name (when this is implemented)? Or with some WeakMap trickeries? and most likely that code should be on top with all other native prototypes shims or improvements. the correct this is bound as expected, the click function will have this === object indeed When I wrote any sort of object, i implicity meant any that inherits from Object.prototype ... are other objects ? I don't think so ... I would never do something like alert.on.alert(callback); Actually, in something else than old IE, 'alert' is a regular function and it's [[prototype]] chain is like: alert -- Function.prototype -- Object.prototype -- null So 'alert' should be fine actually. There are indeed other objects that you can create: var o1 = Object.create(null); var o2 = Object.create(o1); var o3 = Object.create(o2); var o4 = Object.create(o2); // both inherit from o2 // etc. None of them contain Object.prototype in their prototype chain and I don't see any strong reason to prevent these objects from emitting events. you know what I mean ;-) I do. Actually, one of my initial thought was to do something with Object.prototype but I stopped as soon as I remembered that some objects may not inherit from it. br P.S. I just pressed reply but I think I removed your text through selection ... apologies No worries :-) David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Event properties on objects, a proxy experiment
I meant that IE alert case indeed ... but yeah, you wrote better examples. Nothing block me to create a function and remove some magic to the on getter so that I can set directly the proxy there. In few words mine was a proof of concept on how we could do it and how to bring the right this through the second property access. Rather than Object.prototype.on via define property .. // horrible name, I know, just as example Object.asEmitter = function asEmitter(o) { return Object.defineProperty(o, on, { // everything else that happens in the original proof of concept // problem with variable event solved }); }; var o = Object.asEmitter(Object.create(null)); o.on.whatever.add(callback); o.on.whatever({type: whatever}); br On Sat, Oct 15, 2011 at 8:19 PM, David Bruant bruan...@gmail.com wrote: Le 15/10/2011 19:52, Andrea Giammarchi a écrit : naaa, event is just a placeholder ... most likely is gonna be var event = @__event__ + Math.random(); Or rather a private name (when this is implemented)? Or with some WeakMap trickeries? and most likely that code should be on top with all other native prototypes shims or improvements. the correct this is bound as expected, the click function will have this === object indeed When I wrote any sort of object, i implicity meant any that inherits from Object.prototype ... are other objects ? I don't think so ... I would never do something like alert.on.alert(callback); Actually, in something else than old IE, 'alert' is a regular function and it's [[prototype]] chain is like: alert -- Function.prototype -- Object.prototype -- null So 'alert' should be fine actually. There are indeed other objects that you can create: var o1 = Object.create(null); var o2 = Object.create(o1); var o3 = Object.create(o2); var o4 = Object.create(o2); // both inherit from o2 // etc. None of them contain Object.prototype in their prototype chain and I don't see any strong reason to prevent these objects from emitting events. you know what I mean ;-) I do. Actually, one of my initial thought was to do something with Object.prototype but I stopped as soon as I remembered that some objects may not inherit from it. br P.S. I just pressed reply but I think I removed your text through selection ... apologies No worries :-) David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Event properties on objects, a proxy experiment
I love it! With some minor nits. I feel like [[Call]] should map to dispatch/fire. And with some sugar on top to sweeten the deal. var obj = { onfoo: event(a, b, c) { ... } }; // addListener obj.onfoo.add(function(a, b, c) { assertEquals(this, obj); ... }); // Syntactic sugar for add obj.onfoo += function(a, b, c) { assertEquals(this, obj); ... } // removeListener obj.onfoo.remove(f); // Syntactic sugar for unlisten obj.onfoo -= f; // dispatch obj.onfoo('a', 'b', 'c') -- erik ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Event properties on objects, a proxy experiment
On Fri, Oct 14, 2011 at 13:49, Erik Arvidsson erik.arvids...@gmail.com wrote: var obj = { onfoo: event(a, b, c) { ... } }; I guess I was too lazy here. The idea, which is not very baked was to allow a body here as a default action. Still I like where this is going and we (me and Alex Russel have brain stormed this on several occasions). -- erik ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Event properties on objects, a proxy experiment
Le 14/10/2011 22:49, Erik Arvidsson a écrit : I love it! I'm glad to create such a reaction :-) With some minor nits. I feel like [[Call]] should map to dispatch/fire. Not only do I like this idea, but it may solve a problem I had regarding |this| binding with inherited events. in o.myEvent.fire, it's hard to bind fire to o because of the middle thing. No problem if what is bound is the event itself. (unless I need the receiver argument that is about to be dropped?) And with some sugar on top to sweeten the deal. My first intention was not necessarily to propose this for standardization, so I didn't mention syntax. And also I cannot implement syntax just with proxies. var obj = { onfoo: event(a, b, c) { ... } }; I was imagining more something like: var obj = { a: 1, event onfoo, // just declaration b: null }; But this idea of a default behavior is an interesting addition. I guess in my property descriptor, I could make the 'event' field a function for a default behavior (instead of the dummy 'true') I guess I was too lazy here. The idea, which is not very baked was to allow a body here as a default action. Still I like where this is going and we (me and Alex Russel have brain stormed this on several occasions). I realized very soon after sending my email that it actually is very close from how DOM events are handled in Dart (http://www.dartlang.org/articles/improving-the-dom/ ) with elem.on.click.add. By the way, do anyone know how the binding with 'elem' is made? Is it before or after the compilation? Because maybe I miss something, but by the time you reach add, you have lost both elem and on I'll try to find some time to implement the fire as [[Call]] this week-end. Thanks, David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Event properties on objects, a proxy experiment
On Fri, Oct 14, 2011 at 16:09, David Bruant bruan...@gmail.com wrote: By the way, do anyone know how the binding with 'elem' is made? Is it before or after the compilation? Because maybe I miss something, but by the time you reach add, you have lost both elem and on Dart only has lexical this. In the Dart DOM, both the on property and the click property (in element.on.click.add(f)) has a way to get to the element. http://code.google.com/p/dart/source/browse/trunk/dart/client/html/src/ElementWrappingImplementation.dart#647 http://code.google.com/p/dart/source/browse/trunk/dart/client/html/src/EventTargetWrappingImplementation.dart -- erik ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Event properties on objects, a proxy experiment
Le 15/10/2011 01:09, David Bruant a écrit : (...) I'll try to find some time to implement the fire as [[Call]] this week-end. Well, actually, it took me a couple of minutes to implement the things you mentionned (fire as [[Call]] and a default behavior): https://github.com/DavidBruant/HarmonyProxyLab/tree/master/EventedObject David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Event properties on objects, a proxy experiment
Hi, I have started a little experiment and I'd like to share it here. _Context_ We've been taught that objects are attributes and methods. Consequently, object clients can inspect attributes (though these are most often private, but there can be constants) and actively call methods. However, a client cannot be told when the object changes states in a particular manner. In order for this to be possible, the object needs a publish/subscribe mecanism of some sort by using methods (.addEventListener and .dispatch for the DOM for instance). This mecanism is usually abstracted out. For the DOM, it is done by inheriting from EventTarget. One downside of using methods is that events are never really considered as part of the interface of the object. addEventListener and dispatch are, but there is no way, by inspecting the object to know which event this object provides. Consequently, events are often poorly documented. For instance, I have never seen in a JavaDoc which events an object support and what their semantics are. Feature detection is even difficult for the case of the DOM. See http://www.w3.org/TR/DOM-Level-3-Events/#feature-detection So I wondered what if events were part of an object and exposed as such?. What if an object, instead of being attributes+methods was attributes+methods+events? (as I learned later having that thought, what I'm describing is actually what some people call component in the software engineering literature) In this case, events would just be a native feature with potential support from a bunch of tooling from doc-generation software to code analysers. This idea is still new to me, but I think interpreters/compilers may be able to optimize better native events than one created with a hand-written library (where the engine cannot reverse-engineer the intention of an event mechanism). _The experiment_ So, I thought about JavaScript and the following line: Object.defineProperty(o, 'e', {configurable: true, enumerable: true, event:true}); The rest can be read at https://github.com/DavidBruant/HarmonyProxyLab/tree/master/EventedObject (the code inside index.html shows how the API would work) Of course, the line above only works with newly created objects. I have not heavily tested this work and there are still open questions (like what would be a good use of the set trap?), but the index.html file works as I expect on Firefox 7. _Lesson learned during the experiment_ 1) first use of finally in JavaScript 2) https://bugzilla.mozilla.org/show_bug.cgi?id=601379 is a bit annoying, but I wrote a workaround for it by redefining Object.defineProperty. I hope this can be useful to others if you want to experiment new property descriptor attributes and test on Firefox until this bug is fixed. _Future work_ 1) see how to deal with inherited events 2) try, based on this kind of event to implement a DOM-like event mechanism with capture, bubble, stopPropagation, etc. to see whether these event properties can be used to easily implement such a thing. David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Event properties on objects, a proxy experiment
On Wed, Oct 12, 2011 at 6:38 AM, David Bruant bruan...@gmail.com wrote: Hi, I have started a little experiment and I'd like to share it here. _Context_ We've been taught that objects are attributes and methods. Consequently, object clients can inspect attributes (though these are most often private, but there can be constants) and actively call methods. However, a client cannot be told when the object changes states in a particular manner. In order for this to be possible, the object needs a publish/subscribe mecanism of some sort by using methods (.addEventListener and .dispatch for the DOM for instance). This mecanism is usually abstracted out. For the DOM, it is done by inheriting from EventTarget. One downside of using methods is that events are never really considered as part of the interface of the object. addEventListener and dispatch are, but there is no way, by inspecting the object to know which event this object provides. Consequently, events are often poorly documented. For instance, I have never seen in a JavaDoc which events an object support and what their semantics are. Feature detection is even difficult for the case of the DOM. See http://www.w3.org/TR/DOM-**Level-3-Events/#feature-**detectionhttp://www.w3.org/TR/DOM-Level-3-Events/#feature-detection So I wondered what if events were part of an object and exposed as such?. What if an object, instead of being attributes+methods was attributes+methods+events? (as I learned later having that thought, what I'm describing is actually what some people call component in the software engineering literature) In this case, events would just be a native feature with potential support from a bunch of tooling from doc-generation software to code analysers. This idea is still new to me, but I think interpreters/compilers may be able to optimize better native events than one created with a hand-written library (where the engine cannot reverse-engineer the intention of an event mechanism). _The experiment_ So, I thought about JavaScript and the following line: Object.defineProperty(o, 'e', {configurable: true, enumerable: true, event:true}); The rest can be read at https://github.com/**DavidBruant/HarmonyProxyLab/* *tree/master/EventedObjecthttps://github.com/DavidBruant/HarmonyProxyLab/tree/master/EventedObject(the code inside index.html shows how the API would work) Of course, the line above only works with newly created objects. I have not heavily tested this work and there are still open questions (like what would be a good use of the set trap?), but the index.html file works as I expect on Firefox 7. _Lesson learned during the experiment_ 1) first use of finally in JavaScript 2) https://bugzilla.mozilla.org/**show_bug.cgi?id=601379https://bugzilla.mozilla.org/show_bug.cgi?id=601379is a bit annoying, but I wrote a workaround for it by redefining Object.defineProperty. I hope this can be useful to others if you want to experiment new property descriptor attributes and test on Firefox until this bug is fixed. _Future work_ 1) see how to deal with inherited events 2) try, based on this kind of event to implement a DOM-like event mechanism with capture, bubble, stopPropagation, etc. to see whether these event properties can be used to easily implement such a thing. Rather than properties, how about modeling events with promises or await? jjb David __**_ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/**listinfo/es-discusshttps://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Event properties on objects, a proxy experiment
On Oct 12, 2011, at 6:38 AM, David Bruant wrote: Hi, ... So I wondered what if events were part of an object and exposed as such?. What if an object, instead of being attributes+methods was attributes+methods+events? (as I learned later having that thought, what I'm describing is actually what some people call component in the software engineering literature) C# does something like this. See http://msdn.microsoft.com/en-us/library/aa645739%28v=vs.71%29.aspx Allen___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Event properties on objects, a proxy experiment
Le 12/10/2011 16:42, John J Barton a écrit : Rather than properties, how about modeling events with promises or await? Could you describe what you mean and add some code of how it would look like? One of the problems I want to solve is to have events as first-class constructs of objects in order to be able to list/document them easily, to be able to statically analyse a publish/subscribe mecanism from source code. The link that Allen just sent is great for that regard. The public event ChangedEventHandler Changed; declaration is great. There is no such thing in JavaScript, but the analysis of the property descriptor would be an equivalent. If events are modeled with promises and awaits and solve the problem I described, it sounds like an interesting idea. David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Event properties on objects, a proxy experiment
On Wed, Oct 12, 2011 at 10:42 AM, John J Barton johnjbar...@johnjbarton.com wrote: On Wed, Oct 12, 2011 at 6:38 AM, David Bruant bruan...@gmail.com wrote: Hi, I have started a little experiment and I'd like to share it here. _Context_ We've been taught that objects are attributes and methods. Consequently, object clients can inspect attributes (though these are most often private, but there can be constants) and actively call methods. However, a client cannot be told when the object changes states in a particular manner. In order for this to be possible, the object needs a publish/subscribe mecanism of some sort by using methods (.addEventListener and .dispatch for the DOM for instance). This mecanism is usually abstracted out. For the DOM, it is done by inheriting from EventTarget. One downside of using methods is that events are never really considered as part of the interface of the object. addEventListener and dispatch are, but there is no way, by inspecting the object to know which event this object provides. Consequently, events are often poorly documented. For instance, I have never seen in a JavaDoc which events an object support and what their semantics are. Feature detection is even difficult for the case of the DOM. See http://www.w3.org/TR/DOM-**Level-3-Events/#feature-**detectionhttp://www.w3.org/TR/DOM-Level-3-Events/#feature-detection So I wondered what if events were part of an object and exposed as such?. What if an object, instead of being attributes+methods was attributes+methods+events? (as I learned later having that thought, what I'm describing is actually what some people call component in the software engineering literature) In this case, events would just be a native feature with potential support from a bunch of tooling from doc-generation software to code analysers. This idea is still new to me, but I think interpreters/compilers may be able to optimize better native events than one created with a hand-written library (where the engine cannot reverse-engineer the intention of an event mechanism). _The experiment_ So, I thought about JavaScript and the following line: Object.defineProperty(o, 'e', {configurable: true, enumerable: true, event:true}); The rest can be read at https://github.com/**DavidBruant/HarmonyProxyLab/ **tree/master/EventedObjecthttps://github.com/DavidBruant/HarmonyProxyLab/tree/master/EventedObject(the code inside index.html shows how the API would work) Of course, the line above only works with newly created objects. I have not heavily tested this work and there are still open questions (like what would be a good use of the set trap?), but the index.html file works as I expect on Firefox 7. _Lesson learned during the experiment_ 1) first use of finally in JavaScript 2) https://bugzilla.mozilla.org/**show_bug.cgi?id=601379https://bugzilla.mozilla.org/show_bug.cgi?id=601379is a bit annoying, but I wrote a workaround for it by redefining Object.defineProperty. I hope this can be useful to others if you want to experiment new property descriptor attributes and test on Firefox until this bug is fixed. _Future work_ 1) see how to deal with inherited events 2) try, based on this kind of event to implement a DOM-like event mechanism with capture, bubble, stopPropagation, etc. to see whether these event properties can be used to easily implement such a thing. Rather than properties, how about modeling events with promises or await? To my mind, a promise is to an event as a scalar is to a vector. In the past I've experimented with modelling events as a kind of a lazy array -- an object with a forEach method that takes a handler function and returns a promise that eventually resolves to undefined (when the event stream is over). It's certainly possible, but a little more awkward to explain to a javascript dev than the run-of-the-mill event emitter pattern. ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Event properties on objects, a proxy experiment
On Wed, Oct 12, 2011 at 9:38 AM, David Bruant bruan...@gmail.com wrote: Hi, I have started a little experiment and I'd like to share it here. _Context_ We've been taught that objects are attributes and methods. Consequently, object clients can inspect attributes (though these are most often private, but there can be constants) and actively call methods. However, a client cannot be told when the object changes states in a particular manner. In order for this to be possible, the object needs a publish/subscribe mecanism of some sort by using methods (.addEventListener and .dispatch for the DOM for instance). This mecanism is usually abstracted out. For the DOM, it is done by inheriting from EventTarget. One downside of using methods is that events are never really considered as part of the interface of the object. addEventListener and dispatch are, but there is no way, by inspecting the object to know which event this object provides. Consequently, events are often poorly documented. For instance, I have never seen in a JavaDoc which events an object support and what their semantics are. Feature detection is even difficult for the case of the DOM. See http://www.w3.org/TR/DOM-**Level-3-Events/#feature-**detectionhttp://www.w3.org/TR/DOM-Level-3-Events/#feature-detection So I wondered what if events were part of an object and exposed as such?. What if an object, instead of being attributes+methods was attributes+methods+events? (as I learned later having that thought, what I'm describing is actually what some people call component in the software engineering literature) In this case, events would just be a native feature with potential support from a bunch of tooling from doc-generation software to code analysers. This idea is still new to me, but I think interpreters/compilers may be able to optimize better native events than one created with a hand-written library (where the engine cannot reverse-engineer the intention of an event mechanism). _The experiment_ So, I thought about JavaScript and the following line: Object.defineProperty(o, 'e', {configurable: true, enumerable: true, event:true}); The rest can be read at https://github.com/**DavidBruant/HarmonyProxyLab/* *tree/master/EventedObjecthttps://github.com/DavidBruant/HarmonyProxyLab/tree/master/EventedObject(the code inside index.html shows how the API would work) Of course, the line above only works with newly created objects. I have not heavily tested this work and there are still open questions (like what would be a good use of the set trap?), but the index.html file works as I expect on Firefox 7. _Lesson learned during the experiment_ 1) first use of finally in JavaScript 2) https://bugzilla.mozilla.org/**show_bug.cgi?id=601379https://bugzilla.mozilla.org/show_bug.cgi?id=601379is a bit annoying, but I wrote a workaround for it by redefining Object.defineProperty. I hope this can be useful to others if you want to experiment new property descriptor attributes and test on Firefox until this bug is fixed. _Future work_ 1) see how to deal with inherited events 2) try, based on this kind of event to implement a DOM-like event mechanism with capture, bubble, stopPropagation, etc. to see whether these event properties can be used to easily implement such a thing. ISTM a lot of this is already pretty common, and almost a de facto standard ducktype using the `on` method (e.g. dojo, node, etc.). This pattern is common enough that maybe it merits some kind of de jure support, but obviously it'd be tough to do it using the string `on` as a method. A private name combined with the module system could be perfect for this though, and would enable stratified ducktyping: // get private name `on` from some made up @events module import on from @events // turn some `foo` obj into an event emitter foo[on] = {} // add a `change` handler foo[on].change = function(handler) { /* ... */ } So in this way component objects can be reflected on at runtime, and if done in a controlled fashion could even be extracted out by doc tools automatically. The only de jure aspect to this would be where to put this particular private name in the grand es-next ontology. And maybe we don't even need that. There are other ducktypes that could really stand to gain from this treatment -- one that comes to mind is the Promises/A `then` method. For various reasons, largely around the possibility of sandboxing, `instanceof` is insufficient as a universal branding for promises. The ducktyped `then` approach overcomes this obstacle, and opens the doors to interoperability between any number of promise producers and consumers, as we're witnessing now. But it's still a hazard -- one that private names could fix. But unless we can agree where to put that private name we'd be taking a step back WRT interop. And the same could be said of the ducktyped `on` I suggested above. I'm curious what folks think
Re: Event properties on objects, a proxy experiment
On Wed, Oct 12, 2011 at 9:50 AM, Dean Landolt d...@deanlandolt.com wrote: On Wed, Oct 12, 2011 at 10:42 AM, John J Barton johnjbar...@johnjbarton.com wrote: On Wed, Oct 12, 2011 at 6:38 AM, David Bruant bruan...@gmail.com wrote: Rather than properties, how about modeling events with promises or await? To my mind, a promise is to an event as a scalar is to a vector. Ah, nice analogy. Let me just see if I understand. An observer of an object's 'event-api-thingy' expects a stream of calls, once for each occasion of the event. If the thingy were a promise, then the first occasion would consume it. The C# solution maps addEventListener(name, fnc) into +=() on the |event| object and removeEventListener into -=(). The |event| then is a function with a list attached; calling the function dispatches to the list. http://msdn.microsoft.com/en-us/library/aa645739%28v=vs.71%29.aspx In the past I've experimented with modelling events as a kind of a lazy array -- an object with a forEach method that takes a handler function and returns a promise that eventually resolves to undefined (when the event stream is over). It's certainly possible, but a little more awkward to explain to a javascript dev than the run-of-the-mill event emitter pattern. Is their any hope of solving the GC problem with events? By that I mean the tedious business of matching removeEventListener to every addEventListener. If I take an event-thingy from an object, then drop the reference, the remove is automatic: foo.observeBar = function(event) { // foo deals with bar's change }.magicHere( bar.changed); ... delete foo.observeBar; // remove event listener or foo gets deleted or goes out of scope etc. And to round out my random comment, take a look at MDV as well: http://code.google.com/p/mdv/ jjb ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: Event properties on objects, a proxy experiment
Le 12/10/2011 19:32, John J Barton a écrit : Is their any hope of solving the GC problem with events? By that I mean the tedious business of matching removeEventListener to every addEventListener. If I take an event-thingy from an object, then drop the reference, the remove is automatic: foo.observeBar = function(event) { // foo deals with bar's change }.magicHere( bar.changed); ... delete foo.observeBar; // remove event listener or foo gets deleted or goes out of scope etc. In my implementation, the only things which have access to the listeners are addListener, removeListener and fire (+revokeEvent if the implementation doesn't figure out that this method actually doesn't use listeners). Once all references to these are lost, (when doing delete o.e; (see delete trap) or if a reference to the object is lost), then, references to the listeners can be freed. A leak remains if someone keeps a reference to any of the 3 functions (revokeEvent is internal and I take care of removing all references to it internally). ... wait a minute... Instead of the canFire boolean mess, I could just do listeners = null;. The only to the array of listener would be lost enabling freeing the listeners. Unless removed manually, listeners would be bound to the lifetime of the event property which sounds good to me. If the event property is deleted, listeners can be removed. If the object is GC'd, then so can be the event property, then so can be the listeners. Do you see another leak? David ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss