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

P T Withington ptw at pobox.com
Wed Jan 9 14:37:41 PST 2008


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




More information about the Laszlo-user mailing list