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 1127 matching lines...) Loading... | |
1138 obj.stack = $Error.prepareStackTrace(obj, array); | 1138 obj.stack = $Error.prepareStackTrace(obj, array); |
1139 } catch (e) { | 1139 } catch (e) { |
1140 throw e; // The custom formatting function threw. Rethrow. | 1140 throw e; // The custom formatting function threw. Rethrow. |
1141 } finally { | 1141 } finally { |
1142 formatting_custom_stack_trace = false; | 1142 formatting_custom_stack_trace = false; |
1143 } | 1143 } |
1144 return; | 1144 return; |
1145 } | 1145 } |
1146 | 1146 |
1147 var error_string = FormatErrorString(obj); | 1147 var error_string = FormatErrorString(obj); |
1148 // Note that 'obj' and 'this' maybe different when called on objects that | 1148 // The holder of this getter ('obj') may not be the receiver ('this'). |
1149 // have the error object on its prototype chain. The getter replaces itself | 1149 // When this getter is called the first time, we use the context values to |
1150 // with a data property as soon as the stack trace has been formatted. | 1150 // format a stack trace string and turn this accessor pair into a data |
1151 // The getter must not change the object layout as it may be called after GC. | 1151 // property (on the holder). |
1152 var getter = function() { | 1152 var getter = function() { |
1153 if (IS_STRING(stack)) return stack; | |
1154 // Stack is still a raw array awaiting to be formatted. | 1153 // Stack is still a raw array awaiting to be formatted. |
1155 stack = FormatStackTrace(error_string, GetStackFrames(stack)); | 1154 var result = FormatStackTrace(error_string, GetStackFrames(stack)); |
1156 // Release context value. | 1155 // Turn this accessor into a data property. |
1157 error_string = void 0; | 1156 %DefineOrRedefineDataProperty(obj, 'stack', result, NONE); |
1158 return stack; | 1157 // Release context values. |
1158 stack = error_string = void 0; | |
1159 return result; | |
1159 }; | 1160 }; |
1160 %MarkOneShotGetter(getter); | |
1161 | 1161 |
1162 // The 'stack' property of the receiver is set as data property. If | 1162 // Set the 'stack' property on the receiver. If the receiver is the same as |
1163 // the receiver is the same as holder, this accessor pair is replaced. | 1163 // holder of this setter, the accessor pair is turned into a data property. |
1164 var setter = function(v) { | 1164 var setter = function(v) { |
1165 // Set data property on the receiver (not necessarily holder). | |
1165 %DefineOrRedefineDataProperty(this, 'stack', v, NONE); | 1166 %DefineOrRedefineDataProperty(this, 'stack', v, NONE); |
1167 if (this == obj) { | |
Michael Starzinger
2013/07/24 12:07:40
I think you want strict equality here.
| |
1168 // Release context values if holder is the same as the receiver. | |
1169 stack = error_string = void 0; | |
1170 } | |
1166 }; | 1171 }; |
1167 | 1172 |
1168 %DefineOrRedefineAccessorProperty(obj, 'stack', getter, setter, DONT_ENUM); | 1173 %DefineOrRedefineAccessorProperty(obj, 'stack', getter, setter, DONT_ENUM); |
1169 } | 1174 } |
1170 | 1175 |
1171 | 1176 |
1172 function SetUpError() { | 1177 function SetUpError() { |
1173 // Define special error type constructors. | 1178 // Define special error type constructors. |
1174 | 1179 |
1175 var DefineError = function(f) { | 1180 var DefineError = function(f) { |
(...skipping 117 matching lines...) Loading... | |
1293 } | 1298 } |
1294 | 1299 |
1295 | 1300 |
1296 InstallFunctions($Error.prototype, DONT_ENUM, ['toString', ErrorToString]); | 1301 InstallFunctions($Error.prototype, DONT_ENUM, ['toString', ErrorToString]); |
1297 | 1302 |
1298 // Boilerplate for exceptions for stack overflows. Used from | 1303 // Boilerplate for exceptions for stack overflows. Used from |
1299 // Isolate::StackOverflow(). | 1304 // Isolate::StackOverflow(). |
1300 function SetUpStackOverflowBoilerplate() { | 1305 function SetUpStackOverflowBoilerplate() { |
1301 var boilerplate = MakeRangeError('stack_overflow', []); | 1306 var boilerplate = MakeRangeError('stack_overflow', []); |
1302 | 1307 |
1303 // The raw stack trace is stored as hidden property of the copy of this | |
1304 // boilerplate error object. Note that the receiver 'this' may not be that | |
1305 // error object copy, but can be found on the prototype chain of 'this'. | |
1306 // When the stack trace is formatted, this accessor property is replaced by | |
1307 // a data property. | |
1308 var error_string = boilerplate.name + ": " + boilerplate.message; | 1308 var error_string = boilerplate.name + ": " + boilerplate.message; |
1309 | 1309 |
1310 // The getter must not change the object layout as it may be called after GC. | 1310 // The raw stack trace is stored as a hidden property on the holder of this |
1311 function getter() { | 1311 // getter, which may not be the same as the receiver. Find the holder to |
1312 // retrieve the raw stack trace and then turn this accessor pair into a | |
1313 // data property. | |
1314 var getter = function() { | |
1312 var holder = this; | 1315 var holder = this; |
1313 while (!IS_ERROR(holder)) { | 1316 while (!IS_ERROR(holder)) { |
1314 holder = %GetPrototype(holder); | 1317 holder = %GetPrototype(holder); |
1315 if (holder == null) return MakeSyntaxError('illegal_access', []); | 1318 if (holder == null) return MakeSyntaxError('illegal_access', []); |
1316 } | 1319 } |
1317 var stack = %GetOverflowedStackTrace(holder); | 1320 var stack = %GetAndClearOverflowedStackTrace(holder); |
1318 if (IS_STRING(stack)) return stack; | 1321 // We may not have captured any stack trace. |
1319 if (IS_ARRAY(stack)) { | 1322 if (IS_UNDEFINED(stack)) return stack; |
1320 var result = FormatStackTrace(error_string, GetStackFrames(stack)); | |
1321 %SetOverflowedStackTrace(holder, result); | |
1322 return result; | |
1323 } | |
1324 return void 0; | |
1325 } | |
1326 %MarkOneShotGetter(getter); | |
1327 | 1323 |
1328 // The 'stack' property of the receiver is set as data property. If | 1324 var result = FormatStackTrace(error_string, GetStackFrames(stack)); |
1329 // the receiver is the same as holder, this accessor pair is replaced. | 1325 // Replace this accessor with a data property. |
1330 function setter(v) { | 1326 %DefineOrRedefineDataProperty(holder, 'stack', result, NONE); |
1327 return result; | |
1328 }; | |
1329 | |
1330 // Set the 'stack' property on the receiver. If the receiver is the same as | |
1331 // holder of this setter, the accessor pair is turned into a data property. | |
1332 var setter = function(v) { | |
1331 %DefineOrRedefineDataProperty(this, 'stack', v, NONE); | 1333 %DefineOrRedefineDataProperty(this, 'stack', v, NONE); |
1332 // Release the stack trace that is stored as hidden property, if exists. | 1334 // Tentatively clear the hidden property. If the receiver is the same as |
1333 %SetOverflowedStackTrace(this, void 0); | 1335 // holder, we release the raw stack trace this way. |
1334 } | 1336 %GetAndClearOverflowedStackTrace(this); |
1337 }; | |
1335 | 1338 |
1336 %DefineOrRedefineAccessorProperty( | 1339 %DefineOrRedefineAccessorProperty( |
1337 boilerplate, 'stack', getter, setter, DONT_ENUM); | 1340 boilerplate, 'stack', getter, setter, DONT_ENUM); |
1338 | 1341 |
1339 return boilerplate; | 1342 return boilerplate; |
1340 } | 1343 } |
1341 | 1344 |
1342 var kStackOverflowBoilerplate = SetUpStackOverflowBoilerplate(); | 1345 var kStackOverflowBoilerplate = SetUpStackOverflowBoilerplate(); |
OLD | NEW |