ANN: JavaScript Debug Library

J

Jim Davis

I've a JavaScript debug library which I've finally documented and posted. I
find it very useful (especailly to check out returns from AJAX-type
services) and I hope you might as well.

A zip of the library, documentation and examples are here (at this very long
URL):

http://www.depressedpress.com/depre...ment/JavaScript/Extensions/DP_DeBug/Index.cfm

The library adds two methods to the Object prototype: dpDump() which
presents an HTML display of any object and dpGetType() which provides a more
refined type mechanism than the typeof operator.

dpDump is the more useful of the two by far. It provides:

+) HTML representation of any complex object including nesting and data
type.
+) It supports circular/recursive references in objects (which I think is
damn spiffy).
+) It provides a dedicated debug window which can log multiple
dpDump() calls over time.
+) It returns a reference to the object enabling insertion of dpDump calls
into method calls. For example this is legal:
MyArray.dpDump().reverse().dpDump() and will result in a "before and after"
view of the array.

It has a very small footprint - only those two methods are added to the
Object Prototype - no extra properties, sub functions or anything. All of
the code (style sheets, html, etc) is embedded in the library - there are no
external calls (although there is a link to my site on the debug window).

I've tested the library in IE 6.x and FireFox 1.x - but I'm sure there are
still some bugs floating around.

I'd love to hear any comment or suggestions you may have about the Library
itself, the documentation or the examples. I'd especially love reports of
any bugs you might come across.

Thanks,

Jim Davis
 
J

Jim Davis

Matt Kruse said:
Your implementation is good, and the presentation is nice.

I have a similar, more perl-like implementation at:
http://www.javascripttoolbox.com/datadumper/
if anyone wants to check out an alternative.

Cool! Change a few characters and you've got a JSON parser! ;^)

I was nearly positive that, although I searched for this and couldn't find
one, as soon as I spent the time to build one and post it I would be deluged
with perfectly useful, existing options. Isn't that the way of things?

Jim Davis
 
M

Matt Kruse

Jim said:
I was nearly positive that, although I searched for this and couldn't
find one, as soon as I spent the time to build one and post it I
would be deluged with perfectly useful, existing options. Isn't that
the way of things?

It is!

But yours handles recursive references better, and is much prettier :)
 
M

Martin Bialasinski

Jim Davis said:
The library adds two methods to the Object prototype: dpDump() which
presents an HTML display of any object

In Opera 8.02, I get on all of your examples:

Error:
name: TypeError
message: Statement on line 106:
Could not convert undefined or null
to object

Line 106 is the document.write statement.

Also, it is not a good idea to add to the Object prototype. Many
scripts expect a new object to not have any enumerable properties.

The prototype.js author changed his code from
Object.prototype.extend() to Object.extend(), so you now use
Object.extend(myObj, foobar) instead of myObj.extend(foobar)

Maybe not that pretty, but it won't break existing scripts and won't
get you the WaSP DOM Scripting Task Force's wrath.

Bye,
Martin
 
J

Jim Davis

Martin Bialasinski said:
In Opera 8.02, I get on all of your examples:

Error:
name: TypeError
message: Statement on line 106:
Could not convert undefined or null
to object

Line 106 is the document.write statement.

I'll take a look at some point (unless you have a suggestion for fixing it)
but to be blunt Opera's not a priority right now. In fact DP_Debug isn't a
priority right now either...
Also, it is not a good idea to add to the Object prototype. Many
scripts expect a new object to not have any enumerable properties.

I don't agree, at least for functions, but that's purely my opinion.

The argument here is that it "breaks" "for in" processing... well, it only
breaks it if you're making assumptions. I feel VERY strongly that all
JavaScripts should respect that functions are data and may be inheirited and
guard themselves accordingly.

In my opinion (nothing more!) no loop over a hash table should lack (at the
very least!) a typeof "function" check - it's just ignoring a fundamental
part of the language.

I will also say that any addition to any built-in prototype should be
considered very carefully. Gravely even. Like most things if you can't
intelligently defend the decision then you probably shouldn't have done it.
Here are my informal rules:

+) Does it need to be a prototype? What benefits do you gain over
making it a function or distinct object type? What do you lose by not
making a prototype?
+) Which prototype is most appropriate and least invasive? Don't add
String methods to the Object prototype "just in case you need them someplace
else".
+) Never add properties to built-in prototypes. There's no easy, built
in way to prevent enumeration of them as there is with functions. (This is
one reason I dislike the "official" JSON parser for example).

For example my original library also included a set of serialization
functions (JSON, WDDX, etc). However they just didn't pass my muster as a
requirement of "Object". Instead they became a separate function library.

In this case:

+) The functions only work with JavaScript Objects (objects which extend
Object). For example pass the same function a built-in object (like
"document" or "window") and the script hangs (not completely sure why
yet...). I would have also lost the ability to insert the call into method
chains (something I find really useful).
+) The functions are applicable to every child of the Object and to the
Object itself (otherwise I would have extended each prototype individually).
+) I've purposfully added no properties (although, dammit, there were a
few places where that would have come in VERY handy).

All that said however I could easily convert the functions to static
methods. As noted passing in certain things will still break the script
however (although I'm working on that) and it would be less useful in some
circumstances.

Still - I may... I'm nothing if not a whore for public approval.
The prototype.js author changed his code from
Object.prototype.extend() to Object.extend(), so you now use
Object.extend(myObj, foobar) instead of myObj.extend(foobar)

I'm not sure... in the version I just downloaded I still see:

Object.prototype.extend = function(object) {
return Object.extend.apply(this, [this, object]);
}

It look like he's added the capability of "Object.extend()" as well - but it
doesn't look like he's removed "MyObject.extend()"
Maybe not that pretty, but it won't break existing scripts and won't
get you the WaSP DOM Scripting Task Force's wrath.

And I should fear this why? I've never had wrath before... ;^)

Jim Davis
 
J

Jim Davis

I think I've come with a reasonable compromise. Let me know what you think:

I've repurposed the two debug methods (dpDump and dpGetType) as static
methods of Object. They can now always be called as:

Object.dpDebug(object) and Object.dpGetType(object).

HOWEVER - I've also added a new static method:

Object.dpDebugInstances(boolean)

If passed "true" this function places dpDump and dpGetType into the
Object.prototype. If passed false it removes them.

I'm actually quite pleased with this.

If you, like me, want the functions available everywhere you add
Object.dpDebugInstances(true); to the top of the page and you're set.

If you need to eliminate them to deal with (I still say poorly written) code
you can do this:

Object.dpDebugInstances(false);

.... code what craps the bed if you extend object prototypes...

Object.dpDebugInstances(true);

If you don't care about having them available for every object instance you
can just ignore it and always use the static method.

So... what do you think? I'm I still gonna wrathed all over? ;^)

Jim Davis
 
M

Martin Bialasinski

Jim Davis said:
I'll take a look at some point (unless you have a suggestion for fixing it)
but to be blunt Opera's not a priority right now. In fact DP_Debug isn't a
priority right now either...

It looks like (from some alert()s) Opera does not create

window.document for a frame created with <frame src=''>. If this is
the case, I cannot judge on how sensible this is. One can argue there
is no document.
I don't agree, at least for functions, but that's purely my opinion.

The argument here is that it "breaks" "for in" processing... well, it only
breaks it if you're making assumptions. I feel VERY strongly that all
JavaScripts should respect that functions are data and may be inheirited and
guard themselves accordingly.
In my opinion (nothing more!) no loop over a hash table should lack (at the
very least!) a typeof "function" check - it's just ignoring a fundamental
part of the language.

This is not enough, as assigning functions to members of objects is
also a fundamental part of the language, you would have to check the
prototype on any access of a object member. What really is missing
from javascript is the ability to declare members non-enumerable.

Whatever the POV, Objects as empty shells is the predominant usage
pattern. Ignoring this, is like making ones stuff usable for only a
tiny minority. The script has to be immensely useful to make others
rewrite their existing code-base.
For example pass the same function a built-in object (like
"document" or "window") and the script hangs (not completely sure why
yet...).

Venkman could be useful to debug this. It is probably the recursion
check not catching something.
Still - I may... I'm nothing if not a whore for public approval.

:) You have done it, good thing.

I'm not sure... in the version I just downloaded I still see:

I thing he did not release the new version yet. The beta has it all
rewritten.
And I should fear this why? I've never had wrath before... ;^)

Well, look up its members, I wouldn't like my stuff to be labeled as
"on how not to do it" by them :) But hey, quick, undo the changes and
let them issue a un-honourable mention. Once you have the eye-balls,
quickly change back ;-)


Bye,
Martin

PS: Your documentation says <script language="javascript1.3"
src="DP_Debug.js"></script>. You might also have noticed the recent
"language vs. type" thread.
 
J

Jim Davis

Martin Bialasinski said:
It looks like (from some alert()s) Opera does not create

window.document for a frame created with <frame src=''>. If this is
the case, I cannot judge on how sensible this is. One can argue there
is no document.

Well - in honor of Opera being free today I might try to debug it... but
it'still not a priority.

The whole windowing aspect of the code was a HUGE pain in the ass (mostly
due to XPSP2)... I'm truly loath to revisit it. ;^)
This is not enough, as assigning functions to members of objects is
also a fundamental part of the language, you would have to check the
prototype on any access of a object member. What really is missing
from javascript is the ability to declare members non-enumerable.

Whatever the POV, Objects as empty shells is the predominant usage
pattern. Ignoring this, is like making ones stuff usable for only a
tiny minority. The script has to be immensely useful to make others
rewrite their existing code-base.

I've addressed this in the latest release of the code with a compromise.

The two debug functions are added by default as static methods of Object
(non-enumerable). However a third function allows you to add the functions
to Object.prototype (and remove them again) if that's the way you want to
work.

I think it's a very workable compromise and am quite (perhaps inordinately)
pleased with the idea, what do you think?
Venkman could be useful to debug this. It is probably the recursion
check not catching something.

I've looked into this.

Actually it looks like it's just plain too much. The code WOULD work fine
with, say, "document" - but once you recurse through you've got several
thousand distinct properties (it recurses through each style property for
example) - the script engine just can't deal with it and you, eventually,
get a stack overflow.

However you can do smaller segments well-enough. For example (if there's a
"body" tag) this works fine:

Object.dpDump(document.getElementsByTagName("body")[0].currentStyle);

But trying just:

Object.dpDump(document);

Will bring the script engine to it's knees - although it happily dumps
non-recursive view of "document" quickly.

In the next release I'll be adding an optional "recurse" parameter so that
you can get some information about these monsters. I may even play with
"recurselevel" and see if, for example, I could recurse, say, three levels
down "document" without blowing up the machine. ;^)
Well, look up its members, I wouldn't like my stuff to be labeled as
"on how not to do it" by them :) But hey, quick, undo the changes and
let them issue a un-honourable mention. Once you have the eye-balls,
quickly change back ;-)

I'm completely willing to admit that I was wrong and change things... but
I've never approved of the kind of public shame some of these groups seem to
enjoy. Ask people to do something, if they don't, fine - but
blog-based-blackmail is just plain nasty.

I can't see anything on the groups site that bothers me (I don't see any
reference to "un-honourable mentions" or "how not to do it" notes). In
general, from what I've seen of them I like them: they seem to follow the
general rule of teaching: you denounce behavior (not specific authors) and
celebrate individuals.

Unless I'm missing something I just don't see the "wrath" (or the potential
for wrath) any place. If I did the group would immediately lose my respect.

I guess all I'm saying is that the original post made them sound like...
well... mean-spirited, self-appointed, self-important tzars. You know,
assholes. ;^) I'm not seeing that from the materials I can find.
PS: Your documentation says <script language="javascript1.3"
src="DP_Debug.js"></script>. You might also have noticed the recent
"language vs. type" thread.

Yeah... old habits. ;^) Another thing to address when I get the chance to
update it again.

Jim Davis
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,236
Members
46,822
Latest member
israfaceZa

Latest Threads

Top