Indeed, I was talking about case 3.

There is still another problem, beside tying a method directly to an event, there are at least two places where you're indirectly tying it to an event-like structure: LzTimer and LzIdle. (see "LzTimer#addTimer(..)" and "LzIdle#removeCallIdleDelegates(..)" resp. "LzIdleKernel.__update()".)
So, what we actually need to do, is to change the LzDelegate-API.
New rule: every method for a delegate must accept at least one argument, (also see "LzDelegate#execute(..)", so that's definitely necessary.) What to do: move the argument-length checking from "LzDelegate#register(..)" to the LzDelegate-constructor.

And as you said, the route 3a should be clearly discouraged, for instance the public API for "LzDataset#doRequest()" or "LzState#apply()" has been changed to get around swf9 warnings. A good example for what we should do, is "LzLazyReplicationManager#__LZhandleUpdate(..)". This method was added to be compatible to the event-system.

However, we really want to force people to update all their applications?! So the step from 4.0.x (or even 3.x) to 4.2 will require quite some work.

As an example, a call to "LzFocus#clearFocus()" needs to changed like so, from:
new LzDelegate(LzFocus, "clearFocus", this, "onfoo");
to:
new LzDelegate(this, "_handleFoo", this, "onfoo");
+ private function _handleFoo (ignore:*) {LzFocus.clearFocus();}
or to (short-form):
new LzDelegate({_handle: function (ignore) {LzFocus.clearFocus();}}, "_handle", this, "onfoo");


On 5/3/2008 10:18 PM, P T Withington wrote:
Yes, I am not _really_ happy with the solution, but I think it is the best compromise.

I think there are three cases to consider:

1) You are writing a method that you will use as an event handler, e.g.,

  <handler name="onfoo" method="handleOnfoo" />

In this case, you have specifically declared your intent to handle a sendEvent message, which by definition calls your handler method with one value. You had better accept that value, even if you ignore it; otherwise, your method is not eligible to be an event handler. So you define your method:

  <method name="handleOnfoo" args="value">
    Debug.debug("onfoo sent: %w", value);
  </method>

If your handler method does not accept the sendEvent value, you will get a warning and you should fix it.

2) You have a method that you want called when an event happens, e.g.,

  <... onfoo="eventHappens()" ...>

or

  <handler name="onfoo">
    eventHappens();
  </handler>

In this case, you are using the open tag event syntax or the handler tag to make the connection between an event and a method, which automatically introduces an 'event handling wrapper' with the requisite argument processing, so your method can take whatever form you like. (Note: you can declare args in the handler tag if you want the sendEvent value, but if you don't the tag compiler will automatically declare one ignore arg for you.)

3) You are basically cheating. You are trying to use a method that was not intended to be an event handler and tie it directly to an event. You could get away with this in the past because the runtime did not care if methods were called with the correct number and type of arguments. You can't any more. You have two choices:

a) Add a nonsensical `ignore` parameter to your method to match the sendEvent call (and repair all other calls of your method to pass a `null` value).

b) Do the right thing: either use the <handler> tag, or if you are in Javascript, your own wrapper, to mediate between the event and the other method.

--

I think what you are complaining about is case 3, which was done flagrantly throughout our system, probably as a premature optimization. I think we just have to fix these cases. If we _really_ think the event and handler are so central to the performance of the system, then we will have to add that `ignore` parameter (3a). But most likely, we can fix this cleanly by using the handler tag or a javascript wrapper (3b), which should not be as objectionable.

I _do_ think it is important to discourage people from taking the 3a route as much as possible. (Although I may have been lazy and done this myself in a couple of places already.)

On 2008-05-03, at 10:12 EDT, André Bargull wrote:

We're adding an "ignore"-argument all over the place, so that our event-system works in swf9. This a really cumbersome work and some of these warnings don't really help you:
WARNING @lz/gridcolumn.lzx#90: Invalid delegate: «LzCursorService function(0)#0| kernel/swf/LzMouseKernel.as#59/21» (must accept one argument to handle .resizer.onmouseout)

This warning was triggered by "LzSprite#setCursor(..)" (swf), because there is this delegate:
this._muDel = new LzDelegate( LzMouseKernel , 'restoreCursor', this.owner , 'onmouseout');
And as "LzMouseKernel#restoreCursor()" does expect an argument (why should it!?), you get this warning.

If we followed our current practice, we would add an "ignore"-argument to "LzMouseKernel#restoreCursor()". But that's not really convincing, to change a semi-public API (see LzCursor) just to get around this. Also think about user applications, which may have a delegate to i.e. "LzFocus#clearFocus()". They'll get a warning, because the LzFocus-API is not compatible to the event-API. So, do we need to change the public "LzFocus#clearFocus()" API because of this? Surely not!

Therefore, I'd like to propose:
- either do the function wrapping in "LzDelegate#register(..)" in swf9 automatically, but without any warnings (but consider possible performance disadvantages!) - or add at compile to every function without any arguments a default "ignore"-argument, so that it is compatible to our event-system.

Thoughts?


Reply via email to