PageRenderTime 1ms CodeModel.GetById 39ms app.highlight 7ms RepoModel.GetById 1ms app.codeStats 0ms

/examples/ext/src/core/src/lang/Error.js

http://github.com/brunotavares/Ext.ux.Router
JavaScript | 329 lines | 100 code | 28 blank | 201 comment | 23 complexity | abde042a99e201412e4a26fd3cb620ab MD5 | raw file
  1//@tag foundation,core
  2//@require ../class/Loader.js
  3
  4/**
  5 * @author Brian Moeskau <brian@sencha.com>
  6 * @docauthor Brian Moeskau <brian@sencha.com>
  7 *
  8 * A wrapper class for the native JavaScript Error object that adds a few useful capabilities for handling
  9 * errors in an Ext application. When you use Ext.Error to {@link #raise} an error from within any class that
 10 * uses the Ext 4 class system, the Error class can automatically add the source class and method from which
 11 * the error was raised. It also includes logic to automatically log the error to the console, if available,
 12 * with additional metadata about the error. In all cases, the error will always be thrown at the end so that
 13 * execution will halt.
 14 *
 15 * Ext.Error also offers a global error {@link #handle handling} method that can be overridden in order to
 16 * handle application-wide errors in a single spot. You can optionally {@link #ignore} errors altogether,
 17 * although in a real application it's usually a better idea to override the handling function and perform
 18 * logging or some other method of reporting the errors in a way that is meaningful to the application.
 19 *
 20 * At its simplest you can simply raise an error as a simple string from within any code:
 21 *
 22 * Example usage:
 23 *
 24 *     Ext.Error.raise('Something bad happened!');
 25 *
 26 * If raised from plain JavaScript code, the error will be logged to the console (if available) and the message
 27 * displayed. In most cases however you'll be raising errors from within a class, and it may often be useful to add
 28 * additional metadata about the error being raised.  The {@link #raise} method can also take a config object.
 29 * In this form the `msg` attribute becomes the error description, and any other data added to the config gets
 30 * added to the error object and, if the console is available, logged to the console for inspection.
 31 *
 32 * Example usage:
 33 *
 34 *     Ext.define('Ext.Foo', {
 35 *         doSomething: function(option){
 36 *             if (someCondition === false) {
 37 *                 Ext.Error.raise({
 38 *                     msg: 'You cannot do that!',
 39 *                     option: option,   // whatever was passed into the method
 40 *                     'error code': 100 // other arbitrary info
 41 *                 });
 42 *             }
 43 *         }
 44 *     });
 45 *
 46 * If a console is available (that supports the `console.dir` function) you'll see console output like:
 47 *
 48 *     An error was raised with the following data:
 49 *     option:         Object { foo: "bar"}
 50 *         foo:        "bar"
 51 *     error code:     100
 52 *     msg:            "You cannot do that!"
 53 *     sourceClass:   "Ext.Foo"
 54 *     sourceMethod:  "doSomething"
 55 *
 56 *     uncaught exception: You cannot do that!
 57 *
 58 * As you can see, the error will report exactly where it was raised and will include as much information as the
 59 * raising code can usefully provide.
 60 *
 61 * If you want to handle all application errors globally you can simply override the static {@link #handle} method
 62 * and provide whatever handling logic you need. If the method returns true then the error is considered handled
 63 * and will not be thrown to the browser. If anything but true is returned then the error will be thrown normally.
 64 *
 65 * Example usage:
 66 *
 67 *     Ext.Error.handle = function(err) {
 68 *         if (err.someProperty == 'NotReallyAnError') {
 69 *             // maybe log something to the application here if applicable
 70 *             return true;
 71 *         }
 72 *         // any non-true return value (including none) will cause the error to be thrown
 73 *     }
 74 *
 75 */
 76Ext.Error = Ext.extend(Error, {
 77    statics: {
 78        /**
 79         * @property {Boolean} ignore
 80         * Static flag that can be used to globally disable error reporting to the browser if set to true
 81         * (defaults to false). Note that if you ignore Ext errors it's likely that some other code may fail
 82         * and throw a native JavaScript error thereafter, so use with caution. In most cases it will probably
 83         * be preferable to supply a custom error {@link #handle handling} function instead.
 84         *
 85         * Example usage:
 86         *
 87         *     Ext.Error.ignore = true;
 88         *
 89         * @static
 90         */
 91        ignore: false,
 92
 93        /**
 94         * @property {Boolean} notify
 95         * Static flag that can be used to globally control error notification to the user. Unlike
 96         * Ex.Error.ignore, this does not effect exceptions. They are still thrown. This value can be
 97         * set to false to disable the alert notification (default is true for IE6 and IE7).
 98         *
 99         * Only the first error will generate an alert. Internally this flag is set to false when the
100         * first error occurs prior to displaying the alert.
101         *
102         * This flag is not used in a release build.
103         *
104         * Example usage:
105         *
106         *     Ext.Error.notify = false;
107         *
108         * @static
109         */
110        //notify: Ext.isIE6 || Ext.isIE7,
111
112        /**
113         * Raise an error that can include additional data and supports automatic console logging if available.
114         * You can pass a string error message or an object with the `msg` attribute which will be used as the
115         * error message. The object can contain any other name-value attributes (or objects) to be logged
116         * along with the error.
117         *
118         * Note that after displaying the error message a JavaScript error will ultimately be thrown so that
119         * execution will halt.
120         *
121         * Example usage:
122         *
123         *     Ext.Error.raise('A simple string error message');
124         *
125         *     // or...
126         *
127         *     Ext.define('Ext.Foo', {
128         *         doSomething: function(option){
129         *             if (someCondition === false) {
130         *                 Ext.Error.raise({
131         *                     msg: 'You cannot do that!',
132         *                     option: option,   // whatever was passed into the method
133         *                     'error code': 100 // other arbitrary info
134         *                 });
135         *             }
136         *         }
137         *     });
138         *
139         * @param {String/Object} err The error message string, or an object containing the attribute "msg" that will be
140         * used as the error message. Any other data included in the object will also be logged to the browser console,
141         * if available.
142         * @static
143         */
144        raise: function(err){
145            err = err || {};
146            if (Ext.isString(err)) {
147                err = { msg: err };
148            }
149
150            var method = this.raise.caller,
151                msg;
152
153            if (method) {
154                if (method.$name) {
155                    err.sourceMethod = method.$name;
156                }
157                if (method.$owner) {
158                    err.sourceClass = method.$owner.$className;
159                }
160            }
161
162            if (Ext.Error.handle(err) !== true) {
163                msg = Ext.Error.prototype.toString.call(err);
164
165                Ext.log({
166                    msg: msg,
167                    level: 'error',
168                    dump: err,
169                    stack: true
170                });
171
172                throw new Ext.Error(err);
173            }
174        },
175
176        /**
177         * Globally handle any Ext errors that may be raised, optionally providing custom logic to
178         * handle different errors individually. Return true from the function to bypass throwing the
179         * error to the browser, otherwise the error will be thrown and execution will halt.
180         *
181         * Example usage:
182         *
183         *     Ext.Error.handle = function(err) {
184         *         if (err.someProperty == 'NotReallyAnError') {
185         *             // maybe log something to the application here if applicable
186         *             return true;
187         *         }
188         *         // any non-true return value (including none) will cause the error to be thrown
189         *     }
190         *
191         * @param {Ext.Error} err The Ext.Error object being raised. It will contain any attributes that were originally
192         * raised with it, plus properties about the method and class from which the error originated (if raised from a
193         * class that uses the Ext 4 class system).
194         * @static
195         */
196        handle: function(){
197            return Ext.Error.ignore;
198        }
199    },
200
201    // This is the standard property that is the name of the constructor.
202    name: 'Ext.Error',
203
204    /**
205     * Creates new Error object.
206     * @param {String/Object} config The error message string, or an object containing the
207     * attribute "msg" that will be used as the error message. Any other data included in
208     * the object will be applied to the error instance and logged to the browser console, if available.
209     */
210    constructor: function(config){
211        if (Ext.isString(config)) {
212            config = { msg: config };
213        }
214
215        var me = this;
216
217        Ext.apply(me, config);
218
219        me.message = me.message || me.msg; // 'message' is standard ('msg' is non-standard)
220        // note: the above does not work in old WebKit (me.message is readonly) (Safari 4)
221    },
222
223    /**
224     * Provides a custom string representation of the error object. This is an override of the base JavaScript
225     * `Object.toString` method, which is useful so that when logged to the browser console, an error object will
226     * be displayed with a useful message instead of `[object Object]`, the default `toString` result.
227     *
228     * The default implementation will include the error message along with the raising class and method, if available,
229     * but this can be overridden with a custom implementation either at the prototype level (for all errors) or on
230     * a particular error instance, if you want to provide a custom description that will show up in the console.
231     * @return {String} The error message. If raised from within the Ext 4 class system, the error message will also
232     * include the raising class and method names, if available.
233     */
234    toString: function(){
235        var me = this,
236            className = me.sourceClass ? me.sourceClass : '',
237            methodName = me.sourceMethod ? '.' + me.sourceMethod + '(): ' : '',
238            msg = me.msg || '(No description provided)';
239
240        return className + methodName + msg;
241    }
242});
243
244/*
245 * Create a function that will throw an error if called (in debug mode) with a message that
246 * indicates the method has been removed.
247 * @param {String} suggestion Optional text to include in the message (a workaround perhaps).
248 * @return {Function} The generated function.
249 * @private
250 */
251Ext.deprecated = function (suggestion) {
252    //<debug>
253    if (!suggestion) {
254        suggestion = '';
255    }
256
257    function fail () {
258        Ext.Error.raise('The method "' + fail.$owner.$className + '.' + fail.$name + 
259                '" has been removed. ' + suggestion);
260    }
261
262    return fail;
263    //</debug>
264    return Ext.emptyFn;
265};
266
267/*
268 * This mechanism is used to notify the user of the first error encountered on the page. This
269 * was previously internal to Ext.Error.raise and is a desirable feature since errors often
270 * slip silently under the radar. It cannot live in Ext.Error.raise since there are times
271 * where exceptions are handled in a try/catch.
272 */
273//<debug>
274(function () {
275    var timer, errors = 0,
276        win = Ext.global,
277        msg;
278
279    if (typeof window === 'undefined') {
280        return; // build system or some such environment...
281    }
282
283    // This method is called to notify the user of the current error status.
284    function notify () {
285        var counters = Ext.log.counters,
286            supports = Ext.supports,
287            hasOnError = supports && supports.WindowOnError; // TODO - timing
288
289        // Put log counters to the status bar (for most browsers):
290        if (counters && (counters.error + counters.warn + counters.info + counters.log)) {
291            msg = [ 'Logged Errors:',counters.error, 'Warnings:',counters.warn,
292                        'Info:',counters.info, 'Log:',counters.log].join(' ');
293            if (errors) {
294                msg = '*** Errors: ' + errors + ' - ' + msg;
295            } else if (counters.error) {
296                msg = '*** ' + msg;
297            }
298            win.status = msg;
299        }
300
301        // Display an alert on the first error:
302        if (!Ext.isDefined(Ext.Error.notify)) {
303            Ext.Error.notify = Ext.isIE6 || Ext.isIE7; // TODO - timing
304        }
305        if (Ext.Error.notify && (hasOnError ? errors : (counters && counters.error))) {
306            Ext.Error.notify = false;
307
308            if (timer) {
309                win.clearInterval(timer); // ticks can queue up so stop...
310                timer = null;
311            }
312
313            alert('Unhandled error on page: See console or log');
314            poll();
315        }
316    }
317
318    // Sets up polling loop. This is the only way to know about errors in some browsers
319    // (Opera/Safari) and is the only way to update the status bar for warnings and other
320    // non-errors.
321    function poll () {
322        timer = win.setInterval(notify, 1000);
323    }
324
325    // window.onerror sounds ideal but it prevents the built-in error dialog from doing
326    // its (better) thing.
327    poll();
328}());
329//</debug>