diff options
49 files changed, 534 insertions, 270 deletions
diff --git a/jstests/core/type5.js b/jstests/core/type5.js new file mode 100644 index 00000000000..414af2be7eb --- /dev/null +++ b/jstests/core/type5.js @@ -0,0 +1,22 @@ +(function(){ + "use strict"; + + // This checks SERVER-20375 - Constrain JS method thisv + // + // Check to make sure we can't invoke methods on incorrect types, or on + // prototypes of objects that aren't intended to have methods invoked on + // them. + + assert.throws(function(){ + HexData(0, "aaaa").hex.apply({}); + }, [], "invoke method on object of incorrect type"); + assert.throws(function(){ + var x = HexData(0, "aaaa"); + x.hex.apply(10); + }, [], "invoke method on incorrect type"); + assert.throws(function(){ + var x = HexData(0, "aaaa"); + x.hex.apply(x.__proto__); + }, [], "invoke method on prototype of correct type"); + +})(); 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; |