Reviewers: Vyacheslav Egorov,

Message:
Not sure whether this makes sense, as this is not really part of the spec.
Basically this changes chaining Errors when rethrown from this

try {
  error;
} catch (e) {
  throw new Error(e.stack);
}

to
try {
  error;
} catch (e) {
  throw new Error(e);
}

Also see the thread here:
http://code.google.com/p/chromium/issues/detail?id=60240

Description:
Include stack trace to error message when constructing a new Error with another
Error as argument.


BUG=60240
TEST=cctest/RethrowWrapStackTrace

Please review this at http://codereview.chromium.org/9333001/

SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge

Affected files:
  M src/messages.js
  M test/cctest/test-api.cc


Index: src/messages.js
diff --git a/src/messages.js b/src/messages.js
index cd4add4bcba5fe773f1ff848844bf082e6f6abb3..2edf2f21565a064d74f7dd909585afab28a35abb 100644
--- a/src/messages.js
+++ b/src/messages.js
@@ -1137,10 +1137,11 @@ function SetUpError() {
return FormatMessage(%NewMessageObject(obj.type, obj.arguments));
           });
         } else if (!IS_UNDEFINED(m)) {
-          %IgnoreAttributesAndSetProperty(this,
-                                          'message',
-                                          ToString(m),
-                                          DONT_ENUM);
+          %IgnoreAttributesAndSetProperty(
+              this,
+              'message',
+              (m instanceof $Error) ? m.stack : ToString(m),
+              DONT_ENUM);
         }
         captureStackTrace(this, f);
       } else {
Index: test/cctest/test-api.cc
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index b8cd7099990b36f96eacad21b145099ea351673e..fd8c0c62df1d900ff956df7415e27ed9abf1194f 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -13538,7 +13538,6 @@ TEST(CaptureStackTraceForUncaughtExceptionAndSetters) {
 static void RethrowStackTraceHandler(v8::Handle<v8::Message> message,
                                      v8::Handle<v8::Value> data) {
   // Use the frame where JavaScript is called from.
-  v8::Handle<v8::String> error_message = message->Get();
   v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
   CHECK(!stack_trace.IsEmpty());
   int frame_count = stack_trace->GetFrameCount();
@@ -13580,9 +13579,58 @@ TEST(RethrowStackTrace) {
 }


+static void RethrowWrapStackTraceHandler(v8::Handle<v8::Message> message,
+                                         v8::Handle<v8::Value> data) {
+  // Use the frame where JavaScript is called from.
+  v8::Handle<v8::String> error_message = message->Get();
+  CHECK_EQ("Uncaught Error: ReferenceError: error is not defined\n"
+           "    at g (unknown source)\n"
+           "    at f (unknown source)\n"
+           "    at unknown source",
+           *v8::String::AsciiValue(error_message));
+  v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
+  CHECK(!stack_trace.IsEmpty());
+  int frame_count = stack_trace->GetFrameCount();
+  CHECK_EQ(2, frame_count);
+  int line_number[] = {3, 10};
+  for (int i = 0; i < frame_count; i++) {
+    CHECK_EQ(line_number[i], stack_trace->GetFrame(i)->GetLineNumber());
+  }
+}
+
+
+// Test that we only return the stack trace at the site where the exception
+// is first thrown (not where it is rethrown).
+TEST(RethrowWrapStackTrace) {
+  v8::HandleScope scope;
+  LocalContext env;
+  // We make sure that
+  // - the stack trace of the ReferenceError in g() is reported.
+  // - the stack trace is not overwritten when e1 is rethrown by t().
+  // - the stack trace of e2 does not overwrite that of e1.
+  const char* source =
+      "function g() { error; }               \n"
+      "function f() { g(); }                 \n"
+      "function t(e) { throw new Error(e); } \n"
+      "try {                                 \n"
+      "  f();                                \n"
+      "} catch (e1) {                        \n"
+      "  try {                               \n"
+      "    error;                            \n"
+      "  } catch (e2) {                      \n"
+      "    t(e1);                            \n"
+      "  }                                   \n"
+      "}                                     \n";
+  v8::V8::AddMessageListener(RethrowWrapStackTraceHandler);
+  v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
+  CompileRun(source);
+  v8::V8::SetCaptureStackTraceForUncaughtExceptions(false);
+  v8::V8::RemoveMessageListeners(RethrowWrapStackTraceHandler);
+}
+
+
static void RethrowPrimitiveStackTraceHandler(v8::Handle<v8::Message> message,
                                               v8::Handle<v8::Value> data) {
-  v8::Handle<v8::String> error_message = message->Get();
   v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
   CHECK(!stack_trace.IsEmpty());
   int frame_count = stack_trace->GetFrameCount();
@@ -13620,7 +13668,6 @@ TEST(RethrowPrimitiveStackTrace) {
static void RethrowExistingStackTraceHandler(v8::Handle<v8::Message> message,
                                               v8::Handle<v8::Value> data) {
   // Use the frame where JavaScript is called from.
-  v8::Handle<v8::String> error_message = message->Get();
   v8::Handle<v8::StackTrace> stack_trace = message->GetStackTrace();
   CHECK(!stack_trace.IsEmpty());
   CHECK_EQ(1, stack_trace->GetFrameCount());


--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to