[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