|
View:
New views
20 Messages
—
Rating Filter:
Alert me
|
| < Prev | 1 - 2 | Next > |
|
|
arguments.callee in HarmonyHi 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@... https://mail.mozilla.org/listinfo/es-discuss |
|
|
Re: arguments.callee in HarmonyOn Sep 24, 2009, at 2:56 PM, Charles Jolley wrote:
Given your example, a named function expression would do the job trivially: foo: function foo() { foo.base.apply(this, arguments); // calls super! // other code } }); It is likely to be both faster and safer than arguments.callee as both arguments and callee can be overridden, and the lookup up for 'foo' is guaranteed. One other thing to consider is that arguments.callee is only invalid in strict mode -- arguments.callee will continue to work fine in the general case. --Oliver _______________________________________________ es-discuss mailing list es-discuss@... https://mail.mozilla.org/listinfo/es-discuss |
|
|
Re: arguments.callee in Harmony
This works but, as I said, this approach has a couple of drawbacks: 1. The function has to be named twice (foo: function foo()). This makes the code harder to read (especially with long names) and its not very developer-friendly since its pointless cruft. 2. This is also fragile. If you forget the second name, the code would still parse but it will be seriously broken. Additionally, if you decided to rename the function you would also have to edit the code on the inside. Hurts the "copy and paste" aspect of it. In general I think this particular approach is not developer friendly enough. -- It is likely to be both faster and safer than arguments.callee as both arguments and callee can be overridden, and the lookup up for 'foo' is guaranteed. Agreed on the faster side of things but, as I said, I think there are developer-friendlyness issues with this approach that make it unsuitable as a general solution for this pattern. I would rather have a way to get at the currently running function w/o having to go through arguments. I have no love lost with arguments. :-)
True. My assumption is that strict mode is defined so that you can continue to run older code until you can transition it. in other words, one should aspire to convert all of their code to strict mode at some time; compatibility mode is intended just to help transition. In that is the case, then "strict" mode should be able to implement a common design pattern like method overloading in a friendly way, otherwise developers may never convert. -Charles _______________________________________________ es-discuss mailing list es-discuss@... https://mail.mozilla.org/listinfo/es-discuss |
|
|
Re: arguments.callee in HarmonyOn Sep 24, 2009, at 3:55 PM, Charles Jolley wrote: The function expression name is fairly irrelevant, so you could have a standard style guideline foo : function callee() { callee.base.apply ... } --Oliver _______________________________________________ es-discuss mailing list es-discuss@... https://mail.mozilla.org/listinfo/es-discuss |
|
|
Re: arguments.callee in HarmonyOn 2009-09-24, at 17:56, Charles Jolley wrote:
> 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. OpenLaszlo have a similar scheme (http://bit.ly/1E6xig), but have a pre-processor that lets the developer write in something closer to 'real' classes (based on ActionScript 3 and what was proposed for es4, before we were so rudely interrupted). Because of the pre-processor we could just re-write our uses of arguments.callee to use named function expressions -- for platforms that implement the named function expressions correctly. My biggest concern therefore is not that arguments.callee is going away, but that named function expressions have been mis-implemented so many times before (e.g., early versions of webkit and JScript to this day: http://bit.ly/19QxUO). _______________________________________________ es-discuss mailing list es-discuss@... https://mail.mozilla.org/listinfo/es-discuss |
|
|
Re: arguments.callee in Harmony
-- I'm curious, why not just give anonymous functions a default name like "callee". Or perhaps have "callee" defined in a function scope to represent the function? That seems to be exactly the same as the above; it just makes it easier for developers. Is there a perf issue here? -Charles _______________________________________________ es-discuss mailing list es-discuss@... https://mail.mozilla.org/listinfo/es-discuss |
|
|
Re: arguments.callee in HarmonyOn Sep 24, 2009, at 4:06 PM, Charles Jolley wrote:
> I'm curious, why not just give anonymous functions a default name > like "callee". Or perhaps have "callee" defined in a function scope > to represent the function? That seems to be exactly the same as the > above; it just makes it easier for developers. Is there a perf > issue here? No, there's simply a backward compatibility problem. Anonymous functions do not inject any such name on the scope chain (in any object, new or expected, on the scope chain). Changing the language to inject callee (even in an ES5 declarative envirnment frame) is not backward compatible and probably will break some content out there that uses callee in an outer scope to mean something else. /be _______________________________________________ es-discuss mailing list es-discuss@... https://mail.mozilla.org/listinfo/es-discuss |
|
|
Re: arguments.callee in HarmonyWhat I'd like to know is what the rationale for removing arguments.callee from strict mode is. Is it a performance problem? If so, have implementors tried other solutions at compile-time before agitating for the removal of a language feature?
The argument that this is simply a strict mode change falls flat when we're also told that Harmony will be built on ES5 strict mode. As far as I'm concerned, anything missing in strict mode is effectively being removed from the language.
-- YehudaÂ
On Thu, Sep 24, 2009 at 4:26 PM, Brendan Eich <brendan@...> wrote:
-- Yehuda Katz Developer | Engine Yard (ph) 718.877.1325 _______________________________________________ es-discuss mailing list es-discuss@... https://mail.mozilla.org/listinfo/es-discuss |
|
|
Re: arguments.callee in HarmonyOn Fri, Sep 25, 2009 at 9:26 AM, Brendan Eich <brendan@...> wrote:
> On Sep 24, 2009, at 4:06 PM, Charles Jolley wrote: > >> I'm curious, why not just give anonymous functions a default name like >> "callee". Â Or perhaps have "callee" defined in a function scope to represent >> the function? Â That seems to be exactly the same as the above; it just makes >> it easier for developers. Â Is there a perf issue here? > > No, there's simply a backward compatibility problem. Anonymous functions do > not inject any such name on the scope chain (in any object, new or expected, > on the scope chain). Changing the language to inject callee (even in an ES5 > declarative envirnment frame) is not backward compatible and probably will > break some content out there that uses callee in an outer scope to mean > something else. > > /be > _______________________________________________ > es-discuss mailing list > es-discuss@... > https://mail.mozilla.org/listinfo/es-discuss > this discussion reminds me a little bit of the aspect oriented pattern that has been used in javascript on occasion. The idea there is that it's possible to replace a function with a wrapped version of the function that has the original function in the outer scope. So for instance: var myarray = [3,4,5]; myarray.toString = (function () { var ofunc = myarray.toString; return function () { return "Extended toString: "+ofunc.apply(this,arguments); } })() myarray.toString(); //returns "Extended toString: 3,4,5" This pattern can be generalised: function extendFunc (object, methodname, func) { var ofunc = object[methodname]; object[methodname]=function () { return func.apply(object,[ofunc].concat(arguments)); } } you can see that in that version, the new function recieves the old function as its first parameter. Now, my specific implementation has almost certainly got some flaws in it (not a lot of error checking or robustness), I'm sure- and people will argue about the details. It's the basic idea of aspect orientation that I'm trying to get at here. The reason I'm bringing this up though is that this is a simple highly general building block that can be used to build the super abstraction, I believe (among many other useful abstractions). It's also implementable in current ecmascript, and it's something that could become canonized as a native function in a future version of ecmascript- similar to the array extras that were first in the prototype library, but are now in ecmascript 5. There might be even more clever ways to build it so that it doesn't require an extra parameter (using "with" perhaps?) that could be used now, but built in native code and optimised in future editions. Anyway, I just thought I would put that out there for discussion. _______________________________________________ es-discuss mailing list es-discuss@... https://mail.mozilla.org/listinfo/es-discuss |
|
|
Re: arguments.callee in Harmonyx
On Fri, Sep 25, 2009 at 9:31 AM, Yehuda Katz <wycats@...> wrote: > What I'd like to know is what the rationale for removing arguments.callee > from strict mode is. Is it a performance problem? If so, have implementors > tried other solutions at compile-time before agitating for the removal of a > language feature? > The argument that this is simply a strict mode change falls flat when we're > also told that Harmony will be built on ES5 strict mode. As far as I'm > concerned, anything missing in strict mode is effectively being removed from > the language. > -- Yehuda https://mail.mozilla.org/pipermail/es-discuss/2009-March/008970.html _______________________________________________ es-discuss mailing list es-discuss@... https://mail.mozilla.org/listinfo/es-discuss |
|
|
Re: arguments.callee in HarmonyMy general concern about strict mode is that it seems to be the result of a smoke-filled-room compromise. I'd like to see the perspective of JavaScript practitioners consulted about the strict mode definition (especially if it's going to form the basis for ES Harmony).
-- Yehuda On Thu, Sep 24, 2009 at 5:04 PM, Breton Slivka <zen@...> wrote:
-- Yehuda Katz Developer | Engine Yard (ph) 718.877.1325 _______________________________________________ es-discuss mailing list es-discuss@... https://mail.mozilla.org/listinfo/es-discuss |
|
|
Re: arguments.callee in HarmonyOn Fri, Sep 25, 2009 at 10:49 AM, Breton Slivka <zen@...> wrote:
> x > > > On Fri, Sep 25, 2009 at 9:31 AM, Yehuda Katz <wycats@...> wrote: >> What I'd like to know is what the rationale for removing arguments.callee >> from strict mode is. Is it a performance problem? If so, have implementors >> tried other solutions at compile-time before agitating for the removal of a >> language feature? >> The argument that this is simply a strict mode change falls flat when we're >> also told that Harmony will be built on ES5 strict mode. As far as I'm >> concerned, anything missing in strict mode is effectively being removed from >> the language. >> -- Yehuda > > https://mail.mozilla.org/pipermail/es-discuss/2009-March/008970.html > Apologies with the curt message. I seem to have suddenly lost my ability to operate my computer competantly. I meant to say, that the rational has been discussed at length in the past. Here's the link to the mailing list thread about it: https://mail.mozilla.org/pipermail/es-discuss/2009-March/008970.html _______________________________________________ es-discuss mailing list es-discuss@... https://mail.mozilla.org/listinfo/es-discuss |
|
|
Re: arguments.callee in HarmonyThanks for the pointer. It seems like the argument against it is security: if I pass you my arguments object, you now have access to the original function, which violates the POLA.
Isn't the fact (pointed out by Allen in the original thread) that arguments.callee can be deleted a mitigating factor here?Â
Aren't there other fixes that would work as well (such as making arguments.callee only available lexically) without completely removing the feature. On a related topic, would you mind pointing me at the thread where the removal of with() was discussed?
-- Yehuda
On Thu, Sep 24, 2009 at 5:51 PM, Breton Slivka <zen@...> wrote:
-- Yehuda Katz Developer | Engine Yard (ph) 718.877.1325 _______________________________________________ es-discuss mailing list es-discuss@... https://mail.mozilla.org/listinfo/es-discuss |
|
|
Re: arguments.callee in HarmonyThe use of named function expressions is not correctly implemented by at least IE 6-8. The basic use case works fine (e.g.) var foo = function callee() { // do something setTimeout(callee, 10); }; But declared as (function callee() { // do something setTimeout(callee, 10); })(); the name callee leaks to the enclosing scope. Also, the callee function inside the function body is not the same function. foo !== callee in IE. So if you use the function as a namespace, callee.someProperty = "foo" is not exposed on foo.someProperty. Luke On Sep 24, 2009, at 3:59 PM, Oliver Hunt wrote:
_______________________________________________ es-discuss mailing list es-discuss@... https://mail.mozilla.org/listinfo/es-discuss |
|
|
Re: arguments.callee in HarmonyHi,
we have exactly the same problem in qooxdoo <http://www.qooxdoo.org>. We use arguments.callee.base.call(this, ...); in the same way. Using named functions isn't a solution for us because it would break IE compatibility. In this example ClassB = ClassA.extend({ foo: function foo() { foo.base.apply(this, arguments); // calls super! // other code } }); "foo" would leak into the global namespace due to implementation bugs in JScript <http://yura.thinkweb2.com/named-function-expressions/>. Right now I don't see a good solution for this in strict mode. Best Fabian
|
|
|
Re: arguments.callee in HarmonyOn Sep 25, 2009, at 4:14 AM, Fabian Jakobs wrote:
> "foo" would leak into the global namespace due to implementation > bugs in > JScript <http://yura.thinkweb2.com/named-function-expressions/>. > Right now I > don't see a good solution for this in strict mode. 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. 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@... >> 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@... > https://mail.mozilla.org/listinfo/es-discuss _______________________________________________ es-discuss mailing list es-discuss@... https://mail.mozilla.org/listinfo/es-discuss |
|
|
Re: arguments.callee in Harmony> 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? 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. 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. -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@... >>> 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@... >> https://mail.mozilla.org/listinfo/es-discuss > > _______________________________________________ > es-discuss mailing list > es-discuss@... > https://mail.mozilla.org/listinfo/es-discuss _______________________________________________ es-discuss mailing list es-discuss@... https://mail.mozilla.org/listinfo/es-discuss |
|
|
RE: arguments.callee in HarmonyI thought I had already responded to this, but I guess I missed the "send"...
The Microsoft intent is that when we support ES5 it will conform to the specified FunctionDeclaratiion/FunctionExpression semantics. However, this doesn't mean that ES5 semantics will be unilaterally imposed upon existing code that depends upon JScript 5.x semantics. Allen >-----Original Message----- >From: es-discuss-bounces@... [mailto:es-discuss- >bounces@...] On Behalf Of Brendan Eich >Sent: Friday, September 25, 2009 9:23 AM >To: Fabian Jakobs >Cc: es-discuss@... >Subject: Re: arguments.callee in Harmony > >On Sep 25, 2009, at 4:14 AM, Fabian Jakobs wrote: > >> "foo" would leak into the global namespace due to implementation >> bugs in >> JScript <http://yura.thinkweb2.com/named-function-expressions/>. >> Right now I >> don't see a good solution for this in strict mode. > >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. > >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@... >>> 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@... >> https://mail.mozilla.org/listinfo/es-discuss > >_______________________________________________ >es-discuss mailing list >es-discuss@... >https://mail.mozilla.org/listinfo/es-discuss _______________________________________________ es-discuss mailing list es-discuss@... https://mail.mozilla.org/listinfo/es-discuss |
|
|
Re: arguments.callee in HarmonyOn 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@... >>>> 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@... >>> https://mail.mozilla.org/listinfo/es-discuss >> >> _______________________________________________ >> es-discuss mailing list >> es-discuss@... >> https://mail.mozilla.org/listinfo/es-discuss > _______________________________________________ es-discuss mailing list es-discuss@... https://mail.mozilla.org/listinfo/es-discuss |
|
|
Re: arguments.callee in HarmonyOn Sep 25, 2009, at 11:28 AM, Brendan Eich wrote:
> function compile(...) { > eval("var f = function() {" + compile_optimized_query(); + "}"); (Stray ; there in the + chain, oops.) > 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. I did raise this issue in the course of strict mode's evolution, while corresponding with Jack. I'm sorry I didn't follow up on it, although the results may not have changed. Even if Microsoft fixes bad old lambda bugs in JScript (glad to hear from Allen that it will in some configuration or opt-in setting), old IE versions, and not-opted-in scripts, will see the bugs and need the kind of structure Jack had to use to compile optimized query functions. Again, perhaps extjs has found another way. If not, it may be impossible for the compiler function to be strict. But the ES5 strict mode design may take that hit for some hoped-for greater good. > 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. But we can hear feedback, esp. on this list, about hardship adopting strict mode in early ES5 implementations. Mozilla's will be done shortly, and it sounds like WebKit's is coming along quickly too. Feedback based on two interoperable implementations in developers' hands before the ES5 spec is stamped done would have been best. But real-code/real-world feedback better late than never is welcome. /be _______________________________________________ es-discuss mailing list es-discuss@... https://mail.mozilla.org/listinfo/es-discuss |
| < Prev | 1 - 2 | Next > |
| Free embeddable forum powered by Nabble | Forum Help |