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, error_string, frames) { | 1083 function FormatStackTrace(obj, raw_stack) { |
1084 var frames = GetStackFrames(raw_stack); | |
1084 if (IS_FUNCTION($Error.prepareStackTrace) && !formatting_custom_stack_trace) { | 1085 if (IS_FUNCTION($Error.prepareStackTrace) && !formatting_custom_stack_trace) { |
1085 var array = []; | 1086 var array = []; |
1086 %MoveArrayContents(frames, array); | 1087 %MoveArrayContents(frames, array); |
1087 formatting_custom_stack_trace = true; | 1088 formatting_custom_stack_trace = true; |
1088 var stack_trace = UNDEFINED; | 1089 var stack_trace = UNDEFINED; |
1089 try { | 1090 try { |
1090 stack_trace = $Error.prepareStackTrace(obj, array); | 1091 stack_trace = $Error.prepareStackTrace(obj, array); |
1091 } catch (e) { | 1092 } catch (e) { |
1092 throw e; // The custom formatting function threw. Rethrow. | 1093 throw e; // The custom formatting function threw. Rethrow. |
1093 } finally { | 1094 } finally { |
1094 formatting_custom_stack_trace = false; | 1095 formatting_custom_stack_trace = false; |
1095 } | 1096 } |
1096 return stack_trace; | 1097 return stack_trace; |
1097 } | 1098 } |
1098 | 1099 |
1099 var lines = new InternalArray(); | 1100 var lines = new InternalArray(); |
1100 lines.push(error_string); | 1101 lines.push(FormatErrorString(obj)); |
1101 for (var i = 0; i < frames.length; i++) { | 1102 for (var i = 0; i < frames.length; i++) { |
1102 var frame = frames[i]; | 1103 var frame = frames[i]; |
1103 var line; | 1104 var line; |
1104 try { | 1105 try { |
1105 line = frame.toString(); | 1106 line = frame.toString(); |
1106 } catch (e) { | 1107 } catch (e) { |
1107 try { | 1108 try { |
1108 line = "<error: " + e + ">"; | 1109 line = "<error: " + e + ">"; |
1109 } catch (ee) { | 1110 } catch (ee) { |
1110 // Any code that reaches this point is seriously nasty! | 1111 // Any code that reaches this point is seriously nasty! |
(...skipping 14 matching lines...) Expand all Loading... | |
1125 } | 1126 } |
1126 var constructorName = constructor.name; | 1127 var constructorName = constructor.name; |
1127 if (!constructorName) { | 1128 if (!constructorName) { |
1128 return requireConstructor ? null : | 1129 return requireConstructor ? null : |
1129 %_CallFunction(receiver, ObjectToString); | 1130 %_CallFunction(receiver, ObjectToString); |
1130 } | 1131 } |
1131 return constructorName; | 1132 return constructorName; |
1132 } | 1133 } |
1133 | 1134 |
1134 | 1135 |
1136 var stack_trace_symbol; // Set during bootstrapping. | |
1137 var formatted_stack_trace_symbol = NEW_PRIVATE("formatted stack trace"); | |
1138 | |
1139 | |
1140 // Format the stack trace if not yet done, and return it. | |
1141 // Cache the formatted stack trace on the holder. | |
1142 function StackTraceGetter() { | |
1143 var formatted_stack_trace = GET_PRIVATE(this, formatted_stack_trace_symbol); | |
1144 if (IS_UNDEFINED(formatted_stack_trace)) { | |
1145 var stack_trace = GET_PRIVATE(this, stack_trace_symbol); | |
1146 if (IS_UNDEFINED(stack_trace)) return UNDEFINED; | |
1147 var holder = this; | |
1148 while (!HAS_PRIVATE(holder, stack_trace_symbol)) { | |
1149 holder = %GetPrototype(holder); | |
Toon Verwaest
2014/06/30 09:56:30
This runs through the prototype chain twice, and t
| |
1150 } | |
1151 formatted_stack_trace = FormatStackTrace(holder, stack_trace); | |
1152 SET_PRIVATE(holder, stack_trace_symbol, UNDEFINED); | |
1153 SET_PRIVATE(holder, formatted_stack_trace_symbol, formatted_stack_trace); | |
1154 } | |
1155 return formatted_stack_trace; | |
1156 }; | |
1157 | |
1158 | |
1159 // If the receiver equals the holder, set the formatted stack trace that the | |
1160 // getter returns. | |
1161 function StackTraceSetter(v) { | |
1162 if (HAS_PRIVATE(this, stack_trace_symbol)) { | |
1163 SET_PRIVATE(this, stack_trace_symbol, UNDEFINED); | |
1164 SET_PRIVATE(this, formatted_stack_trace_symbol, v); | |
1165 } | |
1166 }; | |
1167 | |
1168 | |
1135 function captureStackTrace(obj, cons_opt) { | 1169 function captureStackTrace(obj, cons_opt) { |
1136 var stackTraceLimit = $Error.stackTraceLimit; | 1170 // Define accessors first, as this may fail and throw. |
1137 if (!stackTraceLimit || !IS_NUMBER(stackTraceLimit)) return; | 1171 ObjectDefineProperty(obj, 'stack', { get: StackTraceGetter, |
1138 if (stackTraceLimit < 0 || stackTraceLimit > 10000) { | 1172 set: StackTraceSetter}); |
1139 stackTraceLimit = 10000; | 1173 %CollectStackTrace(obj, cons_opt ? cons_opt : captureStackTrace); |
1140 } | |
1141 var stack = %CollectStackTrace(obj, | |
1142 cons_opt ? cons_opt : captureStackTrace, | |
1143 stackTraceLimit); | |
1144 | |
1145 var error_string = FormatErrorString(obj); | |
1146 | |
1147 // Set the 'stack' property on the receiver. If the receiver is the same as | |
1148 // holder of this setter, the accessor pair is turned into a data property. | |
1149 var setter = function(v) { | |
1150 // Set data property on the receiver (not necessarily holder). | |
1151 %DefineOrRedefineDataProperty(this, 'stack', v, NONE); | |
1152 if (this === obj) { | |
1153 // Release context values if holder is the same as the receiver. | |
1154 stack = error_string = UNDEFINED; | |
1155 } | |
1156 }; | |
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 %DefineOrRedefineAccessorProperty( | |
1167 obj, 'stack', function() { return result }, setter, DONT_ENUM); | |
1168 // Release context values. | |
1169 stack = error_string = UNDEFINED; | |
1170 return result; | |
1171 }; | |
1172 | |
1173 %DefineOrRedefineAccessorProperty(obj, 'stack', getter, setter, DONT_ENUM); | |
1174 } | 1174 } |
1175 | 1175 |
1176 | 1176 |
1177 function SetUpError() { | 1177 function SetUpError() { |
1178 // Define special error type constructors. | 1178 // Define special error type constructors. |
1179 | 1179 |
1180 var DefineError = function(f) { | 1180 var DefineError = function(f) { |
1181 // Store the error function in both the global object | 1181 // Store the error function in both the global object |
1182 // and the runtime object. The function is fetched | 1182 // and the runtime object. The function is fetched |
1183 // 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... | |
1299 } | 1299 } |
1300 | 1300 |
1301 | 1301 |
1302 InstallFunctions($Error.prototype, DONT_ENUM, ['toString', ErrorToString]); | 1302 InstallFunctions($Error.prototype, DONT_ENUM, ['toString', ErrorToString]); |
1303 | 1303 |
1304 // Boilerplate for exceptions for stack overflows. Used from | 1304 // Boilerplate for exceptions for stack overflows. Used from |
1305 // Isolate::StackOverflow(). | 1305 // Isolate::StackOverflow(). |
1306 function SetUpStackOverflowBoilerplate() { | 1306 function SetUpStackOverflowBoilerplate() { |
1307 var boilerplate = MakeRangeError('stack_overflow', []); | 1307 var boilerplate = MakeRangeError('stack_overflow', []); |
1308 | 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 %DefineOrRedefineDataProperty(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 %DefineOrRedefineAccessorProperty( | |
1337 holder, 'stack', function() { return result }, setter, DONT_ENUM); | |
1338 return result; | |
1339 }; | |
1340 | |
1341 %DefineOrRedefineAccessorProperty( | 1309 %DefineOrRedefineAccessorProperty( |
1342 boilerplate, 'stack', getter, setter, DONT_ENUM); | 1310 boilerplate, 'stack', StackTraceGetter, StackTraceSetter, DONT_ENUM); |
1343 | 1311 |
1344 return boilerplate; | 1312 return boilerplate; |
1345 } | 1313 } |
1346 | 1314 |
1347 var kStackOverflowBoilerplate = SetUpStackOverflowBoilerplate(); | 1315 var kStackOverflowBoilerplate = SetUpStackOverflowBoilerplate(); |
OLD | NEW |