Comment #8 on issue 278 by [email protected]: Can't change a function's "name" property
http://code.google.com/p/v8/issues/detail?id=278

Many modern javascript patterns would benefit from the name property being "WriteOnce" or even being treated as a regular property.

Here's an example where it'd be helpful to be able to set the name property (assuming the name is what drives what shows up in the stack traces). This encapsulate function takes a function and puts it in a new function. These new functions will always have the same name... Not cool.


//START
function encapsulate(func) {
    return function encapsulatedFunction(){
        func.apply(this,arguments);
    }
}

function yayEmit() {
    EMITTER.emit("YAY!");
}

encapsulate(yayEmit)();
//END


Stack trace:
ReferenceError: EMITTER is not defined
    at yayEmit (eval at <anonymous> (unknown source))
    at encapsulatedFunction (eval at <anonymous> (unknown source))

I'd like not to have "encapsulatedFunction" or something similar show up in my stack traces. That's hardly helpful, and would be downright confusing if there were multiple levels of encapsulation. It'd be better if I could do this:


//START
function encapsulate(func) {
    var encapsulatedFunction = function(){
        func.apply(this,arguments);
    };
    encapsulatedFunction.name = "encapsulated_" + func.name;
    return encapsulatedFunction;
}
//END


That way the stack trace would read something like this:
ReferenceError: EMITTER is not defined
    at yayEmit (eval at <anonymous> (unknown source))
    at encapsulated_yayEmit (eval at <anonymous> (unknown source))


Let's take a look at another example where a writable name would be useful! This little functional inheritance function.


//START
function extender(superConstructor, thisConstructor) {
    return function Extension(){
        superConstructor.apply(this,arguments);
        thisConstructor.apply(this,arguments);
    };
}

function Animal () {
    this.alive = "true";
}

function Dog () {
    this.type = "dog";
}

var myDog = new (extender(Animal,Dog))();

myDog; // ► Extension
myDog.constructor.name; // "Extension"
//END


myDog is now considered an instance of Extension. That's not cool... I'd rather see "Dog" or "Dog_extends_Animal".
This should totally work:


//START
function extender(superConstructor, thisConstructor, name) {
    var extension = function(){
        superConstructor.apply(this,arguments);
        thisConstructor.apply(this,arguments);
    };
    extension.name = name || thisConstructor.name;
// or for something a bit more descriptive: extension.name = thisConstructor.name + "_extends_" + superConstructor.name;
    return extension;
}
//END


Perhaps a nice middle-ground solution would be what Isaac Schlueter suggested ("name" as a WriteOnce property). I'd imagine only anonymous functions would be eligible for "renaming", and non-anonymous function's initial naming would count as their single-allowed [Function].name write.

I'd like to read the thoughts of the devs on this one if at all possible.
It's 2012 now... I should be able to accomplish this without eval.

- Mike Brew

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to