arguments.callee in Harmony

Brendan Eich brendan at mozilla.com
Fri Sep 25 11:28:45 PDT 2009


On Sep 25, 2009, at 10:31 AM, Charles Jolley wrote:

>> But strict mode is not supported in current or downrev IE. So it is  
>> imperative that Microsoft fix these old named function expression  
>> name-binding bugs before, or at the same time as, script mode along  
>> with all of ES5 are supported in a future version of IE.
>
> Wouldn't that violate the principle of strict mode?

Which "that"? IE fixing bad old named function expression bugs  
violates nothing, not ES5 or ES5 strict, and certainly not ES3 which  
spec'ed how named function expressions bind their names (not in the  
variable object! :-P).

Ok, forget IE bugs. It seems you are asking here whether "use strict";  
in ES5 engines causes semantic changes that are not backward  
compatible. The answer is that it does. See Annex C of ES5.

The cases are edgy, e.g., arguments[i] aliasing the i'th formal  
parameter does not happen in an ES5 implementation under "use strict",  
but it would when that code is fed to a pre-ES5 engine. And of course,  
arguemnts.callee and the caller property poison pills, which throw in  
ES5 strict but don't when code using them is fed into a pre-ES5 engine.


>  I thought the idea was that writing code in Harmony could basically  
> boil down to ES3 code if I wanted to.  But in this case it wouldn't;  
> the same code written for Harmony would appear valid ES3 but would  
> fail.

Right. You have to test to see that "use strict"; code works the way  
you expect in older browsers. If you steer clear of arguments objects  
you don't have much to do. There's another runtime semantic change, to  
eval (it can't create bindings in its dynamic scope), which under ES5  
strict will break such examples (at least when I last checked) as  
extjs.com, which did something like

   function compile(...) {
     eval("var f = function() {" + compile_optimized_query(); + "}");
     return f;
   }

This can be avoided by putting the var f = outside the eval, if you  
parenthesize the lambda of course -- except Jack Slocum pointed out to  
me that IE has bugs (perhaps only old IE versions still have these)  
that bite this alternative! I'm not sure what the latest extjs code  
does, since it seems hidden by dual licensing stuff I didn't click  
through.


> Sorry if I'm misunderstanding the goal here.  I thought the point of  
> "use strict" is the same code could still run on older browsers who  
> don't understand the directive.

The code runs, but certain edge cases don't work the same. In old  
engines they work as ever, in ES5 engines they may throw due to the  
poison pills, or they may do something "better" (e.g., eval binds in  
its own declarative environment).

A strict mode that only prevents programs from reaching runtime would  
require too much static analysis.

A strict mode that adds runtime errors will require testing in ES5 and  
pre-ES5 engines.

Given our inability to avoid runtime errors new with strict mode, we  
managed to reach consensus on a few further runtime semantic changes.  
If these cause trouble, we may find fewer strict mode uses than we'd  
like to find. But it's hard to evaluate strict mode adoption for  
success or failure  based on whether these runtime changes bite back  
-- we can't run the experiment a different way.

/be

>
> -Charles
>
>
>>
>> We talked about this issue yesterday at the end of the TC39  
>> meeting. I think Allen had to leave but I mailed him about it.
>>
>> /be
>>
>>>
>>> Best Fabian
>>>
>>>
>>> Charles Jolley wrote:
>>>>
>>>> Hi everyone,
>>>>
>>>> First an introduction: I am the lead developer of SproutCore
>>>> (http://www.sproutcore.com
>>>> ), an open source framework for building client-side applications  
>>>> in
>>>> HTML5.  SproutCore is used in several large projects including  
>>>> Apple's
>>>> MobileMe and iwork.com, OtherInbox, and some other large projects  
>>>> that
>>>> are not yet public.
>>>>
>>>> Point is, we write very large applications in JavaScript and HTML5.
>>>> I've been following ES5/Harmony closely.  By and large I am very
>>>> excited about the features to be added.  One critical feature (imo)
>>>> that is missing, however, is "arguments.callee" - at least some  
>>>> way to
>>>> identify the current function that is executing.
>>>>
>>>> I spoke with Brenden Eich and Yehuda Katz about this on Friday and
>>>> talked to Doug Crockford about it today and they suggested I email
>>>> this list to make my case so here it is:
>>>>
>>>> USE CASE
>>>>
>>>> Currently SproutCore implements a class-like system on top of
>>>> JavaScript.  That is, you can have "classes" with "subclasses"  
>>>> and you
>>>> can instantiate both.  SproutCore is not strictly classical, and  
>>>> JS is
>>>> not class-based of course, but I think this is a pattern that many
>>>> developers commonly want to implement and use in JS.
>>>>
>>>> The problem comes with implementing methods that "override"  
>>>> methods in
>>>> superclasses.  Take the following example [extend() is the  
>>>> SproutCore
>>>> function that creates a new "subclass"]:
>>>>
>>>> ClassA = SC.Object.extend({
>>>>
>>>> foo: function() {
>>>> // do something
>>>> }
>>>>
>>>> });
>>>>
>>>> ClassB = ClassA.extend({
>>>>
>>>> // NOTE: overrides foo in classA!
>>>> foo: function() {
>>>> // call ClassA.foo();
>>>> // do something else
>>>> }
>>>>
>>>> });
>>>>
>>>> --
>>>>
>>>> Now the question is, how can ClassB.foo() call ClassA.foo() in a
>>>> generic fashion?
>>>>
>>>> I could force developers to hard code this knowledge  (i.e. when
>>>> implementing ClassB.foo() you have to explicitly call  
>>>> ClassA.foo.apply
>>>> (this)) but this is prone to developer error and also makes the  
>>>> code
>>>> not easily transportable from one method to another; violating the
>>>> sort of "copy-and-paste" ethos that is part of JavaScript.
>>>>
>>>> I've been told that I could name the functions.  e.g.:
>>>>
>>>> ClassB = ClassA.extend({
>>>> foo:  function foo() {
>>>> // ..code
>>>> }
>>>> });
>>>>
>>>> Somehow that should solve my problem, though I can't really work  
>>>> out
>>>> how.  But regardless, asking developers to name each method twice  
>>>> in
>>>> the declaration is also error prone and fragile.
>>>>
>>>> --
>>>>
>>>> The way I solve this currently is to implement extend() so that  
>>>> when
>>>> it copies an overloaded method, it sets a property ("base") on the
>>>> Function to point to the Function it is overloading.  In the  
>>>> example
>>>> above, for example, this means that ClassB.foo.base === ClassA.foo.
>>>>
>>>> This way I can write a generic call to "super" like so:
>>>>
>>>> ClassB = ClassA.extend({
>>>>
>>>> foo: function() {
>>>> arguments.callee.base.apply(this, arguments); // calls super!
>>>> // other code
>>>> }
>>>>
>>>> });
>>>>
>>>> --
>>>>
>>>> I realize this is not the most elegant looking code, but  
>>>> currently its
>>>> the only way I can figure out to implement the "super" pattern in a
>>>> generic way in JS.
>>>>
>>>> SOLUTIONS?
>>>>
>>>> With ES5, arguments.callee is gone.
>>>>
>>>> One suggestion Brenden had was to perhaps include a  
>>>> "thisFunction" or
>>>> some such property that returns the current function instance you  
>>>> are
>>>> in.  This seems useful to me for a bunch of other meta-programming
>>>> patterns as well but would certainly work here.
>>>>
>>>> Another solution suggested by Douglas would be to provide a way  
>>>> for a
>>>> function to get its current "name" AND for ECMAScript to follow a
>>>> convention that anonymous functions when declared as part of an  
>>>> object
>>>> literal take on the name they are assigned to by default.
>>>>
>>>> Either of these would work for this pattern; there are probably  
>>>> other
>>>> solutions as well.
>>>>
>>>> I don't really care what ends up in the final implementation only  
>>>> that
>>>> there is some way to generically implement the ultra-common class-
>>>> based-with-method-overloading pattern in ECMAScript >= 5 without
>>>> jumping through some crazy hoops.
>>>>
>>>> --
>>>>
>>>> So that's my best argument on this.  Any suggestions of alternative
>>>> implementations that will work in ECMAScript 5?  If this is a
>>>> limitation of the new language, what I can do to agitate for  
>>>> something
>>>> to be added?
>>>>
>>>> Thanks,
>>>> -Charles
>>>>
>>>>
>>>> _______________________________________________
>>>> es-discuss mailing list
>>>> es-discuss at mozilla.org
>>>> https://mail.mozilla.org/listinfo/es-discuss
>>>>
>>>>
>>>
>>> -- 
>>> View this message in context: http://www.nabble.com/arguments.callee-in-Harmony-tp25603357p25610255.html
>>> Sent from the Mozilla - ECMAScript 4 discussion mailing list  
>>> archive at Nabble.com.
>>>
>>> _______________________________________________
>>> es-discuss mailing list
>>> es-discuss at mozilla.org
>>> https://mail.mozilla.org/listinfo/es-discuss
>>
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>



More information about the es-discuss mailing list