Revision: 2545
Author: [email protected]
Date: Tue Jul 28 01:14:49 2009
Log: Merge r2541 and r2542 to branches/1.2.
Review URL: http://codereview.chromium.org/160263
http://code.google.com/p/v8/source/detail?r=2545

Modified:
  /branches/1.2/src/messages.js
  /branches/1.2/src/runtime.cc
  /branches/1.2/src/version.cc
  /branches/1.2/test/mjsunit/stack-traces.js

=======================================
--- /branches/1.2/src/messages.js       Wed Jul  8 23:00:35 2009
+++ /branches/1.2/src/messages.js       Tue Jul 28 01:14:49 2009
@@ -561,20 +561,24 @@
  var kAddMessageAccessorsMarker = { };

  // Defines accessors for a property that is calculated the first time
-// the property is read and then replaces the accessor with the value.
-// Also, setting the property causes the accessors to be deleted.
+// the property is read.
  function DefineOneShotAccessor(obj, name, fun) {
    // Note that the accessors consistently operate on 'obj', not 'this'.
    // Since the object may occur in someone else's prototype chain we
    // can't rely on 'this' being the same as 'obj'.
+  var hasBeenSet = false;
+  var value;
    obj.__defineGetter__(name, function () {
-    var value = fun(obj);
-    obj[name] = value;
+    if (hasBeenSet) {
+      return value;
+    }
+    hasBeenSet = true;
+    value = fun(obj);
      return value;
    });
    obj.__defineSetter__(name, function (v) {
-    delete obj[name];
-    obj[name] = v;
+    hasBeenSet = true;
+    value = v;
    });
  }

@@ -833,22 +837,25 @@
        } else if (!IS_UNDEFINED(m)) {
          this.message = ToString(m);
        }
-      var stackTraceLimit = $Error.stackTraceLimit;
-      if (stackTraceLimit) {
-        // Cap the limit to avoid extremely big traces
-        if (stackTraceLimit < 0 || stackTraceLimit > 10000)
-          stackTraceLimit = 10000;
-        var raw_stack = %CollectStackTrace(f, stackTraceLimit);
-        DefineOneShotAccessor(this, 'stack', function (obj) {
-          return FormatRawStackTrace(obj, raw_stack);
-        });
-      }
+      captureStackTrace(this, f);
      } else {
        return new f(m);
      }
    });
  }

+function captureStackTrace(obj, cons_opt) {
+  var stackTraceLimit = $Error.stackTraceLimit;
+  if (!stackTraceLimit) return;
+  if (stackTraceLimit < 0 || stackTraceLimit > 10000)
+    stackTraceLimit = 10000;
+  var raw_stack = %CollectStackTrace(cons_opt ? cons_opt :  
captureStackTrace,
+      stackTraceLimit);
+  DefineOneShotAccessor(obj, 'stack', function (obj) {
+    return FormatRawStackTrace(obj, raw_stack);
+  });
+};
+
  $Math.__proto__ = global.Object.prototype;

  DefineError(function Error() { });
@@ -859,6 +866,8 @@
  DefineError(function EvalError() { });
  DefineError(function URIError() { });

+$Error.captureStackTrace = captureStackTrace;
+
  // Setup extra properties of the Error.prototype object.
  $Error.prototype.message = '';

=======================================
--- /branches/1.2/src/runtime.cc        Mon Jul 13 07:04:26 2009
+++ /branches/1.2/src/runtime.cc        Tue Jul 28 01:14:49 2009
@@ -7408,14 +7408,15 @@
    // Not sure when this can happen but skip it just in case.
    if (!raw_fun->IsJSFunction())
      return false;
-  if ((raw_fun == caller) && !(*seen_caller) && frame->IsConstructor()) {
+  if ((raw_fun == caller) && !(*seen_caller)) {
      *seen_caller = true;
      return false;
    }
-  // Skip the most obvious builtin calls.  Some builtin calls (such as
-  // Number.ADD which is invoked using 'call') are very difficult to
-  // recognize so we're leaving them in for now.
-  return !frame->receiver()->IsJSBuiltinsObject();
+  // Skip all frames until we've seen the caller.  Also, skip the most
+  // obvious builtin calls.  Some builtin calls (such as Number.ADD
+  // which is invoked using 'call') are very difficult to recognize
+  // so we're leaving them in for now.
+  return *seen_caller && !frame->receiver()->IsJSBuiltinsObject();
  }


@@ -7424,7 +7425,7 @@
  // code offset.
  static Object* Runtime_CollectStackTrace(Arguments args) {
    ASSERT_EQ(args.length(), 2);
-  Object* caller = args[0];
+  Handle<Object> caller = args.at<Object>(0);
    CONVERT_NUMBER_CHECKED(int32_t, limit, Int32, args[1]);

    HandleScope scope;
@@ -7433,12 +7434,14 @@
    Handle<JSArray> result = Factory::NewJSArray(initial_size * 3);

    StackFrameIterator iter;
-  bool seen_caller = false;
+  // If the caller parameter is a function we skip frames until we're
+  // under it before starting to collect.
+  bool seen_caller = !caller->IsJSFunction();
    int cursor = 0;
    int frames_seen = 0;
    while (!iter.done() && frames_seen < limit) {
      StackFrame* raw_frame = iter.frame();
-    if (ShowFrameInStackTrace(raw_frame, caller, &seen_caller)) {
+    if (ShowFrameInStackTrace(raw_frame, *caller, &seen_caller)) {
        frames_seen++;
        JavaScriptFrame* frame = JavaScriptFrame::cast(raw_frame);
        Object* recv = frame->receiver();
@@ -7453,8 +7456,10 @@
          elements->set(cursor++, offset, SKIP_WRITE_BARRIER);
        } else {
          HandleScope scope;
-        SetElement(result, cursor++, Handle<Object>(recv));
-        SetElement(result, cursor++, Handle<Object>(fun));
+        Handle<Object> recv_handle(recv);
+        Handle<Object> fun_handle(fun);
+        SetElement(result, cursor++, recv_handle);
+        SetElement(result, cursor++, fun_handle);
          SetElement(result, cursor++, Handle<Smi>(offset));
        }
      }
=======================================
--- /branches/1.2/src/version.cc        Thu Jul 23 07:57:42 2009
+++ /branches/1.2/src/version.cc        Tue Jul 28 01:14:49 2009
@@ -35,7 +35,7 @@
  #define MAJOR_VERSION     1
  #define MINOR_VERSION     2
  #define BUILD_NUMBER      14
-#define PATCH_LEVEL       6
+#define PATCH_LEVEL       7
  #define CANDIDATE_VERSION false

  // Define SONAME to have the SCons build the put a specific SONAME into the
=======================================
--- /branches/1.2/test/mjsunit/stack-traces.js  Mon Jul  6 01:21:57 2009
+++ /branches/1.2/test/mjsunit/stack-traces.js  Tue Jul 28 01:14:49 2009
@@ -83,10 +83,27 @@
  function testAnonymousMethod() {
    (function () { FAIL }).call([1, 2, 3]);
  }
+
+function CustomError(message, stripPoint) {
+  this.message = message;
+  Error.captureStackTrace(this, stripPoint);
+}
+
+CustomError.prototype.toString = function () {
+  return "CustomError: " + this.message;
+};
+
+function testDefaultCustomError() {
+  throw new CustomError("hep-hey", undefined);
+}
+
+function testStrippedCustomError() {
+  throw new CustomError("hep-hey", CustomError);
+}

  // Utility function for testing that the expected strings occur
  // in the stack trace produced when running the given function.
-function testTrace(fun, expected) {
+function testTrace(fun, expected, unexpected) {
    var threw = false;
    try {
      fun();
@@ -94,6 +111,11 @@
      for (var i = 0; i < expected.length; i++) {
        assertTrue(e.stack.indexOf(expected[i]) != -1);
      }
+    if (unexpected) {
+      for (var i = 0; i < unexpected.length; i++) {
+        assertEquals(e.stack.indexOf(unexpected[i]), -1);
+      }
+    }
      threw = true;
    }
    assertTrue(threw);
@@ -165,6 +187,10 @@
  testTrace(testConstructor, ["new Plonk"]);
  testTrace(testRenamedMethod, ["Wookie.a$b$c$d [as d]"]);
  testTrace(testAnonymousMethod, ["Array.<anonymous>"]);
+testTrace(testDefaultCustomError, ["hep-hey", "new CustomError"],
+    ["collectStackTrace"]);
+testTrace(testStrippedCustomError, ["hep-hey"], ["new CustomError",
+    "collectStackTrace"]);

  testCallerCensorship();
  testUnintendedCallerCensorship();

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

Reply via email to