name property for built-in functions??

Garrett Smith dhtmlkitchen at gmail.com
Tue Mar 10 17:29:43 PDT 2009


On Sun, Mar 8, 2009 at 12:10 PM, Brendan Eich <brendan at mozilla.com> wrote:
> On Mar 8, 2009, at 10:28 AM, Allen Wirfs-Brock wrote:
>
>> I have another concern about the potential interactions between the
>> proposed name property and toString.  Apparently, there is a known use case
>> of eval'ing the result of toString'ing a function in order to create a new
>> function. If we assign synthetic names such as "get_foo" or "set_foo" to
>> syntactically defined getter/setter functions or allow a user to associate a
>> name with an anonymous function which then appears in the toString
>> representation will mean that eval will parse the toString result as a
>> FunctionDeclaration rather than a FunctionExpression.
>
> But eval requires its first argument parse as a Program, and Programs cannot
> consist entirely of, or begin with, an anonymous function expression.
>
> IOW, if someone is editing function source via toString/replace/eval, they
> are not doing it portably per ES3 if the function originated as an anonymous
> function expression.
>
> In the case of an object literal, e.g.
>
> js> var o = { get foo() {return 42}, set foo(x) {print(arguments.callee)} };
> js> uneval(o)
> ({get foo () {return 42;}, set foo (x) {print(arguments.callee);}})
> js> o.foo
> 42
> js> o.foo = 43
> function (x) {
>    print(arguments.callee);
> }
> 43
>
> there is no standard "uneval" (SpiderMonkey has one) by which you could hope
> to recover the getter and setter.
>
> You could write such an uneval using 3.1's reflective meta-programming API.
> Say you did: then there would be no way to give a property name *and* a
> (different, assigned post-creation per the recent discussion) intrinsic name
> to an initially-anonymous getter or setter function. SpiderMonkey again:
>
> js> var o = { get foo bar() {return 42}, set foo bar(x)
> {print(arguments.callee)} };
> js> uneval(o)
> ({get foo bar() {return 42;}, set foo bar(x) {print(arguments.callee);}})
> js> o.foo
> 42
> js> o.foo = 43
> function bar(x) {
>    print(arguments.callee);
> }
> 43
>
> Now you are quite right that the print(arguments.callee) in the setter for
> property id foo (but with intrinsic name bar) has output a string that is a
> function definition, if parsed as a whole program. But in the context of o
> -- as the result of uneval(o) -- there is no problem, provided you accept
> the (unusual but consistent) SpiderMonkey extension which allows two names
> after the get or set.
>
> Function context always matters, since anonymous functions are illegal at
> top level of a program or function body, and named function expressions
> moved to top level become function definitions.
>
>
>> For non-strict evals, that means that the synthetic name will get added to
>> the Declaration Environment of the eval. Note that for indirect evals, the
>> Declaration Environment is now the Global Environment but even for nested
>> eval this possibility seems like a hazard that that most uses are not
>> dealing with.
>
> True, but again it seems your hypothesis starts with an anonymous function
> being decorated with a name property, but eval of toString of an anonymous
> function (without the name decoration, or run in an ES3 implementation)
> produces an anonymous function which standard eval will reject.
>
>
>> Of course, this issue already exists in ES3 for syntactically named
>> functions and functions that are internally assigned the name "anonymous" so
>> maybe these additions aren't actually making things much worse.
>
> The "anonymous" botch is peculiar to the Function constructor. I like
> Maciej's Function.create proposal, and it helps us avoid making more bad law
> on the old "anonymous" hard case.
>


I (finally) realized it would be useful to allow setting the name dynamically.

In a good number of cases, a closure is used where
Function.prototype.bind() would be used. In this case, a
generically-named or anonymous function is created and returned. It is
not possible to parametrize the function name.

EventPublisher.fireEvent = function(publisher) {

  return function [publisher.eventName+"Handler"](ev) {
    // code here.
  };
};

The square bracket is just pseudo. The syntax is incompatible.

Maciej' Function.create proposal:-

Function.create("[Foo bar]", "param1", "param2", "code(); goes(); here();");

- uses strings to create a function. Escaping strings in strings is
awkward to read and write. Refactoring a function into strings to
arguments to Function.create would be tedious and error-prone.
Especiall if the soure already contains strings in strings (html = "<p
id='p'>p<\/p>". Using with strings to build functions cumbersome.

Eval uses the calling context's scope. I do not know what the scope
would be for a function created with Function.create.  To use the
calling context's scope would seem to be not secure. However, it would
seem necessary to wrap a function.

Possible alternative:-
  Function.create( name, fun[, context] );

Garrett


More information about the Es-discuss mailing list