Ah, thanks! I had missed "forwardCall" completely. Got to say that I
like the MochiKit API:s more and more. Most of the basic stuff missing
in JavaScript is there. Documented and with a nice API. Great!

I'll prepare a proper patch later on, but below you'll find the functions
I'm using to prepare stack traces for logging. Basically, since most
function objects are anonymous, it is necessary to propagate the
names from the prototype objects into the function objects
themselves. Has it's drawbacks and problems, for sure, but works
quite well for me. :-)

To integrate with MochiKit, some bookkeeping for signalling and
bind stuff might be desired. Anyway, that is what I'm currently
doing (outside of MochiKit right now, though).

/**
 * Registers a class. This assigns class name and method name
 * identifiers to each function in the class and class prototype.
 *
 * @param cls                the class constructor function
 * @param className          the name of the class
 */
FunctionUtil.registerClass = function(cls, className) {
    if (className == null) {
        className = (cls.name != null) ? cls.name : cls.className;
    }
    if (className == null) {
        className = ObjectUtil.indexOf(window, cls);
    }
    cls.className = className;
    for (var name in cls) {
        var obj = cls[name];
        if (typeof(obj) == "function") {
            obj.className = className;
            obj.methodName = name;
        }
    }
    for (var name in cls.prototype) {
        var obj = cls.prototype[name];
        if (typeof(obj) == "function") {
            obj.className = className;
            obj.methodName = name;
        }
    }
}

/**
 * Returns the stack trace for the currently executing function. The
 * stack trace is an array of function or method names ordered with
 * the top of the stack at the lowest index. The maximum function
 * call depth searched by this method is 20.
 *
 * @return the stack trace array
 */
FunctionUtil.getStackTrace = function() {
    var func = this.getStackTrace.caller;
    var res = [];
    var oldFuncs = [];
    var name;

    while (func != null) {
        if (func.stackTrace instanceof Array) {
            return res.concat(func.stackTrace);
        } else if (func.stackTrace != false) {
            res.push(this.getName(func));
        }
        if (ArrayUtil.indexOf(oldFuncs, func) >= 0) {
            res.push("...recursion...");
            return res;
        }
        oldFuncs.push(func);
        if (oldFuncs.length >= 20) {
            res.push("...");
            return res;
        }
        func = func.caller;
    }
    return res;
}


/**
 * Injects a stack trace for the currently executing function. This
 * method is useful for creating a fake stack trace in callback
 * functions and similar. A null value can be used to clear any
 * previously created stack trace.
 *
 * @param stackTrace         the stack trace array,
 *                           false to skip function, or
 *                           null to reset to default
 */
FunctionUtil.setStackTrace = function(stackTrace) {
    var func = this.setStackTrace.caller;

    if (func != null) {
        func.stackTrace = stackTrace;
    }
}

/**
 * Returns the name of a function. If the function is registered in
 * a class, the full method name (with class prefix) will be
 * returned.
 *
 * @param func               the function object
 *
 * @return the function name, or
 *         null if not available
 */
FunctionUtil.getName = function(func) {
    if (func != null && func.name != null && func.name != "") {
        return func.name;
    } else if (func != null && func.className != null) {
        return func.className + "." + func.methodName;
    } else if (func != null && func.methodName != null) {
        return func.methodName;
    } else {
        return null;
    }
}

/Per

On Nov 21, 2007 12:19 AM, Bob Ippolito <[EMAIL PROTECTED]> wrote:
> On 11/18/07, Per Cederberg <[EMAIL PROTECTED]> wrote:
> >
> > #1. Is there a way to do "late" binding with MochiKit.Base.bind? I.e.
> > allowing function names to be resolved when the returned function is
> > called, rather than when bind() is called. See example below:
> >
> > obj = {
> >     a: function() { return "a"; },
> > }
> > var test = MochiKit.Base.bind("a", obj);
> > test() ==> "a"
> > obj.a = function() { return "b"; }
> > test() ==> "b" (currently MochiKit returns "a" here)
> >
> > It is easy enough to modify the MochiKit.Base.bind(), but it would of
> > course break semantic backwards compability a bit.
>
> I gave it a shot and it definitely breaks backwards compatibility in a
> way that the tests fail. I won't be doing this, but you can do this
> with forwardCall.
>
> >>> obj = {a: function () { return "a"; }}
> [object Object]
> >>> test = bind(forwardCall("a"), obj)
> function () {...}
> >>> test()
> "a"
> >>> obj.a = function () { return "b"; }
> function () {...}
> >>> test()
> "b"
>
> > #3. With a few quick hacks to set class and function names on object
> > functions I've been able to implement JavaScript stack traces. And
> > combined with logging, this has proven extremely powerful for
> > debugging issues in the application.
> >
> > Is there something for stacktraces already in MochiKit? Would it be
> > welcomed as a patch?
>
> I've done things like this before, but not in MochiKit. I started
> caring a lot less about debugging tools since Firebug came out :) A
> patch would be good.
>
> -bob
>

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"MochiKit" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/mochikit?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to