diff options
Diffstat (limited to 'src/mongo/scripting/mozjs')
38 files changed, 245 insertions, 246 deletions
diff --git a/src/mongo/scripting/mozjs/PosixNSPR.cpp b/src/mongo/scripting/mozjs/PosixNSPR.cpp index 55a821450e6..63177fa9735 100644 --- a/src/mongo/scripting/mozjs/PosixNSPR.cpp +++ b/src/mongo/scripting/mozjs/PosixNSPR.cpp @@ -289,31 +289,3 @@ PRStatus PR_WaitCondVar(PRCondVar* cvar, uint32_t timeout) { } } } - -int32_t PR_FileDesc2NativeHandle(PRFileDesc* fd) { - MOZ_CRASH("PR_FileDesc2NativeHandle"); -} - -PRStatus PR_GetOpenFileInfo(PRFileDesc* fd, PRFileInfo* info) { - MOZ_CRASH("PR_GetOpenFileInfo"); -} - -int32_t PR_Seek(PRFileDesc* fd, int32_t offset, PRSeekWhence whence) { - MOZ_CRASH("PR_Seek"); -} - -PRFileMap* PR_CreateFileMap(PRFileDesc* fd, int64_t size, PRFileMapProtect prot) { - MOZ_CRASH("PR_CreateFileMap"); -} - -void* PR_MemMap(PRFileMap* fmap, int64_t offset, uint32_t len) { - MOZ_CRASH("PR_MemMap"); -} - -PRStatus PR_MemUnmap(void* addr, uint32_t len) { - MOZ_CRASH("PR_MemUnmap"); -} - -PRStatus PR_CloseFileMap(PRFileMap* fmap) { - MOZ_CRASH("PR_CloseFileMap"); -} diff --git a/src/mongo/scripting/mozjs/base.cpp b/src/mongo/scripting/mozjs/base.cpp index b36edd7375f..c7496dc073e 100644 --- a/src/mongo/scripting/mozjs/base.cpp +++ b/src/mongo/scripting/mozjs/base.cpp @@ -54,11 +54,10 @@ void BaseInfo::enumerate(JSContext* cx, JS::HandleObject obj, JS::AutoIdVector& 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, - JS::HandleValue receiver, JS::MutableHandleValue vp) {} void BaseInfo::hasInstance(JSContext* cx, JS::HandleObject obj, @@ -72,8 +71,7 @@ void BaseInfo::resolve(JSContext* cx, JS::HandleObject obj, JS::HandleId id, boo void BaseInfo::setProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, - JS::HandleValue v, - JS::HandleValue receiver, + JS::MutableHandleValue vp, JS::ObjectOpResult& result) {} } // namespace mozjs diff --git a/src/mongo/scripting/mozjs/base.h b/src/mongo/scripting/mozjs/base.h index ee60999b1c3..8ed28449f01 100644 --- a/src/mongo/scripting/mozjs/base.h +++ b/src/mongo/scripting/mozjs/base.h @@ -74,11 +74,10 @@ struct BaseInfo { JS::HandleObject obj, JS::AutoIdVector& 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, - JS::HandleValue receiver, JS::MutableHandleValue vp); static void hasInstance(JSContext* cx, JS::HandleObject obj, @@ -90,8 +89,7 @@ struct BaseInfo { static void setProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, - JS::HandleValue v, - JS::HandleValue receiver, + JS::MutableHandleValue vp, JS::ObjectOpResult& result); }; diff --git a/src/mongo/scripting/mozjs/bindata.cpp b/src/mongo/scripting/mozjs/bindata.cpp index 91d81182204..ddf5df2ba1d 100644 --- a/src/mongo/scripting/mozjs/bindata.cpp +++ b/src/mongo/scripting/mozjs/bindata.cpp @@ -109,7 +109,7 @@ std::string* getEncoded(JSObject* thisv) { } // namespace -void BinDataInfo::finalize(js::FreeOp* fop, JSObject* obj) { +void BinDataInfo::finalize(JSFreeOp* fop, JSObject* obj) { auto str = getEncoded(obj); if (str) { diff --git a/src/mongo/scripting/mozjs/bindata.h b/src/mongo/scripting/mozjs/bindata.h index 446c81f8107..58ec68d4ad5 100644 --- a/src/mongo/scripting/mozjs/bindata.h +++ b/src/mongo/scripting/mozjs/bindata.h @@ -42,7 +42,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 e3a24a94e23..7ce68bf1a77 100644 --- a/src/mongo/scripting/mozjs/bson.cpp +++ b/src/mongo/scripting/mozjs/bson.cpp @@ -126,7 +126,7 @@ void BSONInfo::make( JS_SetPrivate(obj, scope->trackedNew<BSONHolder>(bson, parent, scope, ro)); } -void BSONInfo::finalize(js::FreeOp* fop, JSObject* obj) { +void BSONInfo::finalize(JSFreeOp* fop, JSObject* obj) { auto holder = static_cast<BSONHolder*>(JS_GetPrivate(obj)); if (!holder) @@ -163,24 +163,21 @@ void BSONInfo::enumerate(JSContext* cx, if (!JS_ValueToId(cx, val, &id)) uasserted(ErrorCodes::JSInterpreterFailure, "Failed to invoke JS_ValueToId"); - if (!properties.append(id)) - uasserted(ErrorCodes::JSInterpreterFailure, "Failed to append property"); + properties.append(id); } } void BSONInfo::setProperty(JSContext* cx, - JS::HandleObject obj, JS::HandleId id, - JS::HandleValue vp, - JS::HandleValue receiver, + JS::MutableHandleValue vp, JS::ObjectOpResult& result) { - auto holder = getValidHolder(cx, obj); if (holder) { if (holder->_readOnly) { uasserted(ErrorCodes::BadValue, "Read only object"); + return; } auto iter = holder->_removed.find(IdWrapper(cx, id).toString()); diff --git a/src/mongo/scripting/mozjs/bson.h b/src/mongo/scripting/mozjs/bson.h index 565f5b0d7a8..a6c55408790 100644 --- a/src/mongo/scripting/mozjs/bson.h +++ b/src/mongo/scripting/mozjs/bson.h @@ -57,13 +57,12 @@ struct BSONInfo : public BaseInfo { JS::HandleObject obj, JS::AutoIdVector& 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, JS::HandleId id, - JS::HandleValue v, - JS::HandleValue receiver, + JS::MutableHandleValue vp, JS::ObjectOpResult& result); static const char* const className; diff --git a/src/mongo/scripting/mozjs/cursor.cpp b/src/mongo/scripting/mozjs/cursor.cpp index 2b9b7da0549..11cc9912f7c 100644 --- a/src/mongo/scripting/mozjs/cursor.cpp +++ b/src/mongo/scripting/mozjs/cursor.cpp @@ -66,7 +66,7 @@ DBClientCursor* getCursor(JS::CallArgs& args) { } // namespace -void CursorInfo::finalize(js::FreeOp* fop, JSObject* obj) { +void CursorInfo::finalize(JSFreeOp* fop, JSObject* obj) { auto cursor = static_cast<CursorInfo::CursorHolder*>(JS_GetPrivate(obj)); if (cursor) { diff --git a/src/mongo/scripting/mozjs/cursor.h b/src/mongo/scripting/mozjs/cursor.h index 5a16563ff15..db56bd9d184 100644 --- a/src/mongo/scripting/mozjs/cursor.h +++ b/src/mongo/scripting/mozjs/cursor.h @@ -43,7 +43,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 fc2eda5d4e5..4ce16e32c67 100644 --- a/src/mongo/scripting/mozjs/cursor_handle.cpp +++ b/src/mongo/scripting/mozjs/cursor_handle.cpp @@ -65,7 +65,7 @@ long long* getCursorId(JS::CallArgs& args) { } // namespace -void CursorHandleInfo::finalize(js::FreeOp* fop, JSObject* 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; diff --git a/src/mongo/scripting/mozjs/cursor_handle.h b/src/mongo/scripting/mozjs/cursor_handle.h index 1f0f27fb299..8d3641c061a 100644 --- a/src/mongo/scripting/mozjs/cursor_handle.h +++ b/src/mongo/scripting/mozjs/cursor_handle.h @@ -43,7 +43,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/dbref.cpp b/src/mongo/scripting/mozjs/dbref.cpp index 5340b69b097..77cf56aed23 100644 --- a/src/mongo/scripting/mozjs/dbref.cpp +++ b/src/mongo/scripting/mozjs/dbref.cpp @@ -69,7 +69,7 @@ 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); } @@ -83,10 +83,9 @@ void DBRefInfo::enumerate(JSContext* cx, void DBRefInfo::setProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, - JS::HandleValue vp, - JS::HandleValue receiver, + JS::MutableHandleValue vp, JS::ObjectOpResult& result) { - BSONInfo::setProperty(cx, obj, id, vp, receiver, result); + BSONInfo::setProperty(cx, obj, id, vp, result); } void DBRefInfo::delProperty(JSContext* cx, diff --git a/src/mongo/scripting/mozjs/dbref.h b/src/mongo/scripting/mozjs/dbref.h index cab66b18d4c..0e847dd3296 100644 --- a/src/mongo/scripting/mozjs/dbref.h +++ b/src/mongo/scripting/mozjs/dbref.h @@ -59,13 +59,12 @@ struct DBRefInfo : public BaseInfo { JS::HandleObject obj, JS::AutoIdVector& 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, JS::HandleId id, - JS::HandleValue vp, - JS::HandleValue receiver, + JS::MutableHandleValue vp, JS::ObjectOpResult& result); static void make( diff --git a/src/mongo/scripting/mozjs/exception.cpp b/src/mongo/scripting/mozjs/exception.cpp index 56e5544d58e..35e4155e257 100644 --- a/src/mongo/scripting/mozjs/exception.cpp +++ b/src/mongo/scripting/mozjs/exception.cpp @@ -35,11 +35,9 @@ #include <jsfriendapi.h> #include <limits> - #include "mongo/base/static_assert.h" #include "mongo/scripting/mozjs/implscope.h" #include "mongo/scripting/mozjs/jsstringwrapper.h" -#include "mongo/scripting/mozjs/mongoErrorReportToString.h" #include "mongo/scripting/mozjs/objectwrapper.h" #include "mongo/scripting/mozjs/valuewriter.h" #include "mongo/util/assert_util.h" @@ -84,7 +82,7 @@ Status JSErrorReportToStatus(JSContext* cx, JSErrorReport* report, ErrorCodes::Error altCode, StringData altReason) { - JSStringWrapper jsstr(cx, mongoErrorReportToString(cx, report)); + JSStringWrapper jsstr(cx, js::ErrorReportToString(cx, report)); if (!jsstr) return Status(altCode, altReason.rawData()); diff --git a/src/mongo/scripting/mozjs/implscope.cpp b/src/mongo/scripting/mozjs/implscope.cpp index 9f201cc3dc7..830d2df320a 100644 --- a/src/mongo/scripting/mozjs/implscope.cpp +++ b/src/mongo/scripting/mozjs/implscope.cpp @@ -121,6 +121,63 @@ struct MozJSImplScope::MozJSEntry { MozJSImplScope* _scope; }; +void MozJSImplScope::_reportError(JSContext* cx, const char* message, JSErrorReport* report) { + auto scope = getScope(cx); + + // If we are recursively calling _reportError because of ReportOverRecursed, lets just quit now + if (scope->_inReportError) { + return; + } + + scope->_inReportError = true; + const auto guard = makeGuard([&] { scope->_inReportError = false; }); + + if (!JSREPORT_IS_WARNING(report->flags)) { + + std::string exceptionMsg; + + try { + // TODO: something far more elaborate that mimics the stack printing from v8 + JS::RootedValue excn(cx); + if (JS_GetPendingException(cx, &excn) && excn.isObject()) { + JS::RootedValue stack(cx); + + JS::RootedObject obj(cx, excn.toObjectOrNull()); + ObjectWrapper o(cx, obj); + o.getValue("stack", &stack); + + auto stackStr = ValueWriter(cx, stack).toString(); + + if (stackStr.empty()) { + // The JavaScript Error objects resulting from C++ exceptions may not always + // have a non-empty "stack" property. We instead use the line and column + // numbers of where in the JavaScript code the C++ function was called from. + str::stream ss; + ss << "@" << report->filename << ":" << report->lineno << ":" << report->column + << "\n"; + stackStr = ss; + } + + auto status = + jsExceptionToStatus(cx, excn, ErrorCodes::JSInterpreterFailure, message) + .withReason(message); + scope->_status = {JSExceptionInfo(std::move(stackStr), std::move(status)), message}; + + return; + } + + exceptionMsg = message; + } catch (const DBException& dbe) { + exceptionMsg = "Unknown error occured while processing exception"; + log() << exceptionMsg << ":" << dbe.toString() << ":" << message; + } + + scope->_status = + JSErrorReportToStatus(cx, report, ErrorCodes::JSInterpreterFailure, message) + .withReason(exceptionMsg); + } +} + std::string MozJSImplScope::getError() { return ""; } @@ -162,11 +219,11 @@ void MozJSImplScope::kill() { } } _sleepCondition.notify_all(); - JS_RequestInterruptCallback(_context); + JS_RequestInterruptCallback(_runtime); } void MozJSImplScope::interrupt() { - JS_RequestInterruptCallback(_context); + JS_RequestInterruptCallback(_runtime); } bool MozJSImplScope::isKillPending() const { @@ -185,12 +242,12 @@ bool MozJSImplScope::isJavaScriptProtectionEnabled() const { bool MozJSImplScope::_interruptCallback(JSContext* cx) { auto scope = getScope(cx); - JS_DisableInterruptCallback(scope->_context); - auto guard = makeGuard([&]() { JS_ResetInterruptCallback(scope->_context, false); }); + JS_SetInterruptCallback(scope->_runtime, nullptr); + auto guard = makeGuard([&]() { JS_SetInterruptCallback(scope->_runtime, _interruptCallback); }); if (scope->_pendingGC.load() || closeToMaxMemory()) { scope->_pendingGC.store(false); - JS_GC(scope->_context); + JS_GC(scope->_runtime); } else { JS_MaybeGC(cx); } @@ -216,7 +273,7 @@ bool MozJSImplScope::_interruptCallback(JSContext* cx) { return scope->_status.isOK(); } -void MozJSImplScope::_gcCallback(JSContext* rt, JSGCStatus status, void* data) { +void MozJSImplScope::_gcCallback(JSRuntime* rt, JSGCStatus status, void* data) { if (!shouldLog(logger::LogSeverity::Debug(1))) { // don't collect stats unless verbose return; @@ -303,14 +360,13 @@ MozJSImplScope::MozRuntime::MozRuntime(const MozJSScriptEngine* engine) { gFirstRuntimeCreated = true; } - _context = std::unique_ptr<JSContext, std::function<void(JSContext*)>>( - JS_NewContext(kMaxBytesBeforeGC, JS::DefaultNurseryBytes), - [](JSContext* ptr) { JS_DestroyContext(ptr); }); - uassert(ErrorCodes::JSInterpreterFailure, "Failed to initialize JSContext", _context); + _runtime = std::unique_ptr<JSRuntime, std::function<void(JSRuntime*)>>( + JS_NewRuntime(kMaxBytesBeforeGC), [](JSRuntime* ptr) { JS_DestroyRuntime(ptr); }); + uassert(ErrorCodes::JSInterpreterFailure, "Failed to initialize JSRuntime", _runtime); // We turn on a variety of optimizations if the jit is enabled if (engine->isJITEnabled()) { - JS::ContextOptionsRef(_context.get()) + JS::RuntimeOptionsRef(_runtime.get()) .setAsmJS(true) .setThrowOnAsmJSValidationFailure(true) .setBaseline(true) @@ -318,7 +374,7 @@ MozJSImplScope::MozRuntime::MozRuntime(const MozJSScriptEngine* engine) { .setAsyncStack(false) .setNativeRegExp(true); } else { - JS::ContextOptionsRef(_context.get()) + JS::RuntimeOptionsRef(_runtime.get()) .setAsmJS(false) .setThrowOnAsmJSValidationFailure(false) .setBaseline(false) @@ -327,14 +383,6 @@ MozJSImplScope::MozRuntime::MozRuntime(const MozJSScriptEngine* engine) { .setNativeRegExp(false); } - uassert(ErrorCodes::JSInterpreterFailure, - "InitSelfHostedCode", - JS::InitSelfHostedCode(_context.get())); - - uassert(ErrorCodes::ExceededMemoryLimit, - "Out of memory while trying to initialize javascript scope", - mallocMemoryLimit == 0 || mongo::sm::get_total_bytes() < mallocMemoryLimit); - const StackLocator locator; const auto available = locator.available(); if (available) { @@ -364,19 +412,26 @@ MozJSImplScope::MozRuntime::MozRuntime(const MozJSScriptEngine* engine) { const decltype(available_stack_space) reserve_stack_space = 64 * 1024; #endif - JS_SetNativeStackQuota(_context.get(), available_stack_space - reserve_stack_space); + JS_SetNativeStackQuota(_runtime.get(), available_stack_space - reserve_stack_space); } // The memory limit is in megabytes - JS_SetGCParametersBasedOnAvailableMemory(_context.get(), engine->getJSHeapLimitMB()); - // TODO SERVER-39152 apply the mozilla patch to stop overriding JSGC_MAX_BYTES - JS_SetGCParameter(_context.get(), JSGC_MAX_BYTES, 0xffffffff); + JS_SetGCParametersBasedOnAvailableMemory(_runtime.get(), engine->getJSHeapLimitMB()); } + + _context = std::unique_ptr<JSContext, std::function<void(JSContext*)>>( + JS_NewContext(_runtime.get(), kStackChunkSize), + [](JSContext* ptr) { JS_DestroyContext(ptr); }); + uassert(ErrorCodes::JSInterpreterFailure, "Failed to initialize JSContext", _context); + uassert(ErrorCodes::ExceededMemoryLimit, + "Out of memory while trying to initialize javascript scope", + mallocMemoryLimit == 0 || mongo::sm::get_total_bytes() < mallocMemoryLimit); } MozJSImplScope::MozJSImplScope(MozJSScriptEngine* engine) : _engine(engine), _mr(engine), + _runtime(_mr._runtime.get()), _context(_mr._context.get()), _globalProto(_context), _global(_globalProto.getProto()), @@ -426,13 +481,16 @@ MozJSImplScope::MozJSImplScope(MozJSScriptEngine* engine) // The default is quite low and doesn't seem to directly correlate with // malloc'd bytes. Set it to MAX_INT here and catching things in the // jscustomallocator.cpp - JS_SetGCParameter(_context, JSGC_MAX_BYTES, 0xffffffff); + JS_SetGCParameter(_runtime, JSGC_MAX_BYTES, 0xffffffff); - JS_AddInterruptCallback(_context, _interruptCallback); - JS_SetGCCallback(_context, _gcCallback, this); + JS_SetInterruptCallback(_runtime, _interruptCallback); + JS_SetGCCallback(_runtime, _gcCallback, this); JS_SetContextPrivate(_context, this); + JS_SetRuntimePrivate(_runtime, this); JSAutoRequest ar(_context); + JS_SetErrorReporter(_runtime, _reportError); + JSAutoCompartment ac(_context, _global); _checkErrorState(JS_InitStandardClasses(_context, _global)); @@ -607,8 +665,7 @@ BSONObj MozJSImplScope::callThreadArgs(const BSONObj& args) { for (int i = 0; i < argc; ++i) { ValueReader(_context, &value).fromBSONElement(*it, args, true); - if (!argv.append(value)) - uasserted(ErrorCodes::JSInterpreterFailure, "Failed to append property"); + argv.append(value); it.next(); } @@ -675,8 +732,7 @@ int MozJSImplScope::invoke(ScriptingFunction func, JS::RootedValue value(_context); ValueReader(_context, &value).fromBSONElement(next, *argsObject, readOnlyArgs); - if (!args.append(value)) - uasserted(ErrorCodes::JSInterpreterFailure, "Failed to append property"); + args.append(value); } } @@ -775,7 +831,7 @@ void MozJSImplScope::injectNative(const char* field, NativeFunction func, void* void MozJSImplScope::gc() { _pendingGC.store(true); - JS_RequestInterruptCallback(_context); + JS_RequestInterruptCallback(_runtime); } void MozJSImplScope::sleep(Milliseconds ms) { @@ -872,10 +928,9 @@ bool MozJSImplScope::_checkErrorState(bool success, bool reportError, bool asser if (_status.isOK()) { JS::RootedValue excn(_context); if (JS_GetPendingException(_context, &excn) && excn.isObject()) { + str::stream ss; - auto ss = ValueWriter(_context, excn).toString(); auto stackStr = ObjectWrapper(_context, excn).getString(InternedString::stack); - auto status = jsExceptionToStatus(_context, excn, ErrorCodes::JSInterpreterFailure, ss); auto fnameStr = ObjectWrapper(_context, excn).getString(InternedString::fileName); auto lineNum = ObjectWrapper(_context, excn).getNumberInt(InternedString::lineNumber); auto colNum = ObjectWrapper(_context, excn).getNumberInt(InternedString::columnNumber); @@ -889,12 +944,17 @@ bool MozJSImplScope::_checkErrorState(bool success, bool reportError, bool asser stackStr = ss; } - _status = Status(JSExceptionInfo(std::move(stackStr), status), ss); + if (fnameStr != "") { + ss << "[" << fnameStr << ":" << lineNum << ":" << colNum << "] "; + } + ss << ValueWriter(_context, excn).toString(); + _status = { + JSExceptionInfo(std::move(stackStr), Status(ErrorCodes::JSInterpreterFailure, ss)), + ss}; } else { _status = Status(ErrorCodes::UnknownError, "Unknown Failure from JSInterpreter"); } } - JS_ClearPendingException(_context); if (auto extraInfo = _status.extraInfo<JSExceptionInfo>()) { str::stream reasonWithStack; @@ -933,7 +993,7 @@ auto MozJSImplScope::ASANHandles::getThreadASANHandles() -> ASANHandles* { void MozJSImplScope::setOOM() { _hasOutOfMemoryException = true; - JS_RequestInterruptCallback(_context); + JS_RequestInterruptCallback(_runtime); } void MozJSImplScope::setParentStack(std::string parentStack) { diff --git a/src/mongo/scripting/mozjs/implscope.h b/src/mongo/scripting/mozjs/implscope.h index 83f8981a683..7e129477b0f 100644 --- a/src/mongo/scripting/mozjs/implscope.h +++ b/src/mongo/scripting/mozjs/implscope.h @@ -33,7 +33,6 @@ #include <jsapi.h> #include <vm/PosixNSPR.h> - #include "mongo/client/dbclient_cursor.h" #include "mongo/scripting/mozjs/bindata.h" #include "mongo/scripting/mozjs/bson.h" @@ -48,7 +47,6 @@ #include "mongo/scripting/mozjs/dbref.h" #include "mongo/scripting/mozjs/engine.h" #include "mongo/scripting/mozjs/error.h" -#include "mongo/scripting/mozjs/freeOpToJSContext.h" #include "mongo/scripting/mozjs/global.h" #include "mongo/scripting/mozjs/internedstring.h" #include "mongo/scripting/mozjs/jsthread.h" @@ -395,8 +393,9 @@ private: struct MozJSEntry; friend struct MozJSEntry; + static void _reportError(JSContext* cx, const char* message, JSErrorReport* report); static bool _interruptCallback(JSContext* cx); - static void _gcCallback(JSContext* rt, JSGCStatus status, void* data); + static void _gcCallback(JSRuntime* rt, JSGCStatus status, void* data); bool _checkErrorState(bool success, bool reportError = true, bool assertOnError = true); void installDBAccess(); @@ -408,6 +407,7 @@ private: ASANHandles _asanHandles; MozJSScriptEngine* _engine; MozRuntime _mr; + JSRuntime* _runtime; JSContext* _context; WrapType<GlobalInfo> _globalProto; JS::HandleObject _global; @@ -464,10 +464,9 @@ inline MozJSImplScope* getScope(JSContext* cx) { return static_cast<MozJSImplScope*>(JS_GetContextPrivate(cx)); } -inline MozJSImplScope* getScope(js::FreeOp* fop) { - return getScope(freeOpToJSContext(fop)); +inline MozJSImplScope* getScope(JSFreeOp* fop) { + return static_cast<MozJSImplScope*>(JS_GetRuntimePrivate(fop->runtime())); } - } // namespace mozjs } // namespace mongo diff --git a/src/mongo/scripting/mozjs/jscustomallocator.cpp b/src/mongo/scripting/mozjs/jscustomallocator.cpp index b74fbcdac7b..d2d8741bca6 100644 --- a/src/mongo/scripting/mozjs/jscustomallocator.cpp +++ b/src/mongo/scripting/mozjs/jscustomallocator.cpp @@ -258,6 +258,16 @@ void* js_realloc(void* p, size_t bytes) { [](void* ptr, size_t b) { return std::realloc(ptr, b); }, p, bytes); } -void js::InitMallocAllocator() {} +char* js_strdup(const char* s) { + size_t bytes = std::strlen(s) + 1; -void js::ShutDownMallocAllocator() {} + char* new_s = static_cast<char*>(js_malloc(bytes)); + + if (!new_s) { + return nullptr; + } + + std::memcpy(new_s, s, bytes); + + return new_s; +} diff --git a/src/mongo/scripting/mozjs/jsthread.cpp b/src/mongo/scripting/mozjs/jsthread.cpp index be1ca939f55..9c1c7b6195a 100644 --- a/src/mongo/scripting/mozjs/jsthread.cpp +++ b/src/mongo/scripting/mozjs/jsthread.cpp @@ -234,7 +234,7 @@ JSThreadConfig* getConfig(JSContext* cx, JS::CallArgs args) { } // namespace -void JSThreadInfo::finalize(js::FreeOp* fop, JSObject* obj) { +void JSThreadInfo::finalize(JSFreeOp* fop, JSObject* obj) { auto config = static_cast<JSThreadConfig*>(JS_GetPrivate(obj)); if (!config) diff --git a/src/mongo/scripting/mozjs/jsthread.h b/src/mongo/scripting/mozjs/jsthread.h index 4ecef8097fa..1bda214f44f 100644 --- a/src/mongo/scripting/mozjs/jsthread.h +++ b/src/mongo/scripting/mozjs/jsthread.h @@ -47,7 +47,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 a7dd4ee1de3..5188c0f3888 100644 --- a/src/mongo/scripting/mozjs/mongo.cpp +++ b/src/mongo/scripting/mozjs/mongo.cpp @@ -201,7 +201,7 @@ void setHiddenMongo(JSContext* cx, } } // namespace -void MongoBase::finalize(js::FreeOp* fop, JSObject* obj) { +void MongoBase::finalize(JSFreeOp* fop, JSObject* obj) { auto conn = static_cast<std::shared_ptr<DBClientBase>*>(JS_GetPrivate(obj)); if (conn) { diff --git a/src/mongo/scripting/mozjs/mongo.h b/src/mongo/scripting/mozjs/mongo.h index 699ba2c2749..f99f50b6334 100644 --- a/src/mongo/scripting/mozjs/mongo.h +++ b/src/mongo/scripting/mozjs/mongo.h @@ -43,7 +43,7 @@ namespace mozjs { * 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); struct Functions { MONGO_DECLARE_JS_FUNCTION(auth); diff --git a/src/mongo/scripting/mozjs/nativefunction.cpp b/src/mongo/scripting/mozjs/nativefunction.cpp index 7388794e5d4..7354365aa80 100644 --- a/src/mongo/scripting/mozjs/nativefunction.cpp +++ b/src/mongo/scripting/mozjs/nativefunction.cpp @@ -89,7 +89,7 @@ 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) { +void NativeFunctionInfo::finalize(JSFreeOp* fop, JSObject* obj) { auto holder = static_cast<NativeHolder*>(JS_GetPrivate(obj)); if (holder) diff --git a/src/mongo/scripting/mozjs/nativefunction.h b/src/mongo/scripting/mozjs/nativefunction.h index b4c188e0c4a..e8a4d7522c1 100644 --- a/src/mongo/scripting/mozjs/nativefunction.h +++ b/src/mongo/scripting/mozjs/nativefunction.h @@ -51,7 +51,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 c928b95c9f1..8f6ebfb21ea 100644 --- a/src/mongo/scripting/mozjs/numberdecimal.cpp +++ b/src/mongo/scripting/mozjs/numberdecimal.cpp @@ -52,7 +52,7 @@ const JSFunctionSpec NumberDecimalInfo::methods[3] = { const char* const NumberDecimalInfo::className = "NumberDecimal"; -void NumberDecimalInfo::finalize(js::FreeOp* fop, JSObject* obj) { +void NumberDecimalInfo::finalize(JSFreeOp* fop, JSObject* obj) { auto x = static_cast<Decimal128*>(JS_GetPrivate(obj)); if (x) diff --git a/src/mongo/scripting/mozjs/numberdecimal.h b/src/mongo/scripting/mozjs/numberdecimal.h index 689257ba925..f601dbeb786 100644 --- a/src/mongo/scripting/mozjs/numberdecimal.h +++ b/src/mongo/scripting/mozjs/numberdecimal.h @@ -44,7 +44,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 b805a03d985..28994955f7b 100644 --- a/src/mongo/scripting/mozjs/numberint.cpp +++ b/src/mongo/scripting/mozjs/numberint.cpp @@ -52,7 +52,7 @@ const JSFunctionSpec NumberIntInfo::methods[5] = { const char* const NumberIntInfo::className = "NumberInt"; -void NumberIntInfo::finalize(js::FreeOp* fop, JSObject* obj) { +void NumberIntInfo::finalize(JSFreeOp* fop, JSObject* obj) { auto x = static_cast<int*>(JS_GetPrivate(obj)); if (x) diff --git a/src/mongo/scripting/mozjs/numberint.h b/src/mongo/scripting/mozjs/numberint.h index edea69ebbca..3bd5e215237 100644 --- a/src/mongo/scripting/mozjs/numberint.h +++ b/src/mongo/scripting/mozjs/numberint.h @@ -42,7 +42,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 3617e1bc35a..ff60d031198 100644 --- a/src/mongo/scripting/mozjs/numberlong.cpp +++ b/src/mongo/scripting/mozjs/numberlong.cpp @@ -58,7 +58,7 @@ const JSFunctionSpec NumberLongInfo::methods[6] = { const char* const NumberLongInfo::className = "NumberLong"; -void NumberLongInfo::finalize(js::FreeOp* fop, JSObject* obj) { +void NumberLongInfo::finalize(JSFreeOp* fop, JSObject* obj) { auto numLong = static_cast<int64_t*>(JS_GetPrivate(obj)); if (numLong) @@ -210,9 +210,10 @@ void NumberLongInfo::postInstall(JSContext* cx, JS::HandleObject global, JS::Han cx, proto, getScope(cx)->getInternedStringId(InternedString::floatApprox), + undef, + JSPROP_ENUMERATE | JSPROP_SHARED, smUtils::wrapConstrainedMethod<Functions::floatApprox, false, NumberLongInfo>, - nullptr, - JSPROP_ENUMERATE)) { + nullptr)) { uasserted(ErrorCodes::JSInterpreterFailure, "Failed to JS_DefinePropertyById"); } @@ -221,9 +222,10 @@ void NumberLongInfo::postInstall(JSContext* cx, JS::HandleObject global, JS::Han cx, proto, getScope(cx)->getInternedStringId(InternedString::top), + undef, + JSPROP_ENUMERATE | JSPROP_SHARED, smUtils::wrapConstrainedMethod<Functions::top, false, NumberLongInfo>, - nullptr, - JSPROP_ENUMERATE)) { + nullptr)) { uasserted(ErrorCodes::JSInterpreterFailure, "Failed to JS_DefinePropertyById"); } @@ -232,9 +234,10 @@ void NumberLongInfo::postInstall(JSContext* cx, JS::HandleObject global, JS::Han cx, proto, getScope(cx)->getInternedStringId(InternedString::bottom), + undef, + JSPROP_ENUMERATE | JSPROP_SHARED, smUtils::wrapConstrainedMethod<Functions::bottom, false, NumberLongInfo>, - nullptr, - JSPROP_ENUMERATE)) { + nullptr)) { uasserted(ErrorCodes::JSInterpreterFailure, "Failed to JS_DefinePropertyById"); } } diff --git a/src/mongo/scripting/mozjs/numberlong.h b/src/mongo/scripting/mozjs/numberlong.h index 2697be1b661..e1e6ff52774 100644 --- a/src/mongo/scripting/mozjs/numberlong.h +++ b/src/mongo/scripting/mozjs/numberlong.h @@ -53,7 +53,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 01bb79a8890..61030ce0274 100644 --- a/src/mongo/scripting/mozjs/objectwrapper.cpp +++ b/src/mongo/scripting/mozjs/objectwrapper.cpp @@ -109,57 +109,29 @@ void ObjectWrapper::Key::set(JSContext* cx, JS::HandleObject o, JS::HandleValue void ObjectWrapper::Key::define(JSContext* cx, JS::HandleObject o, JS::HandleValue value, - unsigned attrs) { + unsigned attrs, + JSNative getter, + JSNative setter) { switch (_type) { case Type::Field: - if (JS_DefineProperty(cx, o, _field, value, attrs)) + if (JS_DefineProperty(cx, o, _field, value, attrs, getter, setter)) return; break; case Type::Index: - if (JS_DefineElement(cx, o, _idx, value, attrs)) + if (JS_DefineElement(cx, o, _idx, value, attrs, getter, setter)) return; break; case Type::Id: { JS::RootedId id(cx, _id); - if (JS_DefinePropertyById(cx, o, id, value, attrs)) + if (JS_DefinePropertyById(cx, o, id, value, attrs, getter, setter)) return; break; } case Type::InternedString: { InternedStringId id(cx, _internedString); - if (JS_DefinePropertyById(cx, o, id, value, attrs)) - return; - break; - } - } - - throwCurrentJSException(cx, ErrorCodes::InternalError, "Failed to define value on a JSObject"); -} - -void ObjectWrapper::Key::define( - JSContext* cx, JS::HandleObject o, unsigned attrs, JSNative getter, JSNative setter) { - switch (_type) { - case Type::Field: - if (JS_DefineProperty(cx, o, _field, getter, setter, attrs)) - return; - break; - case Type::Index: - if (JS_DefineElement(cx, o, _idx, getter, setter, attrs)) - return; - break; - case Type::Id: { - JS::RootedId id(cx, _id); - - if (JS_DefinePropertyById(cx, o, id, getter, setter, attrs)) - return; - break; - } - case Type::InternedString: { - InternedStringId id(cx, _internedString); - - if (JS_DefinePropertyById(cx, o, id, getter, setter, attrs)) + if (JS_DefinePropertyById(cx, o, id, value, attrs, getter, setter)) return; break; } @@ -418,12 +390,9 @@ void ObjectWrapper::setPrototype(JS::HandleObject object) { throwCurrentJSException(_context, ErrorCodes::InternalError, "Failed to set prototype"); } -void ObjectWrapper::defineProperty(Key key, JS::HandleValue val, unsigned attrs) { - key.define(_context, _object, val, attrs); -} - -void ObjectWrapper::defineProperty(Key key, unsigned attrs, JSNative getter, JSNative setter) { - key.define(_context, _object, attrs, getter, setter); +void ObjectWrapper::defineProperty( + Key key, JS::HandleValue val, unsigned attrs, JSNative getter, JSNative setter) { + key.define(_context, _object, val, attrs, getter, setter); } void ObjectWrapper::deleteProperty(Key key) { diff --git a/src/mongo/scripting/mozjs/objectwrapper.h b/src/mongo/scripting/mozjs/objectwrapper.h index ddbba2f5c17..10e5233f5b2 100644 --- a/src/mongo/scripting/mozjs/objectwrapper.h +++ b/src/mongo/scripting/mozjs/objectwrapper.h @@ -86,9 +86,12 @@ public: void set(JSContext* cx, JS::HandleObject o, JS::HandleValue value); bool has(JSContext* cx, JS::HandleObject o); bool hasOwn(JSContext* cx, JS::HandleObject o); - void define( - JSContext* cx, JS::HandleObject o, unsigned attrs, JSNative getter, JSNative setter); - void define(JSContext* cx, JS::HandleObject o, JS::HandleValue value, unsigned attrs); + void define(JSContext* cx, + JS::HandleObject o, + JS::HandleValue value, + unsigned attrs, + JSNative getter, + JSNative setter); void del(JSContext* cx, JS::HandleObject o); std::string toString(JSContext* cx); StringData toStringData(JSContext* cx, JSStringWrapper* jsstr); @@ -127,8 +130,11 @@ public: /** * See JS_DefineProperty for what sort of attributes might be useful */ - void defineProperty(Key key, unsigned attrs, JSNative getter, JSNative setter); - void defineProperty(Key key, JS::HandleValue value, unsigned attrs); + void defineProperty(Key key, + JS::HandleValue value, + unsigned attrs, + JSNative getter = nullptr, + JSNative setter = nullptr); void deleteProperty(Key key); diff --git a/src/mongo/scripting/mozjs/oid.cpp b/src/mongo/scripting/mozjs/oid.cpp index a3b822ba3dc..290ba4e99ea 100644 --- a/src/mongo/scripting/mozjs/oid.cpp +++ b/src/mongo/scripting/mozjs/oid.cpp @@ -51,7 +51,7 @@ const JSFunctionSpec OIDInfo::methods[3] = { const char* const OIDInfo::className = "ObjectId"; -void OIDInfo::finalize(js::FreeOp* fop, JSObject* obj) { +void OIDInfo::finalize(JSFreeOp* fop, JSObject* obj) { auto oid = static_cast<OID*>(JS_GetPrivate(obj)); if (oid) { @@ -125,9 +125,10 @@ void OIDInfo::postInstall(JSContext* cx, JS::HandleObject global, JS::HandleObje if (!JS_DefinePropertyById(cx, proto, getScope(cx)->getInternedStringId(InternedString::str), + undef, + JSPROP_ENUMERATE | JSPROP_SHARED, smUtils::wrapConstrainedMethod<Functions::getter, true, OIDInfo>, - nullptr, - JSPROP_ENUMERATE)) { + nullptr)) { uasserted(ErrorCodes::JSInterpreterFailure, "Failed to JS_DefinePropertyById"); } } diff --git a/src/mongo/scripting/mozjs/oid.h b/src/mongo/scripting/mozjs/oid.h index 09356bf3085..947b06faa01 100644 --- a/src/mongo/scripting/mozjs/oid.h +++ b/src/mongo/scripting/mozjs/oid.h @@ -42,7 +42,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 950c75378af..1899d1e83c4 100644 --- a/src/mongo/scripting/mozjs/session.cpp +++ b/src/mongo/scripting/mozjs/session.cpp @@ -143,7 +143,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) { diff --git a/src/mongo/scripting/mozjs/session.h b/src/mongo/scripting/mozjs/session.h index 4fcf975b87a..8b00d77aff4 100644 --- a/src/mongo/scripting/mozjs/session.h +++ b/src/mongo/scripting/mozjs/session.h @@ -43,7 +43,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 0fc7e5e3df3..0062799e839 100644 --- a/src/mongo/scripting/mozjs/status.cpp +++ b/src/mongo/scripting/mozjs/status.cpp @@ -67,24 +67,25 @@ void MongoStatusInfo::fromStatus(JSContext* cx, Status status, JS::MutableHandle JS::RootedObject thisv(cx); scope->getProto<MongoStatusInfo>().newObjectWithProto(&thisv, error); ObjectWrapper thisvObj(cx, thisv); - thisvObj.defineProperty(InternedString::code, - JSPROP_ENUMERATE, - smUtils::wrapConstrainedMethod<Functions::code, false, MongoStatusInfo>, - nullptr); + thisvObj.defineProperty( + InternedString::code, + undef, + JSPROP_ENUMERATE | JSPROP_SHARED, + smUtils::wrapConstrainedMethod<Functions::code, false, MongoStatusInfo>); thisvObj.defineProperty( InternedString::reason, - JSPROP_ENUMERATE, - smUtils::wrapConstrainedMethod<Functions::reason, false, MongoStatusInfo>, - nullptr); + undef, + JSPROP_ENUMERATE | JSPROP_SHARED, + smUtils::wrapConstrainedMethod<Functions::reason, false, MongoStatusInfo>); // We intentionally omit JSPROP_ENUMERATE to match how Error.prototype.stack is a non-enumerable // property. thisvObj.defineProperty( InternedString::stack, - 0, - smUtils::wrapConstrainedMethod<Functions::stack, false, MongoStatusInfo>, - nullptr); + undef, + JSPROP_SHARED, + smUtils::wrapConstrainedMethod<Functions::stack, false, MongoStatusInfo>); JS_SetPrivate(thisv, scope->trackedNew<Status>(std::move(status))); @@ -101,7 +102,7 @@ void MongoStatusInfo::construct(JSContext* cx, JS::CallArgs args) { args.rval().set(out); } -void MongoStatusInfo::finalize(js::FreeOp* fop, JSObject* obj) { +void MongoStatusInfo::finalize(JSFreeOp* fop, JSObject* obj) { auto status = static_cast<Status*>(JS_GetPrivate(obj)); if (status) @@ -137,8 +138,7 @@ void MongoStatusInfo::Functions::stack::call(JSContext* cx, JS::CallArgs args) { .fromStringData(extraInfo->stack + parentWrapper.getString(InternedString::stack)); // We redefine the "stack" property as the combined JavaScript stacktrace. It is important - // that we omit (TODO/FIXME, no more JSPROP_SHARED) JSPROP_SHARED to the - // thisvObj.defineProperty() call in order to have + // that we omit JSPROP_SHARED to the thisvObj.defineProperty() call in order to have // SpiderMonkey allocate memory for the string value. We also intentionally omit // JSPROP_ENUMERATE to match how Error.prototype.stack is a non-enumerable property. ObjectWrapper thisvObj(cx, args.thisv()); diff --git a/src/mongo/scripting/mozjs/status.h b/src/mongo/scripting/mozjs/status.h index d8d2f875fb8..b738605800f 100644 --- a/src/mongo/scripting/mozjs/status.h +++ b/src/mongo/scripting/mozjs/status.h @@ -48,7 +48,7 @@ namespace mozjs { */ struct MongoStatusInfo : 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(code); diff --git a/src/mongo/scripting/mozjs/wraptype.h b/src/mongo/scripting/mozjs/wraptype.h index 0160b1c029f..e4912d04c7c 100644 --- a/src/mongo/scripting/mozjs/wraptype.h +++ b/src/mongo/scripting/mozjs/wraptype.h @@ -64,7 +64,7 @@ }; #define MONGO_ATTACH_JS_FUNCTION_WITH_FLAGS(name, flags) \ - JS_FN(#name, smUtils::wrapFunction<Functions::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) @@ -161,11 +161,7 @@ bool enumerate(JSContext* cx, }; template <typename T> -bool getProperty(JSContext* cx, - JS::HandleObject obj, - JS::HandleValue receiver, - JS::HandleId id, - JS::MutableHandleValue vp) { +bool getProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::MutableHandleValue vp) { if (JSID_IS_SYMBOL(id)) { // Just default to the SpiderMonkey's standard implementations for Symbol methods vp.setUndefined(); @@ -173,7 +169,7 @@ bool getProperty(JSContext* cx, } try { - T::getProperty(cx, obj, id, receiver, vp); + T::getProperty(cx, obj, id, vp); return true; } catch (...) { mongoToJSException(cx); @@ -196,11 +192,10 @@ template <typename T> bool setProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, - JS::HandleValue vp, - JS::HandleValue receiver, + JS::MutableHandleValue vp, JS::ObjectOpResult& result) { try { - T::setProperty(cx, obj, id, vp, receiver, result); + T::setProperty(cx, obj, id, vp, result); return true; } catch (...) { mongoToJSException(cx); @@ -236,53 +231,34 @@ public: _constructor(), _jsclass({T::className, T::classFlags, - &_jsclassOps, - JS_NULL_CLASS_SPEC, - JS_NULL_CLASS_EXT, - &_jsoOps}), - _jsclassOps({T::addProperty != BaseInfo::addProperty ? smUtils::addProperty<T> : nullptr, - T::delProperty != BaseInfo::delProperty ? smUtils::delProperty<T> : nullptr, - nullptr, // enumerate - T::enumerate != BaseInfo::enumerate ? smUtils::enumerate<T> - : nullptr, // newEnumerate - T::resolve != BaseInfo::resolve ? smUtils::resolve<T> : nullptr, - T::mayResolve != BaseInfo::mayResolve ? T::mayResolve : nullptr, - T::finalize != BaseInfo::finalize ? T::finalize : nullptr, - T::call != BaseInfo::call ? smUtils::call<T> : nullptr, - T::hasInstance != BaseInfo::hasInstance ? smUtils::hasInstance<T> : nullptr, - T::construct != BaseInfo::construct ? smUtils::construct<T> : nullptr, - nullptr}), // trace - _jsoOps({ - nullptr, // lookupProperty - nullptr, // defineProperty - nullptr, // hasProperty - T::getProperty != BaseInfo::getProperty ? smUtils::getProperty<T> - : nullptr, // getProperty - T::setProperty != BaseInfo::setProperty ? smUtils::setProperty<T> - : nullptr, // setProperty - nullptr, // getOwnPropertyDescriptor - nullptr, // deleteProperty - nullptr, // getElements - nullptr // funToString - }) { + T::addProperty != BaseInfo::addProperty ? smUtils::addProperty<T> : nullptr, + T::delProperty != BaseInfo::delProperty ? smUtils::delProperty<T> : nullptr, + T::getProperty != BaseInfo::getProperty ? smUtils::getProperty<T> : nullptr, + T::setProperty != BaseInfo::setProperty ? smUtils::setProperty<T> : nullptr, + // We don't use the regular enumerate because we want the fancy new one + nullptr, + T::resolve != BaseInfo::resolve ? smUtils::resolve<T> : nullptr, + T::mayResolve != BaseInfo::mayResolve ? T::mayResolve : nullptr, + T::finalize != BaseInfo::finalize ? T::finalize : nullptr, + T::call != BaseInfo::call ? smUtils::call<T> : nullptr, + T::hasInstance != BaseInfo::hasInstance ? smUtils::hasInstance<T> : nullptr, + T::construct != BaseInfo::construct ? smUtils::construct<T> : nullptr, + nullptr}) { + _installEnumerate(T::enumerate != BaseInfo::enumerate ? smUtils::enumerate<T> : nullptr); // The global object is different. We need it for basic setup // before the other types are installed. Might as well just do it // in the constructor. if (T::classFlags & JSCLASS_GLOBAL_FLAGS) { - _jsclassOps.trace = JS_GlobalObjectTraceHook; + _jsclass.trace = JS_GlobalObjectTraceHook; JS::RootedObject proto(_context); JSAutoRequest ar(_context); - JS::CompartmentOptions options; _proto.init(_context, - _assertPtr(JS_NewGlobalObject(_context, - js::Jsvalify(&_jsclass), - nullptr, - JS::DontFireOnNewGlobalHook, - options))); + _assertPtr(JS_NewGlobalObject( + _context, &_jsclass, nullptr, JS::DontFireOnNewGlobalHook))); JSAutoCompartment ac(_context, _proto); _installFunctions(_proto, T::freeFunctions); @@ -314,7 +290,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) { @@ -325,7 +301,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) { @@ -370,7 +346,7 @@ public: // 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) { @@ -383,7 +359,7 @@ public: } const JSClass* getJSClass() const { - return js::Jsvalify(&_jsclass); + return &_jsclass; } JS::HandleObject getProto() const { @@ -407,7 +383,7 @@ private: _context, global, parent, - js::Jsvalify(&_jsclass), + &_jsclass, T::construct != BaseInfo::construct ? smUtils::construct<T> : nullptr, 0, nullptr, @@ -429,7 +405,7 @@ private: // 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"); @@ -499,6 +475,23 @@ private: _context, ErrorCodes::JSInterpreterFailure, "Failed to define functions"); } + // We have to do this awkward dance to set the new style enumeration. + // You used to be able to set this with JSCLASS_NEW_ENUMERATE in class + // flags, in the future you'll probably only set ObjectOps, but for now + // we have this. There are a host of static_asserts in js/Class.h that + // ensure that these two structures are equal. + // + // This is a landmine to watch out for during upgrades + using enumerateT = bool (*)(JSContext*, JS::HandleObject, JS::AutoIdVector&, bool); + void _installEnumerate(enumerateT enumerate) { + if (!enumerate) + return; + + auto implClass = reinterpret_cast<js::Class*>(&_jsclass); + + implClass->ops.enumerate = enumerate; + } + // This is for inheriting from something other than Object void _inheritFrom(const char* name, JS::HandleObject global, JS::MutableHandleObject out) { if (!name) @@ -555,9 +548,7 @@ private: JSContext* _context; JS::PersistentRootedObject _proto; JS::PersistentRootedObject _constructor; - js::Class _jsclass; - js::ClassOps _jsclassOps; - js::ObjectOps _jsoOps; + JSClass _jsclass; }; } // namespace mozjs |