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