Event properties on objects, a proxy experiment
On Wed, Oct 12, 2011 at 6:38 AM, David Bruant <bruant.d at 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 www.w3.org/TR/DOM-**Level-3-Events/#feature-**detectionwww.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 *DavidBruant/HarmonyProxyLab/ *tree/master/EventedObjectDavidBruant/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
- first use of "finally" in JavaScript
- bugzilla.mozilla.org/**show_bug.cgi?id=601379bugzilla.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
- see how to deal with inherited events
- 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
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 msdn.microsoft.com/en-us/library/aa645739(v=vs.71).aspx
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.
Le 12/10/2011 17:40, Allen Wirfs-Brock a écrit :
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 msdn.microsoft.com/en-us/library/aa645739(v=vs.71).aspx
True!
I had this idea a while ago, discussed with people and they told me C# had something like this. I forgot to take a look.
Thanks,
On Wed, Oct 12, 2011 at 10:42 AM, John J Barton <johnjbarton at johnjbarton.com
wrote:
On Wed, Oct 12, 2011 at 6:38 AM, David Bruant <bruant.d at 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 www.w3.org/TR/DOM-**Level-3-Events/#feature-**detectionwww.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 **DavidBruant/HarmonyProxyLab **tree/master/EventedObjectDavidBruant/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
- first use of "finally" in JavaScript
- bugzilla.mozilla.org/**show_bug.cgi?id=601379bugzilla.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
- see how to deal with inherited events
- 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.
On Wed, Oct 12, 2011 at 9:38 AM, David Bruant <bruant.d at 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 www.w3.org/TR/DOM-**Level-3-Events/#feature-**detectionwww.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 *DavidBruant/HarmonyProxyLab/ *tree/master/EventedObjectDavidBruant/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
- first use of "finally" in JavaScript
- bugzilla.mozilla.org/**show_bug.cgi?id=601379bugzilla.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
- see how to deal with inherited events
- 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 about this kind of approach? It's the reason I'm such a private name fanboy -- I think it's a pretty interesting opportunity to push library interop forward.
On Wed, Oct 12, 2011 at 9:50 AM, Dean Landolt <dean at deanlandolt.com> wrote:
On Wed, Oct 12, 2011 at 10:42 AM, John J Barton < johnjbarton at johnjbarton.com> wrote:
On Wed, Oct 12, 2011 at 6:38 AM, David Bruant <bruant.d at 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. msdn.microsoft.com/en-us/library/aa645739(v=vs.71).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: code.google.com/p/mdv
jjb
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?
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')
On Fri, Oct 14, 2011 at 13:49, Erik Arvidsson <erik.arvidsson at 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).
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 (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,
On Fri, Oct 14, 2011 at 16:09, David Bruant <bruant.d at 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.
code.google.com/p/dart/source/browse/trunk/dart/client/html/src/ElementWrappingImplementation.dart#647, code.google.com/p/dart/source/browse/trunk/dart/client/html/src/EventTargetWrappingImplementation.dart
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): DavidBruant/HarmonyProxyLab/tree/master/EventedObject
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: gist.github.com/1289809
best
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: gist.github.com/1289809
best
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,
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
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 :-)
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
From: David Bruant <bruant.d at 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 at 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).
Le 16/10/2011 22:16, Axel Rauschmayer a écrit :
*From: *David Bruant <bruant.d at gmail.com <mailto:bruant.d at 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 at mozilla.org <mailto:es-discuss at 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).
Interesting reading. Thanks for sharing :-)
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.
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 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 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
Future work