From a3d232b697dfc7c8833fc1855abbc190fe0d5970 Mon Sep 17 00:00:00 2001 From: Gabriel Russell Date: Fri, 11 Jan 2019 19:27:20 +0000 Subject: SERVER-29286 import and use mozjs-60 --- src/mongo/scripting/SConscript | 2 + src/mongo/scripting/mozjs/PosixNSPR.cpp | 28 +++++ src/mongo/scripting/mozjs/base.cpp | 6 +- src/mongo/scripting/mozjs/base.h | 6 +- src/mongo/scripting/mozjs/bindata.cpp | 2 +- src/mongo/scripting/mozjs/bindata.h | 2 +- src/mongo/scripting/mozjs/bson.cpp | 11 +- src/mongo/scripting/mozjs/bson.h | 5 +- src/mongo/scripting/mozjs/cursor.cpp | 2 +- src/mongo/scripting/mozjs/cursor.h | 2 +- src/mongo/scripting/mozjs/cursor_handle.cpp | 2 +- src/mongo/scripting/mozjs/cursor_handle.h | 2 +- src/mongo/scripting/mozjs/dbref.cpp | 7 +- src/mongo/scripting/mozjs/dbref.h | 5 +- src/mongo/scripting/mozjs/exception.cpp | 4 +- src/mongo/scripting/mozjs/implscope.cpp | 134 +++++++----------------- src/mongo/scripting/mozjs/implscope.h | 11 +- src/mongo/scripting/mozjs/jscustomallocator.cpp | 14 +-- src/mongo/scripting/mozjs/jsthread.cpp | 2 +- src/mongo/scripting/mozjs/jsthread.h | 2 +- src/mongo/scripting/mozjs/mongo.cpp | 2 +- src/mongo/scripting/mozjs/mongo.h | 2 +- src/mongo/scripting/mozjs/nativefunction.cpp | 2 +- src/mongo/scripting/mozjs/nativefunction.h | 2 +- src/mongo/scripting/mozjs/numberdecimal.cpp | 2 +- src/mongo/scripting/mozjs/numberdecimal.h | 2 +- src/mongo/scripting/mozjs/numberint.cpp | 2 +- src/mongo/scripting/mozjs/numberint.h | 2 +- src/mongo/scripting/mozjs/numberlong.cpp | 17 ++- src/mongo/scripting/mozjs/numberlong.h | 2 +- src/mongo/scripting/mozjs/objectwrapper.cpp | 51 +++++++-- src/mongo/scripting/mozjs/objectwrapper.h | 16 +-- src/mongo/scripting/mozjs/oid.cpp | 7 +- src/mongo/scripting/mozjs/oid.h | 2 +- src/mongo/scripting/mozjs/session.cpp | 2 +- src/mongo/scripting/mozjs/session.h | 2 +- src/mongo/scripting/mozjs/status.cpp | 26 ++--- src/mongo/scripting/mozjs/status.h | 2 +- src/mongo/scripting/mozjs/wraptype.h | 101 ++++++++++-------- src/mongo/shell/error_codes.tpl.js | 2 +- src/mongo/shell/mongo.js | 103 +++++++++--------- src/mongo/shell/replsettest.js | 11 +- 42 files changed, 312 insertions(+), 297 deletions(-) (limited to 'src/mongo') diff --git a/src/mongo/scripting/SConscript b/src/mongo/scripting/SConscript index edbc90ce365..5c92196bdc5 100644 --- a/src/mongo/scripting/SConscript +++ b/src/mongo/scripting/SConscript @@ -66,12 +66,14 @@ if usemozjs: if env.TargetOSIs('windows'): scriptingEnv.Append(CCFLAGS=[ '/FI', 'js-config.h', + '/FI', 'js-confdefs.h', '/FI', 'js/RequiredDefines.h', ]) else: scriptingEnv.Append( CCFLAGS=[ '-include', 'js-config.h', + '-include', 'js-confdefs.h', '-include', 'js/RequiredDefines.h', '-Wno-invalid-offsetof', ], diff --git a/src/mongo/scripting/mozjs/PosixNSPR.cpp b/src/mongo/scripting/mozjs/PosixNSPR.cpp index 63177fa9735..55a821450e6 100644 --- a/src/mongo/scripting/mozjs/PosixNSPR.cpp +++ b/src/mongo/scripting/mozjs/PosixNSPR.cpp @@ -289,3 +289,31 @@ 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 c7496dc073e..b36edd7375f 100644 --- a/src/mongo/scripting/mozjs/base.cpp +++ b/src/mongo/scripting/mozjs/base.cpp @@ -54,10 +54,11 @@ void BaseInfo::enumerate(JSContext* cx, JS::HandleObject obj, JS::AutoIdVector& properties, bool enumerableOnly) {} -void BaseInfo::finalize(JSFreeOp* fop, JSObject* obj) {} +void BaseInfo::finalize(js::FreeOp* 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, @@ -71,7 +72,8 @@ void BaseInfo::resolve(JSContext* cx, JS::HandleObject obj, JS::HandleId id, boo void BaseInfo::setProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, - JS::MutableHandleValue vp, + JS::HandleValue v, + JS::HandleValue receiver, JS::ObjectOpResult& result) {} } // namespace mozjs diff --git a/src/mongo/scripting/mozjs/base.h b/src/mongo/scripting/mozjs/base.h index 8ed28449f01..ee60999b1c3 100644 --- a/src/mongo/scripting/mozjs/base.h +++ b/src/mongo/scripting/mozjs/base.h @@ -74,10 +74,11 @@ struct BaseInfo { JS::HandleObject obj, JS::AutoIdVector& properties, bool enumerableOnly); - static void finalize(JSFreeOp* fop, JSObject* obj); + static void finalize(js::FreeOp* 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, @@ -89,7 +90,8 @@ struct BaseInfo { static void setProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, - JS::MutableHandleValue vp, + JS::HandleValue v, + JS::HandleValue receiver, JS::ObjectOpResult& result); }; diff --git a/src/mongo/scripting/mozjs/bindata.cpp b/src/mongo/scripting/mozjs/bindata.cpp index ddf5df2ba1d..91d81182204 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(JSFreeOp* fop, JSObject* obj) { +void BinDataInfo::finalize(js::FreeOp* 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 58ec68d4ad5..446c81f8107 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(JSFreeOp* fop, JSObject* obj); + static void finalize(js::FreeOp* 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 7ce68bf1a77..e3a24a94e23 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(bson, parent, scope, ro)); } -void BSONInfo::finalize(JSFreeOp* fop, JSObject* obj) { +void BSONInfo::finalize(js::FreeOp* fop, JSObject* obj) { auto holder = static_cast(JS_GetPrivate(obj)); if (!holder) @@ -163,21 +163,24 @@ void BSONInfo::enumerate(JSContext* cx, if (!JS_ValueToId(cx, val, &id)) uasserted(ErrorCodes::JSInterpreterFailure, "Failed to invoke JS_ValueToId"); - properties.append(id); + if (!properties.append(id)) + uasserted(ErrorCodes::JSInterpreterFailure, "Failed to append property"); } } void BSONInfo::setProperty(JSContext* cx, + JS::HandleObject obj, JS::HandleId id, - JS::MutableHandleValue vp, + JS::HandleValue vp, + JS::HandleValue receiver, 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 a6c55408790..565f5b0d7a8 100644 --- a/src/mongo/scripting/mozjs/bson.h +++ b/src/mongo/scripting/mozjs/bson.h @@ -57,12 +57,13 @@ struct BSONInfo : public BaseInfo { JS::HandleObject obj, JS::AutoIdVector& properties, bool enumerableOnly); - static void finalize(JSFreeOp* fop, JSObject* obj); + static void finalize(js::FreeOp* 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::MutableHandleValue vp, + JS::HandleValue v, + JS::HandleValue receiver, 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 11cc9912f7c..2b9b7da0549 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(JSFreeOp* fop, JSObject* obj) { +void CursorInfo::finalize(js::FreeOp* fop, JSObject* obj) { auto cursor = static_cast(JS_GetPrivate(obj)); if (cursor) { diff --git a/src/mongo/scripting/mozjs/cursor.h b/src/mongo/scripting/mozjs/cursor.h index db56bd9d184..5a16563ff15 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(JSFreeOp* fop, JSObject* obj); + static void finalize(js::FreeOp* 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 4ce16e32c67..fc2eda5d4e5 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(JSFreeOp* fop, JSObject* obj) { +void CursorHandleInfo::finalize(js::FreeOp* fop, JSObject* obj) { auto cursorTracker = static_cast(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 8d3641c061a..1f0f27fb299 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(JSFreeOp* fop, JSObject* obj); + static void finalize(js::FreeOp* 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 77cf56aed23..5340b69b097 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(JSFreeOp* fop, JSObject* obj) { +void DBRefInfo::finalize(js::FreeOp* fop, JSObject* obj) { BSONInfo::finalize(fop, obj); } @@ -83,9 +83,10 @@ void DBRefInfo::enumerate(JSContext* cx, void DBRefInfo::setProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, - JS::MutableHandleValue vp, + JS::HandleValue vp, + JS::HandleValue receiver, JS::ObjectOpResult& result) { - BSONInfo::setProperty(cx, obj, id, vp, result); + BSONInfo::setProperty(cx, obj, id, vp, receiver, result); } void DBRefInfo::delProperty(JSContext* cx, diff --git a/src/mongo/scripting/mozjs/dbref.h b/src/mongo/scripting/mozjs/dbref.h index 0e847dd3296..cab66b18d4c 100644 --- a/src/mongo/scripting/mozjs/dbref.h +++ b/src/mongo/scripting/mozjs/dbref.h @@ -59,12 +59,13 @@ struct DBRefInfo : public BaseInfo { JS::HandleObject obj, JS::AutoIdVector& properties, bool enumerableOnly); - static void finalize(JSFreeOp* fop, JSObject* obj); + static void finalize(js::FreeOp* 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::MutableHandleValue vp, + JS::HandleValue vp, + JS::HandleValue receiver, JS::ObjectOpResult& result); static void make( diff --git a/src/mongo/scripting/mozjs/exception.cpp b/src/mongo/scripting/mozjs/exception.cpp index 35e4155e257..56e5544d58e 100644 --- a/src/mongo/scripting/mozjs/exception.cpp +++ b/src/mongo/scripting/mozjs/exception.cpp @@ -35,9 +35,11 @@ #include #include + #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" @@ -82,7 +84,7 @@ Status JSErrorReportToStatus(JSContext* cx, JSErrorReport* report, ErrorCodes::Error altCode, StringData altReason) { - JSStringWrapper jsstr(cx, js::ErrorReportToString(cx, report)); + JSStringWrapper jsstr(cx, mongoErrorReportToString(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 830d2df320a..9f201cc3dc7 100644 --- a/src/mongo/scripting/mozjs/implscope.cpp +++ b/src/mongo/scripting/mozjs/implscope.cpp @@ -121,63 +121,6 @@ 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 ""; } @@ -219,11 +162,11 @@ void MozJSImplScope::kill() { } } _sleepCondition.notify_all(); - JS_RequestInterruptCallback(_runtime); + JS_RequestInterruptCallback(_context); } void MozJSImplScope::interrupt() { - JS_RequestInterruptCallback(_runtime); + JS_RequestInterruptCallback(_context); } bool MozJSImplScope::isKillPending() const { @@ -242,12 +185,12 @@ bool MozJSImplScope::isJavaScriptProtectionEnabled() const { bool MozJSImplScope::_interruptCallback(JSContext* cx) { auto scope = getScope(cx); - JS_SetInterruptCallback(scope->_runtime, nullptr); - auto guard = makeGuard([&]() { JS_SetInterruptCallback(scope->_runtime, _interruptCallback); }); + JS_DisableInterruptCallback(scope->_context); + auto guard = makeGuard([&]() { JS_ResetInterruptCallback(scope->_context, false); }); if (scope->_pendingGC.load() || closeToMaxMemory()) { scope->_pendingGC.store(false); - JS_GC(scope->_runtime); + JS_GC(scope->_context); } else { JS_MaybeGC(cx); } @@ -273,7 +216,7 @@ bool MozJSImplScope::_interruptCallback(JSContext* cx) { return scope->_status.isOK(); } -void MozJSImplScope::_gcCallback(JSRuntime* rt, JSGCStatus status, void* data) { +void MozJSImplScope::_gcCallback(JSContext* rt, JSGCStatus status, void* data) { if (!shouldLog(logger::LogSeverity::Debug(1))) { // don't collect stats unless verbose return; @@ -360,13 +303,14 @@ MozJSImplScope::MozRuntime::MozRuntime(const MozJSScriptEngine* engine) { gFirstRuntimeCreated = true; } - _runtime = std::unique_ptr>( - JS_NewRuntime(kMaxBytesBeforeGC), [](JSRuntime* ptr) { JS_DestroyRuntime(ptr); }); - uassert(ErrorCodes::JSInterpreterFailure, "Failed to initialize JSRuntime", _runtime); + _context = std::unique_ptr>( + JS_NewContext(kMaxBytesBeforeGC, JS::DefaultNurseryBytes), + [](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 if (engine->isJITEnabled()) { - JS::RuntimeOptionsRef(_runtime.get()) + JS::ContextOptionsRef(_context.get()) .setAsmJS(true) .setThrowOnAsmJSValidationFailure(true) .setBaseline(true) @@ -374,7 +318,7 @@ MozJSImplScope::MozRuntime::MozRuntime(const MozJSScriptEngine* engine) { .setAsyncStack(false) .setNativeRegExp(true); } else { - JS::RuntimeOptionsRef(_runtime.get()) + JS::ContextOptionsRef(_context.get()) .setAsmJS(false) .setThrowOnAsmJSValidationFailure(false) .setBaseline(false) @@ -383,6 +327,14 @@ 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) { @@ -412,26 +364,19 @@ MozJSImplScope::MozRuntime::MozRuntime(const MozJSScriptEngine* engine) { const decltype(available_stack_space) reserve_stack_space = 64 * 1024; #endif - JS_SetNativeStackQuota(_runtime.get(), available_stack_space - reserve_stack_space); + JS_SetNativeStackQuota(_context.get(), available_stack_space - reserve_stack_space); } // The memory limit is in megabytes - JS_SetGCParametersBasedOnAvailableMemory(_runtime.get(), engine->getJSHeapLimitMB()); + 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); } - - _context = std::unique_ptr>( - 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()), @@ -481,16 +426,13 @@ 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(_runtime, JSGC_MAX_BYTES, 0xffffffff); + JS_SetGCParameter(_context, JSGC_MAX_BYTES, 0xffffffff); - JS_SetInterruptCallback(_runtime, _interruptCallback); - JS_SetGCCallback(_runtime, _gcCallback, this); + JS_AddInterruptCallback(_context, _interruptCallback); + JS_SetGCCallback(_context, _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)); @@ -665,7 +607,8 @@ BSONObj MozJSImplScope::callThreadArgs(const BSONObj& args) { for (int i = 0; i < argc; ++i) { ValueReader(_context, &value).fromBSONElement(*it, args, true); - argv.append(value); + if (!argv.append(value)) + uasserted(ErrorCodes::JSInterpreterFailure, "Failed to append property"); it.next(); } @@ -732,7 +675,8 @@ int MozJSImplScope::invoke(ScriptingFunction func, JS::RootedValue value(_context); ValueReader(_context, &value).fromBSONElement(next, *argsObject, readOnlyArgs); - args.append(value); + if (!args.append(value)) + uasserted(ErrorCodes::JSInterpreterFailure, "Failed to append property"); } } @@ -831,7 +775,7 @@ void MozJSImplScope::injectNative(const char* field, NativeFunction func, void* void MozJSImplScope::gc() { _pendingGC.store(true); - JS_RequestInterruptCallback(_runtime); + JS_RequestInterruptCallback(_context); } void MozJSImplScope::sleep(Milliseconds ms) { @@ -928,9 +872,10 @@ 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); @@ -944,17 +889,12 @@ bool MozJSImplScope::_checkErrorState(bool success, bool reportError, bool asser stackStr = ss; } - if (fnameStr != "") { - ss << "[" << fnameStr << ":" << lineNum << ":" << colNum << "] "; - } - ss << ValueWriter(_context, excn).toString(); - _status = { - JSExceptionInfo(std::move(stackStr), Status(ErrorCodes::JSInterpreterFailure, ss)), - ss}; + _status = Status(JSExceptionInfo(std::move(stackStr), status), ss); } else { _status = Status(ErrorCodes::UnknownError, "Unknown Failure from JSInterpreter"); } } + JS_ClearPendingException(_context); if (auto extraInfo = _status.extraInfo()) { str::stream reasonWithStack; @@ -993,7 +933,7 @@ auto MozJSImplScope::ASANHandles::getThreadASANHandles() -> ASANHandles* { void MozJSImplScope::setOOM() { _hasOutOfMemoryException = true; - JS_RequestInterruptCallback(_runtime); + JS_RequestInterruptCallback(_context); } void MozJSImplScope::setParentStack(std::string parentStack) { diff --git a/src/mongo/scripting/mozjs/implscope.h b/src/mongo/scripting/mozjs/implscope.h index 7e129477b0f..83f8981a683 100644 --- a/src/mongo/scripting/mozjs/implscope.h +++ b/src/mongo/scripting/mozjs/implscope.h @@ -33,6 +33,7 @@ #include #include + #include "mongo/client/dbclient_cursor.h" #include "mongo/scripting/mozjs/bindata.h" #include "mongo/scripting/mozjs/bson.h" @@ -47,6 +48,7 @@ #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" @@ -393,9 +395,8 @@ private: struct MozJSEntry; friend struct MozJSEntry; - static void _reportError(JSContext* cx, const char* message, JSErrorReport* report); static bool _interruptCallback(JSContext* cx); - static void _gcCallback(JSRuntime* rt, JSGCStatus status, void* data); + static void _gcCallback(JSContext* rt, JSGCStatus status, void* data); bool _checkErrorState(bool success, bool reportError = true, bool assertOnError = true); void installDBAccess(); @@ -407,7 +408,6 @@ private: ASANHandles _asanHandles; MozJSScriptEngine* _engine; MozRuntime _mr; - JSRuntime* _runtime; JSContext* _context; WrapType _globalProto; JS::HandleObject _global; @@ -464,9 +464,10 @@ inline MozJSImplScope* getScope(JSContext* cx) { return static_cast(JS_GetContextPrivate(cx)); } -inline MozJSImplScope* getScope(JSFreeOp* fop) { - return static_cast(JS_GetRuntimePrivate(fop->runtime())); +inline MozJSImplScope* getScope(js::FreeOp* fop) { + return getScope(freeOpToJSContext(fop)); } + } // namespace mozjs } // namespace mongo diff --git a/src/mongo/scripting/mozjs/jscustomallocator.cpp b/src/mongo/scripting/mozjs/jscustomallocator.cpp index d2d8741bca6..b74fbcdac7b 100644 --- a/src/mongo/scripting/mozjs/jscustomallocator.cpp +++ b/src/mongo/scripting/mozjs/jscustomallocator.cpp @@ -258,16 +258,6 @@ void* js_realloc(void* p, size_t bytes) { [](void* ptr, size_t b) { return std::realloc(ptr, b); }, p, bytes); } -char* js_strdup(const char* s) { - size_t bytes = std::strlen(s) + 1; +void js::InitMallocAllocator() {} - char* new_s = static_cast(js_malloc(bytes)); - - if (!new_s) { - return nullptr; - } - - std::memcpy(new_s, s, bytes); - - return new_s; -} +void js::ShutDownMallocAllocator() {} diff --git a/src/mongo/scripting/mozjs/jsthread.cpp b/src/mongo/scripting/mozjs/jsthread.cpp index 9c1c7b6195a..be1ca939f55 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(JSFreeOp* fop, JSObject* obj) { +void JSThreadInfo::finalize(js::FreeOp* fop, JSObject* obj) { auto config = static_cast(JS_GetPrivate(obj)); if (!config) diff --git a/src/mongo/scripting/mozjs/jsthread.h b/src/mongo/scripting/mozjs/jsthread.h index 1bda214f44f..4ecef8097fa 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(JSFreeOp* fop, JSObject* obj); + static void finalize(js::FreeOp* 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 5188c0f3888..a7dd4ee1de3 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(JSFreeOp* fop, JSObject* obj) { +void MongoBase::finalize(js::FreeOp* fop, JSObject* obj) { auto conn = static_cast*>(JS_GetPrivate(obj)); if (conn) { diff --git a/src/mongo/scripting/mozjs/mongo.h b/src/mongo/scripting/mozjs/mongo.h index f99f50b6334..699ba2c2749 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(JSFreeOp* fop, JSObject* obj); + static void finalize(js::FreeOp* 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 7354365aa80..7388794e5d4 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(JSFreeOp* fop, JSObject* obj) { +void NativeFunctionInfo::finalize(js::FreeOp* fop, JSObject* obj) { auto holder = static_cast(JS_GetPrivate(obj)); if (holder) diff --git a/src/mongo/scripting/mozjs/nativefunction.h b/src/mongo/scripting/mozjs/nativefunction.h index e8a4d7522c1..b4c188e0c4a 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(JSFreeOp* fop, JSObject* obj); + static void finalize(js::FreeOp* 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 8f6ebfb21ea..c928b95c9f1 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(JSFreeOp* fop, JSObject* obj) { +void NumberDecimalInfo::finalize(js::FreeOp* fop, JSObject* obj) { auto x = static_cast(JS_GetPrivate(obj)); if (x) diff --git a/src/mongo/scripting/mozjs/numberdecimal.h b/src/mongo/scripting/mozjs/numberdecimal.h index f601dbeb786..689257ba925 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(JSFreeOp* fop, JSObject* obj); + static void finalize(js::FreeOp* 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 28994955f7b..b805a03d985 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(JSFreeOp* fop, JSObject* obj) { +void NumberIntInfo::finalize(js::FreeOp* fop, JSObject* obj) { auto x = static_cast(JS_GetPrivate(obj)); if (x) diff --git a/src/mongo/scripting/mozjs/numberint.h b/src/mongo/scripting/mozjs/numberint.h index 3bd5e215237..edea69ebbca 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(JSFreeOp* fop, JSObject* obj); + static void finalize(js::FreeOp* 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 ff60d031198..3617e1bc35a 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(JSFreeOp* fop, JSObject* obj) { +void NumberLongInfo::finalize(js::FreeOp* fop, JSObject* obj) { auto numLong = static_cast(JS_GetPrivate(obj)); if (numLong) @@ -210,10 +210,9 @@ void NumberLongInfo::postInstall(JSContext* cx, JS::HandleObject global, JS::Han cx, proto, getScope(cx)->getInternedStringId(InternedString::floatApprox), - undef, - JSPROP_ENUMERATE | JSPROP_SHARED, smUtils::wrapConstrainedMethod, - nullptr)) { + nullptr, + JSPROP_ENUMERATE)) { uasserted(ErrorCodes::JSInterpreterFailure, "Failed to JS_DefinePropertyById"); } @@ -222,10 +221,9 @@ void NumberLongInfo::postInstall(JSContext* cx, JS::HandleObject global, JS::Han cx, proto, getScope(cx)->getInternedStringId(InternedString::top), - undef, - JSPROP_ENUMERATE | JSPROP_SHARED, smUtils::wrapConstrainedMethod, - nullptr)) { + nullptr, + JSPROP_ENUMERATE)) { uasserted(ErrorCodes::JSInterpreterFailure, "Failed to JS_DefinePropertyById"); } @@ -234,10 +232,9 @@ void NumberLongInfo::postInstall(JSContext* cx, JS::HandleObject global, JS::Han cx, proto, getScope(cx)->getInternedStringId(InternedString::bottom), - undef, - JSPROP_ENUMERATE | JSPROP_SHARED, smUtils::wrapConstrainedMethod, - nullptr)) { + nullptr, + JSPROP_ENUMERATE)) { uasserted(ErrorCodes::JSInterpreterFailure, "Failed to JS_DefinePropertyById"); } } diff --git a/src/mongo/scripting/mozjs/numberlong.h b/src/mongo/scripting/mozjs/numberlong.h index e1e6ff52774..2697be1b661 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(JSFreeOp* fop, JSObject* obj); + static void finalize(js::FreeOp* 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 61030ce0274..01bb79a8890 100644 --- a/src/mongo/scripting/mozjs/objectwrapper.cpp +++ b/src/mongo/scripting/mozjs/objectwrapper.cpp @@ -109,29 +109,57 @@ 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, - JSNative getter, - JSNative setter) { + unsigned attrs) { switch (_type) { case Type::Field: - if (JS_DefineProperty(cx, o, _field, value, attrs, getter, setter)) + if (JS_DefineProperty(cx, o, _field, value, attrs)) return; break; case Type::Index: - if (JS_DefineElement(cx, o, _idx, value, attrs, getter, setter)) + if (JS_DefineElement(cx, o, _idx, value, attrs)) return; break; case Type::Id: { JS::RootedId id(cx, _id); - if (JS_DefinePropertyById(cx, o, id, value, attrs, getter, setter)) + if (JS_DefinePropertyById(cx, o, id, value, attrs)) return; break; } case Type::InternedString: { InternedStringId id(cx, _internedString); - if (JS_DefinePropertyById(cx, o, id, value, attrs, getter, setter)) + 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)) return; break; } @@ -390,9 +418,12 @@ void ObjectWrapper::setPrototype(JS::HandleObject object) { throwCurrentJSException(_context, ErrorCodes::InternalError, "Failed to set prototype"); } -void ObjectWrapper::defineProperty( - Key key, JS::HandleValue val, unsigned attrs, JSNative getter, JSNative setter) { - key.define(_context, _object, val, attrs, getter, setter); +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::deleteProperty(Key key) { diff --git a/src/mongo/scripting/mozjs/objectwrapper.h b/src/mongo/scripting/mozjs/objectwrapper.h index 10e5233f5b2..ddbba2f5c17 100644 --- a/src/mongo/scripting/mozjs/objectwrapper.h +++ b/src/mongo/scripting/mozjs/objectwrapper.h @@ -86,12 +86,9 @@ 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, - JS::HandleValue value, - unsigned attrs, - JSNative getter, - JSNative setter); + 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 del(JSContext* cx, JS::HandleObject o); std::string toString(JSContext* cx); StringData toStringData(JSContext* cx, JSStringWrapper* jsstr); @@ -130,11 +127,8 @@ public: /** * See JS_DefineProperty for what sort of attributes might be useful */ - void defineProperty(Key key, - JS::HandleValue value, - unsigned attrs, - JSNative getter = nullptr, - JSNative setter = nullptr); + void defineProperty(Key key, unsigned attrs, JSNative getter, JSNative setter); + void defineProperty(Key key, JS::HandleValue value, unsigned attrs); void deleteProperty(Key key); diff --git a/src/mongo/scripting/mozjs/oid.cpp b/src/mongo/scripting/mozjs/oid.cpp index 290ba4e99ea..a3b822ba3dc 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(JSFreeOp* fop, JSObject* obj) { +void OIDInfo::finalize(js::FreeOp* fop, JSObject* obj) { auto oid = static_cast(JS_GetPrivate(obj)); if (oid) { @@ -125,10 +125,9 @@ 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, - nullptr)) { + nullptr, + JSPROP_ENUMERATE)) { uasserted(ErrorCodes::JSInterpreterFailure, "Failed to JS_DefinePropertyById"); } } diff --git a/src/mongo/scripting/mozjs/oid.h b/src/mongo/scripting/mozjs/oid.h index 947b06faa01..09356bf3085 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(JSFreeOp* fop, JSObject* obj); + static void finalize(js::FreeOp* 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 1899d1e83c4..950c75378af 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(JSFreeOp* fop, JSObject* obj) { +void SessionInfo::finalize(js::FreeOp* 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 8b00d77aff4..4fcf975b87a 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(JSFreeOp* fop, JSObject* obj); + static void finalize(js::FreeOp* 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 0062799e839..0fc7e5e3df3 100644 --- a/src/mongo/scripting/mozjs/status.cpp +++ b/src/mongo/scripting/mozjs/status.cpp @@ -67,25 +67,24 @@ void MongoStatusInfo::fromStatus(JSContext* cx, Status status, JS::MutableHandle JS::RootedObject thisv(cx); scope->getProto().newObjectWithProto(&thisv, error); ObjectWrapper thisvObj(cx, thisv); - thisvObj.defineProperty( - InternedString::code, - undef, - JSPROP_ENUMERATE | JSPROP_SHARED, - smUtils::wrapConstrainedMethod); + thisvObj.defineProperty(InternedString::code, + JSPROP_ENUMERATE, + smUtils::wrapConstrainedMethod, + nullptr); thisvObj.defineProperty( InternedString::reason, - undef, - JSPROP_ENUMERATE | JSPROP_SHARED, - smUtils::wrapConstrainedMethod); + JSPROP_ENUMERATE, + smUtils::wrapConstrainedMethod, + nullptr); // We intentionally omit JSPROP_ENUMERATE to match how Error.prototype.stack is a non-enumerable // property. thisvObj.defineProperty( InternedString::stack, - undef, - JSPROP_SHARED, - smUtils::wrapConstrainedMethod); + 0, + smUtils::wrapConstrainedMethod, + nullptr); JS_SetPrivate(thisv, scope->trackedNew(std::move(status))); @@ -102,7 +101,7 @@ void MongoStatusInfo::construct(JSContext* cx, JS::CallArgs args) { args.rval().set(out); } -void MongoStatusInfo::finalize(JSFreeOp* fop, JSObject* obj) { +void MongoStatusInfo::finalize(js::FreeOp* fop, JSObject* obj) { auto status = static_cast(JS_GetPrivate(obj)); if (status) @@ -138,7 +137,8 @@ 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 JSPROP_SHARED to the thisvObj.defineProperty() call in order to have + // that we omit (TODO/FIXME, no more JSPROP_SHARED) 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 b738605800f..d8d2f875fb8 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(JSFreeOp* fop, JSObject* obj); + static void finalize(js::FreeOp* 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 e4912d04c7c..0160b1c029f 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_FS(#name, smUtils::wrapFunction, 0, flags) + JS_FN(#name, smUtils::wrapFunction, 0, flags) #define MONGO_ATTACH_JS_FUNCTION(name) MONGO_ATTACH_JS_FUNCTION_WITH_FLAGS(name, 0) @@ -161,7 +161,11 @@ bool enumerate(JSContext* cx, }; template -bool getProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::MutableHandleValue vp) { +bool getProperty(JSContext* cx, + JS::HandleObject obj, + JS::HandleValue receiver, + JS::HandleId id, + JS::MutableHandleValue vp) { if (JSID_IS_SYMBOL(id)) { // Just default to the SpiderMonkey's standard implementations for Symbol methods vp.setUndefined(); @@ -169,7 +173,7 @@ bool getProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::Mutab } try { - T::getProperty(cx, obj, id, vp); + T::getProperty(cx, obj, id, receiver, vp); return true; } catch (...) { mongoToJSException(cx); @@ -192,10 +196,11 @@ template bool setProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, - JS::MutableHandleValue vp, + JS::HandleValue vp, + JS::HandleValue receiver, JS::ObjectOpResult& result) { try { - T::setProperty(cx, obj, id, vp, result); + T::setProperty(cx, obj, id, vp, receiver, result); return true; } catch (...) { mongoToJSException(cx); @@ -231,34 +236,53 @@ public: _constructor(), _jsclass({T::className, T::classFlags, - T::addProperty != BaseInfo::addProperty ? smUtils::addProperty : nullptr, - T::delProperty != BaseInfo::delProperty ? smUtils::delProperty : nullptr, - T::getProperty != BaseInfo::getProperty ? smUtils::getProperty : nullptr, - T::setProperty != BaseInfo::setProperty ? smUtils::setProperty : nullptr, - // We don't use the regular enumerate because we want the fancy new one - nullptr, - T::resolve != BaseInfo::resolve ? smUtils::resolve : nullptr, - T::mayResolve != BaseInfo::mayResolve ? T::mayResolve : nullptr, - T::finalize != BaseInfo::finalize ? T::finalize : nullptr, - T::call != BaseInfo::call ? smUtils::call : nullptr, - T::hasInstance != BaseInfo::hasInstance ? smUtils::hasInstance : nullptr, - T::construct != BaseInfo::construct ? smUtils::construct : nullptr, - nullptr}) { - _installEnumerate(T::enumerate != BaseInfo::enumerate ? smUtils::enumerate : nullptr); + &_jsclassOps, + JS_NULL_CLASS_SPEC, + JS_NULL_CLASS_EXT, + &_jsoOps}), + _jsclassOps({T::addProperty != BaseInfo::addProperty ? smUtils::addProperty : nullptr, + T::delProperty != BaseInfo::delProperty ? smUtils::delProperty : nullptr, + nullptr, // enumerate + T::enumerate != BaseInfo::enumerate ? smUtils::enumerate + : nullptr, // newEnumerate + T::resolve != BaseInfo::resolve ? smUtils::resolve : nullptr, + T::mayResolve != BaseInfo::mayResolve ? T::mayResolve : nullptr, + T::finalize != BaseInfo::finalize ? T::finalize : nullptr, + T::call != BaseInfo::call ? smUtils::call : nullptr, + T::hasInstance != BaseInfo::hasInstance ? smUtils::hasInstance : nullptr, + T::construct != BaseInfo::construct ? smUtils::construct : nullptr, + nullptr}), // trace + _jsoOps({ + nullptr, // lookupProperty + nullptr, // defineProperty + nullptr, // hasProperty + T::getProperty != BaseInfo::getProperty ? smUtils::getProperty + : nullptr, // getProperty + T::setProperty != BaseInfo::setProperty ? smUtils::setProperty + : nullptr, // setProperty + nullptr, // getOwnPropertyDescriptor + nullptr, // deleteProperty + nullptr, // getElements + nullptr // funToString + }) { // 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) { - _jsclass.trace = JS_GlobalObjectTraceHook; + _jsclassOps.trace = JS_GlobalObjectTraceHook; JS::RootedObject proto(_context); JSAutoRequest ar(_context); + JS::CompartmentOptions options; _proto.init(_context, - _assertPtr(JS_NewGlobalObject( - _context, &_jsclass, nullptr, JS::DontFireOnNewGlobalHook))); + _assertPtr(JS_NewGlobalObject(_context, + js::Jsvalify(&_jsclass), + nullptr, + JS::DontFireOnNewGlobalHook, + options))); JSAutoCompartment ac(_context, _proto); _installFunctions(_proto, T::freeFunctions); @@ -290,7 +314,7 @@ public: * types without a constructor or inside the constructor */ void newObject(JS::MutableHandleObject out) { - out.set(_assertPtr(JS_NewObjectWithGivenProto(_context, &_jsclass, _proto))); + out.set(_assertPtr(JS_NewObjectWithGivenProto(_context, js::Jsvalify(&_jsclass), _proto))); } void newObject(JS::MutableHandleValue out) { @@ -301,7 +325,7 @@ public: } void newObjectWithProto(JS::MutableHandleObject out, JS::HandleObject proto) { - out.set(_assertPtr(JS_NewObjectWithGivenProto(_context, &_jsclass, proto))); + out.set(_assertPtr(JS_NewObjectWithGivenProto(_context, js::Jsvalify(&_jsclass), proto))); } void newObjectWithProto(JS::MutableHandleValue out, JS::HandleObject proto) { @@ -346,7 +370,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, &_jsclass, nullptr); + return JS_InstanceOf(_context, obj, js::Jsvalify(&_jsclass), nullptr); } bool instanceOf(JS::HandleValue value) { @@ -359,7 +383,7 @@ public: } const JSClass* getJSClass() const { - return &_jsclass; + return js::Jsvalify(&_jsclass); } JS::HandleObject getProto() const { @@ -383,7 +407,7 @@ private: _context, global, parent, - &_jsclass, + js::Jsvalify(&_jsclass), T::construct != BaseInfo::construct ? smUtils::construct : nullptr, 0, nullptr, @@ -405,7 +429,7 @@ private: // See newObject() for why we have to do this dance with the explicit // SetPrototype - _proto.init(_context, _assertPtr(JS_NewObject(_context, &_jsclass))); + _proto.init(_context, _assertPtr(JS_NewObject(_context, js::Jsvalify(&_jsclass)))); if (parent.get() && !JS_SetPrototype(_context, _proto, parent)) throwCurrentJSException( _context, ErrorCodes::JSInterpreterFailure, "Failed to set prototype"); @@ -475,23 +499,6 @@ 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(&_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) @@ -548,7 +555,9 @@ private: JSContext* _context; JS::PersistentRootedObject _proto; JS::PersistentRootedObject _constructor; - JSClass _jsclass; + js::Class _jsclass; + js::ClassOps _jsclassOps; + js::ObjectOps _jsoOps; }; } // namespace mozjs diff --git a/src/mongo/shell/error_codes.tpl.js b/src/mongo/shell/error_codes.tpl.js index 767a48d1ae3..f4299deae3f 100644 --- a/src/mongo/shell/error_codes.tpl.js +++ b/src/mongo/shell/error_codes.tpl.js @@ -31,7 +31,7 @@ var {ErrorCodes, ErrorCodeStrings} = (function() { const handler = { get: function(obj, prop) { - if (prop !== Symbol.toPrimitive && prop in obj === false && prop in Object === false) { + if (typeof prop !== "symbol" && prop in obj === false && prop in Object === false) { throw new Error('Unknown Error Code: ' + prop.toString()); } diff --git a/src/mongo/shell/mongo.js b/src/mongo/shell/mongo.js index 4b3f95db88d..2f25605536d 100644 --- a/src/mongo/shell/mongo.js +++ b/src/mongo/shell/mongo.js @@ -89,63 +89,66 @@ Mongo.prototype.getDBs = function(driverSession = this._getDefaultSession(), filter = undefined, nameOnly = undefined, authorizedDatabases = undefined) { - 'use strict'; - let cmdObj = {listDatabases: 1}; - if (filter !== undefined) { - cmdObj.filter = filter; - } - if (nameOnly !== undefined) { - cmdObj.nameOnly = nameOnly; - } - if (authorizedDatabases !== undefined) { - cmdObj.authorizedDatabases = authorizedDatabases; - } + return function(driverSession, filter, nameOnly, authorizedDatabases) { + 'use strict'; - if (driverSession._isExplicit || !jsTest.options().disableImplicitSessions) { - cmdObj = driverSession._serverSession.injectSessionId(cmdObj); - } + let cmdObj = {listDatabases: 1}; + if (filter !== undefined) { + cmdObj.filter = filter; + } + if (nameOnly !== undefined) { + cmdObj.nameOnly = nameOnly; + } + if (authorizedDatabases !== undefined) { + cmdObj.authorizedDatabases = authorizedDatabases; + } - const res = this.adminCommand(cmdObj); - if (!res.ok) { - // If "Unauthorized" was returned by the back end and we haven't explicitly - // asked for anything difficult to provide from userspace, then we can - // fallback on inspecting the user's permissions. - // This means that: - // * filter must be undefined, as reimplementing that logic is out of scope. - // * nameOnly must not be false as we can't infer size information. - // * authorizedDatabases must not be false as those are the only DBs we can infer. - // Note that if the above are valid and we get Unauthorized, that also means - // that we MUST be talking to a pre-4.0 mongod. - // - // Like the server response mode, this path will return a simple list of - // names if nameOnly is specified as true. - // If nameOnly is undefined, we come as close as we can to what the - // server would return by supplying the databases key of the returned - // object. Other information is unavailable. - if ((res.code === ErrorCodes.Unauthorized) && (filter === undefined) && - (nameOnly !== false) && (authorizedDatabases !== false)) { - const names = this._getDatabaseNamesFromPrivileges(); - if (nameOnly === true) { - return names; - } else { - return { - databases: names.map(function(x) { - return {name: x}; - }), - }; + if (driverSession._isExplicit || !jsTest.options().disableImplicitSessions) { + cmdObj = driverSession._serverSession.injectSessionId(cmdObj); + } + + const res = this.adminCommand(cmdObj); + if (!res.ok) { + // If "Unauthorized" was returned by the back end and we haven't explicitly + // asked for anything difficult to provide from userspace, then we can + // fallback on inspecting the user's permissions. + // This means that: + // * filter must be undefined, as reimplementing that logic is out of scope. + // * nameOnly must not be false as we can't infer size information. + // * authorizedDatabases must not be false as those are the only DBs we can infer. + // Note that if the above are valid and we get Unauthorized, that also means + // that we MUST be talking to a pre-4.0 mongod. + // + // Like the server response mode, this path will return a simple list of + // names if nameOnly is specified as true. + // If nameOnly is undefined, we come as close as we can to what the + // server would return by supplying the databases key of the returned + // object. Other information is unavailable. + if ((res.code === ErrorCodes.Unauthorized) && (filter === undefined) && + (nameOnly !== false) && (authorizedDatabases !== false)) { + const names = this._getDatabaseNamesFromPrivileges(); + if (nameOnly === true) { + return names; + } else { + return { + databases: names.map(function(x) { + return {name: x}; + }), + }; + } } + throw _getErrorWithCode(res, "listDatabases failed:" + tojson(res)); } - throw _getErrorWithCode(res, "listDatabases failed:" + tojson(res)); - } - if (nameOnly) { - return res.databases.map(function(db) { - return db.name; - }); - } + if (nameOnly) { + return res.databases.map(function(db) { + return db.name; + }); + } - return res; + return res; + }.call(this, driverSession, filter, nameOnly, authorizedDatabases); }; Mongo.prototype.adminCommand = function(cmd) { diff --git a/src/mongo/shell/replsettest.js b/src/mongo/shell/replsettest.js index 8f1522b7618..ea8766968e6 100644 --- a/src/mongo/shell/replsettest.js +++ b/src/mongo/shell/replsettest.js @@ -484,7 +484,7 @@ var ReplSetTest = function(opts) { member._id = i; member.host = this.host; - if (!member.host.contains('/')) { + if (!member.host.includes('/')) { member.host += ":" + this.ports[i]; } @@ -2279,6 +2279,15 @@ var ReplSetTest = function(opts) { // Turn off periodic noop writes for replica sets by default. options.setParameter = options.setParameter || {}; + if (typeof(options.setParameter) === "string") { + var eqIdx = options.setParameter.indexOf("="); + if (eqIdx != -1) { + var param = options.setParameter.substring(0, eqIdx); + var value = options.setParameter.substring(eqIdx + 1); + options.setParameter = {}; + options.setParameter[param] = value; + } + } options.setParameter.writePeriodicNoops = options.setParameter.writePeriodicNoops || false; // We raise the number of initial sync connect attempts for tests that disallow chaining. -- cgit v1.2.1