[mochikit] Re: Looser binding with bind() and more generic signalling

2007-11-21 Thread Per Cederberg

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 clsthe 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 

[mochikit] Re: Looser binding with bind() and more generic signalling

2007-11-20 Thread Bob Ippolito

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 mochikit@googlegroups.com
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
-~--~~~~--~~--~--~---