1 /** 2 * The Render Engine 3 * Console 4 * 5 * @fileoverview A debug console abstraction 6 * 7 * @author: Brett Fattori (brettf@renderengine.com) 8 * @author: $Author: bfattori@gmail.com $ 9 * @version: $Revision: 1562 $ 10 * 11 * Copyright (c) 2011 Brett Fattori (brettf@renderengine.com) 12 * 13 * Permission is hereby granted, free of charge, to any person obtaining a copy 14 * of this software and associated documentation files (the "Software"), to deal 15 * in the Software without restriction, including without limitation the rights 16 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 * copies of the Software, and to permit persons to whom the Software is 18 * furnished to do so, subject to the following conditions: 19 * 20 * The above copyright notice and this permission notice shall be included in 21 * all copies or substantial portions of the Software. 22 * 23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 29 * THE SOFTWARE. 30 * 31 */ 32 33 34 /** 35 * @class The base class for all console objects. Each type of supported console outputs 36 * its data differently. This class allows abstraction between the console and the 37 * browser's console object so the {@link Console} can report to it. 38 */ 39 R.debug.ConsoleRef = Base.extend(/** @scope R.debug.ConsoleRef.prototype */{ 40 constructor:function () { 41 }, 42 43 dumpWindow:null, 44 45 /** @private */ 46 combiner:function () { 47 var out = ""; 48 for (var a = 0; a < arguments.length; a++) { 49 out += arguments[a].toString(); 50 } 51 return out; 52 }, 53 54 cleanup:function (sourceObject) { 55 var str, element; 56 if (R.isUndefined(sourceObject)) { 57 return ""; 58 } else if (R.isNull(sourceObject)) { 59 return "null"; 60 } else if (R.isFunction(sourceObject)) { 61 return "function"; 62 } else if (R.isArray(sourceObject)) { // An array 63 str = "["; 64 for (element in sourceObject) { 65 str += (str.length > 1 ? "," : "") + this.cleanup(sourceObject[element]); 66 } 67 return str + "]"; 68 } else if (typeof sourceObject === "object") { 69 str = "{\n"; 70 for (element in sourceObject) { 71 str += element + ": " + this.cleanup(sourceObject[element]) + "\n"; 72 } 73 return str + "}\n"; 74 } else { 75 return sourceObject.toString(); 76 } 77 }, 78 79 /** @private */ 80 fixArgs:function (a) { 81 var x = []; 82 for (var i = 0; i < a.length; i++) { 83 if (!a[i]) { 84 x.push("null"); 85 } else { 86 x.push(this.cleanup(a[i])); 87 } 88 } 89 return x.join(" "); 90 }, 91 92 /** 93 * Write a debug message to the console. The arguments to the method call will be 94 * concatenated into one string message. 95 */ 96 debug:function () { 97 }, 98 99 /** 100 * Write an info message to the console. The arguments to the method call will be 101 * concatenated into one string message. 102 */ 103 info:function () { 104 }, 105 106 /** 107 * Write a warning message to the console. The arguments to the method call will be 108 * concatenated into one string message. 109 */ 110 warn:function () { 111 }, 112 113 /** 114 * Write an error message to the console. The arguments to the method call will be 115 * concatenated into one string message. 116 */ 117 error:function () { 118 }, 119 120 /** 121 * Dump a stack trace to the console. 122 */ 123 trace:function () { 124 }, 125 126 /** 127 * Get the class name of this object 128 * 129 * @return {String} The string "ConsoleRef" 130 */ 131 getClassName:function () { 132 return "R.debug.ConsoleRef"; 133 } 134 135 }); 136 137 /** 138 * @class A class for logging messages to a console reference object. There are 139 * currently four supported console references: 140 * <ul> 141 * <li>Firebug - logs to the Firebug/Firebug Lite error console</li> 142 * <li>OperaConsoleRef - logs to the Opera error console</li> 143 * <li>HTMLConsoleRef - logs to an HTML div element in the body</li> 144 * <li>SafariConsoleRef - logging for Apple's Safari browser</li> 145 * </ul> 146 */ 147 R.debug.Console = Base.extend(/** @scope R.debug.Console.prototype */{ 148 constructor:null, 149 consoleRef:null, 150 enableDebugOutput:null, 151 152 /** 153 * Output only errors to the console. 154 */ 155 DEBUGLEVEL_ERRORS:4, 156 157 /** 158 * Output warnings and errors to the console. 159 */ 160 DEBUGLEVEL_WARNINGS:3, 161 162 /** 163 * Output warnings, errors, and debug messages to the console. 164 */ 165 DEBUGLEVEL_DEBUG:2, 166 167 /** 168 * Output warnings, errors, debug, and low-level info messages to the console. 169 */ 170 DEBUGLEVEL_INFO:1, 171 172 /** 173 * Output all messages to the console. 174 */ 175 DEBUGLEVEL_VERBOSE:0, 176 177 /** 178 * Output nothing to the console. 179 */ 180 DEBUGLEVEL_NONE:-1, 181 182 /** @private */ 183 verbosity:null, 184 185 /** 186 * Starts up the console. 187 */ 188 startup:function () { 189 R.debug.Console.verbosity = R.debug.Console.DEBUGLEVEL_ERRORS; 190 R.debug.Console.enableDebugOutput = false; 191 192 // if (R.engine.Support.checkBooleanParam("debug") && (R.engine.Support.checkBooleanParam("simWii") || R.browser.Wii)) { 193 // R.debug.Console.consoleRef = new R.debug.HTML(); 194 // } 195 // else if (typeof firebug !== "undefined" || (typeof console !== "undefined" && console.firebug)) { 196 // // Firebug or firebug lite 197 // R.debug.Console.consoleRef = new R.debug.Firebug(); 198 // } 199 // else if (typeof console !== "undefined" && R.browser.msie) { 200 // R.debug.Console.consoleRef = new R.debug.MSIE(); 201 // } 202 // else if (R.browser.chrome || R.browser.safari) { 203 // R.debug.Console.consoleRef = new R.debug.Webkit(); 204 // } 205 // else if (R.browser.opera) { 206 // R.debug.Console.consoleRef = new R.debug.Opera(); 207 // } 208 // else { 209 R.debug.Console.consoleRef = new R.debug.ConsoleRef(); // (null console) 210 // } 211 }, 212 213 /** 214 * Set the console reference object to a new type of console which isn't 215 * natively supported. 216 * 217 * @param refObj {ConsoleRef} A descendent of the <tt>ConsoleRef</tt> class. 218 */ 219 setConsoleRef:function (refObj) { 220 if (refObj instanceof R.debug.ConsoleRef) { 221 R.debug.Console.consoleRef = refObj; 222 } 223 }, 224 225 /** 226 * Set the debug output level of the console. The available levels are: 227 * <ul> 228 * <li><tt>Console.DEBUGLEVEL_ERRORS</tt> = 4</li> 229 * <li><tt>Console.DEBUGLEVEL_WARNINGS</tt> = 3</li> 230 * <li><tt>Console.DEBUGLEVEL_DEBUG</tt> = 2</li> 231 * <li><tt>Console.DEBUGLEVEL_INFO</tt> = 1</li> 232 * <li><tt>Console.DEBUGLEVEL_VERBOSE</tt> = 0</li> 233 * <li><tt>Console.DEBUGLEVEL_NONE</tt> = -1</li> 234 * </ul> 235 * Messages of the same (or lower) level as the specified level will be logged. 236 * For instance, if you set the level to <tt>DEBUGLEVEL_DEBUG</tt>, errors and warnings 237 * will also be logged. The engine must also be in debug mode for warnings, 238 * debug, and log messages to be output. 239 * <p/> 240 * Console messages have been decoupled from engine debugging mode so that messages 241 * can be output without the need to enter engine debug mode. To enable engine 242 * debugging, see {@link R.Engine#setDebugMode}. 243 * 244 * @param level {Number} One of the debug levels. Defaults to DEBUGLEVEL_NONE. 245 */ 246 setDebugLevel:function (level) { 247 R.debug.Console.verbosity = level; 248 249 // Automatically enable output, unless no debugging is specified 250 if (level != R.debug.Console.DEBUGLEVEL_NONE) { 251 R.debug.Console.enableDebugOutput = true; 252 } else { 253 R.debug.Console.enableDebugOutput = false; 254 } 255 }, 256 257 /** 258 * Get the debug level which the console is currently at. 259 * @return {Number} The debug level 260 */ 261 getDebugLevel:function () { 262 return R.debug.Console.verbosity; 263 }, 264 265 /** 266 * Verifies that the debug level is the same as the message to output 267 * @private 268 */ 269 checkVerbosity:function (debugLevel) { 270 if (!R.debug.Console.enableDebugOutput) return; 271 272 return (R.debug.Console.verbosity == R.debug.Console.DEBUGLEVEL_VERBOSE || 273 (debugLevel != R.debug.Console.DEBUGLEVEL_VERBOSE && debugLevel >= R.debug.Console.verbosity)); 274 }, 275 276 /** 277 * Outputs a log message. These messages will only show when <tt>DEBUGLEVEL_VERBOSE</tt> is the level. 278 * You can pass as many parameters as you want to this method. The parameters will be combined into 279 * one message to output to the console. 280 */ 281 log:function () { 282 if (R.debug.Console.checkVerbosity(R.debug.Console.DEBUGLEVEL_VERBOSE)) 283 R.debug.Console.consoleRef.debug.apply(R.debug.Console.consoleRef, arguments); 284 }, 285 286 /** 287 * Outputs an info message. These messages will only show when <tt>DEBUGLEVEL_INFO</tt> is the level. 288 * You can pass as many parameters as you want to this method. The parameters will be combined into 289 * one message to output to the console. 290 */ 291 info:function () { 292 if (R.debug.Console.checkVerbosity(R.debug.Console.DEBUGLEVEL_INFO)) 293 R.debug.Console.consoleRef.debug.apply(R.debug.Console.consoleRef, arguments); 294 }, 295 296 /** 297 * Outputs a debug message. These messages will only show when <tt>DEBUGLEVEL_DEBUG</tt> is the level. 298 * You can pass as many parameters as you want to this method. The parameters will be combined into 299 * one message to output to the console. 300 */ 301 debug:function () { 302 if (R.debug.Console.checkVerbosity(R.debug.Console.DEBUGLEVEL_DEBUG)) 303 R.debug.Console.consoleRef.info.apply(R.debug.Console.consoleRef, arguments); 304 }, 305 306 /** 307 * Outputs a warning message. These messages will only show when <tt>DEBUGLEVEL_WARNINGS</tt> is the level. 308 * You can pass as many parameters as you want to this method. The parameters will be combined into 309 * one message to output to the console. 310 */ 311 warn:function () { 312 if (R.debug.Console.checkVerbosity(R.debug.Console.DEBUGLEVEL_WARNINGS)) 313 R.debug.Console.consoleRef.warn.apply(R.debug.Console.consoleRef, arguments); 314 }, 315 316 /** 317 * Output an error message. These messages always appear unless the debug level is explicitly 318 * set to <tt>DEBUGLEVEL_NONE</tt>. 319 * You can pass as many parameters as you want to this method. The parameters will be combined into 320 * one message to output to the console. 321 */ 322 error:function () { 323 if (R.debug.Console.checkVerbosity(R.debug.Console.DEBUGLEVEL_ERRORS)) 324 R.debug.Console.consoleRef.error.apply(R.debug.Console.consoleRef, arguments); 325 }, 326 327 /** 328 * @private 329 */ 330 trace:function () { 331 R.debug.Console.consoleRef.trace(); 332 } 333 }); 334 335 336 /** 337 * Assert that a condition is <tt>true</tt>, stopping the engine if it is <tt>false</tt>. 338 * If the condifion fails an exception will be thrown. 339 * 340 * @param test {Boolean} A simple test that should evaluate to <tt>true</tt> 341 * @param error {String} The error message to throw if the test fails 342 */ 343 var Assert = function (test, error) { 344 var fail = false; 345 try { 346 if (!test) { 347 fail = true; 348 R.debug.Console.setDebugLevel(R.debug.Console.DEBUGLEVEL_ERRORS); 349 if (arguments.length > 1) { 350 for (var a = 1; a < arguments.length; a++) { 351 R.debug.Console.error("*ASSERT* ", arguments[a]); 352 R.debug.Console.trace(); 353 } 354 } 355 356 R.Engine.shutdown(); 357 358 } 359 } catch (ex) { 360 var pr = R.debug.Console.getDebugLevel(); 361 R.debug.Console.setDebugLevel(R.debug.Console.DEBUGLEVEL_WARNINGS); 362 R.debug.Console.warn("*ASSERT* 'test' would result in an exception: ", ex); 363 R.debug.Console.setDebugLevel(pr); 364 } 365 366 // This will provide a stacktrace for browsers that support it 367 if (fail) { 368 throw new Error(error); 369 } 370 }; 371 372 /** 373 * Assert that a condition is <tt>true</tt>, reporting a warning if the test fails. 374 * 375 * @param test {Boolean} A simple test that should evaluate to <tt>true</tt> 376 * @param error {String} The warning to display if the test fails 377 */ 378 var AssertWarn = function (test, warning) { 379 try { 380 if (!test) { 381 R.debug.Console.setDebugLevel(R.debug.Console.DEBUGLEVEL_WARNINGS); 382 if (arguments.length > 1) { 383 for (var a = 1; a < arguments.length; a++) { 384 R.debug.Console.warn("*ASSERT-WARN* ", arguments[a]); 385 } 386 } 387 R.debug.Console.warn(warning); 388 } 389 } catch (ex) { 390 var pr = R.debug.Console.getDebugLevel(); 391 R.debug.Console.setDebugLevel(R.debug.Console.DEBUGLEVEL_WARNINGS); 392 R.debug.Console.warn("*ASSERT-WARN* 'test' would result in an exception: ", ex); 393 R.debug.Console.setDebugLevel(pr); 394 } 395 }; 396 397