Chromium Code Reviews| 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...) Expand 10 before | Expand all | Expand 10 after 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...) Expand 10 before | Expand all | Expand 10 after 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 |