On 2008-10-02, at 10:55EDT, André Bargull wrote:
In the default event system, what you get if you don't write a
custom setter, sends an event every time you call setAttribute.
It does _not_ make any optimization to not send events if you
happen to set an attribute to a value it already has.
A side note for the interested reader:
It's possible to turn on manually this optimization if you pass as
the third argument to "setAttribute()" ?true?, e.g.
foo.setAttribute("text", "hello world!", true)
(That way the setter is not called when the value did not change.)
My head hurts trying to process that logic. Too many negatives.
This seems like an incredibly dangerous optimization, because if you
have a custom setter, how can the generic code know whether or not the
value 'changed'? E.g., suppose the custom setter ensures your value
is in a particular range or rounded to a particular granularity?
When did setAttribute grow this featureXXXXXXXbug? I don't recall
seeing an API review for this.
And, I wonder, does the compiler know about this featureXXXXXXXbug
where it inlines calls to setAttribute?
If you poke around Jira, you will see many bugs of the form
"setting foo does not send the onFoo event". Invariably, these
are from broken custom setters where the setter writer forgot
about the event part of the setter's contract.
LZX-level changes won't help for LFC bugs (LPP-2273) ;-)
True. LFC code needs to be written correctly, or we need to implement
JS2 setter syntax and have the script compiler implement the sending
of events.
1) If you write a setter in the open tag of an attribute, the event
is always sent (you don't get to control the sending of the
event). E.g., if I say:
<attribute name="foo" setter="this._fooState = foo" />
the compiler will automatically append `this.sendEvent('onfoo',
foo)` to the setter body. (How many places in your code have you
written these shorthand setters and actually remembered that you
need to send an event too?)
2) If you _must_ get control over the sending of the event, you
have to ask for it, and use the long-hand <setter> tag. E.g.:
<setter name="foo" args="newFoo" event="false">
...
if (<i really want to send the event>) this.sendEvent('onfoo',
newFoo);
</setter>
When do you send the event?
1. after setting the property
a) requires code analysis
b) likely to be more natural
c) property may be have any name -> problem...
2. at the end of the setter
a) what happens if the user places return statement in the setter? [1]
b) or an error was thrown?
When do you send no event?
1. if you override a setter
a) because the super-setter should handle this,
b) but if the super-setter is not called? (by purpose or
unintentionally?)
[1] leads to an often encountered code structure in OL sourecode
(hey, there is a thing called "else"!):
//start of method
....
if (condition) {
.....
*return;*
}
.....
//end of method
The tag compiler could compile setters as follows (using pseudo-e4x
and `` to mean compile-time substitution):
function [EMAIL PROTECTED] ([EMAIL PROTECTED]) {
try {
`setter.text()`
} finally {
if (`! setter.(@event == 'true')`) {
if (this['[EMAIL PROTECTED]'] &&
[EMAIL PROTECTED]'ready']) {
this.sendEvent('[EMAIL PROTECTED]', [EMAIL PROTECTED]);
}
}
}
}
Since <setter> is a brand new feature, IWBN to make this change in its
semantics now.