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

André Bargull a.bargull at intensis.de
Wed Jan 9 14:34:04 PST 2008


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
>>>>>
>>>>>
>>>>>
>>>>>
>>>
>>>
>>
>
>



More information about the Laszlo-user mailing list