You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by ra...@apache.org on 2012/01/27 02:37:13 UTC

[6/7] git commit: COUCHDB-111 and COUCHDB-1389 JS Error Tracebacks

COUCHDB-111 and COUCHDB-1389 JS Error Tracebacks

couchjs:
- report stacktraces on exceptions using JS_ReportError

- responds with a trace and message on errors when possible

- propogate Error-like objects from validate_doc_update to the loop

- make Error-like object play nicely with couch_os_process

couch.js:

- transform HTTP error response bodies into an Error instance to
  capture stack information

cli tests:

- print a stacktrace for individual test failures when running the suite

Fix COUCHDB-111
Fix COUCHDB-1389


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/32a11134
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/32a11134
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/32a11134

Branch: refs/heads/master
Commit: 32a1113417c25deee9052e7d3de37cc0faea9914
Parents: 5f55e9f
Author: Randall Leeds <ra...@apache.org>
Authored: Thu Dec 15 19:49:34 2011 -0800
Committer: Randall Leeds <ra...@apache.org>
Committed: Thu Jan 26 17:02:38 2012 -0800

----------------------------------------------------------------------
 share/server/loop.js              |    2 +
 share/server/validate.js          |    5 +++-
 share/www/script/couch.js         |   13 ++++++++-
 src/couchdb/priv/couch_js/sm170.c |    2 +
 src/couchdb/priv/couch_js/sm180.c |    2 +
 src/couchdb/priv/couch_js/sm185.c |    2 +
 src/couchdb/priv/couch_js/util.c  |   45 +++++++++++++++++++++++++++++++-
 test/javascript/cli_runner.js     |   19 ++++++-------
 8 files changed, 77 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/32a11134/share/server/loop.js
----------------------------------------------------------------------
diff --git a/share/server/loop.js b/share/server/loop.js
index eb7f75b..986c8b3 100644
--- a/share/server/loop.js
+++ b/share/server/loop.js
@@ -140,6 +140,8 @@ var Loop = function() {
     } else if (e.error && e.reason) {
       // compatibility with old error format
       respond(["error", e.error, e.reason]);
+    } else if (e.name) {
+      respond(["error", e.name, e]);
     } else {
       respond(["error","unnamed_error",e.toSource()]);
     }

http://git-wip-us.apache.org/repos/asf/couchdb/blob/32a11134/share/server/validate.js
----------------------------------------------------------------------
diff --git a/share/server/validate.js b/share/server/validate.js
index 76a1412..5b50e54 100644
--- a/share/server/validate.js
+++ b/share/server/validate.js
@@ -14,8 +14,11 @@ var Validate = {
   validate : function(fun, ddoc, args) {
     try {
       fun.apply(ddoc, args);
-      print("1");
+      respond(1);
     } catch (error) {
+      if (error.name && error.stack) {
+        throw error;
+      }
       respond(error);
     }
   }

http://git-wip-us.apache.org/repos/asf/couchdb/blob/32a11134/share/www/script/couch.js
----------------------------------------------------------------------
diff --git a/share/www/script/couch.js b/share/www/script/couch.js
index 86aaabf..d078d96 100644
--- a/share/www/script/couch.js
+++ b/share/www/script/couch.js
@@ -462,7 +462,8 @@ CouchDB.maybeThrowError = function(req) {
     } catch (ParseError) {
       var result = {error:"unknown", reason:req.responseText};
     }
-    throw result;
+
+    throw (new CouchError(result));
   }
 }
 
@@ -485,3 +486,13 @@ if (typeof window == 'undefined' || !window) {
   CouchDB.inBrowser = true;
   CouchDB.protocol = window.location.protocol + "//";
 }
+
+// Turns an {error: ..., reason: ...} response into an Error instance
+function CouchError(error) {
+  var inst = new Error(error.reason);
+  inst.name = 'CouchError';
+  inst.error = error.error;
+  inst.reason = error.reason;
+  return inst;
+}
+CouchError.prototype.constructor = CouchError;

http://git-wip-us.apache.org/repos/asf/couchdb/blob/32a11134/src/couchdb/priv/couch_js/sm170.c
----------------------------------------------------------------------
diff --git a/src/couchdb/priv/couch_js/sm170.c b/src/couchdb/priv/couch_js/sm170.c
index 796c1d6..bb28870 100644
--- a/src/couchdb/priv/couch_js/sm170.c
+++ b/src/couchdb/priv/couch_js/sm170.c
@@ -113,6 +113,7 @@ req_status(JSContext* cx, JSObject* obj, jsval idval, jsval* rval)
 
 
 static JSBool
+base_url(JSContext *cx, JSObject* obj, jsval idval, jsval* rval)
 evalcx(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 {
     JSString *str;
@@ -244,6 +245,7 @@ JSClass CouchHTTPClass = {
 
 JSPropertySpec CouchHTTPProperties[] = {
     {"status", 0, JSPROP_READONLY, req_status, NULL},
+    {"base_url", 0, JSPROP_READONLY | JSPROP_SHARED, base_url, NULL},
     {0, 0, 0, 0, 0}
 };
 

http://git-wip-us.apache.org/repos/asf/couchdb/blob/32a11134/src/couchdb/priv/couch_js/sm180.c
----------------------------------------------------------------------
diff --git a/src/couchdb/priv/couch_js/sm180.c b/src/couchdb/priv/couch_js/sm180.c
index 4d1bbf9..d7728a3 100644
--- a/src/couchdb/priv/couch_js/sm180.c
+++ b/src/couchdb/priv/couch_js/sm180.c
@@ -116,6 +116,7 @@ req_status(JSContext* cx, JSObject* obj, jsval idval, jsval* vp)
 
 
 static JSBool
+base_url(JSContext *cx, JSObject* obj, jsid pid, jsval* vp)
 evalcx(JSContext *cx, uintN argc, jsval* vp)
 {
     jsval* argv = JS_ARGV(cx, vp);
@@ -253,6 +254,7 @@ JSClass CouchHTTPClass = {
 
 JSPropertySpec CouchHTTPProperties[] = {
     {"status", 0, JSPROP_READONLY, req_status, NULL},
+    {"base_url", 0, JSPROP_READONLY | JSPROP_SHARED, base_url, NULL},
     {0, 0, 0, 0, 0}
 };
 

http://git-wip-us.apache.org/repos/asf/couchdb/blob/32a11134/src/couchdb/priv/couch_js/sm185.c
----------------------------------------------------------------------
diff --git a/src/couchdb/priv/couch_js/sm185.c b/src/couchdb/priv/couch_js/sm185.c
index 8c4e536..7757514 100644
--- a/src/couchdb/priv/couch_js/sm185.c
+++ b/src/couchdb/priv/couch_js/sm185.c
@@ -134,6 +134,7 @@ req_status(JSContext* cx, JSObject* obj, jsid pid, jsval* vp)
 
 
 static JSBool
+base_url(JSContext *cx, JSObject* obj, jsid pid, jsval* vp)
 evalcx(JSContext *cx, uintN argc, jsval* vp)
 {
     jsval* argv = JS_ARGV(cx, vp);
@@ -279,6 +280,7 @@ JSClass CouchHTTPClass = {
 
 JSPropertySpec CouchHTTPProperties[] = {
     {"status", 0, JSPROP_READONLY, req_status, NULL},
+    {"base_url", 0, JSPROP_READONLY | JSPROP_SHARED, base_url, NULL},
     {0, 0, 0, 0, 0}
 };
 

http://git-wip-us.apache.org/repos/asf/couchdb/blob/32a11134/src/couchdb/priv/couch_js/util.c
----------------------------------------------------------------------
diff --git a/src/couchdb/priv/couch_js/util.c b/src/couchdb/priv/couch_js/util.c
index 0b1e92a..b7bd3e4 100644
--- a/src/couchdb/priv/couch_js/util.c
+++ b/src/couchdb/priv/couch_js/util.c
@@ -227,9 +227,52 @@ couch_print(JSContext* cx, uintN argc, jsval* argv)
 void
 couch_error(JSContext* cx, const char* mesg, JSErrorReport* report)
 {
+    jsval v, replace;
+    char* bytes;
+    JSObject* regexp, *stack;
+    jsval re_args[2];
+
     if(!report || !JSREPORT_IS_WARNING(report->flags))
     {
-        fprintf(stderr, "[couchjs] %s\n", mesg);
+        fprintf(stderr, "%s\n", mesg);
+
+        // Print a stack trace, if available.
+        if (JSREPORT_IS_EXCEPTION(report->flags) &&
+            JS_GetPendingException(cx, &v))
+        {
+            // Clear the exception before an JS method calls or the result is
+            // infinite, recursive error report generation.
+            JS_ClearPendingException(cx);
+
+            // Use JS regexp to indent the stack trace.
+            // If the regexp can't be created, don't JS_ReportError since it is
+            // probably not productive to wind up here again.
+#ifdef SM185
+            if(JS_GetProperty(cx, JSVAL_TO_OBJECT(v), "stack", &v) &&
+               (regexp = JS_NewRegExpObjectNoStatics(
+                   cx, "^(?=.)", 6, JSREG_GLOB | JSREG_MULTILINE)))
+#else
+            if(JS_GetProperty(cx, JSVAL_TO_OBJECT(v), "stack", &v) &&
+               (regexp = JS_NewRegExpObject(
+                   cx, "^(?=.)", 6, JSREG_GLOB | JSREG_MULTILINE)))
+#endif
+            {
+                // Set up the arguments to ``String.replace()``
+                re_args[0] = OBJECT_TO_JSVAL(regexp);
+                re_args[1] = STRING_TO_JSVAL(JS_InternString(cx, "\t"));
+
+                // Perform the replacement
+                if(JS_ValueToObject(cx, v, &stack) &&
+                   JS_GetProperty(cx, stack, "replace", &replace) &&
+                   JS_CallFunctionValue(cx, stack, replace, 2, re_args, &v))
+                {
+                    // Print the result
+                    bytes = enc_string(cx, v, NULL);
+                    fprintf(stderr, "Stacktrace:\n%s", bytes);
+                    JS_free(cx, bytes);
+                }
+            }
+        }
     }
 }
 

http://git-wip-us.apache.org/repos/asf/couchdb/blob/32a11134/test/javascript/cli_runner.js
----------------------------------------------------------------------
diff --git a/test/javascript/cli_runner.js b/test/javascript/cli_runner.js
index 6683ede..d9d7fce 100644
--- a/test/javascript/cli_runner.js
+++ b/test/javascript/cli_runner.js
@@ -19,7 +19,8 @@ var console = {
 
 function T(arg1, arg2) {
   if(!arg1) {
-    throw((arg2 ? arg2 : arg1).toString());
+    var result = (arg2 ? arg2 : arg1);
+    throw((result instanceof Error ? result : Error(result)));
   }
 }
 
@@ -28,9 +29,11 @@ function runTestConsole(num, name, func) {
     func();
     print("ok " + num + " " + name);
   } catch(e) {
-    msg = e.toString();
-    msg = msg.replace(/\n/g, "\n    ");
-    print("not ok " + num + " " + name + " " + msg);
+    print("not ok " + num + " " + name);
+    print("# " + e.toSource());
+    if (e.stack) {
+      print("# Stacktrace:\n" + e.stack.replace(/^/gm, "\t"));
+    }
   }
 }
 
@@ -45,9 +48,5 @@ function runAllTestsConsole() {
   }
 };
 
-try {
-  waitForSuccess(CouchDB.getVersion);
-  runAllTestsConsole();
-} catch (e) {
-  p("# " + e.toString());
-}
+waitForSuccess(CouchDB.getVersion);
+runAllTestsConsole();