summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJason Carey <jcarey@argv.me>2015-09-14 16:19:11 -0400
committerJason Carey <jcarey@argv.me>2015-09-17 20:13:11 -0400
commit041e4fe737342bf40a6aedb7a04d8d99ba20e213 (patch)
tree148c21a538fd93bddf8a1982d463400d73984060 /src
parent8291bbb3a6ec192d177076b1fb0cd28995e48440 (diff)
downloadmongo-041e4fe737342bf40a6aedb7a04d8d99ba20e213.tar.gz
SERVER-20375 Constrain JS method thisv
This constrains universal access to wraptype methods by providing a JS_ATTACH_JS_CONSTRAINED_METHOD() macro which allows for a list of types that are allowed to call said method. In this way we can lock down all methods without having to add uasserts to each individual method body.
Diffstat (limited to 'src')
-rw-r--r--src/mongo/scripting/mozjs/bindata.cpp25
-rw-r--r--src/mongo/scripting/mozjs/bindata.h12
-rw-r--r--src/mongo/scripting/mozjs/bson.cpp4
-rw-r--r--src/mongo/scripting/mozjs/bson.h2
-rw-r--r--src/mongo/scripting/mozjs/countdownlatch.cpp8
-rw-r--r--src/mongo/scripting/mozjs/countdownlatch.h8
-rw-r--r--src/mongo/scripting/mozjs/cursor.cpp17
-rw-r--r--src/mongo/scripting/mozjs/cursor.h8
-rw-r--r--src/mongo/scripting/mozjs/cursor_handle.cpp5
-rw-r--r--src/mongo/scripting/mozjs/cursor_handle.h2
-rw-r--r--src/mongo/scripting/mozjs/db.cpp4
-rw-r--r--src/mongo/scripting/mozjs/dbcollection.cpp2
-rw-r--r--src/mongo/scripting/mozjs/dbpointer.cpp4
-rw-r--r--src/mongo/scripting/mozjs/dbquery.cpp2
-rw-r--r--src/mongo/scripting/mozjs/dbref.cpp2
-rw-r--r--src/mongo/scripting/mozjs/exception.cpp2
-rw-r--r--src/mongo/scripting/mozjs/global.cpp6
-rw-r--r--src/mongo/scripting/mozjs/global.h6
-rw-r--r--src/mongo/scripting/mozjs/implscope.h82
-rw-r--r--src/mongo/scripting/mozjs/jsthread.cpp25
-rw-r--r--src/mongo/scripting/mozjs/jsthread.h14
-rw-r--r--src/mongo/scripting/mozjs/maxkey.cpp11
-rw-r--r--src/mongo/scripting/mozjs/maxkey.h2
-rw-r--r--src/mongo/scripting/mozjs/minkey.cpp11
-rw-r--r--src/mongo/scripting/mozjs/minkey.h2
-rw-r--r--src/mongo/scripting/mozjs/mongo.cpp85
-rw-r--r--src/mongo/scripting/mozjs/mongo.h34
-rw-r--r--src/mongo/scripting/mozjs/mongohelpers.cpp2
-rw-r--r--src/mongo/scripting/mozjs/nativefunction.cpp9
-rw-r--r--src/mongo/scripting/mozjs/nativefunction.h2
-rw-r--r--src/mongo/scripting/mozjs/numberdecimal.cpp9
-rw-r--r--src/mongo/scripting/mozjs/numberdecimal.h2
-rw-r--r--src/mongo/scripting/mozjs/numberint.cpp17
-rw-r--r--src/mongo/scripting/mozjs/numberint.h6
-rw-r--r--src/mongo/scripting/mozjs/numberlong.cpp21
-rw-r--r--src/mongo/scripting/mozjs/numberlong.h8
-rw-r--r--src/mongo/scripting/mozjs/object.cpp4
-rw-r--r--src/mongo/scripting/mozjs/object.h4
-rw-r--r--src/mongo/scripting/mozjs/objectwrapper.cpp14
-rw-r--r--src/mongo/scripting/mozjs/objectwrapper.h2
-rw-r--r--src/mongo/scripting/mozjs/oid.cpp7
-rw-r--r--src/mongo/scripting/mozjs/oid.h2
-rw-r--r--src/mongo/scripting/mozjs/timestamp.cpp2
-rw-r--r--src/mongo/scripting/mozjs/valuereader.cpp24
-rw-r--r--src/mongo/scripting/mozjs/valuewriter.cpp59
-rw-r--r--src/mongo/scripting/mozjs/valuewriter.h5
-rw-r--r--src/mongo/scripting/mozjs/wrapconstrainedmethod.h123
-rw-r--r--src/mongo/scripting/mozjs/wraptype.h75
48 files changed, 512 insertions, 270 deletions
diff --git a/src/mongo/scripting/mozjs/bindata.cpp b/src/mongo/scripting/mozjs/bindata.cpp
index 42ae6c1b491..e9f10cae125 100644
--- a/src/mongo/scripting/mozjs/bindata.cpp
+++ b/src/mongo/scripting/mozjs/bindata.cpp
@@ -37,6 +37,7 @@
#include "mongo/scripting/mozjs/objectwrapper.h"
#include "mongo/scripting/mozjs/valuereader.h"
#include "mongo/scripting/mozjs/valuewriter.h"
+#include "mongo/scripting/mozjs/wrapconstrainedmethod.h"
#include "mongo/util/base64.h"
#include "mongo/util/hex.h"
#include "mongo/util/mongoutils/str.h"
@@ -45,9 +46,9 @@ namespace mongo {
namespace mozjs {
const JSFunctionSpec BinDataInfo::methods[4] = {
- MONGO_ATTACH_JS_FUNCTION(base64),
- MONGO_ATTACH_JS_FUNCTION(hex),
- MONGO_ATTACH_JS_FUNCTION(toString),
+ MONGO_ATTACH_JS_CONSTRAINED_METHOD_NO_PROTO(base64, BinDataInfo),
+ MONGO_ATTACH_JS_CONSTRAINED_METHOD_NO_PROTO(hex, BinDataInfo),
+ MONGO_ATTACH_JS_CONSTRAINED_METHOD_NO_PROTO(toString, BinDataInfo),
JS_FS_END,
};
@@ -89,7 +90,7 @@ void hexToBinData(JSContext* cx,
args[0].setInt32(type);
ValueReader(cx, args[1]).fromStringData(encoded);
- return scope->getBinDataProto().newInstance(args, out);
+ return scope->getProto<BinDataInfo>().newInstance(args, out);
}
std::string* getEncoded(JS::HandleValue thisv) {
@@ -110,7 +111,7 @@ void BinDataInfo::finalize(JSFreeOp* fop, JSObject* obj) {
}
}
-void BinDataInfo::Functions::UUID(JSContext* cx, JS::CallArgs args) {
+void BinDataInfo::Functions::UUID::call(JSContext* cx, JS::CallArgs args) {
if (args.length() != 1)
uasserted(ErrorCodes::BadValue, "UUID needs 1 argument");
@@ -123,7 +124,7 @@ void BinDataInfo::Functions::UUID(JSContext* cx, JS::CallArgs args) {
hexToBinData(cx, bdtUUID, arg, args.rval());
}
-void BinDataInfo::Functions::MD5(JSContext* cx, JS::CallArgs args) {
+void BinDataInfo::Functions::MD5::call(JSContext* cx, JS::CallArgs args) {
if (args.length() != 1)
uasserted(ErrorCodes::BadValue, "MD5 needs 1 argument");
@@ -136,7 +137,7 @@ void BinDataInfo::Functions::MD5(JSContext* cx, JS::CallArgs args) {
hexToBinData(cx, MD5Type, arg, args.rval());
}
-void BinDataInfo::Functions::HexData(JSContext* cx, JS::CallArgs args) {
+void BinDataInfo::Functions::HexData::call(JSContext* cx, JS::CallArgs args) {
if (args.length() != 2)
uasserted(ErrorCodes::BadValue, "HexData needs 2 arguments");
@@ -149,7 +150,7 @@ void BinDataInfo::Functions::HexData(JSContext* cx, JS::CallArgs args) {
hexToBinData(cx, type.toInt32(), args.get(1), args.rval());
}
-void BinDataInfo::Functions::toString(JSContext* cx, JS::CallArgs args) {
+void BinDataInfo::Functions::toString::call(JSContext* cx, JS::CallArgs args) {
ObjectWrapper o(cx, args.thisv());
auto str = getEncoded(args.thisv());
@@ -161,16 +162,16 @@ void BinDataInfo::Functions::toString(JSContext* cx, JS::CallArgs args) {
ValueReader(cx, args.rval()).fromStringData(ss.operator std::string());
}
-void BinDataInfo::Functions::base64(JSContext* cx, JS::CallArgs args) {
+void BinDataInfo::Functions::base64::call(JSContext* cx, JS::CallArgs args) {
auto str = getEncoded(args.thisv());
ValueReader(cx, args.rval()).fromStringData(*str);
}
-void BinDataInfo::Functions::hex(JSContext* cx, JS::CallArgs args) {
+void BinDataInfo::Functions::hex::call(JSContext* cx, JS::CallArgs args) {
auto str = getEncoded(args.thisv());
- std::string data = base64::decode(*str);
+ std::string data = mongo::base64::decode(*str);
std::stringstream ss;
ss.setf(std::ios_base::hex, std::ios_base::basefield);
ss.fill('0');
@@ -208,7 +209,7 @@ void BinDataInfo::construct(JSContext* cx, JS::CallArgs args) {
auto tmpBase64 = base64::decode(str);
JS::RootedObject thisv(cx);
- scope->getBinDataProto().newObject(&thisv);
+ scope->getProto<BinDataInfo>().newObject(&thisv);
ObjectWrapper o(cx, thisv);
JS::RootedValue len(cx);
diff --git a/src/mongo/scripting/mozjs/bindata.h b/src/mongo/scripting/mozjs/bindata.h
index 85b504230ff..57a4f158949 100644
--- a/src/mongo/scripting/mozjs/bindata.h
+++ b/src/mongo/scripting/mozjs/bindata.h
@@ -43,13 +43,13 @@ struct BinDataInfo : public BaseInfo {
static void finalize(JSFreeOp* fop, JSObject* obj);
struct Functions {
- MONGO_DEFINE_JS_FUNCTION(base64);
- MONGO_DEFINE_JS_FUNCTION(hex);
- MONGO_DEFINE_JS_FUNCTION(toString);
+ MONGO_DECLARE_JS_FUNCTION(base64);
+ MONGO_DECLARE_JS_FUNCTION(hex);
+ MONGO_DECLARE_JS_FUNCTION(toString);
- MONGO_DEFINE_JS_FUNCTION(HexData);
- MONGO_DEFINE_JS_FUNCTION(MD5);
- MONGO_DEFINE_JS_FUNCTION(UUID);
+ MONGO_DECLARE_JS_FUNCTION(HexData);
+ MONGO_DECLARE_JS_FUNCTION(MD5);
+ MONGO_DECLARE_JS_FUNCTION(UUID);
};
static const JSFunctionSpec methods[4];
diff --git a/src/mongo/scripting/mozjs/bson.cpp b/src/mongo/scripting/mozjs/bson.cpp
index 9c972a6b3fc..2dd1d717dc3 100644
--- a/src/mongo/scripting/mozjs/bson.cpp
+++ b/src/mongo/scripting/mozjs/bson.cpp
@@ -75,7 +75,7 @@ BSONHolder* getHolder(JSObject* obj) {
void BSONInfo::make(JSContext* cx, JS::MutableHandleObject obj, BSONObj bson, bool ro) {
auto scope = getScope(cx);
- scope->getBsonProto().newObject(obj);
+ scope->getProto<BSONInfo>().newObject(obj);
JS_SetPrivate(obj, new BSONHolder(bson, ro));
}
@@ -202,7 +202,7 @@ std::tuple<BSONObj*, bool> BSONInfo::originalBSON(JSContext* cx, JS::HandleObjec
return out;
}
-void BSONInfo::Functions::bsonWoCompare(JSContext* cx, JS::CallArgs args) {
+void BSONInfo::Functions::bsonWoCompare::call(JSContext* cx, JS::CallArgs args) {
if (args.length() != 2)
uasserted(ErrorCodes::BadValue, "bsonWoCompare needs 2 argument");
diff --git a/src/mongo/scripting/mozjs/bson.h b/src/mongo/scripting/mozjs/bson.h
index 3b150801793..82e1e5d0cdb 100644
--- a/src/mongo/scripting/mozjs/bson.h
+++ b/src/mongo/scripting/mozjs/bson.h
@@ -63,7 +63,7 @@ struct BSONInfo : public BaseInfo {
static void postInstall(JSContext* cx, JS::HandleObject global, JS::HandleObject proto);
struct Functions {
- MONGO_DEFINE_JS_FUNCTION(bsonWoCompare);
+ MONGO_DECLARE_JS_FUNCTION(bsonWoCompare);
};
static const JSFunctionSpec freeFunctions[2];
diff --git a/src/mongo/scripting/mozjs/countdownlatch.cpp b/src/mongo/scripting/mozjs/countdownlatch.cpp
index bf7ae4ff551..9ca93be7618 100644
--- a/src/mongo/scripting/mozjs/countdownlatch.cpp
+++ b/src/mongo/scripting/mozjs/countdownlatch.cpp
@@ -130,7 +130,7 @@ namespace {
CountDownLatchHolder globalCountDownLatchHolder;
} // namespace
-void CountDownLatchInfo::Functions::_new(JSContext* cx, JS::CallArgs args) {
+void CountDownLatchInfo::Functions::_new::call(JSContext* cx, JS::CallArgs args) {
uassert(ErrorCodes::JSInterpreterFailure, "need exactly one argument", args.length() == 1);
uassert(
ErrorCodes::JSInterpreterFailure, "argument must be an integer", args.get(0).isNumber());
@@ -138,7 +138,7 @@ void CountDownLatchInfo::Functions::_new(JSContext* cx, JS::CallArgs args) {
args.rval().setInt32(globalCountDownLatchHolder.make(args.get(0).toNumber()));
}
-void CountDownLatchInfo::Functions::_await(JSContext* cx, JS::CallArgs args) {
+void CountDownLatchInfo::Functions::_await::call(JSContext* cx, JS::CallArgs args) {
uassert(ErrorCodes::JSInterpreterFailure, "need exactly one argument", args.length() == 1);
uassert(
ErrorCodes::JSInterpreterFailure, "argument must be an integer", args.get(0).isNumber());
@@ -148,7 +148,7 @@ void CountDownLatchInfo::Functions::_await(JSContext* cx, JS::CallArgs args) {
args.rval().setUndefined();
}
-void CountDownLatchInfo::Functions::_countDown(JSContext* cx, JS::CallArgs args) {
+void CountDownLatchInfo::Functions::_countDown::call(JSContext* cx, JS::CallArgs args) {
uassert(ErrorCodes::JSInterpreterFailure, "need exactly one argument", args.length() == 1);
uassert(
ErrorCodes::JSInterpreterFailure, "argument must be an integer", args.get(0).isNumber());
@@ -158,7 +158,7 @@ void CountDownLatchInfo::Functions::_countDown(JSContext* cx, JS::CallArgs args)
args.rval().setUndefined();
}
-void CountDownLatchInfo::Functions::_getCount(JSContext* cx, JS::CallArgs args) {
+void CountDownLatchInfo::Functions::_getCount::call(JSContext* cx, JS::CallArgs args) {
uassert(ErrorCodes::JSInterpreterFailure, "need exactly one argument", args.length() == 1);
uassert(
ErrorCodes::JSInterpreterFailure, "argument must be an integer", args.get(0).isNumber());
diff --git a/src/mongo/scripting/mozjs/countdownlatch.h b/src/mongo/scripting/mozjs/countdownlatch.h
index 07001ebf473..b13f26d69eb 100644
--- a/src/mongo/scripting/mozjs/countdownlatch.h
+++ b/src/mongo/scripting/mozjs/countdownlatch.h
@@ -43,10 +43,10 @@ namespace mozjs {
*/
struct CountDownLatchInfo : public BaseInfo {
struct Functions {
- MONGO_DEFINE_JS_FUNCTION(_new);
- MONGO_DEFINE_JS_FUNCTION(_await);
- MONGO_DEFINE_JS_FUNCTION(_countDown);
- MONGO_DEFINE_JS_FUNCTION(_getCount);
+ MONGO_DECLARE_JS_FUNCTION(_new);
+ MONGO_DECLARE_JS_FUNCTION(_await);
+ MONGO_DECLARE_JS_FUNCTION(_countDown);
+ MONGO_DECLARE_JS_FUNCTION(_getCount);
};
static const JSFunctionSpec methods[5];
diff --git a/src/mongo/scripting/mozjs/cursor.cpp b/src/mongo/scripting/mozjs/cursor.cpp
index 8660287a13a..7968480f4ff 100644
--- a/src/mongo/scripting/mozjs/cursor.cpp
+++ b/src/mongo/scripting/mozjs/cursor.cpp
@@ -34,15 +34,16 @@
#include "mongo/scripting/mozjs/implscope.h"
#include "mongo/scripting/mozjs/objectwrapper.h"
#include "mongo/scripting/mozjs/valuereader.h"
+#include "mongo/scripting/mozjs/wrapconstrainedmethod.h"
namespace mongo {
namespace mozjs {
const JSFunctionSpec CursorInfo::methods[5] = {
- MONGO_ATTACH_JS_FUNCTION(hasNext),
- MONGO_ATTACH_JS_FUNCTION(next),
- MONGO_ATTACH_JS_FUNCTION(objsLeftInBatch),
- MONGO_ATTACH_JS_FUNCTION(readOnly),
+ MONGO_ATTACH_JS_CONSTRAINED_METHOD_NO_PROTO(hasNext, CursorInfo),
+ MONGO_ATTACH_JS_CONSTRAINED_METHOD_NO_PROTO(next, CursorInfo),
+ MONGO_ATTACH_JS_CONSTRAINED_METHOD_NO_PROTO(objsLeftInBatch, CursorInfo),
+ MONGO_ATTACH_JS_CONSTRAINED_METHOD_NO_PROTO(readOnly, CursorInfo),
JS_FS_END,
};
@@ -68,7 +69,7 @@ void CursorInfo::finalize(JSFreeOp* fop, JSObject* obj) {
}
}
-void CursorInfo::Functions::next(JSContext* cx, JS::CallArgs args) {
+void CursorInfo::Functions::next::call(JSContext* cx, JS::CallArgs args) {
auto cursor = getCursor(args);
if (!cursor) {
@@ -84,7 +85,7 @@ void CursorInfo::Functions::next(JSContext* cx, JS::CallArgs args) {
ValueReader(cx, args.rval()).fromBSON(bson, ro);
}
-void CursorInfo::Functions::hasNext(JSContext* cx, JS::CallArgs args) {
+void CursorInfo::Functions::hasNext::call(JSContext* cx, JS::CallArgs args) {
auto cursor = getCursor(args);
if (!cursor) {
@@ -95,7 +96,7 @@ void CursorInfo::Functions::hasNext(JSContext* cx, JS::CallArgs args) {
args.rval().setBoolean(cursor->more());
}
-void CursorInfo::Functions::objsLeftInBatch(JSContext* cx, JS::CallArgs args) {
+void CursorInfo::Functions::objsLeftInBatch::call(JSContext* cx, JS::CallArgs args) {
auto cursor = getCursor(args);
if (!cursor) {
@@ -106,7 +107,7 @@ void CursorInfo::Functions::objsLeftInBatch(JSContext* cx, JS::CallArgs args) {
args.rval().setInt32(cursor->objsLeftInBatch());
}
-void CursorInfo::Functions::readOnly(JSContext* cx, JS::CallArgs args) {
+void CursorInfo::Functions::readOnly::call(JSContext* cx, JS::CallArgs args) {
ObjectWrapper(cx, args.thisv()).setBoolean("_ro", true);
args.rval().set(args.thisv());
diff --git a/src/mongo/scripting/mozjs/cursor.h b/src/mongo/scripting/mozjs/cursor.h
index 87bd8e1de80..b354152a027 100644
--- a/src/mongo/scripting/mozjs/cursor.h
+++ b/src/mongo/scripting/mozjs/cursor.h
@@ -45,10 +45,10 @@ struct CursorInfo : public BaseInfo {
static void finalize(JSFreeOp* fop, JSObject* obj);
struct Functions {
- MONGO_DEFINE_JS_FUNCTION(hasNext);
- MONGO_DEFINE_JS_FUNCTION(next);
- MONGO_DEFINE_JS_FUNCTION(objsLeftInBatch);
- MONGO_DEFINE_JS_FUNCTION(readOnly);
+ MONGO_DECLARE_JS_FUNCTION(hasNext);
+ MONGO_DECLARE_JS_FUNCTION(next);
+ MONGO_DECLARE_JS_FUNCTION(objsLeftInBatch);
+ MONGO_DECLARE_JS_FUNCTION(readOnly);
};
static const JSFunctionSpec methods[5];
diff --git a/src/mongo/scripting/mozjs/cursor_handle.cpp b/src/mongo/scripting/mozjs/cursor_handle.cpp
index fcdc3dd525b..c74c7438331 100644
--- a/src/mongo/scripting/mozjs/cursor_handle.cpp
+++ b/src/mongo/scripting/mozjs/cursor_handle.cpp
@@ -33,13 +33,14 @@
#include "mongo/scripting/mozjs/cursor_handle.h"
#include "mongo/scripting/mozjs/implscope.h"
+#include "mongo/scripting/mozjs/wrapconstrainedmethod.h"
#include "mongo/util/log.h"
namespace mongo {
namespace mozjs {
const JSFunctionSpec CursorHandleInfo::methods[2] = {
- MONGO_ATTACH_JS_FUNCTION(zeroCursorId), JS_FS_END,
+ MONGO_ATTACH_JS_CONSTRAINED_METHOD_NO_PROTO(zeroCursorId, CursorHandleInfo), JS_FS_END,
};
const char* const CursorHandleInfo::className = "CursorHandle";
@@ -84,7 +85,7 @@ void CursorHandleInfo::finalize(JSFreeOp* fop, JSObject* obj) {
}
}
-void CursorHandleInfo::Functions::zeroCursorId(JSContext* cx, JS::CallArgs args) {
+void CursorHandleInfo::Functions::zeroCursorId::call(JSContext* cx, JS::CallArgs args) {
long long* cursorId = getCursorId(args);
if (cursorId) {
*cursorId = 0;
diff --git a/src/mongo/scripting/mozjs/cursor_handle.h b/src/mongo/scripting/mozjs/cursor_handle.h
index 792b382ae5e..71bc963d7c3 100644
--- a/src/mongo/scripting/mozjs/cursor_handle.h
+++ b/src/mongo/scripting/mozjs/cursor_handle.h
@@ -45,7 +45,7 @@ struct CursorHandleInfo : public BaseInfo {
static void finalize(JSFreeOp* fop, JSObject* obj);
struct Functions {
- MONGO_DEFINE_JS_FUNCTION(zeroCursorId);
+ MONGO_DECLARE_JS_FUNCTION(zeroCursorId);
};
static const JSFunctionSpec methods[2];
diff --git a/src/mongo/scripting/mozjs/db.cpp b/src/mongo/scripting/mozjs/db.cpp
index 851d6f3e49f..9a5d45b0984 100644
--- a/src/mongo/scripting/mozjs/db.cpp
+++ b/src/mongo/scripting/mozjs/db.cpp
@@ -100,7 +100,7 @@ void DBInfo::getProperty(JSContext* cx,
uassert(16861,
"getCollection returned something other than a collection",
- scope->getDbCollectionProto().instanceOf(coll));
+ scope->getProto<DBCollectionInfo>().instanceOf(coll));
// cache collection for reuse, don't enumerate
ObjectWrapper(cx, obj).defineProperty(sname.c_str(), coll, 0);
@@ -121,7 +121,7 @@ void DBInfo::construct(JSContext* cx, JS::CallArgs args) {
}
JS::RootedObject thisv(cx);
- scope->getDbProto().newObject(&thisv);
+ scope->getProto<DBInfo>().newObject(&thisv);
ObjectWrapper o(cx, thisv);
o.setValue("_mongo", args.get(0));
diff --git a/src/mongo/scripting/mozjs/dbcollection.cpp b/src/mongo/scripting/mozjs/dbcollection.cpp
index fd8bc086676..c4814251839 100644
--- a/src/mongo/scripting/mozjs/dbcollection.cpp
+++ b/src/mongo/scripting/mozjs/dbcollection.cpp
@@ -64,7 +64,7 @@ void DBCollectionInfo::construct(JSContext* cx, JS::CallArgs args) {
}
JS::RootedObject thisv(cx);
- scope->getDbCollectionProto().newObject(&thisv);
+ scope->getProto<DBCollectionInfo>().newObject(&thisv);
ObjectWrapper o(cx, thisv);
o.setValue("_mongo", args.get(0));
diff --git a/src/mongo/scripting/mozjs/dbpointer.cpp b/src/mongo/scripting/mozjs/dbpointer.cpp
index fbfb8282649..20c3882ba72 100644
--- a/src/mongo/scripting/mozjs/dbpointer.cpp
+++ b/src/mongo/scripting/mozjs/dbpointer.cpp
@@ -49,11 +49,11 @@ void DBPointerInfo::construct(JSContext* cx, JS::CallArgs args) {
if (!args.get(0).isString())
uasserted(ErrorCodes::BadValue, "DBPointer 1st parameter must be a string");
- if (!scope->getOidProto().instanceOf(args.get(1)))
+ if (!scope->getProto<OIDInfo>().instanceOf(args.get(1)))
uasserted(ErrorCodes::BadValue, "DBPointer 2nd parameter must be an ObjectId");
JS::RootedObject thisv(cx);
- scope->getDbPointerProto().newObject(&thisv);
+ scope->getProto<DBPointerInfo>().newObject(&thisv);
ObjectWrapper o(cx, thisv);
o.setValue("ns", args.get(0));
diff --git a/src/mongo/scripting/mozjs/dbquery.cpp b/src/mongo/scripting/mozjs/dbquery.cpp
index e9bddf4b30e..d3c68538884 100644
--- a/src/mongo/scripting/mozjs/dbquery.cpp
+++ b/src/mongo/scripting/mozjs/dbquery.cpp
@@ -46,7 +46,7 @@ void DBQueryInfo::construct(JSContext* cx, JS::CallArgs args) {
uasserted(ErrorCodes::BadValue, "dbQuery constructor requires at least 4 arguments");
JS::RootedObject thisv(cx);
- scope->getDbQueryProto().newObject(&thisv);
+ scope->getProto<DBQueryInfo>().newObject(&thisv);
ObjectWrapper o(cx, thisv);
o.setValue("_mongo", args.get(0));
diff --git a/src/mongo/scripting/mozjs/dbref.cpp b/src/mongo/scripting/mozjs/dbref.cpp
index 16ad0058084..4200ebaa67f 100644
--- a/src/mongo/scripting/mozjs/dbref.cpp
+++ b/src/mongo/scripting/mozjs/dbref.cpp
@@ -48,7 +48,7 @@ void DBRefInfo::construct(JSContext* cx, JS::CallArgs args) {
uasserted(ErrorCodes::BadValue, "DBRef 1st parameter must be a string");
JS::RootedObject thisv(cx);
- scope->getDbRefProto().newObject(&thisv);
+ scope->getProto<DBRefInfo>().newObject(&thisv);
ObjectWrapper o(cx, thisv);
o.setValue("$ref", args.get(0));
diff --git a/src/mongo/scripting/mozjs/exception.cpp b/src/mongo/scripting/mozjs/exception.cpp
index 8350d4f3ef1..28ab1545dac 100644
--- a/src/mongo/scripting/mozjs/exception.cpp
+++ b/src/mongo/scripting/mozjs/exception.cpp
@@ -79,7 +79,7 @@ std::string currentJSStackToString(JSContext* cx) {
auto scope = getScope(cx);
JS::RootedValue error(cx);
- scope->getErrorProto().newInstance(&error);
+ scope->getProto<ErrorInfo>().newInstance(&error);
return ObjectWrapper(cx, error).getString("stack");
}
diff --git a/src/mongo/scripting/mozjs/global.cpp b/src/mongo/scripting/mozjs/global.cpp
index d8c6da94e35..b3bdbec47b0 100644
--- a/src/mongo/scripting/mozjs/global.cpp
+++ b/src/mongo/scripting/mozjs/global.cpp
@@ -57,7 +57,7 @@ logger::MessageLogDomain* jsPrintLogDomain;
} // namespace
-void GlobalInfo::Functions::print(JSContext* cx, JS::CallArgs args) {
+void GlobalInfo::Functions::print::call(JSContext* cx, JS::CallArgs args) {
logger::LogstreamBuilder builder(jsPrintLogDomain, getThreadName(), logger::LogSeverity::Log());
std::ostream& ss = builder.stream();
@@ -82,11 +82,11 @@ void GlobalInfo::Functions::print(JSContext* cx, JS::CallArgs args) {
args.rval().setUndefined();
}
-void GlobalInfo::Functions::version(JSContext* cx, JS::CallArgs args) {
+void GlobalInfo::Functions::version::call(JSContext* cx, JS::CallArgs args) {
ValueReader(cx, args.rval()).fromStringData(JS_VersionToString(JS_GetVersion(cx)));
}
-void GlobalInfo::Functions::gc(JSContext* cx, JS::CallArgs args) {
+void GlobalInfo::Functions::gc::call(JSContext* cx, JS::CallArgs args) {
auto scope = getScope(cx);
scope->gc();
diff --git a/src/mongo/scripting/mozjs/global.h b/src/mongo/scripting/mozjs/global.h
index 1da83350137..8e002b57a90 100644
--- a/src/mongo/scripting/mozjs/global.h
+++ b/src/mongo/scripting/mozjs/global.h
@@ -41,9 +41,9 @@ namespace mozjs {
*/
struct GlobalInfo : public BaseInfo {
struct Functions {
- MONGO_DEFINE_JS_FUNCTION(gc);
- MONGO_DEFINE_JS_FUNCTION(print);
- MONGO_DEFINE_JS_FUNCTION(version);
+ MONGO_DECLARE_JS_FUNCTION(gc);
+ MONGO_DECLARE_JS_FUNCTION(print);
+ MONGO_DECLARE_JS_FUNCTION(version);
};
static const JSFunctionSpec freeFunctions[4];
diff --git a/src/mongo/scripting/mozjs/implscope.h b/src/mongo/scripting/mozjs/implscope.h
index a01365fa2d1..5b464d1461f 100644
--- a/src/mongo/scripting/mozjs/implscope.h
+++ b/src/mongo/scripting/mozjs/implscope.h
@@ -147,103 +147,135 @@ public:
BSONObj callThreadArgs(const BSONObj& obj);
- WrapType<BinDataInfo>& getBinDataProto() {
+ template <typename T>
+ typename std::enable_if<std::is_same<T, BinDataInfo>::value, WrapType<T>&>::type getProto() {
return _binDataProto;
}
- WrapType<BSONInfo>& getBsonProto() {
+ template <typename T>
+ typename std::enable_if<std::is_same<T, BSONInfo>::value, WrapType<T>&>::type getProto() {
return _bsonProto;
}
- WrapType<CountDownLatchInfo>& getCountDownLatchProto() {
+ template <typename T>
+ typename std::enable_if<std::is_same<T, CountDownLatchInfo>::value, WrapType<T>&>::type
+ getProto() {
return _countDownLatchProto;
}
- WrapType<CursorInfo>& getCursorProto() {
+ template <typename T>
+ typename std::enable_if<std::is_same<T, CursorInfo>::value, WrapType<T>&>::type getProto() {
return _cursorProto;
}
- WrapType<CursorHandleInfo>& getCursorHandleProto() {
+ template <typename T>
+ typename std::enable_if<std::is_same<T, CursorHandleInfo>::value, WrapType<T>&>::type
+ getProto() {
return _cursorHandleProto;
}
- WrapType<DBCollectionInfo>& getDbCollectionProto() {
+ template <typename T>
+ typename std::enable_if<std::is_same<T, DBCollectionInfo>::value, WrapType<T>&>::type
+ getProto() {
return _dbCollectionProto;
}
- WrapType<DBPointerInfo>& getDbPointerProto() {
+ template <typename T>
+ typename std::enable_if<std::is_same<T, DBPointerInfo>::value, WrapType<T>&>::type getProto() {
return _dbPointerProto;
}
- WrapType<DBQueryInfo>& getDbQueryProto() {
+ template <typename T>
+ typename std::enable_if<std::is_same<T, DBQueryInfo>::value, WrapType<T>&>::type getProto() {
return _dbQueryProto;
}
- WrapType<DBInfo>& getDbProto() {
+ template <typename T>
+ typename std::enable_if<std::is_same<T, DBInfo>::value, WrapType<T>&>::type getProto() {
return _dbProto;
}
- WrapType<DBRefInfo>& getDbRefProto() {
+ template <typename T>
+ typename std::enable_if<std::is_same<T, DBRefInfo>::value, WrapType<T>&>::type getProto() {
return _dbRefProto;
}
- WrapType<ErrorInfo>& getErrorProto() {
+ template <typename T>
+ typename std::enable_if<std::is_same<T, ErrorInfo>::value, WrapType<T>&>::type getProto() {
return _errorProto;
}
- WrapType<JSThreadInfo>& getJSThreadProto() {
+ template <typename T>
+ typename std::enable_if<std::is_same<T, JSThreadInfo>::value, WrapType<T>&>::type getProto() {
return _jsThreadProto;
}
- WrapType<MaxKeyInfo>& getMaxKeyProto() {
+ template <typename T>
+ typename std::enable_if<std::is_same<T, MaxKeyInfo>::value, WrapType<T>&>::type getProto() {
return _maxKeyProto;
}
- WrapType<MinKeyInfo>& getMinKeyProto() {
+ template <typename T>
+ typename std::enable_if<std::is_same<T, MinKeyInfo>::value, WrapType<T>&>::type getProto() {
return _minKeyProto;
}
- WrapType<MongoExternalInfo>& getMongoExternalProto() {
+ template <typename T>
+ typename std::enable_if<std::is_same<T, MongoExternalInfo>::value, WrapType<T>&>::type
+ getProto() {
return _mongoExternalProto;
}
- WrapType<MongoHelpersInfo>& getMongoHelpersProto() {
+ template <typename T>
+ typename std::enable_if<std::is_same<T, MongoHelpersInfo>::value, WrapType<T>&>::type
+ getProto() {
return _mongoHelpersProto;
}
- WrapType<MongoLocalInfo>& getMongoLocalProto() {
+ template <typename T>
+ typename std::enable_if<std::is_same<T, MongoLocalInfo>::value, WrapType<T>&>::type getProto() {
return _mongoLocalProto;
}
- WrapType<NativeFunctionInfo>& getNativeFunctionProto() {
+ template <typename T>
+ typename std::enable_if<std::is_same<T, NativeFunctionInfo>::value, WrapType<T>&>::type
+ getProto() {
return _nativeFunctionProto;
}
- WrapType<NumberIntInfo>& getNumberIntProto() {
+ template <typename T>
+ typename std::enable_if<std::is_same<T, NumberIntInfo>::value, WrapType<T>&>::type getProto() {
return _numberIntProto;
}
- WrapType<NumberLongInfo>& getNumberLongProto() {
+ template <typename T>
+ typename std::enable_if<std::is_same<T, NumberLongInfo>::value, WrapType<T>&>::type getProto() {
return _numberLongProto;
}
- WrapType<NumberDecimalInfo>& getNumberDecimalProto() {
+ template <typename T>
+ typename std::enable_if<std::is_same<T, NumberDecimalInfo>::value, WrapType<T>&>::type
+ getProto() {
return _numberDecimalProto;
}
- WrapType<ObjectInfo>& getObjectProto() {
+ template <typename T>
+ typename std::enable_if<std::is_same<T, ObjectInfo>::value, WrapType<T>&>::type getProto() {
return _objectProto;
}
- WrapType<OIDInfo>& getOidProto() {
+ template <typename T>
+ typename std::enable_if<std::is_same<T, OIDInfo>::value, WrapType<T>&>::type getProto() {
return _oidProto;
}
- WrapType<RegExpInfo>& getRegExpProto() {
+ template <typename T>
+ typename std::enable_if<std::is_same<T, RegExpInfo>::value, WrapType<T>&>::type getProto() {
return _regExpProto;
}
- WrapType<TimestampInfo>& getTimestampProto() {
+ template <typename T>
+ typename std::enable_if<std::is_same<T, TimestampInfo>::value, WrapType<T>&>::type getProto() {
return _timestampProto;
}
diff --git a/src/mongo/scripting/mozjs/jsthread.cpp b/src/mongo/scripting/mozjs/jsthread.cpp
index 0813a369dc2..3b457851efd 100644
--- a/src/mongo/scripting/mozjs/jsthread.cpp
+++ b/src/mongo/scripting/mozjs/jsthread.cpp
@@ -48,6 +48,8 @@
namespace mongo {
namespace mozjs {
+// These are all executed on some object that owns a js thread, rather than a
+// jsthread itself, so CONSTRAINED_METHOD doesn't do the job here.
const JSFunctionSpec JSThreadInfo::threadMethods[6] = {
MONGO_ATTACH_JS_FUNCTION(init),
MONGO_ATTACH_JS_FUNCTION(start),
@@ -211,7 +213,10 @@ JSThreadConfig* getConfig(JSContext* cx, JS::CallArgs args) {
ObjectWrapper(cx, args.thisv()).getValue("_JSThreadConfig", &value);
if (!value.isObject())
- uasserted(ErrorCodes::InternalError, "_JSThreadConfig not an object");
+ uasserted(ErrorCodes::BadValue, "_JSThreadConfig not an object");
+
+ if (!getScope(cx)->getProto<JSThreadInfo>().instanceOf(value))
+ uasserted(ErrorCodes::BadValue, "_JSThreadConfig is not a JSThread");
return static_cast<JSThreadConfig*>(JS_GetPrivate(value.toObjectOrNull()));
}
@@ -227,11 +232,11 @@ void JSThreadInfo::finalize(JSFreeOp* fop, JSObject* obj) {
delete config;
}
-void JSThreadInfo::Functions::init(JSContext* cx, JS::CallArgs args) {
+void JSThreadInfo::Functions::init::call(JSContext* cx, JS::CallArgs args) {
auto scope = getScope(cx);
JS::RootedObject obj(cx);
- scope->getJSThreadProto().newObject(&obj);
+ scope->getProto<JSThreadInfo>().newObject(&obj);
JSThreadConfig* config = new JSThreadConfig(cx, args);
JS_SetPrivate(obj, config);
@@ -240,28 +245,28 @@ void JSThreadInfo::Functions::init(JSContext* cx, JS::CallArgs args) {
args.rval().setUndefined();
}
-void JSThreadInfo::Functions::start(JSContext* cx, JS::CallArgs args) {
+void JSThreadInfo::Functions::start::call(JSContext* cx, JS::CallArgs args) {
getConfig(cx, args)->start();
args.rval().setUndefined();
}
-void JSThreadInfo::Functions::join(JSContext* cx, JS::CallArgs args) {
+void JSThreadInfo::Functions::join::call(JSContext* cx, JS::CallArgs args) {
getConfig(cx, args)->join();
args.rval().setUndefined();
}
-void JSThreadInfo::Functions::hasFailed(JSContext* cx, JS::CallArgs args) {
+void JSThreadInfo::Functions::hasFailed::call(JSContext* cx, JS::CallArgs args) {
args.rval().setBoolean(getConfig(cx, args)->hasFailed());
}
-void JSThreadInfo::Functions::returnData(JSContext* cx, JS::CallArgs args) {
+void JSThreadInfo::Functions::returnData::call(JSContext* cx, JS::CallArgs args) {
ValueReader(cx, args.rval())
.fromBSONElement(getConfig(cx, args)->returnData().firstElement(), true);
}
-void JSThreadInfo::Functions::_threadInject(JSContext* cx, JS::CallArgs args) {
+void JSThreadInfo::Functions::_threadInject::call(JSContext* cx, JS::CallArgs args) {
uassert(ErrorCodes::JSInterpreterFailure,
"threadInject takes exactly 1 argument",
args.length() == 1);
@@ -277,8 +282,8 @@ void JSThreadInfo::Functions::_threadInject(JSContext* cx, JS::CallArgs args) {
args.rval().setUndefined();
}
-void JSThreadInfo::Functions::_scopedThreadInject(JSContext* cx, JS::CallArgs args) {
- _threadInject(cx, args);
+void JSThreadInfo::Functions::_scopedThreadInject::call(JSContext* cx, JS::CallArgs args) {
+ _threadInject::call(cx, args);
}
} // namespace mozjs
diff --git a/src/mongo/scripting/mozjs/jsthread.h b/src/mongo/scripting/mozjs/jsthread.h
index ff468d987ab..2e6c0a70110 100644
--- a/src/mongo/scripting/mozjs/jsthread.h
+++ b/src/mongo/scripting/mozjs/jsthread.h
@@ -48,14 +48,14 @@ struct JSThreadInfo : public BaseInfo {
static void finalize(JSFreeOp* fop, JSObject* obj);
struct Functions {
- MONGO_DEFINE_JS_FUNCTION(init);
- MONGO_DEFINE_JS_FUNCTION(start);
- MONGO_DEFINE_JS_FUNCTION(join);
- MONGO_DEFINE_JS_FUNCTION(hasFailed);
- MONGO_DEFINE_JS_FUNCTION(returnData);
+ MONGO_DECLARE_JS_FUNCTION(init);
+ MONGO_DECLARE_JS_FUNCTION(start);
+ MONGO_DECLARE_JS_FUNCTION(join);
+ MONGO_DECLARE_JS_FUNCTION(hasFailed);
+ MONGO_DECLARE_JS_FUNCTION(returnData);
- MONGO_DEFINE_JS_FUNCTION(_threadInject);
- MONGO_DEFINE_JS_FUNCTION(_scopedThreadInject);
+ MONGO_DECLARE_JS_FUNCTION(_threadInject);
+ MONGO_DECLARE_JS_FUNCTION(_scopedThreadInject);
};
/**
diff --git a/src/mongo/scripting/mozjs/maxkey.cpp b/src/mongo/scripting/mozjs/maxkey.cpp
index 022ce347773..5fcf6c6f901 100644
--- a/src/mongo/scripting/mozjs/maxkey.cpp
+++ b/src/mongo/scripting/mozjs/maxkey.cpp
@@ -33,12 +33,13 @@
#include "mongo/scripting/mozjs/implscope.h"
#include "mongo/scripting/mozjs/objectwrapper.h"
#include "mongo/scripting/mozjs/valuereader.h"
+#include "mongo/scripting/mozjs/wrapconstrainedmethod.h"
namespace mongo {
namespace mozjs {
const JSFunctionSpec MaxKeyInfo::methods[2] = {
- MONGO_ATTACH_JS_FUNCTION(tojson), JS_FS_END,
+ MONGO_ATTACH_JS_CONSTRAINED_METHOD(tojson, MaxKeyInfo), JS_FS_END,
};
const char* const MaxKeyInfo::className = "MaxKey";
@@ -59,13 +60,13 @@ void MaxKeyInfo::construct(JSContext* cx, JS::CallArgs args) {
void MaxKeyInfo::call(JSContext* cx, JS::CallArgs args) {
auto scope = getScope(cx);
- ObjectWrapper o(cx, scope->getMaxKeyProto().getProto());
+ ObjectWrapper o(cx, scope->getProto<MaxKeyInfo>().getProto());
JS::RootedValue val(cx);
if (!o.hasField(kSingleton)) {
JS::RootedObject thisv(cx);
- scope->getMaxKeyProto().newObject(&thisv);
+ scope->getProto<MaxKeyInfo>().newObject(&thisv);
val.setObjectOrNull(thisv);
o.setValue(kSingleton, val);
@@ -76,7 +77,7 @@ void MaxKeyInfo::call(JSContext* cx, JS::CallArgs args) {
args.rval().setObjectOrNull(val.toObjectOrNull());
}
-void MaxKeyInfo::Functions::tojson(JSContext* cx, JS::CallArgs args) {
+void MaxKeyInfo::Functions::tojson::call(JSContext* cx, JS::CallArgs args) {
ValueReader(cx, args.rval()).fromStringData("{ \"$maxKey\" : 1 }");
}
@@ -84,7 +85,7 @@ void MaxKeyInfo::postInstall(JSContext* cx, JS::HandleObject global, JS::HandleO
ObjectWrapper protoWrapper(cx, proto);
JS::RootedValue value(cx);
- getScope(cx)->getMaxKeyProto().newObject(&value);
+ getScope(cx)->getProto<MaxKeyInfo>().newObject(&value);
ObjectWrapper(cx, global).setValue("MaxKey", value);
protoWrapper.setValue(kSingleton, value);
diff --git a/src/mongo/scripting/mozjs/maxkey.h b/src/mongo/scripting/mozjs/maxkey.h
index ac5d937f157..3a1e4bc4d62 100644
--- a/src/mongo/scripting/mozjs/maxkey.h
+++ b/src/mongo/scripting/mozjs/maxkey.h
@@ -45,7 +45,7 @@ struct MaxKeyInfo : public BaseInfo {
static void construct(JSContext* cx, JS::CallArgs args);
struct Functions {
- MONGO_DEFINE_JS_FUNCTION(tojson);
+ MONGO_DECLARE_JS_FUNCTION(tojson);
};
static const JSFunctionSpec methods[2];
diff --git a/src/mongo/scripting/mozjs/minkey.cpp b/src/mongo/scripting/mozjs/minkey.cpp
index fe06fa6bb49..86ec71892f2 100644
--- a/src/mongo/scripting/mozjs/minkey.cpp
+++ b/src/mongo/scripting/mozjs/minkey.cpp
@@ -33,12 +33,13 @@
#include "mongo/scripting/mozjs/implscope.h"
#include "mongo/scripting/mozjs/objectwrapper.h"
#include "mongo/scripting/mozjs/valuereader.h"
+#include "mongo/scripting/mozjs/wrapconstrainedmethod.h"
namespace mongo {
namespace mozjs {
const JSFunctionSpec MinKeyInfo::methods[2] = {
- MONGO_ATTACH_JS_FUNCTION(tojson), JS_FS_END,
+ MONGO_ATTACH_JS_CONSTRAINED_METHOD(tojson, MinKeyInfo), JS_FS_END,
};
const char* const MinKeyInfo::className = "MinKey";
@@ -59,13 +60,13 @@ void MinKeyInfo::construct(JSContext* cx, JS::CallArgs args) {
void MinKeyInfo::call(JSContext* cx, JS::CallArgs args) {
auto scope = getScope(cx);
- ObjectWrapper o(cx, scope->getMinKeyProto().getProto());
+ ObjectWrapper o(cx, scope->getProto<MinKeyInfo>().getProto());
JS::RootedValue val(cx);
if (!o.hasField(kSingleton)) {
JS::RootedObject thisv(cx);
- scope->getMinKeyProto().newObject(&thisv);
+ scope->getProto<MinKeyInfo>().newObject(&thisv);
val.setObjectOrNull(thisv);
o.setValue(kSingleton, val);
@@ -76,7 +77,7 @@ void MinKeyInfo::call(JSContext* cx, JS::CallArgs args) {
args.rval().setObjectOrNull(val.toObjectOrNull());
}
-void MinKeyInfo::Functions::tojson(JSContext* cx, JS::CallArgs args) {
+void MinKeyInfo::Functions::tojson::call(JSContext* cx, JS::CallArgs args) {
ValueReader(cx, args.rval()).fromStringData("{ \"$minKey\" : 1 }");
}
@@ -84,7 +85,7 @@ void MinKeyInfo::postInstall(JSContext* cx, JS::HandleObject global, JS::HandleO
ObjectWrapper protoWrapper(cx, proto);
JS::RootedValue value(cx);
- getScope(cx)->getMinKeyProto().newObject(&value);
+ getScope(cx)->getProto<MinKeyInfo>().newObject(&value);
ObjectWrapper(cx, global).setValue("MinKey", value);
protoWrapper.setValue(kSingleton, value);
diff --git a/src/mongo/scripting/mozjs/minkey.h b/src/mongo/scripting/mozjs/minkey.h
index caea91d54ac..e164bf108f7 100644
--- a/src/mongo/scripting/mozjs/minkey.h
+++ b/src/mongo/scripting/mozjs/minkey.h
@@ -45,7 +45,7 @@ struct MinKeyInfo : public BaseInfo {
static void construct(JSContext* cx, JS::CallArgs args);
struct Functions {
- MONGO_DEFINE_JS_FUNCTION(tojson);
+ MONGO_DECLARE_JS_FUNCTION(tojson);
};
static const JSFunctionSpec methods[2];
diff --git a/src/mongo/scripting/mozjs/mongo.cpp b/src/mongo/scripting/mozjs/mongo.cpp
index 2f1b41e91cd..bf99381de36 100644
--- a/src/mongo/scripting/mozjs/mongo.cpp
+++ b/src/mongo/scripting/mozjs/mongo.cpp
@@ -41,26 +41,33 @@
#include "mongo/scripting/mozjs/objectwrapper.h"
#include "mongo/scripting/mozjs/valuereader.h"
#include "mongo/scripting/mozjs/valuewriter.h"
+#include "mongo/scripting/mozjs/wrapconstrainedmethod.h"
#include "mongo/stdx/memory.h"
namespace mongo {
namespace mozjs {
const JSFunctionSpec MongoBase::methods[] = {
- MONGO_ATTACH_JS_FUNCTION(auth),
- MONGO_ATTACH_JS_FUNCTION(copyDatabaseWithSCRAM),
- MONGO_ATTACH_JS_FUNCTION(cursorFromId),
- MONGO_ATTACH_JS_FUNCTION(cursorHandleFromId),
- MONGO_ATTACH_JS_FUNCTION(find),
- MONGO_ATTACH_JS_FUNCTION(getClientRPCProtocols),
- MONGO_ATTACH_JS_FUNCTION(getServerRPCProtocols),
- MONGO_ATTACH_JS_FUNCTION(insert),
- MONGO_ATTACH_JS_FUNCTION(logout),
- MONGO_ATTACH_JS_FUNCTION(remove),
- MONGO_ATTACH_JS_FUNCTION(runCommand),
- MONGO_ATTACH_JS_FUNCTION(runCommandWithMetadata),
- MONGO_ATTACH_JS_FUNCTION(setClientRPCProtocols),
- MONGO_ATTACH_JS_FUNCTION(update),
+ MONGO_ATTACH_JS_CONSTRAINED_METHOD_NO_PROTO(auth, MongoLocalInfo, MongoExternalInfo),
+ MONGO_ATTACH_JS_CONSTRAINED_METHOD_NO_PROTO(
+ copyDatabaseWithSCRAM, MongoLocalInfo, MongoExternalInfo),
+ MONGO_ATTACH_JS_CONSTRAINED_METHOD_NO_PROTO(cursorFromId, MongoLocalInfo, MongoExternalInfo),
+ MONGO_ATTACH_JS_CONSTRAINED_METHOD_NO_PROTO(
+ cursorHandleFromId, MongoLocalInfo, MongoExternalInfo),
+ MONGO_ATTACH_JS_CONSTRAINED_METHOD_NO_PROTO(find, MongoLocalInfo, MongoExternalInfo),
+ MONGO_ATTACH_JS_CONSTRAINED_METHOD_NO_PROTO(
+ getClientRPCProtocols, MongoLocalInfo, MongoExternalInfo),
+ MONGO_ATTACH_JS_CONSTRAINED_METHOD_NO_PROTO(
+ getServerRPCProtocols, MongoLocalInfo, MongoExternalInfo),
+ MONGO_ATTACH_JS_CONSTRAINED_METHOD_NO_PROTO(insert, MongoLocalInfo, MongoExternalInfo),
+ MONGO_ATTACH_JS_CONSTRAINED_METHOD_NO_PROTO(logout, MongoLocalInfo, MongoExternalInfo),
+ MONGO_ATTACH_JS_CONSTRAINED_METHOD_NO_PROTO(remove, MongoLocalInfo, MongoExternalInfo),
+ MONGO_ATTACH_JS_CONSTRAINED_METHOD_NO_PROTO(runCommand, MongoLocalInfo, MongoExternalInfo),
+ MONGO_ATTACH_JS_CONSTRAINED_METHOD_NO_PROTO(
+ runCommandWithMetadata, MongoLocalInfo, MongoExternalInfo),
+ MONGO_ATTACH_JS_CONSTRAINED_METHOD_NO_PROTO(
+ setClientRPCProtocols, MongoLocalInfo, MongoExternalInfo),
+ MONGO_ATTACH_JS_CONSTRAINED_METHOD_NO_PROTO(update, MongoLocalInfo, MongoExternalInfo),
JS_FS_END,
};
@@ -106,7 +113,7 @@ void MongoBase::finalize(JSFreeOp* fop, JSObject* obj) {
}
}
-void MongoBase::Functions::runCommand(JSContext* cx, JS::CallArgs args) {
+void MongoBase::Functions::runCommand::call(JSContext* cx, JS::CallArgs args) {
if (args.length() != 3)
uasserted(ErrorCodes::BadValue, "runCommand needs 3 args");
@@ -133,7 +140,7 @@ void MongoBase::Functions::runCommand(JSContext* cx, JS::CallArgs args) {
ValueReader(cx, args.rval()).fromBSON(cmdRes, false /* read only */);
}
-void MongoBase::Functions::runCommandWithMetadata(JSContext* cx, JS::CallArgs args) {
+void MongoBase::Functions::runCommandWithMetadata::call(JSContext* cx, JS::CallArgs args) {
if (args.length() != 4)
uasserted(ErrorCodes::BadValue, "runCommandWithMetadata needs 4 args");
@@ -169,7 +176,7 @@ void MongoBase::Functions::runCommandWithMetadata(JSContext* cx, JS::CallArgs ar
ValueReader(cx, args.rval()).fromBSON(mergedResult, false);
}
-void MongoBase::Functions::find(JSContext* cx, JS::CallArgs args) {
+void MongoBase::Functions::find::call(JSContext* cx, JS::CallArgs args) {
auto scope = getScope(cx);
if (args.length() != 7)
@@ -213,14 +220,14 @@ void MongoBase::Functions::find(JSContext* cx, JS::CallArgs args) {
}
JS::RootedObject c(cx);
- scope->getCursorProto().newObject(&c);
+ scope->getProto<CursorInfo>().newObject(&c);
setCursor(c, std::move(cursor), args);
args.rval().setObjectOrNull(c);
}
-void MongoBase::Functions::insert(JSContext* cx, JS::CallArgs args) {
+void MongoBase::Functions::insert::call(JSContext* cx, JS::CallArgs args) {
auto scope = getScope(cx);
if (args.length() != 3)
@@ -250,7 +257,7 @@ void MongoBase::Functions::insert(JSContext* cx, JS::CallArgs args) {
if (!ele.hasField("_id")) {
JS::RootedValue value(cx);
- scope->getOidProto().newInstance(&value);
+ scope->getProto<OIDInfo>().newInstance(&value);
ele.setValue("_id", value);
}
@@ -285,7 +292,7 @@ void MongoBase::Functions::insert(JSContext* cx, JS::CallArgs args) {
args.rval().setUndefined();
}
-void MongoBase::Functions::remove(JSContext* cx, JS::CallArgs args) {
+void MongoBase::Functions::remove::call(JSContext* cx, JS::CallArgs args) {
if (!(args.length() == 2 || args.length() == 3))
uasserted(ErrorCodes::BadValue, "remove needs 2 or 3 args");
@@ -311,7 +318,7 @@ void MongoBase::Functions::remove(JSContext* cx, JS::CallArgs args) {
args.rval().setUndefined();
}
-void MongoBase::Functions::update(JSContext* cx, JS::CallArgs args) {
+void MongoBase::Functions::update::call(JSContext* cx, JS::CallArgs args) {
if (args.length() < 3)
uasserted(ErrorCodes::BadValue, "update needs at least 3 args");
@@ -339,7 +346,7 @@ void MongoBase::Functions::update(JSContext* cx, JS::CallArgs args) {
args.rval().setUndefined();
}
-void MongoBase::Functions::auth(JSContext* cx, JS::CallArgs args) {
+void MongoBase::Functions::auth::call(JSContext* cx, JS::CallArgs args) {
auto conn = getConnection(args);
if (!conn)
uasserted(ErrorCodes::BadValue, "no connection");
@@ -365,7 +372,7 @@ void MongoBase::Functions::auth(JSContext* cx, JS::CallArgs args) {
args.rval().setBoolean(true);
}
-void MongoBase::Functions::logout(JSContext* cx, JS::CallArgs args) {
+void MongoBase::Functions::logout::call(JSContext* cx, JS::CallArgs args) {
if (args.length() != 1)
uasserted(ErrorCodes::BadValue, "logout needs 1 arg");
@@ -381,13 +388,13 @@ void MongoBase::Functions::logout(JSContext* cx, JS::CallArgs args) {
ValueReader(cx, args.rval()).fromBSON(ret, false);
}
-void MongoBase::Functions::cursorFromId(JSContext* cx, JS::CallArgs args) {
+void MongoBase::Functions::cursorFromId::call(JSContext* cx, JS::CallArgs args) {
auto scope = getScope(cx);
if (!(args.length() == 2 || args.length() == 3))
uasserted(ErrorCodes::BadValue, "cursorFromId needs 2 or 3 args");
- if (!scope->getNumberLongProto().instanceOf(args.get(1)))
+ if (!scope->getProto<NumberLongInfo>().instanceOf(args.get(1)))
uasserted(ErrorCodes::BadValue, "2nd arg must be a NumberLong");
if (!(args.get(2).isNumber() || args.get(2).isUndefined()))
@@ -405,34 +412,34 @@ void MongoBase::Functions::cursorFromId(JSContext* cx, JS::CallArgs args) {
cursor->setBatchSize(ValueWriter(cx, args.get(2)).toInt32());
JS::RootedObject c(cx);
- scope->getCursorProto().newObject(&c);
+ scope->getProto<CursorInfo>().newObject(&c);
setCursor(c, std::move(cursor), args);
args.rval().setObjectOrNull(c);
}
-void MongoBase::Functions::cursorHandleFromId(JSContext* cx, JS::CallArgs args) {
+void MongoBase::Functions::cursorHandleFromId::call(JSContext* cx, JS::CallArgs args) {
auto scope = getScope(cx);
if (args.length() != 1) {
uasserted(ErrorCodes::BadValue, "cursorHandleFromId needs 1 arg");
}
- if (!scope->getNumberLongProto().instanceOf(args.get(0))) {
+ if (!scope->getProto<NumberLongInfo>().instanceOf(args.get(0))) {
uasserted(ErrorCodes::BadValue, "1st arg must be a NumberLong");
}
long long cursorId = NumberLongInfo::ToNumberLong(cx, args.get(0));
JS::RootedObject c(cx);
- scope->getCursorHandleProto().newObject(&c);
+ scope->getProto<CursorHandleInfo>().newObject(&c);
setCursorHandle(c, cursorId, args);
args.rval().setObjectOrNull(c);
}
-void MongoBase::Functions::copyDatabaseWithSCRAM(JSContext* cx, JS::CallArgs args) {
+void MongoBase::Functions::copyDatabaseWithSCRAM::call(JSContext* cx, JS::CallArgs args) {
auto conn = getConnection(args);
if (!conn)
@@ -516,7 +523,7 @@ void MongoBase::Functions::copyDatabaseWithSCRAM(JSContext* cx, JS::CallArgs arg
ValueReader(cx, args.rval()).fromBSON(inputObj, true);
}
-void MongoBase::Functions::getClientRPCProtocols(JSContext* cx, JS::CallArgs args) {
+void MongoBase::Functions::getClientRPCProtocols::call(JSContext* cx, JS::CallArgs args) {
auto conn = getConnection(args);
if (args.length() != 0)
@@ -530,7 +537,7 @@ void MongoBase::Functions::getClientRPCProtocols(JSContext* cx, JS::CallArgs arg
ValueReader(cx, args.rval()).fromStringData(protoStr);
}
-void MongoBase::Functions::setClientRPCProtocols(JSContext* cx, JS::CallArgs args) {
+void MongoBase::Functions::setClientRPCProtocols::call(JSContext* cx, JS::CallArgs args) {
auto conn = getConnection(args);
if (args.length() != 1)
@@ -548,7 +555,7 @@ void MongoBase::Functions::setClientRPCProtocols(JSContext* cx, JS::CallArgs arg
args.rval().setUndefined();
}
-void MongoBase::Functions::getServerRPCProtocols(JSContext* cx, JS::CallArgs args) {
+void MongoBase::Functions::getServerRPCProtocols::call(JSContext* cx, JS::CallArgs args) {
auto conn = getConnection(args);
if (args.length() != 0)
@@ -573,7 +580,7 @@ void MongoLocalInfo::construct(JSContext* cx, JS::CallArgs args) {
conn.reset(createDirectClient(scope->getOpContext()));
JS::RootedObject thisv(cx);
- scope->getMongoLocalProto().newObject(&thisv);
+ scope->getProto<MongoLocalInfo>().newObject(&thisv);
ObjectWrapper o(cx, thisv);
JS_SetPrivate(thisv, new std::shared_ptr<DBClientBase>(conn.release()));
@@ -606,7 +613,7 @@ void MongoExternalInfo::construct(JSContext* cx, JS::CallArgs args) {
}
JS::RootedObject thisv(cx);
- scope->getMongoExternalProto().newObject(&thisv);
+ scope->getProto<MongoExternalInfo>().newObject(&thisv);
ObjectWrapper o(cx, thisv);
JS_SetPrivate(thisv, new std::shared_ptr<DBClientBase>(conn.release()));
@@ -617,7 +624,7 @@ void MongoExternalInfo::construct(JSContext* cx, JS::CallArgs args) {
args.rval().setObjectOrNull(thisv);
}
-void MongoExternalInfo::Functions::load(JSContext* cx, JS::CallArgs args) {
+void MongoExternalInfo::Functions::load::call(JSContext* cx, JS::CallArgs args) {
auto scope = getScope(cx);
for (unsigned i = 0; i < args.length(); ++i) {
@@ -631,7 +638,7 @@ void MongoExternalInfo::Functions::load(JSContext* cx, JS::CallArgs args) {
args.rval().setBoolean(true);
}
-void MongoExternalInfo::Functions::quit(JSContext* cx, JS::CallArgs args) {
+void MongoExternalInfo::Functions::quit::call(JSContext* cx, JS::CallArgs args) {
auto scope = getScope(cx);
scope->setQuickExit(args.get(0).isNumber() ? args.get(0).toNumber() : 0);
@@ -639,7 +646,7 @@ void MongoExternalInfo::Functions::quit(JSContext* cx, JS::CallArgs args) {
uasserted(ErrorCodes::JSUncatchableError, "Calling Quit");
}
-void MongoExternalInfo::Functions::_forgetReplSet(JSContext* cx, JS::CallArgs args) {
+void MongoExternalInfo::Functions::_forgetReplSet::call(JSContext* cx, JS::CallArgs args) {
if (args.length() != 1) {
uasserted(ErrorCodes::BadValue,
str::stream() << "_forgetReplSet takes exactly 1 argument, but was given "
diff --git a/src/mongo/scripting/mozjs/mongo.h b/src/mongo/scripting/mozjs/mongo.h
index a5fc7921e92..77a1c17bff2 100644
--- a/src/mongo/scripting/mozjs/mongo.h
+++ b/src/mongo/scripting/mozjs/mongo.h
@@ -44,20 +44,20 @@ struct MongoBase : public BaseInfo {
static void finalize(JSFreeOp* fop, JSObject* obj);
struct Functions {
- MONGO_DEFINE_JS_FUNCTION(auth);
- MONGO_DEFINE_JS_FUNCTION(copyDatabaseWithSCRAM);
- MONGO_DEFINE_JS_FUNCTION(cursorFromId);
- MONGO_DEFINE_JS_FUNCTION(cursorHandleFromId);
- MONGO_DEFINE_JS_FUNCTION(find);
- MONGO_DEFINE_JS_FUNCTION(getClientRPCProtocols);
- MONGO_DEFINE_JS_FUNCTION(getServerRPCProtocols);
- MONGO_DEFINE_JS_FUNCTION(insert);
- MONGO_DEFINE_JS_FUNCTION(logout);
- MONGO_DEFINE_JS_FUNCTION(remove);
- MONGO_DEFINE_JS_FUNCTION(runCommand);
- MONGO_DEFINE_JS_FUNCTION(runCommandWithMetadata);
- MONGO_DEFINE_JS_FUNCTION(setClientRPCProtocols);
- MONGO_DEFINE_JS_FUNCTION(update);
+ MONGO_DECLARE_JS_FUNCTION(auth);
+ MONGO_DECLARE_JS_FUNCTION(copyDatabaseWithSCRAM);
+ MONGO_DECLARE_JS_FUNCTION(cursorFromId);
+ MONGO_DECLARE_JS_FUNCTION(cursorHandleFromId);
+ MONGO_DECLARE_JS_FUNCTION(find);
+ MONGO_DECLARE_JS_FUNCTION(getClientRPCProtocols);
+ MONGO_DECLARE_JS_FUNCTION(getServerRPCProtocols);
+ MONGO_DECLARE_JS_FUNCTION(insert);
+ MONGO_DECLARE_JS_FUNCTION(logout);
+ MONGO_DECLARE_JS_FUNCTION(remove);
+ MONGO_DECLARE_JS_FUNCTION(runCommand);
+ MONGO_DECLARE_JS_FUNCTION(runCommandWithMetadata);
+ MONGO_DECLARE_JS_FUNCTION(setClientRPCProtocols);
+ MONGO_DECLARE_JS_FUNCTION(update);
};
static const JSFunctionSpec methods[15];
@@ -80,9 +80,9 @@ struct MongoExternalInfo : public MongoBase {
static void construct(JSContext* cx, JS::CallArgs args);
struct Functions {
- MONGO_DEFINE_JS_FUNCTION(_forgetReplSet);
- MONGO_DEFINE_JS_FUNCTION(load);
- MONGO_DEFINE_JS_FUNCTION(quit);
+ MONGO_DECLARE_JS_FUNCTION(_forgetReplSet);
+ MONGO_DECLARE_JS_FUNCTION(load);
+ MONGO_DECLARE_JS_FUNCTION(quit);
};
static const JSFunctionSpec freeFunctions[4];
diff --git a/src/mongo/scripting/mozjs/mongohelpers.cpp b/src/mongo/scripting/mozjs/mongohelpers.cpp
index b27163ce7a3..7215c5aa605 100644
--- a/src/mongo/scripting/mozjs/mongohelpers.cpp
+++ b/src/mongo/scripting/mozjs/mongohelpers.cpp
@@ -57,7 +57,7 @@ std::string parseJSFunctionOrExpression(JSContext* cx, const StringData input) {
JS::RootedValue jsStrIn(cx);
ValueReader(cx, &jsStrIn).fromStringData(input);
- ObjectWrapper helpersWrapper(cx, getScope(cx)->getMongoHelpersProto().getProto());
+ ObjectWrapper helpersWrapper(cx, getScope(cx)->getProto<MongoHelpersInfo>().getProto());
helpersWrapper.callMethod("functionExpressionParser", JS::HandleValueArray(jsStrIn), &jsStrOut);
diff --git a/src/mongo/scripting/mozjs/nativefunction.cpp b/src/mongo/scripting/mozjs/nativefunction.cpp
index 5ffdc5f902d..ef5423f0f21 100644
--- a/src/mongo/scripting/mozjs/nativefunction.cpp
+++ b/src/mongo/scripting/mozjs/nativefunction.cpp
@@ -36,6 +36,7 @@
#include "mongo/scripting/mozjs/objectwrapper.h"
#include "mongo/scripting/mozjs/valuereader.h"
#include "mongo/scripting/mozjs/valuewriter.h"
+#include "mongo/scripting/mozjs/wrapconstrainedmethod.h"
#include "mongo/util/mongoutils/str.h"
namespace mongo {
@@ -45,7 +46,7 @@ const char* const NativeFunctionInfo::inheritFrom = "Function";
const char* const NativeFunctionInfo::className = "NativeFunction";
const JSFunctionSpec NativeFunctionInfo::methods[2] = {
- MONGO_ATTACH_JS_FUNCTION(toString), JS_FS_END,
+ MONGO_ATTACH_JS_CONSTRAINED_METHOD(toString, NativeFunctionInfo), JS_FS_END,
};
namespace {
@@ -70,7 +71,7 @@ NativeHolder* getHolder(JS::CallArgs args) {
void NativeFunctionInfo::call(JSContext* cx, JS::CallArgs args) {
auto holder = getHolder(args);
- if (! holder) {
+ if (!holder) {
// Calling the prototype
args.rval().setUndefined();
return;
@@ -99,7 +100,7 @@ void NativeFunctionInfo::finalize(JSFreeOp* fop, JSObject* obj) {
delete holder;
}
-void NativeFunctionInfo::Functions::toString(JSContext* cx, JS::CallArgs args) {
+void NativeFunctionInfo::Functions::toString::call(JSContext* cx, JS::CallArgs args) {
ObjectWrapper o(cx, args.thisv());
str::stream ss;
@@ -115,7 +116,7 @@ void NativeFunctionInfo::make(JSContext* cx,
void* data) {
auto scope = getScope(cx);
- scope->getNativeFunctionProto().newObject(obj);
+ scope->getProto<NativeFunctionInfo>().newObject(obj);
JS_SetPrivate(obj, new NativeHolder(function, data));
}
diff --git a/src/mongo/scripting/mozjs/nativefunction.h b/src/mongo/scripting/mozjs/nativefunction.h
index 6a676a180cf..8b818e03512 100644
--- a/src/mongo/scripting/mozjs/nativefunction.h
+++ b/src/mongo/scripting/mozjs/nativefunction.h
@@ -57,7 +57,7 @@ struct NativeFunctionInfo : public BaseInfo {
static const InstallType installType = InstallType::Private;
struct Functions {
- MONGO_DEFINE_JS_FUNCTION(toString);
+ MONGO_DECLARE_JS_FUNCTION(toString);
};
static const JSFunctionSpec methods[2];
diff --git a/src/mongo/scripting/mozjs/numberdecimal.cpp b/src/mongo/scripting/mozjs/numberdecimal.cpp
index 1891a67a45b..a845b3bb99d 100644
--- a/src/mongo/scripting/mozjs/numberdecimal.cpp
+++ b/src/mongo/scripting/mozjs/numberdecimal.cpp
@@ -35,6 +35,7 @@
#include "mongo/scripting/mozjs/objectwrapper.h"
#include "mongo/scripting/mozjs/valuereader.h"
#include "mongo/scripting/mozjs/valuewriter.h"
+#include "mongo/scripting/mozjs/wrapconstrainedmethod.h"
#include "mongo/util/mongoutils/str.h"
#include "mongo/util/text.h"
@@ -42,7 +43,7 @@ namespace mongo {
namespace mozjs {
const JSFunctionSpec NumberDecimalInfo::methods[2] = {
- MONGO_ATTACH_JS_FUNCTION(toString), JS_FS_END,
+ MONGO_ATTACH_JS_CONSTRAINED_METHOD(toString, NumberDecimalInfo), JS_FS_END,
};
const char* const NumberDecimalInfo::className = "NumberDecimal";
@@ -66,7 +67,7 @@ Decimal128 NumberDecimalInfo::ToNumberDecimal(JSContext* cx, JS::HandleObject th
return x ? *x : Decimal128(0);
}
-void NumberDecimalInfo::Functions::toString(JSContext* cx, JS::CallArgs args) {
+void NumberDecimalInfo::Functions::toString::call(JSContext* cx, JS::CallArgs args) {
Decimal128 val = NumberDecimalInfo::ToNumberDecimal(cx, args.thisv());
str::stream ss;
@@ -80,7 +81,7 @@ void NumberDecimalInfo::construct(JSContext* cx, JS::CallArgs args) {
JS::RootedObject thisv(cx);
- scope->getNumberDecimalProto().newObject(&thisv);
+ scope->getProto<NumberDecimalInfo>().newObject(&thisv);
Decimal128 x(0);
@@ -100,7 +101,7 @@ void NumberDecimalInfo::construct(JSContext* cx, JS::CallArgs args) {
void NumberDecimalInfo::make(JSContext* cx, JS::MutableHandleValue thisv, Decimal128 decimal) {
auto scope = getScope(cx);
- scope->getNumberDecimalProto().newInstance(thisv);
+ scope->getProto<NumberDecimalInfo>().newInstance(thisv);
JS_SetPrivate(thisv.toObjectOrNull(), new Decimal128(decimal));
}
diff --git a/src/mongo/scripting/mozjs/numberdecimal.h b/src/mongo/scripting/mozjs/numberdecimal.h
index 76411b45ca4..698bd8fe212 100644
--- a/src/mongo/scripting/mozjs/numberdecimal.h
+++ b/src/mongo/scripting/mozjs/numberdecimal.h
@@ -45,7 +45,7 @@ struct NumberDecimalInfo : public BaseInfo {
static void finalize(JSFreeOp* fop, JSObject* obj);
struct Functions {
- MONGO_DEFINE_JS_FUNCTION(toString);
+ MONGO_DECLARE_JS_FUNCTION(toString);
};
static const JSFunctionSpec methods[2];
diff --git a/src/mongo/scripting/mozjs/numberint.cpp b/src/mongo/scripting/mozjs/numberint.cpp
index 1704154ac74..c55510502e9 100644
--- a/src/mongo/scripting/mozjs/numberint.cpp
+++ b/src/mongo/scripting/mozjs/numberint.cpp
@@ -34,15 +34,16 @@
#include "mongo/scripting/mozjs/objectwrapper.h"
#include "mongo/scripting/mozjs/valuereader.h"
#include "mongo/scripting/mozjs/valuewriter.h"
+#include "mongo/scripting/mozjs/wrapconstrainedmethod.h"
#include "mongo/util/mongoutils/str.h"
namespace mongo {
namespace mozjs {
const JSFunctionSpec NumberIntInfo::methods[4] = {
- MONGO_ATTACH_JS_FUNCTION(toNumber),
- MONGO_ATTACH_JS_FUNCTION(toString),
- MONGO_ATTACH_JS_FUNCTION(valueOf),
+ MONGO_ATTACH_JS_CONSTRAINED_METHOD(toNumber, NumberIntInfo),
+ MONGO_ATTACH_JS_CONSTRAINED_METHOD(toString, NumberIntInfo),
+ MONGO_ATTACH_JS_CONSTRAINED_METHOD(valueOf, NumberIntInfo),
JS_FS_END,
};
@@ -67,17 +68,17 @@ int NumberIntInfo::ToNumberInt(JSContext* cx, JS::HandleObject thisv) {
return x ? *x : 0;
}
-void NumberIntInfo::Functions::valueOf(JSContext* cx, JS::CallArgs args) {
+void NumberIntInfo::Functions::valueOf::call(JSContext* cx, JS::CallArgs args) {
int out = NumberIntInfo::ToNumberInt(cx, args.thisv());
args.rval().setInt32(out);
}
-void NumberIntInfo::Functions::toNumber(JSContext* cx, JS::CallArgs args) {
- valueOf(cx, args);
+void NumberIntInfo::Functions::toNumber::call(JSContext* cx, JS::CallArgs args) {
+ valueOf::call(cx, args);
}
-void NumberIntInfo::Functions::toString(JSContext* cx, JS::CallArgs args) {
+void NumberIntInfo::Functions::toString::call(JSContext* cx, JS::CallArgs args) {
int val = NumberIntInfo::ToNumberInt(cx, args.thisv());
str::stream ss;
@@ -91,7 +92,7 @@ void NumberIntInfo::construct(JSContext* cx, JS::CallArgs args) {
JS::RootedObject thisv(cx);
- scope->getNumberIntProto().newObject(&thisv);
+ scope->getProto<NumberIntInfo>().newObject(&thisv);
int32_t x = 0;
diff --git a/src/mongo/scripting/mozjs/numberint.h b/src/mongo/scripting/mozjs/numberint.h
index 378c3a0d57e..a9a052bb0b7 100644
--- a/src/mongo/scripting/mozjs/numberint.h
+++ b/src/mongo/scripting/mozjs/numberint.h
@@ -43,9 +43,9 @@ struct NumberIntInfo : public BaseInfo {
static void finalize(JSFreeOp* fop, JSObject* obj);
struct Functions {
- MONGO_DEFINE_JS_FUNCTION(toNumber);
- MONGO_DEFINE_JS_FUNCTION(toString);
- MONGO_DEFINE_JS_FUNCTION(valueOf);
+ MONGO_DECLARE_JS_FUNCTION(toNumber);
+ MONGO_DECLARE_JS_FUNCTION(toString);
+ MONGO_DECLARE_JS_FUNCTION(valueOf);
};
static const JSFunctionSpec methods[4];
diff --git a/src/mongo/scripting/mozjs/numberlong.cpp b/src/mongo/scripting/mozjs/numberlong.cpp
index 5292e372f5c..fcd70b054ff 100644
--- a/src/mongo/scripting/mozjs/numberlong.cpp
+++ b/src/mongo/scripting/mozjs/numberlong.cpp
@@ -36,6 +36,7 @@
#include "mongo/scripting/mozjs/objectwrapper.h"
#include "mongo/scripting/mozjs/valuereader.h"
#include "mongo/scripting/mozjs/valuewriter.h"
+#include "mongo/scripting/mozjs/wrapconstrainedmethod.h"
#include "mongo/util/mongoutils/str.h"
#include "mongo/util/text.h"
@@ -43,10 +44,10 @@ namespace mongo {
namespace mozjs {
const JSFunctionSpec NumberLongInfo::methods[5] = {
- MONGO_ATTACH_JS_FUNCTION(toNumber),
- MONGO_ATTACH_JS_FUNCTION(toString),
- MONGO_ATTACH_JS_FUNCTION(valueOf),
- MONGO_ATTACH_JS_FUNCTION(compare),
+ MONGO_ATTACH_JS_CONSTRAINED_METHOD(toNumber, NumberLongInfo),
+ MONGO_ATTACH_JS_CONSTRAINED_METHOD(toString, NumberLongInfo),
+ MONGO_ATTACH_JS_CONSTRAINED_METHOD(valueOf, NumberLongInfo),
+ MONGO_ATTACH_JS_CONSTRAINED_METHOD(compare, NumberLongInfo),
JS_FS_END,
};
@@ -80,17 +81,17 @@ long long NumberLongInfo::ToNumberLong(JSContext* cx, JS::HandleObject thisv) {
(unsigned)(o.getNumber(kBottom)));
}
-void NumberLongInfo::Functions::valueOf(JSContext* cx, JS::CallArgs args) {
+void NumberLongInfo::Functions::valueOf::call(JSContext* cx, JS::CallArgs args) {
long long out = NumberLongInfo::ToNumberLong(cx, args.thisv());
args.rval().setDouble(out);
}
-void NumberLongInfo::Functions::toNumber(JSContext* cx, JS::CallArgs args) {
- valueOf(cx, args);
+void NumberLongInfo::Functions::toNumber::call(JSContext* cx, JS::CallArgs args) {
+ valueOf::call(cx, args);
}
-void NumberLongInfo::Functions::toString(JSContext* cx, JS::CallArgs args) {
+void NumberLongInfo::Functions::toString::call(JSContext* cx, JS::CallArgs args) {
str::stream ss;
long long val = NumberLongInfo::ToNumberLong(cx, args.thisv());
@@ -105,7 +106,7 @@ void NumberLongInfo::Functions::toString(JSContext* cx, JS::CallArgs args) {
ValueReader(cx, args.rval()).fromStringData(ss.operator std::string());
}
-void NumberLongInfo::Functions::compare(JSContext* cx, JS::CallArgs args) {
+void NumberLongInfo::Functions::compare::call(JSContext* cx, JS::CallArgs args) {
uassert(ErrorCodes::BadValue, "NumberLong.compare() needs 1 argument", args.length() == 1);
uassert(ErrorCodes::BadValue,
"NumberLong.compare() argument must be an object",
@@ -133,7 +134,7 @@ void NumberLongInfo::construct(JSContext* cx, JS::CallArgs args) {
JS::RootedObject thisv(cx);
- scope->getNumberLongProto().newObject(&thisv);
+ scope->getProto<NumberLongInfo>().newObject(&thisv);
ObjectWrapper o(cx, thisv);
JS::RootedValue floatApprox(cx);
diff --git a/src/mongo/scripting/mozjs/numberlong.h b/src/mongo/scripting/mozjs/numberlong.h
index c6f42da0ca7..145afd387b5 100644
--- a/src/mongo/scripting/mozjs/numberlong.h
+++ b/src/mongo/scripting/mozjs/numberlong.h
@@ -51,10 +51,10 @@ struct NumberLongInfo : public BaseInfo {
static void construct(JSContext* cx, JS::CallArgs args);
struct Functions {
- MONGO_DEFINE_JS_FUNCTION(toNumber);
- MONGO_DEFINE_JS_FUNCTION(toString);
- MONGO_DEFINE_JS_FUNCTION(valueOf);
- MONGO_DEFINE_JS_FUNCTION(compare);
+ MONGO_DECLARE_JS_FUNCTION(toNumber);
+ MONGO_DECLARE_JS_FUNCTION(toString);
+ MONGO_DECLARE_JS_FUNCTION(valueOf);
+ MONGO_DECLARE_JS_FUNCTION(compare);
};
static const JSFunctionSpec methods[5];
diff --git a/src/mongo/scripting/mozjs/object.cpp b/src/mongo/scripting/mozjs/object.cpp
index a90bec36a72..0bd33b3d72d 100644
--- a/src/mongo/scripting/mozjs/object.cpp
+++ b/src/mongo/scripting/mozjs/object.cpp
@@ -44,7 +44,7 @@ const JSFunctionSpec ObjectInfo::methods[3] = {
const char* const ObjectInfo::className = "Object";
-void ObjectInfo::Functions::bsonsize(JSContext* cx, JS::CallArgs args) {
+void ObjectInfo::Functions::bsonsize::call(JSContext* cx, JS::CallArgs args) {
if (args.length() != 1)
uasserted(ErrorCodes::BadValue, "bsonsize needs 1 argument");
@@ -59,7 +59,7 @@ void ObjectInfo::Functions::bsonsize(JSContext* cx, JS::CallArgs args) {
args.rval().setInt32(ValueWriter(cx, args.get(0)).toBSON().objsize());
}
-void ObjectInfo::Functions::invalidForStorage(JSContext* cx, JS::CallArgs args) {
+void ObjectInfo::Functions::invalidForStorage::call(JSContext* cx, JS::CallArgs args) {
if (args.length() != 1)
uasserted(ErrorCodes::BadValue, "invalidForStorage needs 1 argument");
diff --git a/src/mongo/scripting/mozjs/object.h b/src/mongo/scripting/mozjs/object.h
index 70f475c3f0e..f5e921155c2 100644
--- a/src/mongo/scripting/mozjs/object.h
+++ b/src/mongo/scripting/mozjs/object.h
@@ -41,8 +41,8 @@ namespace mozjs {
*/
struct ObjectInfo : public BaseInfo {
struct Functions {
- MONGO_DEFINE_JS_FUNCTION(bsonsize);
- MONGO_DEFINE_JS_FUNCTION(invalidForStorage);
+ MONGO_DECLARE_JS_FUNCTION(bsonsize);
+ MONGO_DECLARE_JS_FUNCTION(invalidForStorage);
};
static const JSFunctionSpec methods[3];
diff --git a/src/mongo/scripting/mozjs/objectwrapper.cpp b/src/mongo/scripting/mozjs/objectwrapper.cpp
index 5ca5cdeca97..2dc17726b37 100644
--- a/src/mongo/scripting/mozjs/objectwrapper.cpp
+++ b/src/mongo/scripting/mozjs/objectwrapper.cpp
@@ -343,7 +343,7 @@ void ObjectWrapper::writeThis(BSONObjBuilder* b) {
auto scope = getScope(_context);
BSONObj* originalBSON = nullptr;
- if (scope->getBsonProto().instanceOf(_object)) {
+ if (scope->getProto<BSONInfo>().instanceOf(_object)) {
bool altered;
std::tie(originalBSON, altered) = BSONInfo::originalBSON(_context, _object);
@@ -389,5 +389,17 @@ void ObjectWrapper::_writeField(BSONObjBuilder* b, Key key, BSONObj* originalPar
x.writeThis(b, key.toString(_context));
}
+std::string ObjectWrapper::getClassName() {
+ auto jsclass = JS_GetClass(_object);
+
+ if (jsclass)
+ return jsclass->name;
+
+ JS::RootedValue ctor(_context);
+ getValue("constructor", &ctor);
+
+ return ObjectWrapper(_context, ctor).getString("name");
+}
+
} // namespace mozjs
} // namespace mongo
diff --git a/src/mongo/scripting/mozjs/objectwrapper.h b/src/mongo/scripting/mozjs/objectwrapper.h
index d8d519acc7f..57bdc728494 100644
--- a/src/mongo/scripting/mozjs/objectwrapper.h
+++ b/src/mongo/scripting/mozjs/objectwrapper.h
@@ -160,6 +160,8 @@ public:
return _object;
}
+ std::string getClassName();
+
private:
/**
* writes the field "key" into the associated builder
diff --git a/src/mongo/scripting/mozjs/oid.cpp b/src/mongo/scripting/mozjs/oid.cpp
index cf391bf03e8..8c0debaccc1 100644
--- a/src/mongo/scripting/mozjs/oid.cpp
+++ b/src/mongo/scripting/mozjs/oid.cpp
@@ -34,6 +34,7 @@
#include "mongo/scripting/mozjs/objectwrapper.h"
#include "mongo/scripting/mozjs/valuereader.h"
#include "mongo/scripting/mozjs/valuewriter.h"
+#include "mongo/scripting/mozjs/wrapconstrainedmethod.h"
#include "mongo/stdx/memory.h"
#include "mongo/util/mongoutils/str.h"
@@ -41,12 +42,12 @@ namespace mongo {
namespace mozjs {
const JSFunctionSpec OIDInfo::methods[2] = {
- MONGO_ATTACH_JS_FUNCTION(toString), JS_FS_END,
+ MONGO_ATTACH_JS_CONSTRAINED_METHOD(toString, OIDInfo), JS_FS_END,
};
const char* const OIDInfo::className = "ObjectId";
-void OIDInfo::Functions::toString(JSContext* cx, JS::CallArgs args) {
+void OIDInfo::Functions::toString::call(JSContext* cx, JS::CallArgs args) {
ObjectWrapper o(cx, args.thisv());
if (!o.hasField("str"))
@@ -75,7 +76,7 @@ void OIDInfo::construct(JSContext* cx, JS::CallArgs args) {
}
JS::RootedObject thisv(cx);
- scope->getOidProto().newObject(&thisv);
+ scope->getProto<OIDInfo>().newObject(&thisv);
ObjectWrapper o(cx, thisv);
o.setString("str", oid->toString());
diff --git a/src/mongo/scripting/mozjs/oid.h b/src/mongo/scripting/mozjs/oid.h
index 109282be882..8171d2d2aac 100644
--- a/src/mongo/scripting/mozjs/oid.h
+++ b/src/mongo/scripting/mozjs/oid.h
@@ -42,7 +42,7 @@ struct OIDInfo : public BaseInfo {
static void construct(JSContext* cx, JS::CallArgs args);
struct Functions {
- MONGO_DEFINE_JS_FUNCTION(toString);
+ MONGO_DECLARE_JS_FUNCTION(toString);
};
static const JSFunctionSpec methods[2];
diff --git a/src/mongo/scripting/mozjs/timestamp.cpp b/src/mongo/scripting/mozjs/timestamp.cpp
index f81cc4050ce..8659d8a4d85 100644
--- a/src/mongo/scripting/mozjs/timestamp.cpp
+++ b/src/mongo/scripting/mozjs/timestamp.cpp
@@ -45,7 +45,7 @@ void TimestampInfo::construct(JSContext* cx, JS::CallArgs args) {
auto scope = getScope(cx);
JS::RootedObject thisv(cx);
- scope->getTimestampProto().newObject(&thisv);
+ scope->getProto<TimestampInfo>().newObject(&thisv);
ObjectWrapper o(cx, thisv);
if (args.length() == 0) {
diff --git a/src/mongo/scripting/mozjs/valuereader.cpp b/src/mongo/scripting/mozjs/valuereader.cpp
index e4d005cb399..89289c2f976 100644
--- a/src/mongo/scripting/mozjs/valuereader.cpp
+++ b/src/mongo/scripting/mozjs/valuereader.cpp
@@ -70,7 +70,7 @@ void ValueReader::fromBSONElement(const BSONElement& elem, bool readOnly) {
ValueReader(_context, args[0]).fromStringData(elem.OID().toString());
- scope->getOidProto().newInstance(args, _value);
+ scope->getProto<OIDInfo>().newInstance(args, _value);
return;
}
case mongo::NumberDouble:
@@ -122,7 +122,7 @@ void ValueReader::fromBSONElement(const BSONElement& elem, bool readOnly) {
ValueReader(_context, args[1]).fromStringData(elem.regexFlags());
JS::RootedObject obj(_context);
- scope->getRegExpProto().newInstance(args, &obj);
+ scope->getProto<RegExpInfo>().newInstance(args, &obj);
_value.setObjectOrNull(obj);
@@ -140,7 +140,7 @@ void ValueReader::fromBSONElement(const BSONElement& elem, bool readOnly) {
ValueReader(_context, args[1]).fromStringData(ss.str());
- scope->getBinDataProto().newInstance(args, _value);
+ scope->getProto<BinDataInfo>().newInstance(args, _value);
return;
}
case mongo::bsonTimestamp: {
@@ -149,7 +149,7 @@ void ValueReader::fromBSONElement(const BSONElement& elem, bool readOnly) {
args[0].setDouble(elem.timestampTime().toMillisSinceEpoch() / 1000);
args[1].setNumber(elem.timestampInc());
- scope->getTimestampProto().newInstance(args, _value);
+ scope->getProto<TimestampInfo>().newInstance(args, _value);
return;
}
@@ -163,14 +163,14 @@ void ValueReader::fromBSONElement(const BSONElement& elem, bool readOnly) {
JS::AutoValueArray<1> args(_context);
args[0].setNumber(static_cast<double>(static_cast<long long>(nativeUnsignedLong)));
- scope->getNumberLongProto().newInstance(args, _value);
+ scope->getProto<NumberLongInfo>().newInstance(args, _value);
} else {
JS::AutoValueArray<3> args(_context);
args[0].setNumber(static_cast<double>(static_cast<long long>(nativeUnsignedLong)));
args[1].setDouble(nativeUnsignedLong >> 32);
args[2].setDouble(
static_cast<unsigned long>(nativeUnsignedLong & 0x00000000ffffffff));
- scope->getNumberLongProto().newInstance(args, _value);
+ scope->getProto<NumberLongInfo>().newInstance(args, _value);
}
return;
@@ -181,16 +181,16 @@ void ValueReader::fromBSONElement(const BSONElement& elem, bool readOnly) {
ValueReader(_context, args[0]).fromDecimal128(decimal);
JS::RootedObject obj(_context);
- scope->getNumberDecimalProto().newInstance(args, &obj);
+ scope->getProto<NumberDecimalInfo>().newInstance(args, &obj);
_value.setObjectOrNull(obj);
return;
}
case mongo::MinKey:
- scope->getMinKeyProto().newInstance(_value);
+ scope->getProto<MinKeyInfo>().newInstance(_value);
return;
case mongo::MaxKey:
- scope->getMaxKeyProto().newInstance(_value);
+ scope->getProto<MaxKeyInfo>().newInstance(_value);
return;
case mongo::DBRef: {
JS::AutoValueArray<1> oidArgs(_context);
@@ -198,9 +198,9 @@ void ValueReader::fromBSONElement(const BSONElement& elem, bool readOnly) {
JS::AutoValueArray<2> dbPointerArgs(_context);
ValueReader(_context, dbPointerArgs[0]).fromStringData(elem.dbrefNS());
- scope->getOidProto().newInstance(oidArgs, dbPointerArgs[1]);
+ scope->getProto<OIDInfo>().newInstance(oidArgs, dbPointerArgs[1]);
- scope->getDbPointerProto().newInstance(dbPointerArgs, _value);
+ scope->getProto<DBPointerInfo>().newInstance(dbPointerArgs, _value);
return;
}
default:
@@ -231,7 +231,7 @@ void ValueReader::fromBSON(const BSONObj& obj, bool readOnly) {
auto scope = getScope(_context);
- scope->getDbRefProto().newInstance(args, &obj);
+ scope->getProto<DBRefInfo>().newInstance(args, &obj);
ObjectWrapper o(_context, obj);
while (it.more()) {
diff --git a/src/mongo/scripting/mozjs/valuewriter.cpp b/src/mongo/scripting/mozjs/valuewriter.cpp
index 72a44583a5b..7fdb1596fa3 100644
--- a/src/mongo/scripting/mozjs/valuewriter.cpp
+++ b/src/mongo/scripting/mozjs/valuewriter.cpp
@@ -82,13 +82,42 @@ int ValueWriter::type() {
uasserted(ErrorCodes::BadValue, "unable to get type");
}
+std::string ValueWriter::typeAsString() {
+ if (_value.isNull())
+ return "null";
+ if (_value.isUndefined())
+ return "undefined";
+ if (_value.isString())
+ return "string";
+ if (JS_IsArrayObject(_context, _value))
+ return "array";
+ if (_value.isBoolean())
+ return "boolean";
+ if (_value.isNumber())
+ return "number";
+
+ if (_value.isObject()) {
+ JS::RootedObject obj(_context, _value.toObjectOrNull());
+ if (JS_IsArrayObject(_context, obj))
+ return "array";
+ if (JS_ObjectIsDate(_context, obj))
+ return "date";
+ if (JS_ObjectIsFunction(_context, obj))
+ return "function";
+
+ return ObjectWrapper(_context, _value).getClassName();
+ }
+
+ uasserted(ErrorCodes::BadValue, "unable to get type");
+}
+
BSONObj ValueWriter::toBSON() {
if (!_value.isObject())
return BSONObj();
JS::RootedObject obj(_context, _value.toObjectOrNull());
- if (getScope(_context)->getBsonProto().instanceOf(obj)) {
+ if (getScope(_context)->getProto<BSONInfo>().instanceOf(obj)) {
BSONObj* originalBSON;
bool altered;
@@ -130,7 +159,7 @@ int32_t ValueWriter::toInt32() {
int64_t ValueWriter::toInt64() {
int64_t out;
- if (getScope(_context)->getNumberLongProto().instanceOf(_value))
+ if (getScope(_context)->getProto<NumberLongInfo>().instanceOf(_value))
return NumberLongInfo::ToNumberLong(_context, _value);
if (JS::ToInt64(_context, _value, &out))
@@ -144,13 +173,13 @@ Decimal128 ValueWriter::toDecimal128() {
return Decimal128(toNumber());
}
- if (getScope(_context)->getNumberIntProto().instanceOf(_value))
+ if (getScope(_context)->getProto<NumberIntInfo>().instanceOf(_value))
return Decimal128(NumberIntInfo::ToNumberInt(_context, _value));
- if (getScope(_context)->getNumberLongProto().instanceOf(_value))
+ if (getScope(_context)->getProto<NumberLongInfo>().instanceOf(_value))
return Decimal128(NumberLongInfo::ToNumberLong(_context, _value));
- if (getScope(_context)->getNumberDecimalProto().instanceOf(_value))
+ if (getScope(_context)->getProto<NumberDecimalInfo>().instanceOf(_value))
return NumberDecimalInfo::ToNumberDecimal(_context, _value);
if (_value.isString()) {
@@ -214,7 +243,7 @@ void ValueWriter::_writeObject(BSONObjBuilder* b, StringData sd, JS::HandleObjec
if (JS_ObjectIsFunction(_context, _value.toObjectOrNull())) {
uassert(16716,
"cannot convert native function to BSON",
- !scope->getNativeFunctionProto().instanceOf(obj));
+ !scope->getProto<NativeFunctionInfo>().instanceOf(obj));
b->appendCode(sd, ValueWriter(_context, _value).toString());
} else if (JS_ObjectIsRegExp(_context, obj)) {
JS::RootedValue v(_context);
@@ -232,21 +261,21 @@ void ValueWriter::_writeObject(BSONObjBuilder* b, StringData sd, JS::HandleObjec
auto d = Date_t::fromMillisSinceEpoch(ValueWriter(_context, dateval).toNumber());
b->appendDate(sd, d);
- } else if (scope->getOidProto().instanceOf(obj)) {
+ } else if (scope->getProto<OIDInfo>().instanceOf(obj)) {
b->append(sd, OID(o.getString("str")));
- } else if (scope->getNumberLongProto().instanceOf(obj)) {
+ } else if (scope->getProto<NumberLongInfo>().instanceOf(obj)) {
long long out = NumberLongInfo::ToNumberLong(_context, obj);
b->append(sd, out);
- } else if (scope->getNumberIntProto().instanceOf(obj)) {
+ } else if (scope->getProto<NumberIntInfo>().instanceOf(obj)) {
b->append(sd, NumberIntInfo::ToNumberInt(_context, obj));
- } else if (scope->getNumberDecimalProto().instanceOf(obj)) {
+ } else if (scope->getProto<NumberDecimalInfo>().instanceOf(obj)) {
b->append(sd, NumberDecimalInfo::ToNumberDecimal(_context, obj));
- } else if (scope->getDbPointerProto().instanceOf(obj)) {
+ } else if (scope->getProto<DBPointerInfo>().instanceOf(obj)) {
JS::RootedValue id(_context);
o.getValue("id", &id);
b->appendDBRef(sd, o.getString("ns"), OID(ObjectWrapper(_context, id).getString("str")));
- } else if (scope->getBinDataProto().instanceOf(obj)) {
+ } else if (scope->getProto<BinDataInfo>().instanceOf(obj)) {
auto str = static_cast<std::string*>(JS_GetPrivate(obj));
auto binData = base64::decode(*str);
@@ -255,12 +284,12 @@ void ValueWriter::_writeObject(BSONObjBuilder* b, StringData sd, JS::HandleObjec
binData.size(),
static_cast<mongo::BinDataType>(static_cast<int>(o.getNumber("type"))),
binData.c_str());
- } else if (scope->getTimestampProto().instanceOf(obj)) {
+ } else if (scope->getProto<TimestampInfo>().instanceOf(obj)) {
Timestamp ot(o.getNumber("t"), o.getNumber("i"));
b->append(sd, ot);
- } else if (scope->getMinKeyProto().instanceOf(obj)) {
+ } else if (scope->getProto<MinKeyInfo>().instanceOf(obj)) {
b->appendMinKey(sd);
- } else if (scope->getMaxKeyProto().instanceOf(obj)) {
+ } else if (scope->getProto<MaxKeyInfo>().instanceOf(obj)) {
b->appendMaxKey(sd);
} else {
// nested object or array
diff --git a/src/mongo/scripting/mozjs/valuewriter.h b/src/mongo/scripting/mozjs/valuewriter.h
index dd0eb98af92..1945303867b 100644
--- a/src/mongo/scripting/mozjs/valuewriter.h
+++ b/src/mongo/scripting/mozjs/valuewriter.h
@@ -63,6 +63,11 @@ public:
bool toBoolean();
/**
+ * Provides the type of the value. For objects, it fetches the class name if possible.
+ */
+ std::string typeAsString();
+
+ /**
* Writes the value into a bsonobjbuilder under the name in sd.
*/
void writeThis(BSONObjBuilder* b, StringData sd);
diff --git a/src/mongo/scripting/mozjs/wrapconstrainedmethod.h b/src/mongo/scripting/mozjs/wrapconstrainedmethod.h
new file mode 100644
index 00000000000..db21289cb93
--- /dev/null
+++ b/src/mongo/scripting/mozjs/wrapconstrainedmethod.h
@@ -0,0 +1,123 @@
+/**
+ * Copyright (C) 2015 MongoDB Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License, version 3,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the GNU Affero General Public License in all respects
+ * for all of the code used other than as permitted herein. If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. If you do not
+ * wish to do so, delete this exception statement from your version. If you
+ * delete this exception statement from all source files in the program,
+ * then also delete it in the license file.
+ */
+
+#pragma once
+
+#include <jsapi.h>
+
+#include "mongo/scripting/mozjs/implscope.h"
+#include "mongo/scripting/mozjs/objectwrapper.h"
+#include "mongo/scripting/mozjs/valuewriter.h"
+#include "mongo/util/assert_util.h"
+#include "mongo/util/stringutils.h"
+
+namespace mongo {
+namespace mozjs {
+namespace smUtils {
+
+/**
+ * Returns true if "value" is an instance of any of the types passed as
+ * template parameters. Additionally sets isProto if the value is also the
+ * prototype for that type.
+ *
+ * We recurse until we hit the void specialization which we set up by adding
+ * void as the last type in wrapConstrainedMethod.
+ */
+template <typename T, typename... Args>
+bool instanceOf(MozJSImplScope* scope, bool* isProto, JS::HandleValue value) {
+ auto& proto = scope->getProto<T>();
+
+ if (proto.instanceOf(value)) {
+ if (value.toObjectOrNull() == proto.getProto()) {
+ *isProto = true;
+ }
+
+ return true;
+ }
+
+ return instanceOf<Args...>(scope, isProto, value);
+}
+
+/**
+ * Terminating specialization for instanceOf.
+ *
+ * We use this to identify the end of the template list in the general case.
+ */
+template <>
+inline bool instanceOf<void>(MozJSImplScope* scope, bool* isProto, JS::HandleValue value) {
+ return false;
+}
+
+
+/**
+ * Wraps a method with an additional check against a list of possible wrap types.
+ *
+ * Template Parameters:
+ * T - A type with
+ * ::call - a static function of type void (JSContext* cx, JS::CallArgs args)
+ * ::name - a static function which returns a const char* with the type name
+ * noProto - whether the method can be invoked on the prototype
+ * Args - The list of types to check against scope->getProto<T>().instanceOf
+ * for the thisv the method has been invoked against
+ */
+template <typename T, bool noProto, typename... Args>
+bool wrapConstrainedMethod(JSContext* cx, unsigned argc, JS::Value* vp) {
+ try {
+ JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ bool isProto = false;
+
+ if (!args.thisv().isObject()) {
+ uasserted(ErrorCodes::BadValue,
+ str::stream() << "Cannot call \"" << T::name()
+ << "\" on non-object of type \""
+ << ValueWriter(cx, args.thisv()).typeAsString() << "\"");
+ }
+
+ if (!instanceOf<Args..., void>(getScope(cx), &isProto, args.thisv())) {
+ uasserted(ErrorCodes::BadValue,
+ str::stream() << "Cannot call \"" << T::name() << "\" on object of type \""
+ << ObjectWrapper(cx, args.thisv()).getClassName() << "\"");
+ }
+
+ if (noProto && isProto) {
+ uasserted(ErrorCodes::BadValue,
+ str::stream() << "Cannot call \"" << T::name() << "\" on prototype of \""
+ << ObjectWrapper(cx, args.thisv()).getClassName() << "\"");
+ }
+
+ T::call(cx, args);
+ return true;
+ } catch (...) {
+ mongoToJSException(cx);
+ return false;
+ }
+}
+
+} // namespace smUtils
+} // namespace mozjs
+} // namespace mongo
diff --git a/src/mongo/scripting/mozjs/wraptype.h b/src/mongo/scripting/mozjs/wraptype.h
index 7b45e24e13e..d569bcb9d86 100644
--- a/src/mongo/scripting/mozjs/wraptype.h
+++ b/src/mongo/scripting/mozjs/wraptype.h
@@ -53,35 +53,55 @@
// MONGO_*_JS_FUNCTION_* macros are public and allow wrapped types to install
// their own functions on types and into the global scope
-#define MONGO_DEFINE_JS_FUNCTION(name) \
- static void name(JSContext* cx, JS::CallArgs args); \
- static bool WRAPPER_##name(JSContext* cx, unsigned argc, JS::Value* vp) { \
- try { \
- JS::CallArgs args = JS::CallArgsFromVp(argc, vp); \
- name(cx, args); \
- return true; \
- } catch (...) { \
- mongoToJSException(cx); \
- return false; \
- } \
- }
+#define MONGO_DECLARE_JS_FUNCTION(function) \
+ struct function { \
+ static const char* name() { \
+ return #function; \
+ } \
+ static void call(JSContext* cx, JS::CallArgs args); \
+ };
#define MONGO_ATTACH_JS_FUNCTION_WITH_FLAGS(name, flags) \
- JS_FS(#name, Functions::WRAPPER_##name, 0, flags)
+ JS_FS(#name, smUtils::wrapFunction<Functions::name>, 0, flags)
#define MONGO_ATTACH_JS_FUNCTION(name) MONGO_ATTACH_JS_FUNCTION_WITH_FLAGS(name, 0)
+#define MONGO_ATTACH_JS_CONSTRAINED_METHOD(name, ...) \
+ { \
+ #name, {smUtils::wrapConstrainedMethod < Functions::name, false, __VA_ARGS__ >, nullptr }, \
+ 0, \
+ 0, \
+ nullptr \
+ }
+
+#define MONGO_ATTACH_JS_CONSTRAINED_METHOD_NO_PROTO(name, ...) \
+ { \
+ #name, {smUtils::wrapConstrainedMethod < Functions::name, true, __VA_ARGS__ >, nullptr }, \
+ 0, \
+ 0, \
+ nullptr \
+ }
+
namespace mongo {
namespace mozjs {
namespace smUtils {
+template <typename T>
+bool wrapFunction(JSContext* cx, unsigned argc, JS::Value* vp) {
+ try {
+ JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+ T::call(cx, args);
+ return true;
+ } catch (...) {
+ mongoToJSException(cx);
+ return false;
+ }
+}
+
// Now all the spidermonkey type methods
template <typename T>
-static bool addProperty(JSContext* cx,
- JS::HandleObject obj,
- JS::HandleId id,
- JS::MutableHandleValue v) {
+bool addProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::MutableHandleValue v) {
try {
T::addProperty(cx, obj, id, v);
return true;
@@ -92,7 +112,7 @@ static bool addProperty(JSContext* cx,
};
template <typename T>
-static bool call(JSContext* cx, unsigned argc, JS::Value* vp) {
+bool call(JSContext* cx, unsigned argc, JS::Value* vp) {
try {
T::call(cx, JS::CallArgsFromVp(argc, vp));
return true;
@@ -103,7 +123,7 @@ static bool call(JSContext* cx, unsigned argc, JS::Value* vp) {
};
template <typename T>
-static bool construct(JSContext* cx, unsigned argc, JS::Value* vp) {
+bool construct(JSContext* cx, unsigned argc, JS::Value* vp) {
try {
T::construct(cx, JS::CallArgsFromVp(argc, vp));
return true;
@@ -114,7 +134,7 @@ static bool construct(JSContext* cx, unsigned argc, JS::Value* vp) {
};
template <typename T>
-static bool convert(JSContext* cx, JS::HandleObject obj, JSType type, JS::MutableHandleValue vp) {
+bool convert(JSContext* cx, JS::HandleObject obj, JSType type, JS::MutableHandleValue vp) {
try {
T::convert(cx, obj, type, vp);
return true;
@@ -125,7 +145,7 @@ static bool convert(JSContext* cx, JS::HandleObject obj, JSType type, JS::Mutabl
};
template <typename T>
-static bool delProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool* succeeded) {
+bool delProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool* succeeded) {
try {
T::delProperty(cx, obj, id, succeeded);
return true;
@@ -136,7 +156,7 @@ static bool delProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bo
};
template <typename T>
-static bool enumerate(JSContext* cx, JS::HandleObject obj, JS::AutoIdVector& properties) {
+bool enumerate(JSContext* cx, JS::HandleObject obj, JS::AutoIdVector& properties) {
try {
T::enumerate(cx, obj, properties);
return true;
@@ -147,10 +167,7 @@ static bool enumerate(JSContext* cx, JS::HandleObject obj, JS::AutoIdVector& pro
};
template <typename T>
-static bool getProperty(JSContext* cx,
- JS::HandleObject obj,
- JS::HandleId id,
- JS::MutableHandleValue vp) {
+bool getProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::MutableHandleValue vp) {
try {
T::getProperty(cx, obj, id, vp);
return true;
@@ -161,7 +178,7 @@ static bool getProperty(JSContext* cx,
};
template <typename T>
-static bool hasInstance(JSContext* cx, JS::HandleObject obj, JS::MutableHandleValue vp, bool* bp) {
+bool hasInstance(JSContext* cx, JS::HandleObject obj, JS::MutableHandleValue vp, bool* bp) {
try {
T::hasInstance(cx, obj, vp, bp);
return true;
@@ -172,7 +189,7 @@ static bool hasInstance(JSContext* cx, JS::HandleObject obj, JS::MutableHandleVa
};
template <typename T>
-static bool setProperty(
+bool setProperty(
JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool strict, JS::MutableHandleValue vp) {
try {
T::setProperty(cx, obj, id, strict, vp);
@@ -184,7 +201,7 @@ static bool setProperty(
};
template <typename T>
-static bool resolve(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool* resolvedp) {
+bool resolve(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool* resolvedp) {
try {
T::resolve(cx, obj, id, resolvedp);
return true;