Do everything with javascript

Dumping Firefox XUL object

I am not sure is it correct to call it XUL object, what I mean to do is transversing javascript object. It sounds silly as we got firebug but it makes sense when working on firefox addon where the script debugger in firebug doesn’t work for javascript running in chrome.

There is a XUL reference in MDC(https://developer.mozilla.org/en/XUL_Reference). It listing out objects and its associated attributes, properties, and methods, but seems not all the reference are update and complete. Sometimes I don’t even know what kind of xul object I am dealing with, I need to have something like var_dump or print_r in PHP. And I have written my own object dumping function.

My dump function:

myUtil = {
dump:function(o,depth,name,filter,filterMode) {
    var doc = gBrowser.contentDocument,
        el = doc.getElementById("fduDump"),
        str = "" || name + "\n",
        depthLimit = depth || 1,
        filterDefaultMode = filterMode || 1;
    // filterMode is either 1 or -1.
    // 1 => Like the iptable Allow all, it dig into all object exclude object name in the filter object
    // -1 => Like the iptable Deny all, it will not dig into any object unless object name is inside the filter

    if ( !el ) {
        el = doc.createElement("pre");
        el.id = "fduDump";
        doc.body.appendChild(el);
    }

    var transverse = function(o,thisLv,name,filter) {
        var indent = "", i, tmp, filterMode, dig, f;
        if ( filter && filter.__mode ) {
            filterMode = filter.__mode;
        } else {
            filterMode = filterDefaultMode;
        }
        for ( i = 0 ; i < thisLv ; i++ ) {
            indent += "    ";
        }

        if ( name ) {
            str += "\n" + indent + "=== lv "+thisLv+", Start "+name+" ===\n";
        }

        if ( o && thisLv < depthLimit ) {
            for ( k in o ) {
                try{
                    tmp = o[k] + "";
                    tmp = tmp.split("\n");
                    tmp = tmp.join("\n"+indent);
                    str += indent + k + " : " + tmp + "\n";
                    if (typeof(o[k]) === "object" && o[k] && thisLv + 1 < depthLimit ) {
                        if ( filter && typeof filter[k] !== "undefined") {
                            dig = (filterMode === -1);
                        } else {
                            dig = (filterMode === 1);
                        }
                        if ( dig ) {
                            if ( filter && filter[k] ) {
                                f = filter;
                            } else {
                                f = null;
                            }
                            transverse(o[k], thisLv + 1, k, f);
                        }
                    }
                } catch (e) {
                }
            }
        }

        if ( name ) {
            str += indent + "=== lv "+thisLv+", End "+name+" ===\n\n";
        }
    }
    transverse(o,0,"",filter);
    el.innerHTML = str;
}
}

Calling the dump function:

// e.g. here I amd dumping the event object form a "TabSelect" event
// 1st param is object to be dumped
// 2nd param is the depth (optional, default = 1)
// 3rd is just a string to be shown in the first line of the dump (optional default = "")
// 4th is filter (optional)
// 5th is default filter mode (optional default = 1, dump all properties exclude specified in filter object)
myUtil.dump(evt,2,"tabEvent",{"__mode":-1,"target":null});

// if you just want to dump an object itself, you can simply: myUtil.dump(evt);

Sample output of the dump

tabEvent
originalTarget : [object XULElement]
preventCapture : function preventCapture() {
    [native code]
}
target : [object XULElement]

    === lv 1, Start target ===
    _tPos : 0
    linkedBrowser : [object XULElement]
    ...
    selected : true
    _selected : undefined
    linkedPanel : panel1259045062233
    ...
    tagName : xul:tab
    ...
    nodeName : xul:tab
    ...
    className : tabbrowser-tab
    ...
    === lv 1, End target ===

cancelable : false
currentTarget : [object XULElement]
timeStamp : 1172581376
bubbles : true
type : TabSelect
eventPhase : 3
preventDefault : function preventDefault() {
    [native code]
}
initEvent : function initEvent() {
    [native code]
}
stopPropagation : function stopPropagation() {
    [native code]
}
CAPTURING_PHASE : 1
AT_TARGET : 2
BUBBLING_PHASE : 3
explicitOriginalTarget : [object XULElement]
preventBubble : function preventBubble() {
    [native code]
}
...

By dumping the event object and the target in the event object, there are something useful can be found. In the TabSelect Event, there is target, originalTarget, currentTarget, explicitOriginalTarget!?
And in the target object, it has a tagName and nodeName equals to “xul:tab”, so now I can be sure it is a “tab” object instead of tabPanel, tabbox, or tabbrowser….Also it has a linkedBrowser object which is the browser object contained in the tab. This is not documented in the xul reference…maybe they don’t want us to use it? Have fun dumping.

Other resources on message logging and debugging in writing Firefox addon:

https://developer.mozilla.org/en/JavaScript_Console

http://www.borngeek.com/firefox/toolbar-tutorial/chapter-8/

Leave a Reply

You can use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>