OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // ------------------------------------------------------------------- | 5 // ------------------------------------------------------------------- |
6 | 6 |
7 var kMessages = { | 7 var kMessages = { |
8 // Error | 8 // Error |
9 cyclic_proto: ["Cyclic __proto__ value"], | 9 cyclic_proto: ["Cyclic __proto__ value"], |
10 code_gen_from_strings: ["%0"], | 10 code_gen_from_strings: ["%0"], |
(...skipping 1062 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1073 frames.push(new CallSite(recv, fun, pos, (sloppy_frames < 0))); | 1073 frames.push(new CallSite(recv, fun, pos, (sloppy_frames < 0))); |
1074 } | 1074 } |
1075 return frames; | 1075 return frames; |
1076 } | 1076 } |
1077 | 1077 |
1078 | 1078 |
1079 // Flag to prevent recursive call of Error.prepareStackTrace. | 1079 // Flag to prevent recursive call of Error.prepareStackTrace. |
1080 var formatting_custom_stack_trace = false; | 1080 var formatting_custom_stack_trace = false; |
1081 | 1081 |
1082 | 1082 |
1083 function FormatStackTrace(obj, raw_stack) { | 1083 function FormatStackTrace(obj, error_string, frames) { |
1084 var frames = GetStackFrames(raw_stack); | |
1085 if (IS_FUNCTION($Error.prepareStackTrace) && !formatting_custom_stack_trace) { | 1084 if (IS_FUNCTION($Error.prepareStackTrace) && !formatting_custom_stack_trace) { |
1086 var array = []; | 1085 var array = []; |
1087 %MoveArrayContents(frames, array); | 1086 %MoveArrayContents(frames, array); |
1088 formatting_custom_stack_trace = true; | 1087 formatting_custom_stack_trace = true; |
1089 var stack_trace = UNDEFINED; | 1088 var stack_trace = UNDEFINED; |
1090 try { | 1089 try { |
1091 stack_trace = $Error.prepareStackTrace(obj, array); | 1090 stack_trace = $Error.prepareStackTrace(obj, array); |
1092 } catch (e) { | 1091 } catch (e) { |
1093 throw e; // The custom formatting function threw. Rethrow. | 1092 throw e; // The custom formatting function threw. Rethrow. |
1094 } finally { | 1093 } finally { |
1095 formatting_custom_stack_trace = false; | 1094 formatting_custom_stack_trace = false; |
1096 } | 1095 } |
1097 return stack_trace; | 1096 return stack_trace; |
1098 } | 1097 } |
1099 | 1098 |
1100 var lines = new InternalArray(); | 1099 var lines = new InternalArray(); |
1101 lines.push(FormatErrorString(obj)); | 1100 lines.push(error_string); |
1102 for (var i = 0; i < frames.length; i++) { | 1101 for (var i = 0; i < frames.length; i++) { |
1103 var frame = frames[i]; | 1102 var frame = frames[i]; |
1104 var line; | 1103 var line; |
1105 try { | 1104 try { |
1106 line = frame.toString(); | 1105 line = frame.toString(); |
1107 } catch (e) { | 1106 } catch (e) { |
1108 try { | 1107 try { |
1109 line = "<error: " + e + ">"; | 1108 line = "<error: " + e + ">"; |
1110 } catch (ee) { | 1109 } catch (ee) { |
1111 // Any code that reaches this point is seriously nasty! | 1110 // Any code that reaches this point is seriously nasty! |
(...skipping 14 matching lines...) Expand all Loading... |
1126 } | 1125 } |
1127 var constructorName = constructor.name; | 1126 var constructorName = constructor.name; |
1128 if (!constructorName) { | 1127 if (!constructorName) { |
1129 return requireConstructor ? null : | 1128 return requireConstructor ? null : |
1130 %_CallFunction(receiver, ObjectToString); | 1129 %_CallFunction(receiver, ObjectToString); |
1131 } | 1130 } |
1132 return constructorName; | 1131 return constructorName; |
1133 } | 1132 } |
1134 | 1133 |
1135 | 1134 |
1136 var stack_trace_symbol; // Set during bootstrapping. | 1135 function captureStackTrace(obj, cons_opt) { |
1137 var formatted_stack_trace_symbol = NEW_PRIVATE("formatted stack trace"); | 1136 var stackTraceLimit = $Error.stackTraceLimit; |
| 1137 if (!stackTraceLimit || !IS_NUMBER(stackTraceLimit)) return; |
| 1138 if (stackTraceLimit < 0 || stackTraceLimit > 10000) { |
| 1139 stackTraceLimit = 10000; |
| 1140 } |
| 1141 var stack = %CollectStackTrace(obj, |
| 1142 cons_opt ? cons_opt : captureStackTrace, |
| 1143 stackTraceLimit); |
1138 | 1144 |
| 1145 var error_string = FormatErrorString(obj); |
1139 | 1146 |
1140 // Format the stack trace if not yet done, and return it. | 1147 // Set the 'stack' property on the receiver. If the receiver is the same as |
1141 // Cache the formatted stack trace on the holder. | 1148 // holder of this setter, the accessor pair is turned into a data property. |
1142 function StackTraceGetter() { | 1149 var setter = function(v) { |
1143 var formatted_stack_trace = GET_PRIVATE(this, formatted_stack_trace_symbol); | 1150 // Set data property on the receiver (not necessarily holder). |
1144 if (IS_UNDEFINED(formatted_stack_trace)) { | 1151 %DefineDataPropertyUnchecked(this, 'stack', v, NONE); |
1145 var holder = this; | 1152 if (this === obj) { |
1146 while (!HAS_PRIVATE(holder, stack_trace_symbol)) { | 1153 // Release context values if holder is the same as the receiver. |
1147 holder = %GetPrototype(holder); | 1154 stack = error_string = UNDEFINED; |
1148 if (!holder) return UNDEFINED; | |
1149 } | 1155 } |
1150 var stack_trace = GET_PRIVATE(holder, stack_trace_symbol); | 1156 }; |
1151 if (IS_UNDEFINED(stack_trace)) return UNDEFINED; | |
1152 formatted_stack_trace = FormatStackTrace(holder, stack_trace); | |
1153 SET_PRIVATE(holder, stack_trace_symbol, UNDEFINED); | |
1154 SET_PRIVATE(holder, formatted_stack_trace_symbol, formatted_stack_trace); | |
1155 } | |
1156 return formatted_stack_trace; | |
1157 }; | |
1158 | 1157 |
| 1158 // The holder of this getter ('obj') may not be the receiver ('this'). |
| 1159 // When this getter is called the first time, we use the context values to |
| 1160 // format a stack trace string and turn this accessor pair into a data |
| 1161 // property (on the holder). |
| 1162 var getter = function() { |
| 1163 // Stack is still a raw array awaiting to be formatted. |
| 1164 var result = FormatStackTrace(obj, error_string, GetStackFrames(stack)); |
| 1165 // Replace this accessor to return result directly. |
| 1166 %DefineAccessorPropertyUnchecked( |
| 1167 obj, 'stack', function() { return result }, setter, DONT_ENUM); |
| 1168 // Release context values. |
| 1169 stack = error_string = UNDEFINED; |
| 1170 return result; |
| 1171 }; |
1159 | 1172 |
1160 // If the receiver equals the holder, set the formatted stack trace that the | 1173 %DefineAccessorPropertyUnchecked(obj, 'stack', getter, setter, DONT_ENUM); |
1161 // getter returns. | |
1162 function StackTraceSetter(v) { | |
1163 if (HAS_PRIVATE(this, stack_trace_symbol)) { | |
1164 SET_PRIVATE(this, stack_trace_symbol, UNDEFINED); | |
1165 SET_PRIVATE(this, formatted_stack_trace_symbol, v); | |
1166 } | |
1167 }; | |
1168 | |
1169 | |
1170 function captureStackTrace(obj, cons_opt) { | |
1171 // Define accessors first, as this may fail and throw. | |
1172 ObjectDefineProperty(obj, 'stack', { get: StackTraceGetter, | |
1173 set: StackTraceSetter}); | |
1174 %CollectStackTrace(obj, cons_opt ? cons_opt : captureStackTrace); | |
1175 } | 1174 } |
1176 | 1175 |
1177 | 1176 |
1178 function SetUpError() { | 1177 function SetUpError() { |
1179 // Define special error type constructors. | 1178 // Define special error type constructors. |
1180 | 1179 |
1181 var DefineError = function(f) { | 1180 var DefineError = function(f) { |
1182 // Store the error function in both the global object | 1181 // Store the error function in both the global object |
1183 // and the runtime object. The function is fetched | 1182 // and the runtime object. The function is fetched |
1184 // from the runtime object when throwing errors from | 1183 // from the runtime object when throwing errors from |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1300 } | 1299 } |
1301 | 1300 |
1302 | 1301 |
1303 InstallFunctions($Error.prototype, DONT_ENUM, ['toString', ErrorToString]); | 1302 InstallFunctions($Error.prototype, DONT_ENUM, ['toString', ErrorToString]); |
1304 | 1303 |
1305 // Boilerplate for exceptions for stack overflows. Used from | 1304 // Boilerplate for exceptions for stack overflows. Used from |
1306 // Isolate::StackOverflow(). | 1305 // Isolate::StackOverflow(). |
1307 function SetUpStackOverflowBoilerplate() { | 1306 function SetUpStackOverflowBoilerplate() { |
1308 var boilerplate = MakeRangeError('stack_overflow', []); | 1307 var boilerplate = MakeRangeError('stack_overflow', []); |
1309 | 1308 |
| 1309 var error_string = boilerplate.name + ": " + boilerplate.message; |
| 1310 |
| 1311 // Set the 'stack' property on the receiver. If the receiver is the same as |
| 1312 // holder of this setter, the accessor pair is turned into a data property. |
| 1313 var setter = function(v) { |
| 1314 %DefineDataPropertyUnchecked(this, 'stack', v, NONE); |
| 1315 // Tentatively clear the hidden property. If the receiver is the same as |
| 1316 // holder, we release the raw stack trace this way. |
| 1317 %GetAndClearOverflowedStackTrace(this); |
| 1318 }; |
| 1319 |
| 1320 // The raw stack trace is stored as a hidden property on the holder of this |
| 1321 // getter, which may not be the same as the receiver. Find the holder to |
| 1322 // retrieve the raw stack trace and then turn this accessor pair into a |
| 1323 // data property. |
| 1324 var getter = function() { |
| 1325 var holder = this; |
| 1326 while (!IS_ERROR(holder)) { |
| 1327 holder = %GetPrototype(holder); |
| 1328 if (IS_NULL(holder)) return MakeSyntaxError('illegal_access', []); |
| 1329 } |
| 1330 var stack = %GetAndClearOverflowedStackTrace(holder); |
| 1331 // We may not have captured any stack trace. |
| 1332 if (IS_UNDEFINED(stack)) return stack; |
| 1333 |
| 1334 var result = FormatStackTrace(holder, error_string, GetStackFrames(stack)); |
| 1335 // Replace this accessor to return result directly. |
| 1336 %DefineAccessorPropertyUnchecked( |
| 1337 holder, 'stack', function() { return result }, setter, DONT_ENUM); |
| 1338 return result; |
| 1339 }; |
| 1340 |
1310 %DefineAccessorPropertyUnchecked( | 1341 %DefineAccessorPropertyUnchecked( |
1311 boilerplate, 'stack', StackTraceGetter, StackTraceSetter, DONT_ENUM); | 1342 boilerplate, 'stack', getter, setter, DONT_ENUM); |
1312 | 1343 |
1313 return boilerplate; | 1344 return boilerplate; |
1314 } | 1345 } |
1315 | 1346 |
1316 var kStackOverflowBoilerplate = SetUpStackOverflowBoilerplate(); | 1347 var kStackOverflowBoilerplate = SetUpStackOverflowBoilerplate(); |
OLD | NEW |