}
-function FormatStackTrace(error_string, frames) {
+// Flag to prevent recursive call of Error.prepareStackTrace.
+var formatting_custom_stack_trace = false;
+
+
+function FormatStackTrace(obj, error_string, frames) {
+ if (IS_FUNCTION($Error.prepareStackTrace) && !formatting_custom_stack_trace) {
+ var array = [];
+ %MoveArrayContents(frames, array);
+ formatting_custom_stack_trace = true;
+ var stack_trace = void 0;
+ try {
+ stack_trace = $Error.prepareStackTrace(obj, array);
+ } catch (e) {
+ throw e; // The custom formatting function threw. Rethrow.
+ } finally {
+ formatting_custom_stack_trace = false;
+ }
+ return stack_trace;
+ }
+
var lines = new InternalArray();
lines.push(error_string);
for (var i = 0; i < frames.length; i++) {
}
-// Flag to prevent recursive call of Error.prepareStackTrace.
-var formatting_custom_stack_trace = false;
-
-
function captureStackTrace(obj, cons_opt) {
var stackTraceLimit = $Error.stackTraceLimit;
if (!stackTraceLimit || !IS_NUMBER(stackTraceLimit)) return;
cons_opt ? cons_opt : captureStackTrace,
stackTraceLimit);
- // Don't be lazy if the error stack formatting is custom (observable).
- if (IS_FUNCTION($Error.prepareStackTrace) && !formatting_custom_stack_trace) {
- var array = [];
- %MoveArrayContents(GetStackFrames(stack), array);
- formatting_custom_stack_trace = true;
- try {
- obj.stack = $Error.prepareStackTrace(obj, array);
- } catch (e) {
- throw e; // The custom formatting function threw. Rethrow.
- } finally {
- formatting_custom_stack_trace = false;
- }
- return;
- }
-
var error_string = FormatErrorString(obj);
// The holder of this getter ('obj') may not be the receiver ('this').
// When this getter is called the first time, we use the context values to
// property (on the holder).
var getter = function() {
// Stack is still a raw array awaiting to be formatted.
- var result = FormatStackTrace(error_string, GetStackFrames(stack));
+ var result = FormatStackTrace(obj, error_string, GetStackFrames(stack));
// Turn this accessor into a data property.
%DefineOrRedefineDataProperty(obj, 'stack', result, NONE);
// Release context values.
// We may not have captured any stack trace.
if (IS_UNDEFINED(stack)) return stack;
- var result = FormatStackTrace(error_string, GetStackFrames(stack));
+ var result = FormatStackTrace(holder, error_string, GetStackFrames(stack));
// Replace this accessor with a data property.
%DefineOrRedefineDataProperty(holder, 'stack', result, NONE);
return result;
--- /dev/null
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+function testPrepareStackTrace(closure) {
+ var error = undefined;
+ try {
+ closure();
+ assertUnreachable();
+ } catch (e) {
+ error = e;
+ }
+
+ // We expect custom formatting to be lazy. Setting the custom
+ // function right before calling error.stack should be fine.
+ Error.prepareStackTrace = function(e, frames) {
+ return "bar";
+ }
+
+ assertEquals("bar", error.stack);
+ Error.prepareStackTrace = undefined;
+}
+
+testPrepareStackTrace(function() { throw new Error("foo"); });
+testPrepareStackTrace(function f() { f(); });
+