diff options
author | Justin Seyster <justin.seyster@mongodb.com> | 2022-02-28 22:30:51 -0500 |
---|---|---|
committer | Justin Seyster <justin.seyster@mongodb.com> | 2022-03-07 12:08:01 -0500 |
commit | 26bab136615f5f7a5d6c35e767e2321dcc31b956 (patch) | |
tree | 63ecab22fa06e3b308f91697864f272c44152595 /src/mongo/scripting | |
parent | 82190f17c29d5090c16af894ec21a9b51312cc4f (diff) | |
download | mongo-26bab136615f5f7a5d6c35e767e2321dcc31b956.tar.gz |
SERVER-61008 Upgrade vendorized mozjs to esr91.3
Co-authored-by: Mohammad Dashti <mdashti@gmail.com>
Diffstat (limited to 'src/mongo/scripting')
47 files changed, 441 insertions, 296 deletions
diff --git a/src/mongo/scripting/SConscript b/src/mongo/scripting/SConscript index 22c51451b76..5f028499008 100644 --- a/src/mongo/scripting/SConscript +++ b/src/mongo/scripting/SConscript @@ -125,13 +125,13 @@ if usemozjs: LIBDEPS=[ '$BUILD_DIR/mongo/db/service_context', '$BUILD_DIR/mongo/shell/mongojs', + '$BUILD_DIR/third_party/mozjs/mozjs', 'bson_template_evaluator', 'scripting_common', ], LIBDEPS_PRIVATE=[ '$BUILD_DIR/mongo/client/clientdriver_network', '$BUILD_DIR/mongo/idl/server_parameter', - '$BUILD_DIR/third_party/shim_mozjs', ], ) else: diff --git a/src/mongo/scripting/mozjs/base.cpp b/src/mongo/scripting/mozjs/base.cpp index 96e635f8419..7fe0081f207 100644 --- a/src/mongo/scripting/mozjs/base.cpp +++ b/src/mongo/scripting/mozjs/base.cpp @@ -51,9 +51,9 @@ void BaseInfo::delProperty(JSContext* cx, JS::ObjectOpResult& result) {} void BaseInfo::enumerate(JSContext* cx, JS::HandleObject obj, - JS::AutoIdVector& properties, + JS::MutableHandleIdVector properties, bool enumerableOnly) {} -void BaseInfo::finalize(js::FreeOp* fop, JSObject* obj) {} +void BaseInfo::finalize(JSFreeOp* fop, JSObject* obj) {} void BaseInfo::getProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, diff --git a/src/mongo/scripting/mozjs/base.h b/src/mongo/scripting/mozjs/base.h index dbfeaab669e..8a3916942f3 100644 --- a/src/mongo/scripting/mozjs/base.h +++ b/src/mongo/scripting/mozjs/base.h @@ -71,9 +71,9 @@ struct BaseInfo { JS::ObjectOpResult& result); static void enumerate(JSContext* cx, JS::HandleObject obj, - JS::AutoIdVector& properties, + JS::MutableHandleIdVector properties, bool enumerableOnly); - static void finalize(js::FreeOp* fop, JSObject* obj); + static void finalize(JSFreeOp* fop, JSObject* obj); static void getProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, diff --git a/src/mongo/scripting/mozjs/bindata.cpp b/src/mongo/scripting/mozjs/bindata.cpp index 6182aac28c1..a20aec48088 100644 --- a/src/mongo/scripting/mozjs/bindata.cpp +++ b/src/mongo/scripting/mozjs/bindata.cpp @@ -32,6 +32,8 @@ #include "mongo/scripting/mozjs/bindata.h" #include <iomanip> +#include <js/Object.h> +#include <js/ValueArray.h> #include "mongo/bson/bsonobjbuilder.h" #include "mongo/scripting/mozjs/implscope.h" @@ -80,7 +82,7 @@ void hexToBinData(JSContext* cx, ErrorCodes::BadValue, "BinData hex string must be an even length", hexstr.size() % 2 == 0); std::string encoded = base64::encode(hexblob::decode(hexstr)); - JS::AutoValueArray<2> args(cx); + JS::RootedValueArray<2> args(cx); args[0].setInt32(type); ValueReader(cx, args[1]).fromStringData(encoded); @@ -88,16 +90,16 @@ void hexToBinData(JSContext* cx, } std::string* getEncoded(JS::HandleValue thisv) { - return static_cast<std::string*>(JS_GetPrivate(thisv.toObjectOrNull())); + return static_cast<std::string*>(JS::GetPrivate(thisv.toObjectOrNull())); } std::string* getEncoded(JSObject* thisv) { - return static_cast<std::string*>(JS_GetPrivate(thisv)); + return static_cast<std::string*>(JS::GetPrivate(thisv)); } } // namespace -void BinDataInfo::finalize(js::FreeOp* fop, JSObject* obj) { +void BinDataInfo::finalize(JSFreeOp* fop, JSObject* obj) { auto str = getEncoded(obj); if (str) { @@ -126,7 +128,7 @@ void BinDataInfo::Functions::UUID::call(JSContext* cx, JS::CallArgs args) { ConstDataRange cdr = uuid->toCDR(); std::string encoded = mongo::base64::encode(StringData(cdr.data(), cdr.length())); - JS::AutoValueArray<2> newArgs(cx); + JS::RootedValueArray<2> newArgs(cx); newArgs[0].setInt32(newUUID); ValueReader(cx, newArgs[1]).fromStringData(encoded); getScope(cx)->getProto<BinDataInfo>().newInstance(newArgs, args.rval()); @@ -253,7 +255,7 @@ void BinDataInfo::construct(JSContext* cx, JS::CallArgs args) { o.defineProperty(InternedString::len, len, JSPROP_READONLY); o.defineProperty(InternedString::type, type, JSPROP_READONLY); - JS_SetPrivate(thisv, scope->trackedNew<std::string>(std::move(str))); + JS::SetPrivate(thisv, scope->trackedNew<std::string>(std::move(str))); args.rval().setObjectOrNull(thisv); } diff --git a/src/mongo/scripting/mozjs/bindata.h b/src/mongo/scripting/mozjs/bindata.h index f1b491e3f9b..eafecc602e9 100644 --- a/src/mongo/scripting/mozjs/bindata.h +++ b/src/mongo/scripting/mozjs/bindata.h @@ -41,7 +41,7 @@ namespace mozjs { */ struct BinDataInfo : public BaseInfo { static void construct(JSContext* cx, JS::CallArgs args); - static void finalize(js::FreeOp* fop, JSObject* obj); + static void finalize(JSFreeOp* fop, JSObject* obj); struct Functions { MONGO_DECLARE_JS_FUNCTION(base64); diff --git a/src/mongo/scripting/mozjs/bson.cpp b/src/mongo/scripting/mozjs/bson.cpp index efe78d2feab..69a892a4b39 100644 --- a/src/mongo/scripting/mozjs/bson.cpp +++ b/src/mongo/scripting/mozjs/bson.cpp @@ -32,6 +32,7 @@ #include <boost/optional.hpp> #include <fmt/format.h> +#include <js/Object.h> #include <set> #include "mongo/scripting/mozjs/idwrapper.h" @@ -114,7 +115,7 @@ struct BSONHolder { }; BSONHolder* getValidHolder(JSContext* cx, JSObject* obj) { - auto holder = static_cast<BSONHolder*>(JS_GetPrivate(obj)); + auto holder = static_cast<BSONHolder*>(JS::GetPrivate(obj)); if (holder) holder->uassertValid(cx); @@ -129,11 +130,11 @@ void BSONInfo::make( auto scope = getScope(cx); scope->getProto<BSONInfo>().newObject(obj); - JS_SetPrivate(obj, scope->trackedNew<BSONHolder>(bson, parent, scope, ro)); + JS::SetPrivate(obj, scope->trackedNew<BSONHolder>(bson, parent, scope, ro)); } -void BSONInfo::finalize(js::FreeOp* fop, JSObject* obj) { - auto holder = static_cast<BSONHolder*>(JS_GetPrivate(obj)); +void BSONInfo::finalize(JSFreeOp* fop, JSObject* obj) { + auto holder = static_cast<BSONHolder*>(JS::GetPrivate(obj)); if (!holder) return; @@ -143,7 +144,7 @@ void BSONInfo::finalize(js::FreeOp* fop, JSObject* obj) { void BSONInfo::enumerate(JSContext* cx, JS::HandleObject obj, - JS::AutoIdVector& properties, + JS::MutableHandleIdVector properties, bool enumerableOnly) { auto holder = getValidHolder(cx, obj); diff --git a/src/mongo/scripting/mozjs/bson.h b/src/mongo/scripting/mozjs/bson.h index a2cc5f1d2d3..868c40173c8 100644 --- a/src/mongo/scripting/mozjs/bson.h +++ b/src/mongo/scripting/mozjs/bson.h @@ -54,9 +54,9 @@ struct BSONInfo : public BaseInfo { JS::ObjectOpResult& result); static void enumerate(JSContext* cx, JS::HandleObject obj, - JS::AutoIdVector& properties, + JS::MutableHandleIdVector properties, bool enumerableOnly); - static void finalize(js::FreeOp* fop, JSObject* obj); + static void finalize(JSFreeOp* fop, JSObject* obj); static void resolve(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool* resolvedp); static void setProperty(JSContext* cx, JS::HandleObject obj, diff --git a/src/mongo/scripting/mozjs/countdownlatch.cpp b/src/mongo/scripting/mozjs/countdownlatch.cpp index 6ddbed549de..1e3974b8959 100644 --- a/src/mongo/scripting/mozjs/countdownlatch.cpp +++ b/src/mongo/scripting/mozjs/countdownlatch.cpp @@ -201,8 +201,10 @@ void CountDownLatchInfo::postInstall(JSContext* cx, JS::RootedValue val(cx); for (auto iter = methods; iter->name; ++iter) { - protoWrapper.getValue(iter->name, &val); - objWrapper.setValue(iter->name, val); + invariant(!iter->name.isSymbol()); + ObjectWrapper::Key key(iter->name.string()); + protoWrapper.getValue(key, &val); + objWrapper.setValue(key, val); } val.setObjectOrNull(obj); diff --git a/src/mongo/scripting/mozjs/cursor.cpp b/src/mongo/scripting/mozjs/cursor.cpp index 23cb6fd7082..9a019b96be2 100644 --- a/src/mongo/scripting/mozjs/cursor.cpp +++ b/src/mongo/scripting/mozjs/cursor.cpp @@ -29,6 +29,8 @@ #include "mongo/platform/basic.h" +#include <js/Object.h> + #include "mongo/scripting/mozjs/cursor.h" #include "mongo/scripting/mozjs/bson.h" @@ -58,7 +60,7 @@ const char* const CursorInfo::className = "Cursor"; namespace { DBClientCursor* getCursor(JSObject* thisv) { - return static_cast<CursorInfo::CursorHolder*>(JS_GetPrivate(thisv))->cursor.get(); + return static_cast<CursorInfo::CursorHolder*>(JS::GetPrivate(thisv))->cursor.get(); } DBClientCursor* getCursor(JS::CallArgs& args) { @@ -67,8 +69,8 @@ DBClientCursor* getCursor(JS::CallArgs& args) { } // namespace -void CursorInfo::finalize(js::FreeOp* fop, JSObject* obj) { - auto cursor = static_cast<CursorInfo::CursorHolder*>(JS_GetPrivate(obj)); +void CursorInfo::finalize(JSFreeOp* fop, JSObject* obj) { + auto cursor = static_cast<CursorInfo::CursorHolder*>(JS::GetPrivate(obj)); if (cursor) { getScope(fop)->trackedDelete(cursor); diff --git a/src/mongo/scripting/mozjs/cursor.h b/src/mongo/scripting/mozjs/cursor.h index 6373d21fe04..287182a79c3 100644 --- a/src/mongo/scripting/mozjs/cursor.h +++ b/src/mongo/scripting/mozjs/cursor.h @@ -42,7 +42,7 @@ namespace mozjs { * from C++. Current callers are all via the Mongo object. */ struct CursorInfo : public BaseInfo { - static void finalize(js::FreeOp* fop, JSObject* obj); + static void finalize(JSFreeOp* fop, JSObject* obj); struct Functions { MONGO_DECLARE_JS_FUNCTION(close); diff --git a/src/mongo/scripting/mozjs/cursor_handle.cpp b/src/mongo/scripting/mozjs/cursor_handle.cpp index 34ecada45f0..083032bb75f 100644 --- a/src/mongo/scripting/mozjs/cursor_handle.cpp +++ b/src/mongo/scripting/mozjs/cursor_handle.cpp @@ -31,6 +31,8 @@ #include "mongo/platform/basic.h" +#include <js/Object.h> + #include "mongo/client/dbclient_base.h" #include "mongo/logv2/log.h" #include "mongo/scripting/mozjs/cursor_handle.h" @@ -52,7 +54,7 @@ namespace { long long* getCursorId(JSObject* thisv) { CursorHandleInfo::CursorTracker* tracker = - static_cast<CursorHandleInfo::CursorTracker*>(JS_GetPrivate(thisv)); + static_cast<CursorHandleInfo::CursorTracker*>(JS::GetPrivate(thisv)); if (tracker) { return &tracker->cursorId; } @@ -66,8 +68,8 @@ long long* getCursorId(JS::CallArgs& args) { } // namespace -void CursorHandleInfo::finalize(js::FreeOp* fop, JSObject* obj) { - auto cursorTracker = static_cast<CursorHandleInfo::CursorTracker*>(JS_GetPrivate(obj)); +void CursorHandleInfo::finalize(JSFreeOp* fop, JSObject* obj) { + auto cursorTracker = static_cast<CursorHandleInfo::CursorTracker*>(JS::GetPrivate(obj)); if (cursorTracker) { const long long cursorId = cursorTracker->cursorId; if (!skipShellCursorFinalize && cursorId) { diff --git a/src/mongo/scripting/mozjs/cursor_handle.h b/src/mongo/scripting/mozjs/cursor_handle.h index e16b66ffd5f..eb28e206d22 100644 --- a/src/mongo/scripting/mozjs/cursor_handle.h +++ b/src/mongo/scripting/mozjs/cursor_handle.h @@ -42,7 +42,7 @@ namespace mozjs { * callers are all via the Mongo object. */ struct CursorHandleInfo : public BaseInfo { - static void finalize(js::FreeOp* fop, JSObject* obj); + static void finalize(JSFreeOp* fop, JSObject* obj); struct Functions { MONGO_DECLARE_JS_FUNCTION(zeroCursorId); diff --git a/src/mongo/scripting/mozjs/db.cpp b/src/mongo/scripting/mozjs/db.cpp index 4748e9a308b..22e3ca486e5 100644 --- a/src/mongo/scripting/mozjs/db.cpp +++ b/src/mongo/scripting/mozjs/db.cpp @@ -31,6 +31,9 @@ #include "mongo/scripting/mozjs/db.h" +#include <js/ValueArray.h> +#include <jsfriendapi.h> + #include "mongo/db/namespace_string.h" #include "mongo/db/operation_context.h" #include "mongo/scripting/mozjs/idwrapper.h" @@ -91,11 +94,11 @@ void DBInfo::resolve(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool* // Check if getCollection has been installed yet // It is undefined if the user has a db name the same as one of methods/properties of the DB // object. - if (!(getCollection.isObject() && JS_ObjectIsFunction(cx, getCollection.toObjectOrNull()))) { + if (!(getCollection.isObject() && js::IsFunctionObject(getCollection.toObjectOrNull()))) { return; } - JS::AutoValueArray<1> args(cx); + JS::RootedValueArray<1> args(cx); idw.toValue(args[0]); diff --git a/src/mongo/scripting/mozjs/dbquery.cpp b/src/mongo/scripting/mozjs/dbquery.cpp index 3148a702bd3..e196c8d6a72 100644 --- a/src/mongo/scripting/mozjs/dbquery.cpp +++ b/src/mongo/scripting/mozjs/dbquery.cpp @@ -31,6 +31,9 @@ #include "mongo/scripting/mozjs/dbquery.h" +#include <js/ValueArray.h> +#include <jsfriendapi.h> + #include "mongo/scripting/mozjs/idwrapper.h" #include "mongo/scripting/mozjs/implscope.h" #include "mongo/scripting/mozjs/internedstring.h" @@ -125,8 +128,8 @@ void DBQueryInfo::resolve(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::RootedValue arrayAccess(cx); parentWrapper.getValue(InternedString::arrayAccess, &arrayAccess); - if (arrayAccess.isObject() && JS_ObjectIsFunction(cx, arrayAccess.toObjectOrNull())) { - JS::AutoValueArray<1> args(cx); + if (arrayAccess.isObject() && js::IsFunctionObject(arrayAccess.toObjectOrNull())) { + JS::RootedValueArray<1> args(cx); args[0].setInt32(wid.toInt32()); diff --git a/src/mongo/scripting/mozjs/dbref.cpp b/src/mongo/scripting/mozjs/dbref.cpp index 036efc1983e..9f602813c84 100644 --- a/src/mongo/scripting/mozjs/dbref.cpp +++ b/src/mongo/scripting/mozjs/dbref.cpp @@ -27,11 +27,12 @@ * it in the license file. */ -#include "mongo/platform/basic.h" +#include <js/Object.h> -#include "mongo/scripting/mozjs/dbref.h" +#include "mongo/platform/basic.h" #include "mongo/scripting/mozjs/bson.h" +#include "mongo/scripting/mozjs/dbref.h" #include "mongo/scripting/mozjs/implscope.h" #include "mongo/scripting/mozjs/internedstring.h" #include "mongo/scripting/mozjs/objectwrapper.h" @@ -68,13 +69,13 @@ void DBRefInfo::construct(JSContext* cx, JS::CallArgs args) { args.rval().setObjectOrNull(out); } -void DBRefInfo::finalize(js::FreeOp* fop, JSObject* obj) { +void DBRefInfo::finalize(JSFreeOp* fop, JSObject* obj) { BSONInfo::finalize(fop, obj); } void DBRefInfo::enumerate(JSContext* cx, JS::HandleObject obj, - JS::AutoIdVector& properties, + JS::MutableHandleIdVector properties, bool enumerableOnly) { BSONInfo::enumerate(cx, obj, properties, enumerableOnly); } @@ -108,8 +109,8 @@ void DBRefInfo::make( auto scope = getScope(cx); scope->getProto<DBRefInfo>().newObject(obj); - JS_SetPrivate(obj, JS_GetPrivate(local)); - JS_SetPrivate(local, nullptr); + JS::SetPrivate(obj, JS::GetPrivate(local)); + JS::SetPrivate(local, nullptr); } } // namespace mozjs diff --git a/src/mongo/scripting/mozjs/dbref.h b/src/mongo/scripting/mozjs/dbref.h index 33a34134eb0..9f446d2de02 100644 --- a/src/mongo/scripting/mozjs/dbref.h +++ b/src/mongo/scripting/mozjs/dbref.h @@ -56,9 +56,9 @@ struct DBRefInfo : public BaseInfo { JS::ObjectOpResult& result); static void enumerate(JSContext* cx, JS::HandleObject obj, - JS::AutoIdVector& properties, + JS::MutableHandleIdVector properties, bool enumerableOnly); - static void finalize(js::FreeOp* fop, JSObject* obj); + static void finalize(JSFreeOp* fop, JSObject* obj); static void resolve(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool* resolvedp); static void setProperty(JSContext* cx, JS::HandleObject obj, diff --git a/src/mongo/scripting/mozjs/exception.cpp b/src/mongo/scripting/mozjs/exception.cpp index e73ef8e394a..e9ede34b9aa 100644 --- a/src/mongo/scripting/mozjs/exception.cpp +++ b/src/mongo/scripting/mozjs/exception.cpp @@ -31,6 +31,7 @@ #include "mongo/scripting/mozjs/exception.h" +#include <js/friend/ErrorMessages.h> #include <jsfriendapi.h> #include <limits> diff --git a/src/mongo/scripting/mozjs/idwrapper.cpp b/src/mongo/scripting/mozjs/idwrapper.cpp index 068374bbc28..a774d9e0f81 100644 --- a/src/mongo/scripting/mozjs/idwrapper.cpp +++ b/src/mongo/scripting/mozjs/idwrapper.cpp @@ -47,9 +47,9 @@ std::string IdWrapper::toString() const { } StringData IdWrapper::toStringData(JSStringWrapper* jsstr) const { - if (JSID_IS_STRING(_value)) { + if (_value.isString()) { *jsstr = JSStringWrapper(_context, JSID_TO_STRING(_value)); - } else if (JSID_IS_INT(_value)) { + } else if (_value.isInt()) { *jsstr = JSStringWrapper(JSID_TO_INT(_value)); } else { throwCurrentJSException(_context, @@ -61,7 +61,7 @@ StringData IdWrapper::toStringData(JSStringWrapper* jsstr) const { } uint32_t IdWrapper::toInt32() const { - uassert(ErrorCodes::TypeMismatch, "Cannot toInt32() non-integer jsid", JSID_IS_INT(_value)); + uassert(ErrorCodes::TypeMismatch, "Cannot toInt32() non-integer jsid", _value.isInt()); return JSID_TO_INT(_value); } @@ -110,11 +110,11 @@ bool IdWrapper::equalsAscii(StringData sd) const { } bool IdWrapper::isInt() const { - return JSID_IS_INT(_value); + return _value.isInt(); } bool IdWrapper::isString() const { - return JSID_IS_STRING(_value); + return _value.isString(); } } // namespace mozjs diff --git a/src/mongo/scripting/mozjs/implscope.cpp b/src/mongo/scripting/mozjs/implscope.cpp index 7cf6e8c28c8..1bc935b0741 100644 --- a/src/mongo/scripting/mozjs/implscope.cpp +++ b/src/mongo/scripting/mozjs/implscope.cpp @@ -37,6 +37,13 @@ #include <memory> #include <js/CharacterEncoding.h> +#include <js/CompilationAndEvaluation.h> +#include <js/ContextOptions.h> +#include <js/Initialization.h> +#include <js/Object.h> +#include <js/SourceText.h> +#include <js/TypeDecls.h> +#include <jsapi.h> #include <jscustomallocator.h> #include <jsfriendapi.h> @@ -121,8 +128,7 @@ thread_local MozJSImplScope::ASANHandles* kCurrentASANHandles = nullptr; thread_local std::atomic<MozJSImplScope*> kCurrentScope = nullptr; // NOLINT struct MozJSImplScope::MozJSEntry { - MozJSEntry(MozJSImplScope* scope) - : ar(scope->_context), ac(scope->_context, scope->_global), _scope(scope) { + MozJSEntry(MozJSImplScope* scope) : ac(scope->_context, scope->_global), _scope(scope) { ++_scope->_inOp; } @@ -130,8 +136,7 @@ struct MozJSImplScope::MozJSEntry { --_scope->_inOp; } - JSAutoRequest ar; - JSAutoCompartment ac; + JSAutoRealm ac; MozJSImplScope* _scope; }; @@ -165,8 +170,8 @@ void MozJSImplScope::kill() { { stdx::lock_guard<Latch> lk(_mutex); - // If we are on the right thread, in the middle of an operation, and we have a registered - // opCtx, then we should check the opCtx for interrupts. + // If we are on the right thread, in the middle of an operation, and we have a + // registered opCtx, then we should check the opCtx for interrupts. if (_opCtxThreadId == stdx::this_thread::get_id() && _inOp > 0 && _opCtx) { _killStatus = _opCtx->checkForInterruptNoAssert(); } @@ -232,7 +237,10 @@ bool MozJSImplScope::_interruptCallback(JSContext* cx) { return scope->_status.isOK(); } -void MozJSImplScope::_gcCallback(JSContext* rt, JSGCStatus status, void* data) { +void MozJSImplScope::_gcCallback(JSContext* rt, + JSGCStatus status, + JS::GCReason reason, + void* data) { if (!shouldLog(MONGO_LOGV2_DEFAULT_COMPONENT, logv2::LogSeverity::Debug(1))) { // don't collect stats unless verbose return; @@ -241,6 +249,7 @@ void MozJSImplScope::_gcCallback(JSContext* rt, JSGCStatus status, void* data) { LOGV2_INFO(22787, "MozJS GC heap stats", "phase"_attr = (status == JSGC_BEGIN ? "prologue" : "epilogue"), + "reason"_attr = reason, "total"_attr = mongo::sm::get_total_bytes(), "limit"_attr = mongo::sm::get_max_bytes()); } @@ -284,8 +293,8 @@ MozJSImplScope::MozRuntime::MozRuntime(const MozJSScriptEngine* engine, /** * The maximum amount of memory to be given out per thread to mozilla. We * manage this by trapping all calls to malloc, free, etc. and keeping track of - * counts in some thread locals. If 'jsHeapLimitMB' is specified then we use this instead of the - * engine limit, given it does not exceed the engine limit. + * counts in some thread locals. If 'jsHeapLimitMB' is specified then we use this instead of + * the engine limit, given it does not exceed the engine limit. */ const auto engineJsHeapLimit = engine->getJSHeapLimitMB(); const auto jsHeapLimit = @@ -311,8 +320,7 @@ MozJSImplScope::MozRuntime::MozRuntime(const MozJSScriptEngine* engine, } _context = std::unique_ptr<JSContext, std::function<void(JSContext*)>>( - JS_NewContext(kMaxBytesBeforeGC, JS::DefaultNurseryBytes), - [](JSContext* ptr) { JS_DestroyContext(ptr); }); + JS_NewContext(kMaxBytesBeforeGC), [](JSContext* ptr) { JS_DestroyContext(ptr); }); uassert(ErrorCodes::JSInterpreterFailure, "Failed to initialize JSContext", _context); // We turn on a variety of optimizations if the jit is enabled @@ -320,23 +328,20 @@ MozJSImplScope::MozRuntime::MozRuntime(const MozJSScriptEngine* engine, JS::ContextOptionsRef(_context.get()) .setAsmJS(true) .setThrowOnAsmJSValidationFailure(true) - .setBaseline(true) - .setIon(true) - .setAsyncStack(false) - .setNativeRegExp(true); + .setWasmBaseline(true) + .setAsyncStack(false); } else { JS::ContextOptionsRef(_context.get()) .setAsmJS(false) .setThrowOnAsmJSValidationFailure(false) - .setBaseline(false) - .setIon(false) - .setAsyncStack(false) - .setNativeRegExp(false); + .setWasmBaseline(false) + .setDisableIon() + .setAsyncStack(false); } uassert(ErrorCodes::JSInterpreterFailure, "UseInternalJobQueues", - js::UseInternalJobQueues(_context.get(), true)); + js::UseInternalJobQueues(_context.get())); uassert(ErrorCodes::JSInterpreterFailure, "InitSelfHostedCode", @@ -363,10 +368,10 @@ MozJSImplScope::MozRuntime::MozRuntime(const MozJSScriptEngine* engine, const auto available_stack_space = available.get(); #if defined(__powerpc64__) && defined(MONGO_CONFIG_DEBUG_BUILD) - // From experimentation, we need a larger reservation of 96k since debug ppc64le code - // needs more stack space to process stack overflow. In debug builds, more variables are - // stored on the stack which increases the stack pressure. It does not affects non-debug - // builds. + // From experimentation, we need a larger reservation of 96k since debug ppc64le + // code needs more stack space to process stack overflow. In debug builds, more + // variables are stored on the stack which increases the stack pressure. It does not + // affects non-debug builds. const decltype(available_stack_space) reserve_stack_space = 96 * 1024; #elif defined(_WIN32) // Windows is greedy for stack space while processing exceptions. @@ -437,11 +442,10 @@ MozJSImplScope::MozJSImplScope(MozJSScriptEngine* engine, boost::optional<int> j JS_AddInterruptCallback(_context, _interruptCallback); JS_SetGCCallback(_context, _gcCallback, this); JS_SetContextPrivate(_context, this); - JSAutoRequest ar(_context); - JSAutoCompartment ac(_context, _global); + JSAutoRealm ac(_context, _global); - _checkErrorState(JS_InitStandardClasses(_context, _global)); + _checkErrorState(JS::InitRealmStandardClasses(_context)); installBSONTypes(); @@ -454,7 +458,8 @@ MozJSImplScope::MozJSImplScope(MozJSScriptEngine* engine, boost::optional<int> j installGlobalUtils(*this); _mongoHelpersProto.install(_global); - // install process-specific utilities in the global scope (dependancy: types.js, assert.js) + // install process-specific utilities in the global scope (dependancy: types.js, + // assert.js) if (_engine->getScopeInitCallback()) _engine->getScopeInitCallback()(*this); } catch (...) { @@ -494,17 +499,17 @@ auto MozJSImplScope::_runSafely(ImplScopeFunction&& functionToRun) -> decltype(f MozJSEntry entry(this); return functionToRun(); } catch (...) { - // There may have already been an error reported by SpiderMonkey. If not, then we use the - // active C++ exception as the cause of the error. + // There may have already been an error reported by SpiderMonkey. If not, then we use + // the active C++ exception as the cause of the error. if (_status.isOK()) { _status = exceptionToStatus(); } if (auto extraInfo = _status.extraInfo<JSExceptionInfo>()) { - // We intentionally don't transmit an JSInterpreterFailureWithStack error over the wire - // because of the complexity it'd entail on the recipient to reach inside to the - // underlying error for how it should be handled. Instead, the error is unwrapped and - // the JavaScript stacktrace is included as part of the error message. + // We intentionally don't transmit an JSInterpreterFailureWithStack error over the + // wire because of the complexity it'd entail on the recipient to reach inside to + // the underlying error for how it should be handled. Instead, the error is + // unwrapped and the JavaScript stacktrace is included as part of the error message. str::stream reasonWithStack; reasonWithStack << extraInfo->originalError.reason() << " :\n" << extraInfo->stack; _status = extraInfo->originalError.withReason(reasonWithStack); @@ -586,17 +591,19 @@ void MozJSImplScope::_MozJSCreateFunction(StringData raw, JS::MutableHandleValue JS::CompileOptions co(_context); setCompileOptions(&co); - _checkErrorState(JS::Evaluate(_context, co, code.c_str(), code.length(), fun)); - uassert(10232, - "not a function", - fun.isObject() && JS_ObjectIsFunction(_context, fun.toObjectOrNull())); + JS::SourceText<mozilla::Utf8Unit> srcBuf; + + _checkErrorState( + srcBuf.init(_context, code.c_str(), code.length(), JS::SourceOwnership::Borrowed) && + JS::Evaluate(_context, co, srcBuf, fun)); + uassert(10232, "not a function", fun.isObject() && js::IsFunctionObject(fun.toObjectOrNull())); } BSONObj MozJSImplScope::callThreadArgs(const BSONObj& args) { // The _runSafely() function is called for all codepaths of executing JavaScript other than - // callThreadArgs(). We intentionally don't unwrap the JSInterpreterFailureWithStack error to - // make it possible for the parent thread to chain its JavaScript stacktrace with the child - // thread's JavaScript stacktrace. + // callThreadArgs(). We intentionally don't unwrap the JSInterpreterFailureWithStack error + // to make it possible for the parent thread to chain its JavaScript stacktrace with the + // child thread's JavaScript stacktrace. MozJSEntry entry(this); JS::RootedValue function(_context); @@ -610,7 +617,7 @@ BSONObj MozJSImplScope::callThreadArgs(const BSONObj& args) { int argc = args.nFields() - 1; - JS::AutoValueVector argv(_context); + JS::RootedValueVector argv(_context); BSONObjIterator it(args); it.next(); JS::RootedValue value(_context); @@ -683,7 +690,7 @@ int MozJSImplScope::invoke(ScriptingFunction func, const int nargs = argsObject ? argsObject->nFields() : 0; - JS::AutoValueVector args(_context); + JS::RootedValueVector args(_context); if (nargs) { BSONObjIterator it(*argsObject); @@ -751,13 +758,22 @@ bool MozJSImplScope::exec(StringData code, JS::CompileOptions co(_context); setCompileOptions(&co); co.setFileAndLine(name.c_str(), 1); - JS::RootedScript script(_context); - bool success = JS::Compile(_context, co, code.rawData(), code.size(), &script); + JS::SourceText<mozilla::Utf8Unit> srcBuf; + JSScript* scriptPtr; + + bool success = + srcBuf.init(_context, code.rawData(), code.size(), JS::SourceOwnership::Borrowed); + if (_checkErrorState(success, reportError, assertOnError)) + return false; + scriptPtr = JS::Compile(_context, co, srcBuf); + success = scriptPtr != nullptr; if (_checkErrorState(success, reportError, assertOnError)) return false; + JS::RootedScript script(_context, scriptPtr); + if (timeoutMs) { _engine->getDeadlineMonitor().startDeadline(this, timeoutMs); } else { @@ -901,7 +917,7 @@ bool MozJSImplScope::_checkErrorState(bool success, bool reportError, bool asser if (excn.isObject()) { str::stream ss; // exceptions originating from c++ don't get the "uncaught exception: " prefix - if (!JS_GetPrivate(excn.toObjectOrNull())) { + if (!JS::GetPrivate(excn.toObjectOrNull())) { ss << "uncaught exception: "; } ss << ValueWriter(_context, excn).toString(); @@ -964,9 +980,7 @@ bool MozJSImplScope::_checkErrorState(bool success, bool reportError, bool asser } -void MozJSImplScope::setCompileOptions(JS::CompileOptions* co) { - co->setUTF8(true); -} +void MozJSImplScope::setCompileOptions(JS::CompileOptions* co) {} MozJSImplScope* MozJSImplScope::getThreadScope() { return kCurrentScope; @@ -1013,7 +1027,7 @@ std::string MozJSImplScope::buildStackString() { } JS::RootedString out(_context); - if (JS::BuildStackString(_context, stack, &out)) { + if (JS::BuildStackString(_context, nullptr, stack, &out)) { return JSStringWrapper(_context, out.get()).toString(); } else { return {}; diff --git a/src/mongo/scripting/mozjs/implscope.h b/src/mongo/scripting/mozjs/implscope.h index 86aa6c5dd05..0dbf3a8aa2b 100644 --- a/src/mongo/scripting/mozjs/implscope.h +++ b/src/mongo/scripting/mozjs/implscope.h @@ -396,7 +396,7 @@ private: friend struct MozJSEntry; static bool _interruptCallback(JSContext* cx); - static void _gcCallback(JSContext* rt, JSGCStatus status, void* data); + static void _gcCallback(JSContext* rt, JSGCStatus status, JS::GCReason reason, void* data); bool _checkErrorState(bool success, bool reportError = true, bool assertOnError = true); void installDBAccess(); @@ -466,7 +466,7 @@ inline MozJSImplScope* getScope(JSContext* cx) { return static_cast<MozJSImplScope*>(JS_GetContextPrivate(cx)); } -inline MozJSImplScope* getScope(js::FreeOp* fop) { +inline MozJSImplScope* getScope(JSFreeOp* fop) { return getScope(freeOpToJSContext(fop)); } diff --git a/src/mongo/scripting/mozjs/internedstring.cpp b/src/mongo/scripting/mozjs/internedstring.cpp index 559bfbd224a..a4e040317f4 100644 --- a/src/mongo/scripting/mozjs/internedstring.cpp +++ b/src/mongo/scripting/mozjs/internedstring.cpp @@ -37,8 +37,6 @@ namespace mongo { namespace mozjs { InternedStringTable::InternedStringTable(JSContext* cx) { - JSAutoRequest ar(cx); - int i = 0; #define MONGO_MOZJS_INTERNED_STRING(name, str) \ @@ -47,7 +45,7 @@ InternedStringTable::InternedStringTable(JSContext* cx) { if (!s) { \ uasserted(ErrorCodes::JSInterpreterFailure, "Failed to JS_InternString"); \ } \ - _internedStrings[i++].init(cx, INTERNED_STRING_TO_JSID(cx, s)); \ + _internedStrings[i++].init(cx, JS::PropertyKey::fromPinnedString(s)); \ } while (0); #include "mongo/scripting/mozjs/internedstring.defs" #undef MONGO_MOZJS_INTERNED_STRING diff --git a/src/mongo/scripting/mozjs/jscustomallocator.cpp b/src/mongo/scripting/mozjs/jscustomallocator.cpp index d170e9a0873..f8031f54ad2 100644 --- a/src/mongo/scripting/mozjs/jscustomallocator.cpp +++ b/src/mongo/scripting/mozjs/jscustomallocator.cpp @@ -30,6 +30,7 @@ #include "mongo/platform/basic.h" #include <cstddef> +#include <js/Utility.h> #include <jscustomallocator.h> #include <type_traits> @@ -196,19 +197,92 @@ size_t get_current(void* ptr) { } // namespace sm } // namespace mongo +JS_PUBLIC_DATA arena_id_t js::MallocArena; +JS_PUBLIC_DATA arena_id_t js::ArrayBufferContentsArena; +JS_PUBLIC_DATA arena_id_t js::StringBufferArena; + +void* mongo_arena_malloc(arena_id_t arena, size_t bytes) { + return std::malloc(bytes); +} + +void* mongo_arena_calloc(arena_id_t arena, size_t nmemb, size_t size) { + return std::calloc(nmemb, size); +} + +void* mongo_arena_realloc(arena_id_t arena, void* p, size_t bytes) { + if (!p) { + return mongo_arena_malloc(arena, bytes); + } + + if (!bytes) { + js_free(p); + return nullptr; + } + + size_t current = mongo::sm::get_current(p); + + if (current >= bytes) { + return p; + } + + size_t tb = mongo::sm::total_bytes; + + if (tb >= current) { + mongo::sm::total_bytes = tb - current; + } + + return std::realloc(p, bytes); +} + +void* js_arena_malloc(size_t arena, size_t bytes) { + JS_OOM_POSSIBLY_FAIL(); + JS_CHECK_LARGE_ALLOC(bytes); + return mongo::sm::wrap_alloc( + [&](void* ptr, size_t b) { return mongo_arena_malloc(arena, bytes); }, nullptr, bytes); +} + void* js_malloc(size_t bytes) { + return js_arena_malloc(js::MallocArena, bytes); +} + +void* js_arena_calloc(arena_id_t arena, size_t bytes) { + JS_OOM_POSSIBLY_FAIL(); + JS_CHECK_LARGE_ALLOC(bytes); return mongo::sm::wrap_alloc( - [](void* ptr, size_t b) { return std::malloc(b); }, nullptr, bytes); + [&](void* ptr, size_t b) { return mongo_arena_calloc(arena, 1, b); }, nullptr, bytes); } -void* js_calloc(size_t bytes) { +void* js_arena_calloc(arena_id_t arena, size_t nmemb, size_t size) { + JS_OOM_POSSIBLY_FAIL(); + JS_CHECK_LARGE_ALLOC(size); return mongo::sm::wrap_alloc( - [](void* ptr, size_t b) { return std::calloc(b, 1); }, nullptr, bytes); + [&](void* ptr, size_t b) { return mongo_arena_calloc(arena, nmemb, size); }, + nullptr, + size * nmemb); +} + +void* js_calloc(size_t bytes) { + return js_arena_calloc(js::MallocArena, bytes); } void* js_calloc(size_t nmemb, size_t size) { + return js_arena_calloc(js::MallocArena, nmemb, size); +} + +void* js_arena_realloc(arena_id_t arena, void* p, size_t bytes) { + // realloc() with zero size is not portable, as some implementations may + // return nullptr on success and free |p| for this. We assume nullptr + // indicates failure and that |p| is still valid. + MOZ_ASSERT(bytes != 0); + + JS_OOM_POSSIBLY_FAIL(); + JS_CHECK_LARGE_ALLOC(bytes); return mongo::sm::wrap_alloc( - [](void* ptr, size_t b) { return std::calloc(b, 1); }, nullptr, nmemb * size); + [&](void* ptr, size_t b) { return mongo_arena_realloc(arena, ptr, b); }, p, bytes); +} + +void* js_realloc(void* p, size_t bytes) { + return js_arena_realloc(js::MallocArena, p, bytes); } void js_free(void* p) { @@ -231,32 +305,10 @@ void js_free(void* p) { 0); } -void* js_realloc(void* p, size_t bytes) { - if (!p) { - return js_malloc(bytes); - } - - if (!bytes) { - js_free(p); - return nullptr; - } - - size_t current = mongo::sm::get_current(p); - - if (current >= bytes) { - return p; - } - - size_t tb = mongo::sm::total_bytes; - - if (tb >= current) { - mongo::sm::total_bytes = tb - current; - } - - return mongo::sm::wrap_alloc( - [](void* ptr, size_t b) { return std::realloc(ptr, b); }, p, bytes); +void js::InitMallocAllocator() { + MallocArena = 0; + ArrayBufferContentsArena = 1; + StringBufferArena = 2; } -void js::InitMallocAllocator() {} - void js::ShutDownMallocAllocator() {} diff --git a/src/mongo/scripting/mozjs/jsstringwrapper.cpp b/src/mongo/scripting/mozjs/jsstringwrapper.cpp index 3c01ce3e665..441a2415663 100644 --- a/src/mongo/scripting/mozjs/jsstringwrapper.cpp +++ b/src/mongo/scripting/mozjs/jsstringwrapper.cpp @@ -57,8 +57,8 @@ JSStringWrapper::JSStringWrapper(JSContext* cx, JSString* str) : _isSet(true) { // how long the utf8 strings we get out are. // // Well, at least js/CharacterEncoding's GetDeflatedUTF8StringLength - // and JS_flattenString are all in the public headers... - JSFlatString* flat = JS_FlattenString(cx, str); + // and StringToLinearString are all in the public headers... + JSLinearString* flat = JS::StringToLinearString(cx, str); if (!flat) throwCurrentJSException(cx, ErrorCodes::InternalError, "Failed to flatten JSString"); @@ -72,7 +72,7 @@ JSStringWrapper::JSStringWrapper(JSContext* cx, JSString* str) : _isSet(true) { out = _str.get(); } - JS::DeflateStringToUTF8Buffer(flat, mozilla::RangedPtr<char>(out, _length)); + JS::DeflateStringToUTF8Buffer(flat, mozilla::Span(out, _length)); out[_length] = '\0'; } diff --git a/src/mongo/scripting/mozjs/jsthread.cpp b/src/mongo/scripting/mozjs/jsthread.cpp index 26641044afc..550a7db9c11 100644 --- a/src/mongo/scripting/mozjs/jsthread.cpp +++ b/src/mongo/scripting/mozjs/jsthread.cpp @@ -34,6 +34,9 @@ #include "mongo/scripting/mozjs/jsthread.h" #include <cstdio> +#include <js/Array.h> +#include <js/Object.h> +#include <jsfriendapi.h> #include <memory> #include <vm/PosixNSPR.h> @@ -87,11 +90,11 @@ public: uassert(ErrorCodes::JSInterpreterFailure, "need at least one argument", args.length() > 0); uassert(ErrorCodes::JSInterpreterFailure, "first argument must be a function", - args.get(0).isObject() && JS_ObjectIsFunction(cx, args.get(0).toObjectOrNull())); + args.get(0).isObject() && js::IsFunctionObject(args.get(0).toObjectOrNull())); - JS::RootedObject robj(cx, JS_NewArrayObject(cx, args)); + JS::RootedObject robj(cx, JS::NewArrayObject(cx, args)); if (!robj) { - uasserted(ErrorCodes::JSInterpreterFailure, "Failed to JS_NewArrayObject"); + uasserted(ErrorCodes::JSInterpreterFailure, "Failed to JS::NewArrayObject"); } _sharedData->_args = ObjectWrapper(cx, robj).toBSON(); @@ -222,13 +225,13 @@ JSThreadConfig* getConfig(JSContext* cx, JS::CallArgs args) { if (!getScope(cx)->getProto<JSThreadInfo>().instanceOf(value)) uasserted(ErrorCodes::BadValue, "_JSThreadConfig is not a JSThread"); - return static_cast<JSThreadConfig*>(JS_GetPrivate(value.toObjectOrNull())); + return static_cast<JSThreadConfig*>(JS::GetPrivate(value.toObjectOrNull())); } } // namespace -void JSThreadInfo::finalize(js::FreeOp* fop, JSObject* obj) { - auto config = static_cast<JSThreadConfig*>(JS_GetPrivate(obj)); +void JSThreadInfo::finalize(JSFreeOp* fop, JSObject* obj) { + auto config = static_cast<JSThreadConfig*>(JS::GetPrivate(obj)); if (!config) return; @@ -242,7 +245,7 @@ void JSThreadInfo::Functions::init::call(JSContext* cx, JS::CallArgs args) { JS::RootedObject obj(cx); scope->getProto<JSThreadInfo>().newObject(&obj); JSThreadConfig* config = scope->trackedNew<JSThreadConfig>(cx, args); - JS_SetPrivate(obj, config); + JS::SetPrivate(obj, config); ObjectWrapper(cx, args.thisv()).setObject(InternedString::_JSThreadConfig, obj); diff --git a/src/mongo/scripting/mozjs/jsthread.h b/src/mongo/scripting/mozjs/jsthread.h index 3f9034f7814..785ce622a65 100644 --- a/src/mongo/scripting/mozjs/jsthread.h +++ b/src/mongo/scripting/mozjs/jsthread.h @@ -46,7 +46,7 @@ namespace mozjs { * JSThread and add our holder in as our JSThread's private member. */ struct JSThreadInfo : public BaseInfo { - static void finalize(js::FreeOp* fop, JSObject* obj); + static void finalize(JSFreeOp* fop, JSObject* obj); struct Functions { MONGO_DECLARE_JS_FUNCTION(init); diff --git a/src/mongo/scripting/mozjs/mongo.cpp b/src/mongo/scripting/mozjs/mongo.cpp index 58325932609..b06f404c383 100644 --- a/src/mongo/scripting/mozjs/mongo.cpp +++ b/src/mongo/scripting/mozjs/mongo.cpp @@ -31,6 +31,7 @@ #include "mongo/scripting/mozjs/mongo.h" +#include <js/Object.h> #include <memory> #include "mongo/bson/simple_bsonelement_comparator.h" @@ -96,7 +97,7 @@ namespace { const std::shared_ptr<DBClientBase>& getConnectionRef(JS::CallArgs& args) { auto ret = - static_cast<std::shared_ptr<DBClientBase>*>(JS_GetPrivate(args.thisv().toObjectOrNull())); + static_cast<std::shared_ptr<DBClientBase>*>(JS::GetPrivate(args.thisv().toObjectOrNull())); uassert( ErrorCodes::BadValue, "Trying to get connection for closed Mongo object", *ret != nullptr); return *ret; @@ -120,10 +121,10 @@ void setCursor(MozJSImplScope* scope, std::unique_ptr<DBClientCursor> cursor, JS::CallArgs& args) { auto client = - static_cast<std::shared_ptr<DBClientBase>*>(JS_GetPrivate(args.thisv().toObjectOrNull())); + static_cast<std::shared_ptr<DBClientBase>*>(JS::GetPrivate(args.thisv().toObjectOrNull())); // Copy the client shared pointer to up the refcount - JS_SetPrivate(target, scope->trackedNew<CursorInfo::CursorHolder>(std::move(cursor), *client)); + JS::SetPrivate(target, scope->trackedNew<CursorInfo::CursorHolder>(std::move(cursor), *client)); } void setCursorHandle(MozJSImplScope* scope, @@ -132,10 +133,10 @@ void setCursorHandle(MozJSImplScope* scope, long long cursorId, JS::CallArgs& args) { auto client = - static_cast<std::shared_ptr<DBClientBase>*>(JS_GetPrivate(args.thisv().toObjectOrNull())); + static_cast<std::shared_ptr<DBClientBase>*>(JS::GetPrivate(args.thisv().toObjectOrNull())); // Copy the client shared pointer to up the refcount. - JS_SetPrivate( + JS::SetPrivate( target, scope->trackedNew<CursorHandleInfo::CursorTracker>(std::move(ns), cursorId, *client)); } @@ -167,8 +168,8 @@ void setHiddenMongo(JSContext* cx, scope->getProto<MongoExternalInfo>().newObject(&newMongo); auto host = resPtr->getServerAddress(); - JS_SetPrivate(newMongo, - scope->trackedNew<std::shared_ptr<DBClientBase>>(std::move(resPtr))); + JS::SetPrivate(newMongo, + scope->trackedNew<std::shared_ptr<DBClientBase>>(std::move(resPtr))); ObjectWrapper from(cx, args.thisv()); ObjectWrapper to(cx, newMongo); @@ -199,8 +200,8 @@ EncryptionCallbacks* getEncryptionCallbacks(DBClientBase* conn) { } // namespace -void MongoBase::finalize(js::FreeOp* fop, JSObject* obj) { - auto conn = static_cast<std::shared_ptr<DBClientBase>*>(JS_GetPrivate(obj)); +void MongoBase::finalize(JSFreeOp* fop, JSObject* obj) { + auto conn = static_cast<std::shared_ptr<DBClientBase>*>(JS::GetPrivate(obj)); if (conn) { getScope(fop)->trackedDelete(conn); @@ -208,7 +209,7 @@ void MongoBase::finalize(js::FreeOp* fop, JSObject* obj) { } void MongoBase::trace(JSTracer* trc, JSObject* obj) { - auto conn = static_cast<std::shared_ptr<DBClientBase>*>(JS_GetPrivate(obj)); + auto conn = static_cast<std::shared_ptr<DBClientBase>*>(JS::GetPrivate(obj)); if (!conn) { return; } @@ -222,7 +223,7 @@ void MongoBase::Functions::close::call(JSContext* cx, JS::CallArgs args) { getConnection(args); auto thisv = args.thisv().toObjectOrNull(); - auto conn = static_cast<std::shared_ptr<DBClientBase>*>(JS_GetPrivate(thisv)); + auto conn = static_cast<std::shared_ptr<DBClientBase>*>(JS::GetPrivate(thisv)); conn->reset(); @@ -562,7 +563,7 @@ void MongoExternalInfo::construct(JSContext* cx, JS::CallArgs args) { conn = runEncryptedDBClientCallback(std::move(conn), args.get(1), thisv, cx); - JS_SetPrivate(thisv, scope->trackedNew<std::shared_ptr<DBClientBase>>(conn.release())); + JS::SetPrivate(thisv, scope->trackedNew<std::shared_ptr<DBClientBase>>(conn.release())); o.setBoolean(InternedString::slaveOk, false); o.setString(InternedString::host, cs.connectionString().toString()); @@ -618,7 +619,7 @@ void MongoBase::Functions::getApiParameters::call(JSContext* cx, JS::CallArgs ar void MongoBase::Functions::_startSession::call(JSContext* cx, JS::CallArgs args) { auto client = - static_cast<std::shared_ptr<DBClientBase>*>(JS_GetPrivate(args.thisv().toObjectOrNull())); + static_cast<std::shared_ptr<DBClientBase>*>(JS::GetPrivate(args.thisv().toObjectOrNull())); LogicalSessionIdToClient id; id.setId(UUID::gen()); diff --git a/src/mongo/scripting/mozjs/mongo.h b/src/mongo/scripting/mozjs/mongo.h index f7d05742568..24dadb9c232 100644 --- a/src/mongo/scripting/mozjs/mongo.h +++ b/src/mongo/scripting/mozjs/mongo.h @@ -49,7 +49,7 @@ void setEncryptedDBClientCallback(EncryptedDBClientCallback* callback); * info type with common code and differentiate with varying constructors. */ struct MongoBase : public BaseInfo { - static void finalize(js::FreeOp* fop, JSObject* obj); + static void finalize(JSFreeOp* fop, JSObject* obj); static void trace(JSTracer* trc, JSObject* obj); struct Functions { @@ -77,7 +77,7 @@ struct MongoBase : public BaseInfo { MONGO_DECLARE_JS_FUNCTION(_startSession); }; - static const JSFunctionSpec methods[27]; + static const JSFunctionSpec methods[20]; static const char* const className; static const unsigned classFlags = JSCLASS_HAS_PRIVATE; diff --git a/src/mongo/scripting/mozjs/mongohelpers.cpp b/src/mongo/scripting/mozjs/mongohelpers.cpp index badf7a0391b..518ebe10f5c 100644 --- a/src/mongo/scripting/mozjs/mongohelpers.cpp +++ b/src/mongo/scripting/mozjs/mongohelpers.cpp @@ -31,6 +31,8 @@ #include "mongo/scripting/mozjs/mongohelpers.h" +#include <js/ValueArray.h> + #include <jsapi.h> #include "mongo/scripting/engine.h" diff --git a/src/mongo/scripting/mozjs/nativefunction.cpp b/src/mongo/scripting/mozjs/nativefunction.cpp index 135d2600e44..ab60a71721a 100644 --- a/src/mongo/scripting/mozjs/nativefunction.cpp +++ b/src/mongo/scripting/mozjs/nativefunction.cpp @@ -32,6 +32,8 @@ #include "mongo/scripting/mozjs/nativefunction.h" #include <cstdio> +#include <js/Array.h> +#include <js/Object.h> #include "mongo/scripting/mozjs/implscope.h" #include "mongo/scripting/mozjs/objectwrapper.h" @@ -65,7 +67,7 @@ public: }; NativeHolder* getHolder(JS::CallArgs args) { - return static_cast<NativeHolder*>(JS_GetPrivate(&args.callee())); + return static_cast<NativeHolder*>(JS::GetPrivate(&args.callee())); } } // namespace @@ -79,9 +81,9 @@ void NativeFunctionInfo::call(JSContext* cx, JS::CallArgs args) { return; } - JS::RootedObject robj(cx, JS_NewArrayObject(cx, args)); + JS::RootedObject robj(cx, JS::NewArrayObject(cx, args)); if (!robj) { - uasserted(ErrorCodes::JSInterpreterFailure, "Failed to JS_NewArrayObject"); + uasserted(ErrorCodes::JSInterpreterFailure, "Failed to JS::NewArrayObject"); } BSONObj out = holder->_func(ObjectWrapper(cx, robj).toBSON(), holder->_ctx); @@ -89,8 +91,8 @@ void NativeFunctionInfo::call(JSContext* cx, JS::CallArgs args) { ValueReader(cx, args.rval()).fromBSONElement(out.firstElement(), out, false); } -void NativeFunctionInfo::finalize(js::FreeOp* fop, JSObject* obj) { - auto holder = static_cast<NativeHolder*>(JS_GetPrivate(obj)); +void NativeFunctionInfo::finalize(JSFreeOp* fop, JSObject* obj) { + auto holder = static_cast<NativeHolder*>(JS::GetPrivate(obj)); if (holder) getScope(fop)->trackedDelete(holder); @@ -114,7 +116,7 @@ void NativeFunctionInfo::make(JSContext* cx, scope->getProto<NativeFunctionInfo>().newObject(obj); - JS_SetPrivate(obj, scope->trackedNew<NativeHolder>(function, data)); + JS::SetPrivate(obj, scope->trackedNew<NativeHolder>(function, data)); } } // namespace mozjs diff --git a/src/mongo/scripting/mozjs/nativefunction.h b/src/mongo/scripting/mozjs/nativefunction.h index f00299bd526..633f48bd4f2 100644 --- a/src/mongo/scripting/mozjs/nativefunction.h +++ b/src/mongo/scripting/mozjs/nativefunction.h @@ -50,7 +50,7 @@ namespace mozjs { */ struct NativeFunctionInfo : public BaseInfo { static void call(JSContext* cx, JS::CallArgs args); - static void finalize(js::FreeOp* fop, JSObject* obj); + static void finalize(JSFreeOp* fop, JSObject* obj); static const char* const inheritFrom; static const char* const className; diff --git a/src/mongo/scripting/mozjs/numberdecimal.cpp b/src/mongo/scripting/mozjs/numberdecimal.cpp index 58f923271f3..531687bbddf 100644 --- a/src/mongo/scripting/mozjs/numberdecimal.cpp +++ b/src/mongo/scripting/mozjs/numberdecimal.cpp @@ -31,6 +31,8 @@ #include "mongo/scripting/mozjs/numberdecimal.h" +#include <js/Object.h> + #include "mongo/platform/decimal128.h" #include "mongo/scripting/mozjs/implscope.h" #include "mongo/scripting/mozjs/objectwrapper.h" @@ -51,21 +53,21 @@ const JSFunctionSpec NumberDecimalInfo::methods[3] = { const char* const NumberDecimalInfo::className = "NumberDecimal"; -void NumberDecimalInfo::finalize(js::FreeOp* fop, JSObject* obj) { - auto x = static_cast<Decimal128*>(JS_GetPrivate(obj)); +void NumberDecimalInfo::finalize(JSFreeOp* fop, JSObject* obj) { + auto x = static_cast<Decimal128*>(JS::GetPrivate(obj)); if (x) getScope(fop)->trackedDelete(x); } Decimal128 NumberDecimalInfo::ToNumberDecimal(JSContext* cx, JS::HandleValue thisv) { - auto x = static_cast<Decimal128*>(JS_GetPrivate(thisv.toObjectOrNull())); + auto x = static_cast<Decimal128*>(JS::GetPrivate(thisv.toObjectOrNull())); return x ? *x : Decimal128(0); } Decimal128 NumberDecimalInfo::ToNumberDecimal(JSContext* cx, JS::HandleObject thisv) { - auto x = static_cast<Decimal128*>(JS_GetPrivate(thisv)); + auto x = static_cast<Decimal128*>(JS::GetPrivate(thisv)); return x ? *x : Decimal128(0); } @@ -102,7 +104,7 @@ void NumberDecimalInfo::construct(JSContext* cx, JS::CallArgs args) { uasserted(ErrorCodes::BadValue, "NumberDecimal takes 0 or 1 arguments"); } - JS_SetPrivate(thisv, scope->trackedNew<Decimal128>(x)); + JS::SetPrivate(thisv, scope->trackedNew<Decimal128>(x)); args.rval().setObjectOrNull(thisv); } @@ -111,7 +113,7 @@ void NumberDecimalInfo::make(JSContext* cx, JS::MutableHandleValue thisv, Decima auto scope = getScope(cx); scope->getProto<NumberDecimalInfo>().newObject(thisv); - JS_SetPrivate(thisv.toObjectOrNull(), scope->trackedNew<Decimal128>(decimal)); + JS::SetPrivate(thisv.toObjectOrNull(), scope->trackedNew<Decimal128>(decimal)); } } // namespace mozjs diff --git a/src/mongo/scripting/mozjs/numberdecimal.h b/src/mongo/scripting/mozjs/numberdecimal.h index ef3807c07c8..c79158c7fa8 100644 --- a/src/mongo/scripting/mozjs/numberdecimal.h +++ b/src/mongo/scripting/mozjs/numberdecimal.h @@ -43,7 +43,7 @@ namespace mozjs { struct NumberDecimalInfo : public BaseInfo { static void construct(JSContext* cx, JS::CallArgs args); - static void finalize(js::FreeOp* fop, JSObject* obj); + static void finalize(JSFreeOp* fop, JSObject* obj); struct Functions { MONGO_DECLARE_JS_FUNCTION(toString); diff --git a/src/mongo/scripting/mozjs/numberint.cpp b/src/mongo/scripting/mozjs/numberint.cpp index 97f11ed66ca..d1a5892430f 100644 --- a/src/mongo/scripting/mozjs/numberint.cpp +++ b/src/mongo/scripting/mozjs/numberint.cpp @@ -31,6 +31,8 @@ #include "mongo/scripting/mozjs/numberint.h" +#include <js/Object.h> + #include "mongo/scripting/mozjs/implscope.h" #include "mongo/scripting/mozjs/objectwrapper.h" #include "mongo/scripting/mozjs/valuereader.h" @@ -51,21 +53,21 @@ const JSFunctionSpec NumberIntInfo::methods[5] = { const char* const NumberIntInfo::className = "NumberInt"; -void NumberIntInfo::finalize(js::FreeOp* fop, JSObject* obj) { - auto x = static_cast<int*>(JS_GetPrivate(obj)); +void NumberIntInfo::finalize(JSFreeOp* fop, JSObject* obj) { + auto x = static_cast<int*>(JS::GetPrivate(obj)); if (x) getScope(fop)->trackedDelete(x); } int NumberIntInfo::ToNumberInt(JSContext* cx, JS::HandleValue thisv) { - auto x = static_cast<int*>(JS_GetPrivate(thisv.toObjectOrNull())); + auto x = static_cast<int*>(JS::GetPrivate(thisv.toObjectOrNull())); return x ? *x : 0; } int NumberIntInfo::ToNumberInt(JSContext* cx, JS::HandleObject thisv) { - auto x = static_cast<int*>(JS_GetPrivate(thisv)); + auto x = static_cast<int*>(JS::GetPrivate(thisv)); return x ? *x : 0; } @@ -112,7 +114,7 @@ void NumberIntInfo::construct(JSContext* cx, JS::CallArgs args) { uasserted(ErrorCodes::BadValue, "NumberInt takes 0 or 1 arguments"); } - JS_SetPrivate(thisv, scope->trackedNew<int>(x)); + JS::SetPrivate(thisv, scope->trackedNew<int>(x)); args.rval().setObjectOrNull(thisv); } diff --git a/src/mongo/scripting/mozjs/numberint.h b/src/mongo/scripting/mozjs/numberint.h index e1b4a61c6a8..005c8c7540a 100644 --- a/src/mongo/scripting/mozjs/numberint.h +++ b/src/mongo/scripting/mozjs/numberint.h @@ -41,7 +41,7 @@ namespace mozjs { */ struct NumberIntInfo : public BaseInfo { static void construct(JSContext* cx, JS::CallArgs args); - static void finalize(js::FreeOp* fop, JSObject* obj); + static void finalize(JSFreeOp* fop, JSObject* obj); struct Functions { MONGO_DECLARE_JS_FUNCTION(toNumber); diff --git a/src/mongo/scripting/mozjs/numberlong.cpp b/src/mongo/scripting/mozjs/numberlong.cpp index 33f8fafe76b..55cf3a88bdb 100644 --- a/src/mongo/scripting/mozjs/numberlong.cpp +++ b/src/mongo/scripting/mozjs/numberlong.cpp @@ -33,6 +33,7 @@ #include <boost/optional.hpp> #include <js/Conversions.h> +#include <js/Object.h> #include "mongo/base/parse_number.h" #include "mongo/scripting/mozjs/implscope.h" @@ -57,20 +58,20 @@ const JSFunctionSpec NumberLongInfo::methods[6] = { const char* const NumberLongInfo::className = "NumberLong"; -void NumberLongInfo::finalize(js::FreeOp* fop, JSObject* obj) { - auto numLong = static_cast<int64_t*>(JS_GetPrivate(obj)); +void NumberLongInfo::finalize(JSFreeOp* fop, JSObject* obj) { + auto numLong = static_cast<int64_t*>(JS::GetPrivate(obj)); if (numLong) getScope(fop)->trackedDelete(numLong); } int64_t NumberLongInfo::ToNumberLong(JSContext* cx, JS::HandleValue thisv) { - auto numLong = static_cast<int64_t*>(JS_GetPrivate(thisv.toObjectOrNull())); + auto numLong = static_cast<int64_t*>(JS::GetPrivate(thisv.toObjectOrNull())); return numLong ? *numLong : 0; } int64_t NumberLongInfo::ToNumberLong(JSContext* cx, JS::HandleObject thisv) { - auto numLong = static_cast<int64_t*>(JS_GetPrivate(thisv)); + auto numLong = static_cast<int64_t*>(JS::GetPrivate(thisv)); return numLong ? *numLong : 0; } @@ -202,7 +203,7 @@ void NumberLongInfo::construct(JSContext* cx, JS::CallArgs args) { numLong = (top << 32) + bot; } - JS_SetPrivate(thisv, scope->trackedNew<int64_t>(numLong)); + JS::SetPrivate(thisv, scope->trackedNew<int64_t>(numLong)); args.rval().setObjectOrNull(thisv); } diff --git a/src/mongo/scripting/mozjs/numberlong.h b/src/mongo/scripting/mozjs/numberlong.h index ec2f18e50cd..9400997b0a3 100644 --- a/src/mongo/scripting/mozjs/numberlong.h +++ b/src/mongo/scripting/mozjs/numberlong.h @@ -52,7 +52,7 @@ namespace mozjs { */ struct NumberLongInfo : public BaseInfo { static void construct(JSContext* cx, JS::CallArgs args); - static void finalize(js::FreeOp* fop, JSObject* obj); + static void finalize(JSFreeOp* fop, JSObject* obj); struct Functions { MONGO_DECLARE_JS_FUNCTION(toNumber); diff --git a/src/mongo/scripting/mozjs/objectwrapper.cpp b/src/mongo/scripting/mozjs/objectwrapper.cpp index d934c28ed37..2a755543b48 100644 --- a/src/mongo/scripting/mozjs/objectwrapper.cpp +++ b/src/mongo/scripting/mozjs/objectwrapper.cpp @@ -31,7 +31,10 @@ #include "mongo/scripting/mozjs/objectwrapper.h" +#include <js/Array.h> #include <js/Conversions.h> +#include <js/ValueArray.h> + #include <jsapi.h> #include "mongo/base/error_codes.h" @@ -58,9 +61,9 @@ void ObjectWrapper::Key::get(JSContext* cx, JS::HandleObject o, JS::MutableHandl return; break; case Type::Id: { - JS::RootedId id(cx, _id); + JS::RootedId rid(cx, _id); - if (JS_GetPropertyById(cx, o, id, value)) + if (JS_GetPropertyById(cx, o, rid, value)) return; break; } @@ -137,6 +140,17 @@ void ObjectWrapper::Key::define(JSContext* cx, throwCurrentJSException(cx, ErrorCodes::InternalError, "Failed to define value on a JSObject"); } +/* + * Wrapper functions to create wrappers with no corresponding JSJitInfo from API + * function arguments. + */ +static JSNativeWrapper NativeOpWrapper(JSNative native) { + JSNativeWrapper ret; + ret.op = native; + ret.info = nullptr; + return ret; +} + void ObjectWrapper::Key::define( JSContext* cx, JS::HandleObject o, unsigned attrs, JSNative getter, JSNative setter) { switch (_type) { @@ -144,14 +158,18 @@ void ObjectWrapper::Key::define( if (JS_DefineProperty(cx, o, _field, getter, setter, attrs)) return; break; - case Type::Index: - if (JS_DefineElement(cx, o, _idx, getter, setter, attrs)) + case Type::Index: { + JS::RootedId rid1(cx); + if (!JS_IndexToId(cx, _idx, &rid1)) { + break; + } + if (JS_DefinePropertyById(cx, o, rid1, getter, setter, attrs)) return; break; + } case Type::Id: { - JS::RootedId id(cx, _id); - - if (JS_DefinePropertyById(cx, o, id, getter, setter, attrs)) + JS::RootedId rid2(cx, _id); + if (JS_DefinePropertyById(cx, o, rid2, getter, setter, attrs)) return; break; } @@ -318,12 +336,12 @@ StringData ObjectWrapper::Key::toStringData(JSContext* cx, JSStringWrapper* jsst rid.set(id); } - if (JSID_IS_INT(rid)) { + if (rid.isInt()) { *jsstr = JSStringWrapper(JSID_TO_INT(rid)); return jsstr->toStringData(); } - if (JSID_IS_STRING(rid)) { + if (rid.isString()) { *jsstr = JSStringWrapper(cx, JSID_TO_STRING(rid)); return jsstr->toStringData(); } @@ -506,7 +524,7 @@ void ObjectWrapper::callMethod(const char* field, } void ObjectWrapper::callMethod(const char* field, JS::MutableHandleValue out) { - JS::AutoValueVector args(_context); + JS::RootedValueVector args(_context); callMethod(field, args, out); } @@ -521,7 +539,7 @@ void ObjectWrapper::callMethod(JS::HandleValue fun, } void ObjectWrapper::callMethod(JS::HandleValue fun, JS::MutableHandleValue out) { - JS::AutoValueVector args(_context); + JS::RootedValueVector args(_context); callMethod(fun, args, out); } @@ -629,7 +647,7 @@ ObjectWrapper::WriteFieldRecursionFrame::WriteFieldRecursionFrame(JSContext* cx, : thisv(cx, obj), ids(cx, JS::IdVector(cx)) { bool isArray = false; if (parent) { - if (!JS_IsArrayObject(cx, thisv, &isArray)) { + if (!JS::IsArrayObject(cx, thisv, &isArray)) { throwCurrentJSException( cx, ErrorCodes::JSInterpreterFailure, "Failure to check object is an array"); } @@ -639,7 +657,7 @@ ObjectWrapper::WriteFieldRecursionFrame::WriteFieldRecursionFrame(JSContext* cx, if (isArray) { uint32_t length; - if (!JS_GetArrayLength(cx, thisv, &length)) { + if (!JS::GetArrayLength(cx, thisv, &length)) { throwCurrentJSException( cx, ErrorCodes::JSInterpreterFailure, "Failure to get array length"); } @@ -683,7 +701,7 @@ void ObjectWrapper::_writeField(BSONObjBuilder* b, } std::string ObjectWrapper::getClassName() { - auto jsclass = JS_GetClass(_object); + auto jsclass = JS::GetClass(_object); if (jsclass) return jsclass->name; diff --git a/src/mongo/scripting/mozjs/objectwrapper.h b/src/mongo/scripting/mozjs/objectwrapper.h index 459f9746fe2..6e98f0a70b6 100644 --- a/src/mongo/scripting/mozjs/objectwrapper.h +++ b/src/mongo/scripting/mozjs/objectwrapper.h @@ -29,6 +29,9 @@ #pragma once +#include <js/Object.h> +#include <js/ValueArray.h> + #include <jsapi.h> #include <string> diff --git a/src/mongo/scripting/mozjs/oid.cpp b/src/mongo/scripting/mozjs/oid.cpp index edbc56990ed..b76766e95b3 100644 --- a/src/mongo/scripting/mozjs/oid.cpp +++ b/src/mongo/scripting/mozjs/oid.cpp @@ -31,6 +31,7 @@ #include "mongo/scripting/mozjs/oid.h" +#include <js/Object.h> #include <memory> #include "mongo/scripting/mozjs/implscope.h" @@ -51,8 +52,8 @@ const JSFunctionSpec OIDInfo::methods[3] = { const char* const OIDInfo::className = "ObjectId"; -void OIDInfo::finalize(js::FreeOp* fop, JSObject* obj) { - auto oid = static_cast<OID*>(JS_GetPrivate(obj)); +void OIDInfo::finalize(JSFreeOp* fop, JSObject* obj) { + auto oid = static_cast<OID*>(JS::GetPrivate(obj)); if (oid) { getScope(fop)->trackedDelete(oid); @@ -60,7 +61,7 @@ void OIDInfo::finalize(js::FreeOp* fop, JSObject* obj) { } void OIDInfo::Functions::toString::call(JSContext* cx, JS::CallArgs args) { - auto oid = static_cast<OID*>(JS_GetPrivate(args.thisv().toObjectOrNull())); + auto oid = static_cast<OID*>(JS::GetPrivate(args.thisv().toObjectOrNull())); std::string str = str::stream() << "ObjectId(\"" << oid->toString() << "\")"; @@ -68,13 +69,13 @@ void OIDInfo::Functions::toString::call(JSContext* cx, JS::CallArgs args) { } void OIDInfo::Functions::toJSON::call(JSContext* cx, JS::CallArgs args) { - auto oid = static_cast<OID*>(JS_GetPrivate(args.thisv().toObjectOrNull())); + auto oid = static_cast<OID*>(JS::GetPrivate(args.thisv().toObjectOrNull())); ValueReader(cx, args.rval()).fromBSON(BSON("$oid" << oid->toString()), nullptr, false); } void OIDInfo::Functions::getter::call(JSContext* cx, JS::CallArgs args) { - auto oid = static_cast<OID*>(JS_GetPrivate(args.thisv().toObjectOrNull())); + auto oid = static_cast<OID*>(JS::GetPrivate(args.thisv().toObjectOrNull())); ValueReader(cx, args.rval()).fromStringData(oid->toString()); } @@ -98,7 +99,7 @@ void OIDInfo::make(JSContext* cx, const OID& oid, JS::MutableHandleValue out) { JS::RootedObject thisv(cx); scope->getProto<OIDInfo>().newObject(&thisv); - JS_SetPrivate(thisv, scope->trackedNew<OID>(oid)); + JS::SetPrivate(thisv, scope->trackedNew<OID>(oid)); out.setObjectOrNull(thisv); } @@ -109,7 +110,7 @@ OID OIDInfo::getOID(JSContext* cx, JS::HandleValue value) { } OID OIDInfo::getOID(JSContext* cx, JS::HandleObject object) { - auto oid = static_cast<OID*>(JS_GetPrivate(object)); + auto oid = static_cast<OID*>(JS::GetPrivate(object)); if (oid) { return *oid; diff --git a/src/mongo/scripting/mozjs/oid.h b/src/mongo/scripting/mozjs/oid.h index 57b1b285cce..9d4803f342f 100644 --- a/src/mongo/scripting/mozjs/oid.h +++ b/src/mongo/scripting/mozjs/oid.h @@ -41,7 +41,7 @@ namespace mozjs { */ struct OIDInfo : public BaseInfo { static void construct(JSContext* cx, JS::CallArgs args); - static void finalize(js::FreeOp* fop, JSObject* obj); + static void finalize(JSFreeOp* fop, JSObject* obj); struct Functions { MONGO_DECLARE_JS_FUNCTION(getter); diff --git a/src/mongo/scripting/mozjs/session.cpp b/src/mongo/scripting/mozjs/session.cpp index a73e267356d..6819c1cbfce 100644 --- a/src/mongo/scripting/mozjs/session.cpp +++ b/src/mongo/scripting/mozjs/session.cpp @@ -33,6 +33,8 @@ #include "mongo/scripting/mozjs/session.h" +#include <js/Object.h> + #include "mongo/logv2/log.h" #include "mongo/scripting/mozjs/bson.h" #include "mongo/scripting/mozjs/implscope.h" @@ -105,7 +107,7 @@ SessionHolder::TransactionState transactionStateEnum(StringData name) { } SessionHolder* getHolder(JSObject* thisv) { - return static_cast<SessionHolder*>(JS_GetPrivate(thisv)); + return static_cast<SessionHolder*>(JS::GetPrivate(thisv)); } SessionHolder* getHolder(JS::CallArgs& args) { @@ -138,7 +140,7 @@ void endSession(SessionHolder* holder) { } // namespace -void SessionInfo::finalize(js::FreeOp* fop, JSObject* obj) { +void SessionInfo::finalize(JSFreeOp* fop, JSObject* obj) { auto holder = getHolder(obj); if (holder) { @@ -231,7 +233,7 @@ void SessionInfo::make(JSContext* cx, auto scope = getScope(cx); scope->getProto<SessionInfo>().newObject(obj); - JS_SetPrivate(obj, scope->trackedNew<SessionHolder>(std::move(client), std::move(lsid))); + JS::SetPrivate(obj, scope->trackedNew<SessionHolder>(std::move(client), std::move(lsid))); } } // namespace mozjs diff --git a/src/mongo/scripting/mozjs/session.h b/src/mongo/scripting/mozjs/session.h index bd12f8480e0..a31ce50eaff 100644 --- a/src/mongo/scripting/mozjs/session.h +++ b/src/mongo/scripting/mozjs/session.h @@ -42,7 +42,7 @@ namespace mozjs { * from C++. Current callers are all via the Mongo object. */ struct SessionInfo : public BaseInfo { - static void finalize(js::FreeOp* fop, JSObject* obj); + static void finalize(JSFreeOp* fop, JSObject* obj); struct Functions { MONGO_DECLARE_JS_FUNCTION(end); diff --git a/src/mongo/scripting/mozjs/status.cpp b/src/mongo/scripting/mozjs/status.cpp index 7bbfa706fbb..e272fbf5b5c 100644 --- a/src/mongo/scripting/mozjs/status.cpp +++ b/src/mongo/scripting/mozjs/status.cpp @@ -31,6 +31,9 @@ #include "mongo/scripting/mozjs/status.h" +#include <js/Object.h> +#include <js/ValueArray.h> + #include "mongo/scripting/jsexception.h" #include "mongo/scripting/mozjs/implscope.h" #include "mongo/scripting/mozjs/internedstring.h" @@ -45,11 +48,11 @@ const char* const MongoStatusInfo::className = "MongoStatus"; const char* const MongoStatusInfo::inheritFrom = "Error"; Status MongoStatusInfo::toStatus(JSContext* cx, JS::HandleObject object) { - return *static_cast<Status*>(JS_GetPrivate(object)); + return *static_cast<Status*>(JS::GetPrivate(object)); } Status MongoStatusInfo::toStatus(JSContext* cx, JS::HandleValue value) { - return *static_cast<Status*>(JS_GetPrivate(value.toObjectOrNull())); + return *static_cast<Status*>(JS::GetPrivate(value.toObjectOrNull())); } void MongoStatusInfo::fromStatus(JSContext* cx, Status status, JS::MutableHandleValue value) { @@ -59,7 +62,7 @@ void MongoStatusInfo::fromStatus(JSContext* cx, Status status, JS::MutableHandle JS::RootedValue undef(cx); undef.setUndefined(); - JS::AutoValueArray<1> args(cx); + JS::RootedValueArray<1> args(cx); ValueReader(cx, args[0]).fromStringData(status.reason()); JS::RootedObject error(cx); scope->getProto<ErrorInfo>().newInstance(args, &error); @@ -86,13 +89,13 @@ void MongoStatusInfo::fromStatus(JSContext* cx, Status status, JS::MutableHandle smUtils::wrapConstrainedMethod<Functions::stack, false, MongoStatusInfo>, nullptr); - JS_SetPrivate(thisv, scope->trackedNew<Status>(std::move(status))); + JS::SetPrivate(thisv, scope->trackedNew<Status>(std::move(status))); value.setObjectOrNull(thisv); } -void MongoStatusInfo::finalize(js::FreeOp* fop, JSObject* obj) { - auto status = static_cast<Status*>(JS_GetPrivate(obj)); +void MongoStatusInfo::finalize(JSFreeOp* fop, JSObject* obj) { + auto status = static_cast<Status*>(JS::GetPrivate(obj)); if (status) getScope(fop)->trackedDelete(status); @@ -145,7 +148,7 @@ void MongoStatusInfo::Functions::stack::call(JSContext* cx, JS::CallArgs args) { void MongoStatusInfo::postInstall(JSContext* cx, JS::HandleObject global, JS::HandleObject proto) { auto scope = getScope(cx); - JS_SetPrivate( + JS::SetPrivate( proto, scope->trackedNew<Status>(Status(ErrorCodes::UnknownError, "Mongo Status Prototype"))); } diff --git a/src/mongo/scripting/mozjs/status.h b/src/mongo/scripting/mozjs/status.h index 8d9b04f56df..87881631763 100644 --- a/src/mongo/scripting/mozjs/status.h +++ b/src/mongo/scripting/mozjs/status.h @@ -46,7 +46,7 @@ namespace mozjs { * traces, and instanceOf Error. */ struct MongoStatusInfo : public BaseInfo { - static void finalize(js::FreeOp* fop, JSObject* obj); + static void finalize(JSFreeOp* fop, JSObject* obj); struct Functions { MONGO_DECLARE_JS_FUNCTION(code); diff --git a/src/mongo/scripting/mozjs/valuereader.cpp b/src/mongo/scripting/mozjs/valuereader.cpp index bccc252b800..f2458fafe48 100644 --- a/src/mongo/scripting/mozjs/valuereader.cpp +++ b/src/mongo/scripting/mozjs/valuereader.cpp @@ -35,8 +35,11 @@ #include <cmath> #include <cstdio> +#include <js/Array.h> #include <js/CharacterEncoding.h> #include <js/Date.h> +#include <js/Object.h> +#include <js/ValueArray.h> #include "mongo/base/error_codes.h" #include "mongo/logv2/log.h" @@ -59,7 +62,7 @@ void ValueReader::fromBSONElement(const BSONElement& elem, const BSONObj& parent // javascriptProtection prevents Code and CodeWScope BSON types from // being automatically marshalled into executable functions. if (scope->isJavaScriptProtectionEnabled()) { - JS::AutoValueArray<1> args(_context); + JS::RootedValueArray<1> args(_context); ValueReader(_context, args[0]).fromStringData(elem.valueStringData()); JS::RootedObject obj(_context); @@ -70,7 +73,7 @@ void ValueReader::fromBSONElement(const BSONElement& elem, const BSONObj& parent return; case mongo::CodeWScope: if (scope->isJavaScriptProtectionEnabled()) { - JS::AutoValueArray<2> args(_context); + JS::RootedValueArray<2> args(_context); ValueReader(_context, args[0]).fromStringData(elem.codeWScopeCode()); ValueReader(_context, args[1]) @@ -120,7 +123,7 @@ void ValueReader::fromBSONElement(const BSONElement& elem, const BSONObj& parent _value.setUndefined(); return; case mongo::RegEx: { - JS::AutoValueArray<2> args(_context); + JS::RootedValueArray<2> args(_context); ValueReader(_context, args[0]).fromStringData(elem.regex()); ValueReader(_context, args[1]).fromStringData(elem.regexFlags()); @@ -138,7 +141,7 @@ void ValueReader::fromBSONElement(const BSONElement& elem, const BSONObj& parent std::stringstream ss; base64::encode(ss, StringData(data, len)); - JS::AutoValueArray<2> args(_context); + JS::RootedValueArray<2> args(_context); args[0].setInt32(elem.binDataType()); @@ -148,7 +151,7 @@ void ValueReader::fromBSONElement(const BSONElement& elem, const BSONObj& parent return; } case mongo::bsonTimestamp: { - JS::AutoValueArray<2> args(_context); + JS::RootedValueArray<2> args(_context); ValueReader(_context, args[0]) .fromDouble(elem.timestampTime().toMillisSinceEpoch() / 1000); @@ -161,13 +164,13 @@ void ValueReader::fromBSONElement(const BSONElement& elem, const BSONObj& parent case mongo::NumberLong: { JS::RootedObject thisv(_context); scope->getProto<NumberLongInfo>().newObject(&thisv); - JS_SetPrivate(thisv, scope->trackedNew<int64_t>(elem.numberLong())); + JS::SetPrivate(thisv, scope->trackedNew<int64_t>(elem.numberLong())); _value.setObjectOrNull(thisv); return; } case mongo::NumberDecimal: { Decimal128 decimal = elem.numberDecimal(); - JS::AutoValueArray<1> args(_context); + JS::RootedValueArray<1> args(_context); ValueReader(_context, args[0]).fromDecimal128(decimal); JS::RootedObject obj(_context); @@ -183,10 +186,10 @@ void ValueReader::fromBSONElement(const BSONElement& elem, const BSONObj& parent scope->getProto<MaxKeyInfo>().newInstance(_value); return; case mongo::DBRef: { - JS::AutoValueArray<1> oidArgs(_context); + JS::RootedValueArray<1> oidArgs(_context); ValueReader(_context, oidArgs[0]).fromStringData(elem.dbrefOID().toString()); - JS::AutoValueArray<2> dbPointerArgs(_context); + JS::RootedValueArray<2> dbPointerArgs(_context); ValueReader(_context, dbPointerArgs[0]).fromStringData(elem.dbrefNS()); scope->getProto<OIDInfo>().newInstance(oidArgs, dbPointerArgs[1]); @@ -226,7 +229,7 @@ void ValueReader::fromBSON(const BSONObj& obj, const BSONObj* parent, bool readO } void ValueReader::fromBSONArray(const BSONObj& obj, const BSONObj* parent, bool readOnly) { - JS::AutoValueVector avv(_context); + JS::RootedValueVector avv(_context); BSONForEach(elem, obj) { JS::RootedValue member(_context); @@ -236,9 +239,9 @@ void ValueReader::fromBSONArray(const BSONObj& obj, const BSONObj* parent, bool uasserted(ErrorCodes::JSInterpreterFailure, "Failed to append to JS array"); } } - JS::RootedObject array(_context, JS_NewArrayObject(_context, avv)); + JS::RootedObject array(_context, JS::NewArrayObject(_context, avv)); if (!array) { - uasserted(ErrorCodes::JSInterpreterFailure, "Failed to JS_NewArrayObject"); + uasserted(ErrorCodes::JSInterpreterFailure, "Failed to JS::NewArrayObject"); } _value.setObjectOrNull(array); } @@ -256,7 +259,7 @@ void ValueReader::fromStringData(StringData sd) { // TODO: we have tests that involve dropping garbage in. Do we want to // throw, or to take the lossy conversion? auto utf16 = JS::LossyUTF8CharsToNewTwoByteCharsZ( - _context, JS::UTF8Chars(sd.rawData(), sd.size()), &utf16Len); + _context, JS::UTF8Chars(sd.rawData(), sd.size()), &utf16Len, js::StringBufferArena); mozilla::UniquePtr<char16_t, JS::FreePolicy> utf16Deleter(utf16.get()); @@ -296,7 +299,7 @@ void ValueReader::fromDecimal128(Decimal128 decimal) { */ void ValueReader::fromDouble(double d) { if (std::isnan(d)) { - _value.set(JS_GetNaNValue(_context)); + _value.set(JS::NaNValue()); } else { _value.setDouble(d); } @@ -306,7 +309,7 @@ void ValueReader::fromInt64(int64_t i) { auto scope = getScope(_context); JS::RootedObject num(_context); scope->getProto<NumberLongInfo>().newObject(&num); - JS_SetPrivate(num, scope->trackedNew<int64_t>(i)); + JS::SetPrivate(num, scope->trackedNew<int64_t>(i)); _value.setObjectOrNull(num); } diff --git a/src/mongo/scripting/mozjs/valuewriter.cpp b/src/mongo/scripting/mozjs/valuewriter.cpp index 7af1d5325a6..b3f2fa107bd 100644 --- a/src/mongo/scripting/mozjs/valuewriter.cpp +++ b/src/mongo/scripting/mozjs/valuewriter.cpp @@ -31,7 +31,11 @@ #include "mongo/scripting/mozjs/valuewriter.h" +#include <js/Array.h> #include <js/Conversions.h> +#include <js/Date.h> +#include <js/Object.h> +#include <jsfriendapi.h> #include "mongo/base/error_codes.h" #include "mongo/platform/decimal128.h" @@ -63,7 +67,7 @@ int ValueWriter::type() { bool isArray; - if (!JS_IsArrayObject(_context, _value, &isArray)) { + if (!JS::IsArrayObject(_context, _value, &isArray)) { uasserted(ErrorCodes::BadValue, "unable to check if type is an array"); } if (isArray) @@ -83,13 +87,13 @@ int ValueWriter::type() { JS::RootedObject obj(_context, _value.toObjectOrNull()); bool isDate; - if (!JS_ObjectIsDate(_context, obj, &isDate)) { + if (!JS::ObjectIsDate(_context, obj, &isDate)) { uasserted(ErrorCodes::BadValue, "unable to check if type is a date"); } if (isDate) return Date; - if (JS_ObjectIsFunction(_context, obj)) + if (js::IsFunctionObject(obj)) return Code; return Object; @@ -108,7 +112,7 @@ std::string ValueWriter::typeAsString() { bool isArray; - if (!JS_IsArrayObject(_context, _value, &isArray)) { + if (!JS::IsArrayObject(_context, _value, &isArray)) { uasserted(ErrorCodes::BadValue, "unable to check if type is an array"); } @@ -122,7 +126,7 @@ std::string ValueWriter::typeAsString() { if (_value.isObject()) { JS::RootedObject obj(_context, _value.toObjectOrNull()); - if (!JS_IsArrayObject(_context, obj, &isArray)) { + if (!JS::IsArrayObject(_context, obj, &isArray)) { uasserted(ErrorCodes::BadValue, "unable to check if type is an array"); } if (isArray) @@ -130,13 +134,13 @@ std::string ValueWriter::typeAsString() { bool isDate; - if (!JS_ObjectIsDate(_context, obj, &isDate)) { + if (!JS::ObjectIsDate(_context, obj, &isDate)) { uasserted(ErrorCodes::BadValue, "unable to check if type is a date"); } if (isDate) return "date"; - if (JS_ObjectIsFunction(_context, obj)) + if (js::IsFunctionObject(obj)) return "function"; return ObjectWrapper(_context, _value).getClassName(); @@ -292,7 +296,7 @@ void ValueWriter::_writeObject(BSONObjBuilder* b, JS::RootedObject obj(_context, _value.toObjectOrNull()); ObjectWrapper o(_context, obj); - auto jsclass = JS_GetClass(obj); + auto jsclass = JS::GetClass(obj); if (jsclass) { if (scope->getProto<OIDInfo>().getJSClass() == jsclass) { @@ -353,7 +357,7 @@ void ValueWriter::_writeObject(BSONObjBuilder* b, } if (scope->getProto<BinDataInfo>().getJSClass() == jsclass) { - auto str = static_cast<std::string*>(JS_GetPrivate(obj)); + auto str = static_cast<std::string*>(JS::GetPrivate(obj)); uassert(ErrorCodes::BadValue, "Cannot call getter on BinData prototype", str); diff --git a/src/mongo/scripting/mozjs/wraptype.h b/src/mongo/scripting/mozjs/wraptype.h index e3e4acde7bd..c1da664aec7 100644 --- a/src/mongo/scripting/mozjs/wraptype.h +++ b/src/mongo/scripting/mozjs/wraptype.h @@ -30,6 +30,8 @@ #pragma once #include <cstddef> +#include <js/ValueArray.h> + #include <jsapi.h> #include <type_traits> @@ -67,22 +69,20 @@ #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(name, ...) \ + { \ + JSFunctionSpec::Name(#name), \ + JSNativeWrapper(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 \ +#define MONGO_ATTACH_JS_CONSTRAINED_METHOD_NO_PROTO(name, ...) \ + { \ + JSFunctionSpec::Name(#name), \ + JSNativeWrapper(smUtils::wrapConstrainedMethod<Functions::name, true, __VA_ARGS__>, \ + nullptr), \ + 0, 0, nullptr \ } namespace mongo { @@ -150,7 +150,7 @@ bool delProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::Objec template <typename T> bool enumerate(JSContext* cx, JS::HandleObject obj, - JS::AutoIdVector& properties, + JS::MutableHandleIdVector properties, bool enumerableOnly) { try { T::enumerate(cx, obj, properties, enumerableOnly); @@ -167,7 +167,7 @@ bool getProperty(JSContext* cx, JS::HandleValue receiver, JS::HandleId id, JS::MutableHandleValue vp) { - if (JSID_IS_SYMBOL(id)) { + if (id.isSymbol()) { // Just default to the SpiderMonkey's standard implementations for Symbol methods vp.setUndefined(); return true; @@ -211,7 +211,7 @@ bool setProperty(JSContext* cx, template <typename T> bool resolve(JSContext* cx, JS::HandleObject obj, JS::HandleId id, bool* resolvedp) { - if (JSID_IS_SYMBOL(id)) { + if (id.isSymbol()) { // Just default to the SpiderMonkey's standard implementations for Symbol methods *resolvedp = false; return true; @@ -284,17 +284,12 @@ public: JS::RootedObject proto(_context); - JSAutoRequest ar(_context); - - JS::CompartmentOptions options; + JS::RealmOptions options; _proto.init(_context, - _assertPtr(JS_NewGlobalObject(_context, - js::Jsvalify(&_jsclass), - nullptr, - JS::DontFireOnNewGlobalHook, - options))); + _assertPtr(JS_NewGlobalObject( + _context, &_jsclass, nullptr, JS::DontFireOnNewGlobalHook, options))); - JSAutoCompartment ac(_context, _proto); + JSAutoRealm ac(_context, _proto); _installFunctions(_proto, T::freeFunctions); } } @@ -324,7 +319,7 @@ public: * types without a constructor or inside the constructor */ void newObject(JS::MutableHandleObject out) { - out.set(_assertPtr(JS_NewObjectWithGivenProto(_context, js::Jsvalify(&_jsclass), _proto))); + out.set(_assertPtr(JS_NewObjectWithGivenProto(_context, &_jsclass, _proto))); } void newObject(JS::MutableHandleValue out) { @@ -335,7 +330,7 @@ public: } void newObjectWithProto(JS::MutableHandleObject out, JS::HandleObject proto) { - out.set(_assertPtr(JS_NewObjectWithGivenProto(_context, js::Jsvalify(&_jsclass), proto))); + out.set(_assertPtr(JS_NewObjectWithGivenProto(_context, &_jsclass, proto))); } void newObjectWithProto(JS::MutableHandleValue out, JS::HandleObject proto) { @@ -349,38 +344,51 @@ public: * newInstance calls the constructor, a la new Type() in js */ void newInstance(JS::MutableHandleObject out) { - dassert(T::installType == InstallType::OverNative || T::construct != BaseInfo::construct); + invariant(T::installType == InstallType::OverNative || T::construct != BaseInfo::construct); - JS::AutoValueVector args(_context); + JS::RootedValueVector args(_context); newInstance(args, out); } void newInstance(const JS::HandleValueArray& args, JS::MutableHandleObject out) { - dassert(T::installType == InstallType::OverNative || T::construct != BaseInfo::construct); + invariant(T::installType == InstallType::OverNative || T::construct != BaseInfo::construct); + + JS::RootedValue fVal( + _context, + JS::ObjectValue(T::installType == InstallType::OverNative ? *_constructor : *_proto)); + JS::RootedObject result(_context); + + // TODO SERVER-61008 JS::Construct returns a boolean. What does it mean if it's 'false'? + JS::Construct(_context, fVal, args, &result); - out.set(_assertPtr(JS_New( - _context, T::installType == InstallType::OverNative ? _constructor : _proto, args))); + out.set(_assertPtr(result.get())); } void newInstance(JS::MutableHandleValue out) { - dassert(T::installType == InstallType::OverNative || T::construct != BaseInfo::construct); + invariant(T::installType == InstallType::OverNative || T::construct != BaseInfo::construct); - JS::AutoValueVector args(_context); + JS::RootedValueVector args(_context); newInstance(args, out); } void newInstance(const JS::HandleValueArray& args, JS::MutableHandleValue out) { - dassert(T::installType == InstallType::OverNative || T::construct != BaseInfo::construct); + invariant(T::installType == InstallType::OverNative || T::construct != BaseInfo::construct); + JS::RootedValue fVal( + _context, + JS::ObjectValue(T::installType == InstallType::OverNative ? *_constructor : *_proto)); + JS::RootedObject result(_context); - out.setObjectOrNull(_assertPtr(JS_New( - _context, T::installType == InstallType::OverNative ? _constructor : _proto, args))); + // TODO SERVER-61008 JS::Construct returns a boolean. What does it mean if it's 'false'? + JS::Construct(_context, fVal, args, &result); + + out.setObjectOrNull(_assertPtr(result.get())); } // instanceOf doesn't go up the prototype tree. It's a lower level more specific match bool instanceOf(JS::HandleObject obj) { - return JS_InstanceOf(_context, obj, js::Jsvalify(&_jsclass), nullptr); + return JS_InstanceOf(_context, obj, &_jsclass, nullptr); } bool instanceOf(JS::HandleValue value) { @@ -393,7 +401,7 @@ public: } const JSClass* getJSClass() const { - return js::Jsvalify(&_jsclass); + return &_jsclass; } JS::HandleObject getProto() const { @@ -417,7 +425,7 @@ private: _context, global, parent, - js::Jsvalify(&_jsclass), + &_jsclass, T::construct != BaseInfo::construct ? smUtils::construct<T> : nullptr, 0, nullptr, @@ -427,25 +435,27 @@ private: _installFunctions(global, T::freeFunctions); _postInstall(global, T::postInstall); + _installToStringTag(); } // Use this if you want your types installed, but not visible in the // global scope void _installPrivate(JS::HandleObject global) { - dassert(T::construct == BaseInfo::construct); + invariant(T::construct == BaseInfo::construct); JS::RootedObject parent(_context); _inheritFrom(T::inheritFrom, global, &parent); // See newObject() for why we have to do this dance with the explicit // SetPrototype - _proto.init(_context, _assertPtr(JS_NewObject(_context, js::Jsvalify(&_jsclass)))); + _proto.init(_context, _assertPtr(JS_NewObject(_context, &_jsclass))); if (parent.get() && !JS_SetPrototype(_context, _proto, parent)) throwCurrentJSException( _context, ErrorCodes::JSInterpreterFailure, "Failed to set prototype"); _installFunctions(_proto, T::methods); _installFunctions(global, T::freeFunctions); + _installToStringTag(); _installConstructor(T::construct != BaseInfo::construct ? smUtils::construct<T> : nullptr); @@ -455,16 +465,16 @@ private: // Use this to attach things to types that we don't provide like // Object, or Array void _installOverNative(JS::HandleObject global) { - dassert(T::addProperty == BaseInfo::addProperty); - dassert(T::call == BaseInfo::call); - dassert(T::construct == BaseInfo::construct); - dassert(T::delProperty == BaseInfo::delProperty); - dassert(T::enumerate == BaseInfo::enumerate); - dassert(T::finalize == BaseInfo::finalize); - dassert(T::getProperty == BaseInfo::getProperty); - dassert(T::hasInstance == BaseInfo::hasInstance); - dassert(T::resolve == BaseInfo::resolve); - dassert(T::setProperty == BaseInfo::setProperty); + invariant(T::addProperty == BaseInfo::addProperty); + invariant(T::call == BaseInfo::call); + invariant(T::construct == BaseInfo::construct); + invariant(T::delProperty == BaseInfo::delProperty); + invariant(T::enumerate == BaseInfo::enumerate); + invariant(T::finalize == BaseInfo::finalize); + invariant(T::getProperty == BaseInfo::getProperty); + invariant(T::hasInstance == BaseInfo::hasInstance); + invariant(T::resolve == BaseInfo::resolve); + invariant(T::setProperty == BaseInfo::setProperty); JS::RootedValue value(_context); if (!JS_GetProperty(_context, global, T::className, &value)) @@ -509,6 +519,13 @@ private: _context, ErrorCodes::JSInterpreterFailure, "Failed to define functions"); } + void _installToStringTag() { + static const JSPropertySpec properties[2] = { + JS_STRING_SYM_PS(toStringTag, T::className, JSPROP_READONLY), JS_PS_END}; + + JS_DefineProperties(_context, _proto, properties); + } + // This is for inheriting from something other than Object void _inheritFrom(const char* name, JS::HandleObject global, JS::MutableHandleObject out) { if (!name) @@ -565,8 +582,8 @@ private: JSContext* _context; JS::PersistentRootedObject _proto; JS::PersistentRootedObject _constructor; - js::Class _jsclass; - js::ClassOps _jsclassOps; + JSClass _jsclass; + JSClassOps _jsclassOps; js::ObjectOps _jsoOps; }; |