Re: Strict mode callbacks and setTimeout

On Wed, Jul 6, 2011 at 1:56 PM, Boris Zbarsky <bzbarsky@mit.edu> wrote:

> On 7/6/11 4:42 PM, Mark S. Miller wrote:
>
>> The normative text is the more useful interpretation, in that access to
>> a frame's setTimeout function should provide the ability to schedule a
>> call to happen later, but should not provide access to that frame's
>> global object.
>>
>
> You can't do the former without having the latter.  In particular, invoking
> a frame's setTimeout function without the right |this| will throw.
>
> Of course you could be handed a prebound function which will invoke with
> the right |this|....


On all the browsers I just tested,

    (1,setTimeout)(function(){'use strict'; alert('foo'); }, 0)

alerts 'foo'. On what browsers are you seeing different behavior?


>
>  The alternative, of changing the HTML5 spec to pass some global object
>> explicitly, would require yet more hard to explain and emulate magic,
>> since, for legacy compat, a setTimeout from frame X calling a callback
>> from frame Y would need to explicitly pass Y's global object.
>>
>
> This is true for non-strict-mode code already, right?  Or am I
> misunderstanding the problem?
>

I think you are. For the specified HTML5 behavior, when a setTimeout from
frame X calls a non-strict callback from frame Y passing undefined as the
thisArg, it is the non-strict callback's [[Call]] method that coerces the
thisArg to Y's global object. Nothing requires X's setTimeout to be able to
figure out what Y's global object is.



>
> The problem description strongly reminds me of
> https://bugzilla.mozilla.org/**show_bug.cgi?id=634590<https://bugzilla.mozilla.org/show_bug.cgi?id=634590>by the way.


That is a very interesting bug I hadn't been aware of. It does indeed look
relevant. Will need some study. Thanks for pointing it out.



>
>
>  An emulated setTimeout written in JavaScript *could not* correctly emulate
>> this behavior without introducing a generic way to get Y's global object
>> from a frame Y closure.
>>
>
> Again, you need that anyway to be able to setTimeout non-strict-mode
> things, seems like.


No. The setTimeout should just call the callback with undefined as the
thisArg. If the callback is non-strict, it'll take care of the rest.



>
>
>  I think we should see this as yet more teething pains as browsers
>> improve their ES5 implementations to be more conformant. In that
>> context, given the HTML5 normative spec text above
>>
>
> It's not clear to me that the HTML5 spec normative text is necessarily
> correct.
>
> What do browsers set |this| to in a function if you define it in one frame
> but then pass it to setTimeout in another frame and there's no strict mode
> involved?


Yes, this is the important legacy compat issue. We need to take a cross
browser survey.



>  What does the ES5 spec say about that case? (Probably nothing, since it
> assumes a unique global.)


Correct. But our intent moving forward is clearly towards a lexical
understanding of "which global".



>
>
>  The HTML5 normative text is actually quite clear -- that undefined is
>> provided as the thisArg.
>>
>
> It's clear, but it may still be wrong....
>

If we can achieve consensus on something other than the normative, then
sure, we can all agree the normative text is wrong. However, in this case,
the normative text specifies a behavior that's clearly more useful than the
alternative.


>
> -Boris
>



-- 
    Cheers,
    --MarkM

Received on Wednesday, 6 July 2011 21:23:19 UTC