1 // ========================================================================== 2 // Project: SproutCore - JavaScript Application Framework 3 // Copyright: ©2006-2011 Strobe Inc. and contributors. 4 // Portions ©2008-2011 Apple Inc. All rights reserved. 5 // License: Licensed under MIT license (see license.js) 6 // ========================================================================== 7 // @global SC 8 9 sc_require('ext/function'); 10 11 /** 12 @class 13 14 An error, used to represent an error state. 15 16 Many API's within SproutCore will return an instance of this object whenever 17 they have an error occur. An error includes an error code, description, 18 and optional human readable label that indicates the item that failed. 19 20 Depending on the error, other properties may also be added to the object 21 to help you recover from the failure. 22 23 You can pass error objects to various UI elements to display the error in 24 the interface. You can easily determine if the value returned by some API is 25 an error or not using the helper SC.ok(value). 26 27 Faking Error Objects 28 --- 29 30 You can actually make any object you want to be treated like an Error object 31 by simply implementing two properties: isError and errorValue. If you 32 set isError to YES, then calling SC.ok(obj) on your object will return NO. 33 If isError is YES, then SC.val(obj) will return your errorValue property 34 instead of the receiver. 35 36 When using SC.typeOf(obj), SC.T_ERROR will only be returned if the obj 37 is an instance of SC.Error 38 39 @extends SC.Object 40 @since SproutCore 1.0 41 */ 42 SC.Error = SC.Object.extend( 43 /** @scope SC.Error.prototype */ { 44 45 /** 46 error code. Used to designate the error type. 47 48 @type Number 49 */ 50 code: -1, 51 52 /** 53 Human readable description of the error. This can also be a non-localized 54 key. 55 56 @type String 57 */ 58 message: '', 59 60 /** 61 The value the error represents. This is used when wrapping a value inside 62 of an error to represent the validation failure. 63 64 @type Object 65 */ 66 errorValue: null, 67 68 /** 69 The original error object. Normally this will return the receiver. 70 However, sometimes another object will masquerade as an error; this gives 71 you a way to get at the underlying error. 72 73 @type SC.Error 74 */ 75 errorObject: function() { 76 return this; 77 }.property().cacheable(), 78 79 /** 80 Throw the error. 81 82 @type SC.Error 83 */ 84 'throw': function() { 85 var error = this.toString(); 86 SC.Logger.error(error); 87 88 throw new Error(error); 89 }, 90 91 /** 92 The error stacktrace. 93 94 @type SC.Error 95 */ 96 trace: function() { 97 return (new Error()).trace; 98 }.property().cacheable(), 99 100 /** 101 Human readable name of the item with the error. 102 103 @type String 104 */ 105 label: null, 106 107 /** @private */ 108 toString: function() { 109 return "SC.Error:%@:%@ (%@)".fmt(SC.guidFor(this), this.get('message'), this.get('code')); 110 }, 111 112 /** 113 Walk like a duck. 114 115 @type Boolean 116 */ 117 isError: YES 118 }); 119 120 SC.Error.mixin({ 121 122 /** 123 Creates a new SC.Error instance with the passed description, label, and 124 code. All parameters are optional. 125 126 @param description {String} human readable description of the error 127 @param label {String} human readable name of the item with the error 128 @param code {Number} an error code to use for testing. 129 @returns {SC.Error} new error instance. 130 */ 131 desc: function(description, label, value, code) { 132 var opts = { message: description } ; 133 if (label !== undefined) opts.label = label ; 134 if (code !== undefined) opts.code = code ; 135 if (value !== undefined) opts.errorValue = value ; 136 return this.create(opts) ; 137 }, 138 139 /** 140 Throw a new SC.Error instance with the passed description, label, and 141 code. All parameters are optional. 142 143 @param description {String} human readable description of the error 144 @param label {String} human readable name of the item with the error 145 @param code {Number} an error code to use for testing. 146 @returns {SC.Error} new error instance. 147 */ 148 'throw': function(description, label, value, code) { 149 this.desc.apply(this, arguments).throw(); 150 } 151 152 }); 153 154 /** 155 Shorthand form of the SC.Error.desc method. 156 157 @param description {String} human readable description of the error 158 @param label {String} human readable name of the item with the error 159 @param code {Number} an error code to use for testing. 160 @returns {SC.Error} new error instance. 161 */ 162 SC.$error = function(description, label, value, c) { 163 return SC.Error.desc(description, label, value, c); 164 }; 165 166 /** 167 Shorthand form of the SC.Error.throw method. 168 169 @param description {String} human readable description of the error 170 @param label {String} human readable name of the item with the error 171 @param code {Number} an error code to use for testing. 172 @returns {SC.Error} new error instance. 173 */ 174 SC.throw = function(description, label, value, c) { 175 SC.Error.throw(description, label, value, c); 176 }; 177 178 /** @private */ 179 SC.$throw = SC.throw; 180 181 /** 182 Returns NO if the passed value is an error object or false. 183 184 @param {Object} ret object value 185 @returns {Boolean} 186 */ 187 SC.ok = function(ret) { 188 return (ret !== false) && !(ret && ret.isError); 189 }; 190 191 /** @private */ 192 SC.$ok = SC.ok; 193 194 /** 195 Returns the value of an object. If the passed object is an error, returns 196 the value associated with the error; otherwise returns the receiver itself. 197 198 @param {Object} obj the object 199 @returns {Object} value 200 */ 201 SC.val = function(obj) { 202 if (obj && obj.isError) { 203 return obj.get ? obj.get('errorValue') : null ; // Error has no value 204 } else return obj ; 205 }; 206 207 /** @private */ 208 SC.$val = SC.val; 209 210 // STANDARD ERROR OBJECTS 211 212 /** 213 Standard error code for errors that do not support multiple values. 214 215 @type Number 216 */ 217 SC.Error.HAS_MULTIPLE_VALUES = -100 ; 218