summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJason Carey <jcarey@argv.me>2015-07-31 18:18:07 -0400
committerJason Carey <jcarey@argv.me>2015-08-10 14:42:34 -0400
commitdf71fbb001ce204c9f60b9ec66b1178b851cdbb4 (patch)
treea7bac74c1f97333c510948c7d8a6e71e0afa47ae /src
parentbed94851c02602dcf4ba9dcec376cfda7f33e657 (diff)
downloadmongo-df71fbb001ce204c9f60b9ec66b1178b851cdbb4.tar.gz
SERVER-19705 unmix MozJS and Mongo Error Codes
SpiderMonkey error codes overlap with Mongo error codes in thrown user assertions. Avoid that by lifting our error codes above theirs.
Diffstat (limited to 'src')
-rw-r--r--src/mongo/dbtests/jstests.cpp38
-rw-r--r--src/mongo/scripting/mozjs/exception.cpp34
-rw-r--r--src/mongo/scripting/mozjs/exception.h8
-rw-r--r--src/mongo/scripting/mozjs/implscope.cpp7
-rw-r--r--src/mongo/scripting/mozjs/jsthread.cpp2
5 files changed, 75 insertions, 14 deletions
diff --git a/src/mongo/dbtests/jstests.cpp b/src/mongo/dbtests/jstests.cpp
index 4723fcf9b96..4a4ebb408a4 100644
--- a/src/mongo/dbtests/jstests.cpp
+++ b/src/mongo/dbtests/jstests.cpp
@@ -2175,6 +2175,43 @@ public:
}
};
+class ErrorCodeFromInvoke {
+public:
+ void run() {
+ unique_ptr<Scope> s(globalScriptEngine->newScope());
+
+ {
+ bool threwException = false;
+ try {
+ s->invoke("\"use strict\"; x = 10;", 0, 0);
+ } catch (...) {
+ threwException = true;
+
+ auto status = exceptionToStatus();
+
+ ASSERT_EQUALS(status.code(), ErrorCodes::JSInterpreterFailure);
+ }
+
+ ASSERT(threwException);
+ }
+
+ {
+ bool threwException = false;
+ try {
+ s->invoke("UUID(1,2,3,4,5);", 0, 0);
+ } catch (...) {
+ threwException = true;
+
+ auto status = exceptionToStatus();
+
+ ASSERT_EQUALS(status.code(), ErrorCodes::BadValue);
+ }
+
+ ASSERT(threwException);
+ }
+ }
+};
+
class All : public Suite {
public:
All() : Suite("js") {
@@ -2226,6 +2263,7 @@ public:
add<NoReturnSpecified>();
add<RecursiveInvoke>();
+ add<ErrorCodeFromInvoke>();
add<RoundTripTests::DBRefTest>();
add<RoundTripTests::DBPointerTest>();
diff --git a/src/mongo/scripting/mozjs/exception.cpp b/src/mongo/scripting/mozjs/exception.cpp
index 1d6880da05f..e54de1fa5ca 100644
--- a/src/mongo/scripting/mozjs/exception.cpp
+++ b/src/mongo/scripting/mozjs/exception.cpp
@@ -31,6 +31,7 @@
#include "mongo/scripting/mozjs/exception.h"
#include <jsfriendapi.h>
+#include <limits>
#include "mongo/scripting/mozjs/jsstringwrapper.h"
#include "mongo/util/assert_util.h"
@@ -50,6 +51,9 @@ const JSErrorFormatString* uncatchableErrorCallback(void* data, const unsigned c
return &kUncatchableErrorFormatString;
}
+static_assert(std::numeric_limits<std::uint32_t>::max() - JSErr_Limit > ErrorCodes::MaxError,
+ "Not enough space in an unsigned int for Mongo ErrorCodes and JSErrorNumbers");
+
} // namespace
void mongoToJSException(JSContext* cx) {
@@ -58,14 +62,15 @@ void mongoToJSException(JSContext* cx) {
auto callback =
status.code() == ErrorCodes::JSUncatchableError ? uncatchableErrorCallback : errorCallback;
- JS_ReportErrorNumber(cx, callback, nullptr, status.code(), status.reason().c_str());
+ JS_ReportErrorNumber(
+ cx, callback, nullptr, JSErr_Limit + status.code(), status.reason().c_str());
}
void setJSException(JSContext* cx, ErrorCodes::Error code, StringData sd) {
auto callback =
code == ErrorCodes::JSUncatchableError ? uncatchableErrorCallback : errorCallback;
- JS_ReportErrorNumber(cx, callback, nullptr, code, sd.rawData());
+ JS_ReportErrorNumber(cx, callback, nullptr, JSErr_Limit + code, sd.rawData());
}
Status currentJSExceptionToStatus(JSContext* cx, ErrorCodes::Error altCode, StringData altReason) {
@@ -78,17 +83,28 @@ Status currentJSExceptionToStatus(JSContext* cx, ErrorCodes::Error altCode, Stri
if (!report)
return Status(altCode, altReason.rawData());
+ return JSErrorReportToStatus(cx, report, altCode, altReason);
+}
+
+Status JSErrorReportToStatus(JSContext* cx,
+ JSErrorReport* report,
+ ErrorCodes::Error altCode,
+ StringData altReason) {
JSStringWrapper jsstr(cx, js::ErrorReportToString(cx, report));
if (!jsstr)
return Status(altCode, altReason.rawData());
- /**
- * errorNumber is only set by library consumers of MozJS, and then only via
- * JS_ReportErrorNumber, so all of the codes we see here are ours.
- */
- return Status(report->errorNumber ? static_cast<ErrorCodes::Error>(report->errorNumber)
- : altCode,
- jsstr.toStringData().toString());
+ ErrorCodes::Error error = altCode;
+
+ if (report->errorNumber) {
+ if (report->errorNumber < JSErr_Limit) {
+ error = ErrorCodes::JSInterpreterFailure;
+ } else {
+ error = static_cast<ErrorCodes::Error>(report->errorNumber - JSErr_Limit);
+ }
+ }
+
+ return Status(error, jsstr.toStringData().toString());
}
void throwCurrentJSException(JSContext* cx, ErrorCodes::Error altCode, StringData altReason) {
diff --git a/src/mongo/scripting/mozjs/exception.h b/src/mongo/scripting/mozjs/exception.h
index 9ef48664db6..b3dcbfa67bb 100644
--- a/src/mongo/scripting/mozjs/exception.h
+++ b/src/mongo/scripting/mozjs/exception.h
@@ -55,6 +55,14 @@ void setJSException(JSContext* cx, ErrorCodes::Error code, StringData sd);
Status currentJSExceptionToStatus(JSContext* cx, ErrorCodes::Error altCode, StringData altReason);
/**
+ * Converts a JSErrorReport to status
+ */
+Status JSErrorReportToStatus(JSContext* cx,
+ JSErrorReport* report,
+ ErrorCodes::Error altCode,
+ StringData altReason);
+
+/**
* Turns the current JS exception into a C++ exception
*
* The altCode and altReason are used if no JS exception is pending
diff --git a/src/mongo/scripting/mozjs/implscope.cpp b/src/mongo/scripting/mozjs/implscope.cpp
index f77c130d9f4..0c110ec546a 100644
--- a/src/mongo/scripting/mozjs/implscope.cpp
+++ b/src/mongo/scripting/mozjs/implscope.cpp
@@ -114,10 +114,9 @@ void MozJSImplScope::_reportError(JSContext* cx, const char* message, JSErrorRep
ss << " :\n" << ValueWriter(cx, stack).toString();
}
- scope->_status =
- Status(report->errorNumber ? static_cast<ErrorCodes::Error>(report->errorNumber)
- : ErrorCodes::JSInterpreterFailure,
- ss);
+ scope->_status = Status(
+ JSErrorReportToStatus(cx, report, ErrorCodes::JSInterpreterFailure, message).code(),
+ ss);
}
}
diff --git a/src/mongo/scripting/mozjs/jsthread.cpp b/src/mongo/scripting/mozjs/jsthread.cpp
index 9d409fa9beb..4a3b441a885 100644
--- a/src/mongo/scripting/mozjs/jsthread.cpp
+++ b/src/mongo/scripting/mozjs/jsthread.cpp
@@ -177,7 +177,7 @@ private:
} catch (...) {
auto status = exceptionToStatus();
- log() << "js thread raised js exception: " << status;
+ log() << "js thread raised js exception: " << status.reason();
_sharedData->setErrored(true);
_sharedData->_returnData = BSON("ret" << BSONUndefined);
}