Flash! (Ah-ah!) ActionScript 3 varDump function

So, recently I’ve been doing a fair amount of work with ActionScript 3 in Flash, and its complete lack of a useful variable dumping function has really started to get on my nerves.  So, after a lot of toing-and-froing, I eventually found some examples which partially did what I wanted them to do.

Most of the problem was that they didn’t give enough information, or they only dealt with a small sub-set of the code, so I built this function to give a decent dump of pretty much anything you can throw at it.

So, here’s my varDump function:

package grump.utils {
    import flash.utils.getQualifiedClassName;
    import flash.utils.describeType;

    public function varDump(_obj, includeAccessors:Boolean = false, depth:Number = 0, key:String = ''):void {
        var indent:String = '';
        var i:Number = 0;
        for (i = 0; i < depth; i++) {
            indent += '    ';
        }
        if (_obj == null) {
            if (key) {
                trace(indent + key + ":null");
            } else {
                trace(indent + "null");
            }
        } else if (_obj == undefined) {
            if (key) {
                trace(indent + key + ":undefined");
            } else {
                trace(indent + "undefined");
            }
        } else {
            switch (typeof(_obj)){
                case "object":
                    if (key) {
                        trace(indent + key + ":" + getQualifiedClassName(_obj).replace('::', '.') + " {");
                    } else {
                        trace(indent + getQualifiedClassName(_obj).replace('::', '.') + " {");
                    }
                    var varList:XMLList;
                    if (includeAccessors) {
                        varList = describeType(_obj)..variable.@name + describeType(_obj)..accessor.@name;
                    } else {
                        varList = describeType(_obj)..variable.@name;
                    }
                    var varType:String = '';
                    for (i = 0; i < varList.length(); i++) {
                        try {
                            varDump(_obj[varList[i]], includeAccessors, depth + 1, varList[i]);
                        } catch (e:Error) {
                            if (e.errorID == 1077) {
                                trace(indent + '    ' + varList[i] + ':Unknown = write-only parameter');
                            } else {
                                trace(indent + '    ' + varList[i] + ':' + varType.charAt(0).toUpperCase() + varType.substr(1, varType.length) + ' = unknown - ' + e.message);
                            }
                        }
                    };
                    for (var item:Object in _obj){
                        varDump(_obj[item], includeAccessors, depth + 1, String(item));
                        try {
                            varDump(_obj[item], includeAccessors, depth + 1, String(item));
                        } catch (e:Error) {
                            if (e.errorID == 1077) {
                                trace(indent + '    ' + item + ':Unknown = write-only parameter');
                            } else {
                                trace(indent + '    ' + item + ':' + varType.charAt(0).toUpperCase() + varType.substr(1, varType.length) + ' = unknown - ' + e.message);
                            }
                        }
                    };
                    trace(indent + "}");
                    break;

                case "xml":
                    if (key) {
                        trace(indent + key + ":XML {");
                    } else {
                        trace(indent + "XML {");
                    }
                    trace(indent + "    " + _obj);
                    trace(indent + "}");
                    break;

                case "string":
                    if (key) {
                        trace(indent + key + ":String(" + _obj.length + ') = "' + _obj + '"');
                    } else {
                        trace(indent + "String(" + _obj.length + ') = "' + _obj + '"');
                    }
                    break;

                default:
                    var type:String = typeof(_obj);
                    if (key) {
                        trace(indent + key + ":" + type.charAt(0).toUpperCase() + type.substr(1, type.length) + " = " + _obj);
                    } else {
                        trace(indent + type.charAt(0).toUpperCase() + type.substr(1, type.length) + " = " + _obj);
                    }
                    break;
            }
        }
    }
}

Yes, it’s ugly, full of redundant code, and there’s some arse-about-face logic in it, but it works, and it gives you enough information to properly debug stuff.

Stick that code in grump/utils/varDump.as in the same folder as your Flash source and add import grump.utils.varDump to the top of your package to load it.

Note: Using includeAccessors on some objects will result in an error when it tries to read a write-only parameter. Why Adobe decided to have write-only parameters, I have no idea, but they did, and I haven’t yet figured out how to ignore them, so if anyone knows how to do so, please let me know and I’ll update this code to reflect it.

Note: Still don’t get why they decided to add write-only parameters, but the bug mentioned above is now fixed. :) Output dumped is very useful indeed.

2 Responses to “Flash! (Ah-ah!) ActionScript 3 varDump function”

  1. frodenius - July 16th, 2009

    make a try catch block and try to read the content.
    catch the exception, display “write only” instead, proceed.

  2. Grump - July 17th, 2009

    Aha! I should really have thought of that. Post updated. Thanks. :)

Leave a Reply