[Laszlo-user] Laszlo function as Array.sort argument

P T Withington ptw at pobox.com
Wed Jan 9 15:32:04 PST 2008


Hopefully they have fixed it!  It's really a player bug with callbacks  
from native code just not creating a global scope.  There must just  
not be that many cases in their own tool where people write code like  
that.

On 2008-01-09, at 17:56 EST, Henry Minsky wrote:

> It will be interesting to see what the  behavior of this issue is in  
> swf9.
>
>
> On Jan 9, 2008 5:37 PM, P T Withington <ptw at pobox.com> wrote:
>
>> yes please.
>>
>> Simple test case is to compare the behaviour of the attribute and
>> method declarations.
>>
>> It's a swf-only bug.
>>
>> On 2008-01-09, at 17:34 EST, André Bargull wrote:
>>
>>> Should we create a JIRA-entry for this bug, so either to create a
>>> fix (somehow), or to document it at least.
>>>
>>> - André
>>>
>>> On 1/9/2008 11:07 PM, P T Withington wrote:
>>>> I take back my explanation regarding `this`.
>>>>
>>>> What it really is is a bug in the Flash implementation of "function
>>>> scope".  When you define a function, it is supposed to capture the
>>>> scope that it was defined in (and use that scope to look up free
>>>> references in).  The Flash player makes a optimization of never
>>>> capturing the scope of a function defined in the global scope.
>>>> This would be fine, because you call all your functions in the
>>>> global scope, so it will be there when you call.
>>>>
>>>> BUT, Henry is right (as usual).
>>>>
>>>> There are a bunch of places in the player where as functions are
>>>> being called by player internals (surely C or C++), and the player
>>>> "forgets" to call the function in the global scope.  The most
>>>> common place we run into this is in the idle loop.  But apparently
>>>> the Array#sort method is another case.  We used to have to write
>>>> all our code that would be used in the idle loop to explicitly
>>>> reference everything from `_root` (which must somehow be specially
>>>> looked up, not just looked up in the scope chain).
>>>>
>>>> A while back, we worked around this issue by making sure that every
>>>> method we define is defined in such a way as to trick the runtime
>>>> into capturing the global scope on the function.  It seems like
>>>> that technique is not working 100%.
>>>>
>>>> And it seems that when a free reference is made from a function and
>>>> the scope chain is empty, the function just immediately exits,
>>>> which is why you see no output.
>>>>
>>>> The (apparent) reason that tracing or closing over the function
>>>> works is that both are invoking the scope-less function inside a
>>>> function that _does_ have a scope, so it all works out.
>>>>
>>>> So, really, this is a bug in our compiler's work-around for the
>>>> scope issue.  If you rewrite the canvas method as:
>>>>
>>>> <attribute name="laszloMethod" value='function (n1, n2)
>>>> { Debug.write("%s: %d - %d (%s)", arguments.callee, n1, n2, Debug);
>>>> return 0}' />
>>>>
>>>> (which should be equivalent), everything works...
>>>>
>>>> On 2008-01-09, at 16:13 EST, André Bargull wrote:
>>>>
>>>>> Another riddle for Tucker:
>>>>>
>>>>> I can call:
>>>>> _root.Debug.write("%s: %d - %d", arguments.callee, n1, n2);
>>>>>
>>>>> But I cannot call:
>>>>> _root.Debug.write("%s: %d - %d (%s)", arguments.callee, n1, n2,
>>>>> Debug);//or i.e. global, canvas etc. breaks, too
>>>>>
>>>>> So, in which context does get Array#sort(..) called?
>>>>>
>>>>>> It _is_ getting called.  For some reason, your Debug.write is
>>>>>> failing  to send any output:
>>>>>>
>>>>>> lzx> Debug.trace(canvas, 'laszloMethod')
>>>>>> lzx> [1,2,3].sort(canvas.laszloMethod)
>>>>>> TRACE: [394491.00] laszloMethod.apply(?undefined?, [1, 2])
>>>>>> laszloMethod( 1 , 2 )
>>>>>> TRACE: [394501.00] laszloMethod -> 0
>>>>>> TRACE: [394505.00] laszloMethod.apply(?undefined?, [1, 3])
>>>>>> laszloMethod( 1 , 3 )
>>>>>> TRACE: [394512.00] laszloMethod -> 0
>>>>>> TRACE: [394516.00] laszloMethod.apply(?undefined?, [1, 2])
>>>>>> laszloMethod( 1 , 2 )
>>>>>> TRACE: [394523.00] laszloMethod -> 0
>>>>>> TRACE: [394527.00] laszloMethod.apply(?undefined?, [2, 3])
>>>>>> laszloMethod( 2 , 3 )
>>>>>> TRACE: [394536.00] laszloMethod -> 0
>>>>>> ?Array(3)#15| [1, 2, 3]?
>>>>>> lzx>
>>>>>>
>>>>>> Oh, hah-hah.  I see why.  Because laslzoMethod is a method, it
>>>>>> expects  a 'this' argument, and our compiler inserts an implicit
>>>>>> `with (this)`  around your method body, but you are calling it as
>>>>>> a function, and  `this` is undefined in that case (see the trace
>>>>>> output above).  So  your code is turning into `with (undefined)`
>>>>>> and I bet that causes the  global reference to Debug to fail.
>>>>>> Amusingly, tracing the method  makes the debug output work.  I
>>>>>> can't really explain that.
>>>>>>
>>>>>> If you were to make a closure to call your method, it should  
>>>>>> work:
>>>>>>
>>>>>> lzx> Debug.untrace(canvas, 'laszloMethod')
>>>>>> lzx> [1,2,3].sort(function (a, b) { return canvas.laszloMethod(a,
>>>>>> b) })
>>>>>> laszloMethod( 1 , 2 )
>>>>>> laszloMethod( 1 , 3 )
>>>>>> laszloMethod( 1 , 2 )
>>>>>> laszloMethod( 2 , 3 )
>>>>>> ?Array(3)#57| [1, 2, 3]?
>>>>>> lzx>
>>>>>>
>>>>>> On 2008-01-09, at 14:28 EST, Pablo Kang wrote:
>>>>>>
>>>>>>
>>>>>>> Btw, I know that I can call a laszloMethod from a Javascript
>>>>>>> function like:
>>>>>>>
>>>>>>> <method name="javascriptFunction" args="n1,n2">
>>>>>>>    return canvas.laszloMethod(n1,n2);
>>>>>>> </method>
>>>>>>>
>>>>>>> What I want to know is why it is I can't pass in the the
>>>>>>> laszloMethod directly.
>>>>>>>
>>>>>>> Thanks,
>>>>>>> pablo
>>>>>>>
>>>>>>> On Wed, 9 Jan 2008, Pablo Kang wrote:
>>>>>>>
>>>>>>>
>>>>>>>> Anyone know why passing in a function defined with an LZX
>>>>>>>> method   tag into Array.sort doesn't work? Here's a test case:
>>>>>>>>
>>>>>>>> <canvas debug="true">
>>>>>>>>
>>>>>>>> <method name="laszloMethod" args="n1,n2">
>>>>>>>>    Debug.write('laszloMethod(', n1, ',', n2, ')');
>>>>>>>>     return 0;
>>>>>>>> </method>
>>>>>>>>
>>>>>>>> <script>
>>>>>>>>     function javascriptFunction(n1,n2) {
>>>>>>>>         Debug.write('javascriptFunction(', n1, ',', n2 ,')');
>>>>>>>>         return 0;
>>>>>>>>     }
>>>>>>>> </script>
>>>>>>>>
>>>>>>>> <handler name="oninit">
>>>>>>>>     var arr = [ 1,2,3 ];
>>>>>>>>
>>>>>>>>     Debug.write('-- Javascript Function --');
>>>>>>>>     arr.sort( javascriptFunction );
>>>>>>>>
>>>>>>>>     Debug.write('-- Laszlo Method --------');
>>>>>>>>     arr.sort( canvas.laszloMethod );
>>>>>>>> </handler>
>>>>>>>>
>>>>>>>> </canvas>
>>>>>>>>
>>>>>>>> pablo
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>
>>>>>>
>>>>>
>>>>
>>>>
>>>
>>
>>
>>
>
>
> -- 
> Henry Minsky
> Software Architect
> hminsky at laszlosystems.com




More information about the Laszlo-user mailing list