OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 1107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1118 // special not-a-true-error-but-close-enough object. | 1118 // special not-a-true-error-but-close-enough object. |
1119 var ErrorPrototype = function() {}; | 1119 var ErrorPrototype = function() {}; |
1120 %FunctionSetPrototype(ErrorPrototype, $Object.prototype); | 1120 %FunctionSetPrototype(ErrorPrototype, $Object.prototype); |
1121 %FunctionSetInstanceClassName(ErrorPrototype, 'Error'); | 1121 %FunctionSetInstanceClassName(ErrorPrototype, 'Error'); |
1122 %FunctionSetPrototype(f, new ErrorPrototype()); | 1122 %FunctionSetPrototype(f, new ErrorPrototype()); |
1123 } else { | 1123 } else { |
1124 %FunctionSetPrototype(f, new $Error()); | 1124 %FunctionSetPrototype(f, new $Error()); |
1125 } | 1125 } |
1126 %FunctionSetInstanceClassName(f, 'Error'); | 1126 %FunctionSetInstanceClassName(f, 'Error'); |
1127 %SetProperty(f.prototype, 'constructor', f, DONT_ENUM); | 1127 %SetProperty(f.prototype, 'constructor', f, DONT_ENUM); |
1128 // The name property on the prototype of error objects is not | 1128 %SetProperty(f.prototype, "name", name, DONT_ENUM); |
1129 // specified as being read-one and dont-delete. However, allowing | |
1130 // overwriting allows leaks of error objects between script blocks | |
1131 // in the same context in a browser setting. Therefore we fix the | |
1132 // name. | |
1133 %SetProperty(f.prototype, "name", name, | |
1134 DONT_ENUM | DONT_DELETE | READ_ONLY) ; | |
1135 %SetCode(f, function(m) { | 1129 %SetCode(f, function(m) { |
1136 if (%_IsConstructCall()) { | 1130 if (%_IsConstructCall()) { |
1137 // Define all the expected properties directly on the error | 1131 // Define all the expected properties directly on the error |
1138 // object. This avoids going through getters and setters defined | 1132 // object. This avoids going through getters and setters defined |
1139 // on prototype objects. | 1133 // on prototype objects. |
1140 %IgnoreAttributesAndSetProperty(this, 'stack', void 0, DONT_ENUM); | 1134 %IgnoreAttributesAndSetProperty(this, 'stack', void 0, DONT_ENUM); |
1141 %IgnoreAttributesAndSetProperty(this, 'arguments', void 0, DONT_ENUM); | 1135 %IgnoreAttributesAndSetProperty(this, 'arguments', void 0, DONT_ENUM); |
1142 %IgnoreAttributesAndSetProperty(this, 'type', void 0, DONT_ENUM); | 1136 %IgnoreAttributesAndSetProperty(this, 'type', void 0, DONT_ENUM); |
1143 if (m === kAddMessageAccessorsMarker) { | 1137 if (m === kAddMessageAccessorsMarker) { |
1144 // DefineOneShotAccessor always inserts a message property and | 1138 // DefineOneShotAccessor always inserts a message property and |
1145 // ignores setters. | 1139 // ignores setters. |
1146 DefineOneShotAccessor(this, 'message', function (obj) { | 1140 DefineOneShotAccessor(this, 'message', function (obj) { |
1147 return FormatMessage(%NewMessageObject(obj.type, obj.arguments)); | 1141 return FormatMessage(%NewMessageObject(obj.type, obj.arguments)); |
1148 }); | 1142 }); |
1149 } else if (!IS_UNDEFINED(m)) { | 1143 } else if (!IS_UNDEFINED(m)) { |
1150 %IgnoreAttributesAndSetProperty(this, | 1144 %IgnoreAttributesAndSetProperty( |
1151 'message', | 1145 this, 'message', ToString(m), DONT_ENUM); |
1152 ToString(m), | |
1153 DONT_ENUM); | |
1154 } | 1146 } |
1155 captureStackTrace(this, f); | 1147 captureStackTrace(this, f); |
1156 } else { | 1148 } else { |
1157 return new f(m); | 1149 return new f(m); |
1158 } | 1150 } |
1159 }); | 1151 }); |
1160 %SetNativeFlag(f); | 1152 %SetNativeFlag(f); |
1161 }; | 1153 }; |
1162 | 1154 |
1163 DefineError(function Error() { }); | 1155 DefineError(function Error() { }); |
1164 DefineError(function TypeError() { }); | 1156 DefineError(function TypeError() { }); |
1165 DefineError(function RangeError() { }); | 1157 DefineError(function RangeError() { }); |
1166 DefineError(function SyntaxError() { }); | 1158 DefineError(function SyntaxError() { }); |
1167 DefineError(function ReferenceError() { }); | 1159 DefineError(function ReferenceError() { }); |
1168 DefineError(function EvalError() { }); | 1160 DefineError(function EvalError() { }); |
1169 DefineError(function URIError() { }); | 1161 DefineError(function URIError() { }); |
1170 } | 1162 } |
1171 | 1163 |
1172 SetUpError(); | 1164 SetUpError(); |
1173 | 1165 |
1174 $Error.captureStackTrace = captureStackTrace; | 1166 $Error.captureStackTrace = captureStackTrace; |
1175 | 1167 |
1176 %SetProperty($Error.prototype, 'message', '', DONT_ENUM); | 1168 %SetProperty($Error.prototype, 'message', '', DONT_ENUM); |
1177 | 1169 |
1178 // Global list of error objects visited during ErrorToString. This is | 1170 // Global list of error objects visited during ErrorToString. This is |
1179 // used to detect cycles in error toString formatting. | 1171 // used to detect cycles in error toString formatting. |
1180 var visited_errors = new InternalArray(); | 1172 var visited_errors = new InternalArray(); |
1181 var cyclic_error_marker = new $Object(); | 1173 var cyclic_error_marker = new $Object(); |
1182 | 1174 |
| 1175 function GetPropertyWithoutInvokingMonkeyGetters(error, name) { |
| 1176 // Climb the prototype chain until we find the holder. |
| 1177 while (error && !%HasLocalProperty(error, name)) { |
| 1178 error = error.__proto__; |
| 1179 } |
| 1180 if (error === null) return void 0; |
| 1181 if (!IS_OBJECT(error)) return error[name]; |
| 1182 // If the property is an accessor on one of the predefined errors that can be |
| 1183 // generated statically by the compiler, don't touch it. This is to address |
| 1184 // http://code.google.com/p/chromium/issues/detail?id=69187 |
| 1185 var desc = %GetOwnProperty(error, name); |
| 1186 if (desc && desc[IS_ACCESSOR_INDEX]) { |
| 1187 var isName = name === "name"; |
| 1188 if (error === $ReferenceError.prototype) |
| 1189 return isName ? "ReferenceError" : void 0; |
| 1190 if (error === $SyntaxError.prototype) |
| 1191 return isName ? "SyntaxError" : void 0; |
| 1192 if (error === $TypeError.prototype) |
| 1193 return isName ? "TypeError" : void 0; |
| 1194 } |
| 1195 // Otherwise, read normally. |
| 1196 return error[name]; |
| 1197 } |
| 1198 |
1183 function ErrorToStringDetectCycle(error) { | 1199 function ErrorToStringDetectCycle(error) { |
1184 if (!%PushIfAbsent(visited_errors, error)) throw cyclic_error_marker; | 1200 if (!%PushIfAbsent(visited_errors, error)) throw cyclic_error_marker; |
1185 try { | 1201 try { |
1186 var type = error.type; | 1202 var type = GetPropertyWithoutInvokingMonkeyGetters(error, "type"); |
1187 var name = error.name; | 1203 var name = GetPropertyWithoutInvokingMonkeyGetters(error, "name"); |
1188 name = IS_UNDEFINED(name) ? "Error" : TO_STRING_INLINE(name); | 1204 name = IS_UNDEFINED(name) ? "Error" : TO_STRING_INLINE(name); |
1189 var message = error.message; | 1205 var message = GetPropertyWithoutInvokingMonkeyGetters(error, "message"); |
1190 var hasMessage = %_CallFunction(error, "message", ObjectHasOwnProperty); | 1206 var hasMessage = %_CallFunction(error, "message", ObjectHasOwnProperty); |
1191 if (type && !hasMessage) { | 1207 if (type && !hasMessage) { |
1192 message = FormatMessage(%NewMessageObject(type, error.arguments)); | 1208 var args = GetPropertyWithoutInvokingMonkeyGetters(error, "arguments"); |
| 1209 message = FormatMessage(%NewMessageObject(type, args)); |
1193 } | 1210 } |
1194 message = IS_UNDEFINED(message) ? "" : TO_STRING_INLINE(message); | 1211 message = IS_UNDEFINED(message) ? "" : TO_STRING_INLINE(message); |
1195 if (name === "") return message; | 1212 if (name === "") return message; |
1196 if (message === "") return name; | 1213 if (message === "") return name; |
1197 return name + ": " + message; | 1214 return name + ": " + message; |
1198 } finally { | 1215 } finally { |
1199 visited_errors.length = visited_errors.length - 1; | 1216 visited_errors.length = visited_errors.length - 1; |
1200 } | 1217 } |
1201 } | 1218 } |
1202 | 1219 |
(...skipping 13 matching lines...) Expand all Loading... |
1216 throw e; | 1233 throw e; |
1217 } | 1234 } |
1218 } | 1235 } |
1219 | 1236 |
1220 | 1237 |
1221 InstallFunctions($Error.prototype, DONT_ENUM, ['toString', ErrorToString]); | 1238 InstallFunctions($Error.prototype, DONT_ENUM, ['toString', ErrorToString]); |
1222 | 1239 |
1223 // Boilerplate for exceptions for stack overflows. Used from | 1240 // Boilerplate for exceptions for stack overflows. Used from |
1224 // Isolate::StackOverflow(). | 1241 // Isolate::StackOverflow(). |
1225 var kStackOverflowBoilerplate = MakeRangeError('stack_overflow', []); | 1242 var kStackOverflowBoilerplate = MakeRangeError('stack_overflow', []); |
OLD | NEW |