From db9c20e0a959e0bdf7fa780d638e48853ea88496 Mon Sep 17 00:00:00 2001 From: Yves Date: Sat, 12 Jul 2014 19:08:39 +0000 Subject: [PATCH] Changes FromJSVal to take a JS::HandleValue instead of JS::Value. JS::HandleValue is basically a wrapper around a JS::Value that is safe for exact stack rooting and moving GC. I've tried to keep this changeset rather small and isolated and therefore create additional JS::Rooted values at some places where the function should eventually directly take a JS::Handle. The functions "CallFunction" and "CallFunctionVoid" put their arguments inside a JS::AutoValueVector because this will be passed directly to "CallFunction_" with ESR31. Refs #2462 Refs #2415 This was SVN commit r15517. --- .../gui/scripting/JSInterface_IGUIObject.cpp | 10 +- source/scriptinterface/NativeWrapperDecls.h | 2 +- source/scriptinterface/ScriptConversions.cpp | 46 +++---- source/scriptinterface/ScriptInterface.cpp | 37 ++--- source/scriptinterface/ScriptInterface.h | 130 +++++++++++------- .../tests/test_ScriptConversions.h | 10 +- .../scripting/EngineScriptConversions.cpp | 8 +- .../scripting/MessageTypeConversions.cpp | 2 +- 8 files changed, 141 insertions(+), 104 deletions(-) diff --git a/source/gui/scripting/JSInterface_IGUIObject.cpp b/source/gui/scripting/JSInterface_IGUIObject.cpp index d534a497d5..f5b0213db8 100644 --- a/source/gui/scripting/JSInterface_IGUIObject.cpp +++ b/source/gui/scripting/JSInterface_IGUIObject.cpp @@ -55,12 +55,13 @@ JSFunctionSpec JSI_IGUIObject::JSI_methods[] = JSBool JSI_IGUIObject::getProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::MutableHandleValue vp) { + JSAutoRequest rq(cx); IGUIObject* e = (IGUIObject*)JS_GetInstancePrivate(cx, obj, &JSI_IGUIObject::JSI_class, NULL); if (!e) return JS_FALSE; - jsval idval; - if (!JS_IdToValue(cx, id, &idval)) + JS::RootedValue idval(cx); + if (!JS_IdToValue(cx, id, idval.address())) return JS_FALSE; std::string propName; @@ -304,8 +305,9 @@ JSBool JSI_IGUIObject::setProperty(JSContext* cx, JS::HandleObject obj, JS::Hand if (!e) return JS_FALSE; - jsval idval; - if (!JS_IdToValue(cx, id, &idval)) + JSAutoRequest rq(cx); + JS::RootedValue idval(cx); + if (!JS_IdToValue(cx, id, idval.address())) return JS_FALSE; std::string propName; diff --git a/source/scriptinterface/NativeWrapperDecls.h b/source/scriptinterface/NativeWrapperDecls.h index aa2ade84cb..a14c0afc33 100644 --- a/source/scriptinterface/NativeWrapperDecls.h +++ b/source/scriptinterface/NativeWrapperDecls.h @@ -26,7 +26,7 @@ #define NUMBERED_LIST_BALANCED(z, i, data) BOOST_PP_COMMA_IF(i) data##i // Some other things #define TYPED_ARGS(z, i, data) , T##i a##i -#define CONVERT_ARG(z, i, data) T##i a##i; if (! ScriptInterface::FromJSVal(cx, i < args.length() ? args[i] : JS::UndefinedValue(), a##i)) return false; +#define CONVERT_ARG(z, i, data) T##i a##i; if (! ScriptInterface::FromJSVal(cx, i < args.length() ? args.handleAt(i) : JS::UndefinedHandleValue, a##i)) return false; // List-generating macros, named roughly after their first list item #define TYPENAME_T0_HEAD(z, i) BOOST_PP_REPEAT_##z (i, NUMBERED_LIST_HEAD, typename T) // "typename T0, typename T1, " diff --git a/source/scriptinterface/ScriptConversions.cpp b/source/scriptinterface/ScriptConversions.cpp index 35951bc198..633986a991 100644 --- a/source/scriptinterface/ScriptConversions.cpp +++ b/source/scriptinterface/ScriptConversions.cpp @@ -30,7 +30,7 @@ // Implicit type conversions often hide bugs, so warn about them #define WARN_IF_NOT(c, v) STMT(if (!(c)) { JS_ReportWarning(cx, "Script value conversion check failed: %s (got type %s)", #c, JS_GetTypeName(cx, JS_TypeOfValue(cx, v))); }) -template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, bool& out) +template<> bool ScriptInterface::FromJSVal(JSContext* cx, JS::HandleValue v, bool& out) { JSAutoRequest rq(cx); WARN_IF_NOT(v.isBoolean(), v); @@ -38,7 +38,7 @@ template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, bool& o return true; } -template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, float& out) +template<> bool ScriptInterface::FromJSVal(JSContext* cx, JS::HandleValue v, float& out) { JSAutoRequest rq(cx); double tmp; @@ -49,7 +49,7 @@ template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, float& return true; } -template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, double& out) +template<> bool ScriptInterface::FromJSVal(JSContext* cx, JS::HandleValue v, double& out) { JSAutoRequest rq(cx); WARN_IF_NOT(v.isNumber(), v); @@ -58,7 +58,7 @@ template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, doubl return true; } -template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, i32& out) +template<> bool ScriptInterface::FromJSVal(JSContext* cx, JS::HandleValue v, i32& out) { JSAutoRequest rq(cx); WARN_IF_NOT(v.isNumber(), v); @@ -67,7 +67,7 @@ template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, i32& out return true; } -template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, u32& out) +template<> bool ScriptInterface::FromJSVal(JSContext* cx, JS::HandleValue v, u32& out) { JSAutoRequest rq(cx); WARN_IF_NOT(v.isNumber(), v); @@ -76,7 +76,7 @@ template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, u32& out return true; } -template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, u16& out) +template<> bool ScriptInterface::FromJSVal(JSContext* cx, JS::HandleValue v, u16& out) { JSAutoRequest rq(cx); WARN_IF_NOT(v.isNumber(), v); @@ -85,7 +85,7 @@ template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, u16& out return true; } -template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, u8& out) +template<> bool ScriptInterface::FromJSVal(JSContext* cx, JS::HandleValue v, u8& out) { JSAutoRequest rq(cx); u16 tmp; @@ -96,7 +96,7 @@ template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, u8& out) return true; } -template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, long& out) +template<> bool ScriptInterface::FromJSVal(JSContext* cx, JS::HandleValue v, long& out) { i64 tmp; bool ok = JS::ToInt64(cx, v, &tmp); @@ -104,7 +104,7 @@ template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, long& o return ok; } -template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, unsigned long& out) +template<> bool ScriptInterface::FromJSVal(JSContext* cx, JS::HandleValue v, unsigned long& out) { u64 tmp; bool ok = JS::ToUint64(cx, v, &tmp); @@ -115,7 +115,7 @@ template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v // see comment below (where the same preprocessor condition is used) #if MSC_VERSION && ARCH_AMD64 -template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, size_t& out) +template<> bool ScriptInterface::FromJSVal(JSContext* cx, JS::HandleValue v, size_t& out) { int tmp; if(!FromJSVal(cx, v, tmp)) @@ -126,7 +126,7 @@ template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, size_ return true; } -template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, ssize_t& out) +template<> bool ScriptInterface::FromJSVal(JSContext* cx, JS::HandleValue v, ssize_t& out) { int tmp; if(!FromJSVal(cx, v, tmp)) @@ -139,19 +139,19 @@ template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, ssiz #endif -template<> bool ScriptInterface::FromJSVal(JSContext* UNUSED(cx), jsval v, CScriptVal& out) +template<> bool ScriptInterface::FromJSVal(JSContext* UNUSED(cx), JS::HandleValue v, CScriptVal& out) { - out = v; + out = v.get(); return true; } -template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, CScriptValRooted& out) +template<> bool ScriptInterface::FromJSVal(JSContext* cx, JS::HandleValue v, CScriptValRooted& out) { out = CScriptValRooted(cx, v); return true; } -template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, std::wstring& out) +template<> bool ScriptInterface::FromJSVal(JSContext* cx, JS::HandleValue v, std::wstring& out) { JSAutoRequest rq(cx); WARN_IF_NOT(JSVAL_IS_STRING(v) || JSVAL_IS_NUMBER(v), v); // allow implicit number conversions @@ -166,7 +166,7 @@ template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, return true; } -template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, Path& out) +template<> bool ScriptInterface::FromJSVal(JSContext* cx, JS::HandleValue v, Path& out) { std::wstring string; if (!FromJSVal(cx, v, string)) @@ -175,7 +175,7 @@ template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, Path& o return true; } -template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, std::string& out) +template<> bool ScriptInterface::FromJSVal(JSContext* cx, JS::HandleValue v, std::string& out) { JSAutoRequest rq(cx); WARN_IF_NOT(v.isString() || v.isNumber(), v); // allow implicit number conversions @@ -190,17 +190,17 @@ template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, return true; } -template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, CStr8& out) +template<> bool ScriptInterface::FromJSVal(JSContext* cx, JS::HandleValue v, CStr8& out) { return ScriptInterface::FromJSVal(cx, v, static_cast(out)); } -template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, CStrW& out) +template<> bool ScriptInterface::FromJSVal(JSContext* cx, JS::HandleValue v, CStrW& out) { return ScriptInterface::FromJSVal(cx, v, static_cast(out)); } -template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, Entity& out) +template<> bool ScriptInterface::FromJSVal(JSContext* cx, JS::HandleValue v, Entity& out) { JSAutoRequest rq(cx); if (!v.isObject()) @@ -377,7 +377,7 @@ template static void ToJSVal_vector(JSContext* cx, JS::Value& ret, c ret = JS::ObjectValue(*obj); } -template static bool FromJSVal_vector(JSContext* cx, jsval v, std::vector& out) +template static bool FromJSVal_vector(JSContext* cx, JS::HandleValue v, std::vector& out) { JSAutoRequest rq(cx); JSObject* obj; @@ -411,7 +411,7 @@ template static bool FromJSVal_vector(JSContext* cx, jsval v, std::v { \ ToJSVal_vector(cx, ret, val); \ } \ - template<> bool ScriptInterface::FromJSVal >(JSContext* cx, jsval v, std::vector& out) \ + template<> bool ScriptInterface::FromJSVal >(JSContext* cx, JS::HandleValue v, std::vector& out) \ { \ return FromJSVal_vector(cx, v, out); \ } @@ -430,7 +430,7 @@ template<> void ScriptInterface::ToJSVal >(JSContext* c ToJSVal_vector(cx, ret, val); } -template<> bool ScriptInterface::FromJSVal >(JSContext* cx, jsval v, std::vector& out) +template<> bool ScriptInterface::FromJSVal >(JSContext* cx, JS::HandleValue v, std::vector& out) { return FromJSVal_vector(cx, v, out); } diff --git a/source/scriptinterface/ScriptInterface.cpp b/source/scriptinterface/ScriptInterface.cpp index c2f42e116a..49fbc87ecb 100644 --- a/source/scriptinterface/ScriptInterface.cpp +++ b/source/scriptinterface/ScriptInterface.cpp @@ -428,15 +428,16 @@ void ErrorReporter(JSContext* cx, const char* message, JSErrorReport* report) jsval excn; if (JS_GetPendingException(cx, &excn) && excn.isObject()) { + JS::RootedObject excnObj(cx, &excn.toObject()); // TODO: this violates the docs ("The error reporter callback must not reenter the JSAPI.") // Hide the exception from EvaluateScript JSExceptionState* excnState = JS_SaveExceptionState(cx); JS_ClearPendingException(cx); - jsval rval; + JS::RootedValue rval(cx); const char dumpStack[] = "this.stack.trimRight().replace(/^/mg, ' ')"; // indent each line - if (JS_EvaluateScript(cx, &excn.toObject(), dumpStack, ARRAY_SIZE(dumpStack)-1, "(eval)", 1, &rval)) + if (JS_EvaluateScript(cx, &excn.toObject(), dumpStack, ARRAY_SIZE(dumpStack)-1, "(eval)", 1, rval.address())) { std::string stackTrace; if (ScriptInterface::FromJSVal(cx, rval, stackTrace)) @@ -468,7 +469,7 @@ JSBool print(JSContext* cx, uint argc, jsval* vp) for (uint i = 0; i < args.length(); ++i) { std::wstring str; - if (!ScriptInterface::FromJSVal(cx, args[i], str)) + if (!ScriptInterface::FromJSVal(cx, args.handleAt(i), str)) return JS_FALSE; debug_printf(L"%ls", str.c_str()); } @@ -487,7 +488,7 @@ JSBool logmsg(JSContext* cx, uint argc, jsval* vp) } std::wstring str; - if (!ScriptInterface::FromJSVal(cx, args[0], str)) + if (!ScriptInterface::FromJSVal(cx, args.handleAt(0), str)) return JS_FALSE; LOGMESSAGE(L"%ls", str.c_str()); args.rval().setUndefined(); @@ -504,7 +505,7 @@ JSBool warn(JSContext* cx, uint argc, jsval* vp) } std::wstring str; - if (!ScriptInterface::FromJSVal(cx, args[0], str)) + if (!ScriptInterface::FromJSVal(cx, args.handleAt(0), str)) return JS_FALSE; LOGWARNING(L"%ls", str.c_str()); args.rval().setUndefined(); @@ -521,7 +522,7 @@ JSBool error(JSContext* cx, uint argc, jsval* vp) } std::wstring str; - if (!ScriptInterface::FromJSVal(cx, args[0], str)) + if (!ScriptInterface::FromJSVal(cx, args.handleAt(0), str)) return JS_FALSE; LOGERROR(L"%ls", str.c_str()); args.rval().setUndefined(); @@ -551,7 +552,7 @@ JSBool ProfileStart(JSContext* cx, uint argc, jsval* vp) if (args.length() >= 1) { std::string str; - if (!ScriptInterface::FromJSVal(cx, args[0], str)) + if (!ScriptInterface::FromJSVal(cx, args.handleAt(0), str)) return JS_FALSE; typedef boost::flyweight< @@ -967,11 +968,13 @@ JSObject* ScriptInterface::CreateCustomObject(const std::string & typeName) bool ScriptInterface::CallFunctionVoid(jsval val, const char* name) { - jsval jsRet; - return CallFunction_(val, name, 0, NULL, jsRet); + JSAutoRequest rq(m->m_cx); + JS::RootedValue jsRet(m->m_cx); + JS::RootedValue val1(m->m_cx, val); + return CallFunction_(val1, name, 0, NULL, &jsRet); } -bool ScriptInterface::CallFunction_(jsval val, const char* name, uint argc, jsval* argv, jsval& ret) +bool ScriptInterface::CallFunction_(JS::HandleValue val, const char* name, uint argc, jsval* argv, JS::MutableHandleValue ret) { JSAutoRequest rq(m->m_cx); JS::RootedObject obj(m->m_cx); @@ -984,7 +987,7 @@ bool ScriptInterface::CallFunction_(jsval val, const char* name, uint argc, jsva if (!JS_HasProperty(m->m_cx, obj, name, &found) || !found) return JS_FALSE; - bool ok = JS_CallFunctionName(m->m_cx, obj, name, argc, argv, &ret); + bool ok = JS_CallFunctionName(m->m_cx, obj, name, argc, argv, ret.address()); return ok; } @@ -1266,25 +1269,25 @@ bool ScriptInterface::LoadGlobalScriptFile(const VfsPath& path) bool ScriptInterface::Eval(const char* code) { - jsval rval; - return Eval_(code, rval); + JS::RootedValue rval(m->m_cx); + return Eval_(code, &rval); } -bool ScriptInterface::Eval_(const char* code, jsval& rval) +bool ScriptInterface::Eval_(const char* code, JS::MutableHandleValue rval) { JSAutoRequest rq(m->m_cx); utf16string codeUtf16(code, code+strlen(code)); - bool ok = JS_EvaluateUCScript(m->m_cx, m->m_glob, (const jschar*)codeUtf16.c_str(), (uint)codeUtf16.length(), "(eval)", 1, &rval); + bool ok = JS_EvaluateUCScript(m->m_cx, m->m_glob, (const jschar*)codeUtf16.c_str(), (uint)codeUtf16.length(), "(eval)", 1, rval.address()); return ok; } -bool ScriptInterface::Eval_(const wchar_t* code, jsval& rval) +bool ScriptInterface::Eval_(const wchar_t* code, JS::MutableHandleValue rval) { JSAutoRequest rq(m->m_cx); utf16string codeUtf16(code, code+wcslen(code)); - bool ok = JS_EvaluateUCScript(m->m_cx, m->m_glob, (const jschar*)codeUtf16.c_str(), (uint)codeUtf16.length(), "(eval)", 1, &rval); + bool ok = JS_EvaluateUCScript(m->m_cx, m->m_glob, (const jschar*)codeUtf16.c_str(), (uint)codeUtf16.length(), "(eval)", 1, rval.address()); return ok; } diff --git a/source/scriptinterface/ScriptInterface.h b/source/scriptinterface/ScriptInterface.h index 1b5e3330fd..d17ce6295f 100644 --- a/source/scriptinterface/ScriptInterface.h +++ b/source/scriptinterface/ScriptInterface.h @@ -328,7 +328,7 @@ public: /** * Convert a jsval to a C++ type. (This might trigger GC.) */ - template static bool FromJSVal(JSContext* cx, jsval val, T& ret); + template static bool FromJSVal(JSContext* cx, const JS::HandleValue val, T& ret); /** * Convert a C++ type to a jsval. (This might trigger GC. The return @@ -397,9 +397,9 @@ public: jsval ReadStructuredClone(const shared_ptr& ptr); private: - bool CallFunction_(jsval val, const char* name, uint argc, jsval* argv, jsval& ret); - bool Eval_(const char* code, jsval& ret); - bool Eval_(const wchar_t* code, jsval& ret); + bool CallFunction_(JS::HandleValue val, const char* name, uint argc, jsval* argv, JS::MutableHandleValue ret); + bool Eval_(const char* code, JS::MutableHandleValue ret); + bool Eval_(const wchar_t* code, JS::MutableHandleValue ret); bool SetGlobal_(const char* name, jsval value, bool replace); bool SetProperty_(jsval obj, const char* name, jsval value, bool readonly, bool enumerate); bool SetProperty_(jsval obj, const wchar_t* name, jsval value, bool readonly, bool enumerate); @@ -447,8 +447,11 @@ public: template bool ScriptInterface::CallFunction(jsval val, const char* name, R& ret) { - jsval jsRet; - bool ok = CallFunction_(val, name, 0, NULL, jsRet); + JSContext* cx = GetContext(); + JSAutoRequest rq(cx); + JS::RootedValue jsRet(cx); + JS::RootedValue val1(cx, val); + bool ok = CallFunction_(val1, name, 0, NULL, &jsRet); if (!ok) return false; return FromJSVal(GetContext(), jsRet, ret); @@ -457,85 +460,113 @@ bool ScriptInterface::CallFunction(jsval val, const char* name, R& ret) template bool ScriptInterface::CallFunctionVoid(jsval val, const char* name, const T0& a0) { - jsval jsRet; - jsval argv[1]; - ToJSVal(GetContext(), argv[0], a0); - return CallFunction_(val, name, 1, argv, jsRet); + JSContext* cx = GetContext(); + JSAutoRequest rq(cx); + JS::RootedValue jsRet(cx); + JS::RootedValue val1(cx, val); + JS::AutoValueVector argv(cx); + argv.resize(1); + ToJSVal(cx, argv[0], a0); + return CallFunction_(val1, name, 1, argv.begin(), &jsRet); } template bool ScriptInterface::CallFunctionVoid(jsval val, const char* name, const T0& a0, const T1& a1) { - jsval jsRet; - jsval argv[2]; - ToJSVal(GetContext(), argv[0], a0); - ToJSVal(GetContext(), argv[1], a1); - return CallFunction_(val, name, 2, argv, jsRet); + JSContext* cx = GetContext(); + JSAutoRequest rq(cx); + JS::RootedValue jsRet(cx); + JS::RootedValue val1(cx, val); + JS::AutoValueVector argv(cx); + argv.resize(2); + ToJSVal(cx, argv[0], a0); + ToJSVal(cx, argv[1], a1); + return CallFunction_(val1, name, 2, argv.begin(), &jsRet); } template bool ScriptInterface::CallFunctionVoid(jsval val, const char* name, const T0& a0, const T1& a1, const T2& a2) { - jsval jsRet; - jsval argv[3]; - ToJSVal(GetContext(), argv[0], a0); - ToJSVal(GetContext(), argv[1], a1); - ToJSVal(GetContext(), argv[2], a2); - return CallFunction_(val, name, 3, argv, jsRet); + JSContext* cx = GetContext(); + JSAutoRequest rq(cx); + JS::RootedValue jsRet(cx); + JS::RootedValue val1(cx, val); + JS::AutoValueVector argv(cx); + argv.resize(3); + ToJSVal(cx, argv[0], a0); + ToJSVal(cx, argv[1], a1); + ToJSVal(cx, argv[2], a2); + return CallFunction_(val1, name, 3, argv.begin(), &jsRet); } template bool ScriptInterface::CallFunction(jsval val, const char* name, const T0& a0, R& ret) { - jsval jsRet; - jsval argv[1]; - ToJSVal(GetContext(), argv[0], a0); - bool ok = CallFunction_(val, name, 1, argv, jsRet); + JSContext* cx = GetContext(); + JSAutoRequest rq(cx); + JS::RootedValue jsRet(cx); + JS::RootedValue val1(cx, val); + JS::AutoValueVector argv(cx); + argv.resize(1); + ToJSVal(cx, argv[0], a0); + bool ok = CallFunction_(val1, name, 1, argv.begin(), &jsRet); if (!ok) return false; - return FromJSVal(GetContext(), jsRet, ret); + return FromJSVal(cx, jsRet, ret); } template bool ScriptInterface::CallFunction(jsval val, const char* name, const T0& a0, const T1& a1, R& ret) { - jsval jsRet; - jsval argv[2]; - ToJSVal(GetContext(), argv[0], a0); - ToJSVal(GetContext(), argv[1], a1); - bool ok = CallFunction_(val, name, 2, argv, jsRet); + JSContext* cx = GetContext(); + JSAutoRequest rq(cx); + JS::RootedValue jsRet(cx); + JS::RootedValue val1(cx, val); + JS::AutoValueVector argv(cx); + argv.resize(2); + ToJSVal(cx, argv[0], a0); + ToJSVal(cx, argv[1], a1); + bool ok = CallFunction_(val1, name, 2, argv.begin(), &jsRet); if (!ok) return false; - return FromJSVal(GetContext(), jsRet, ret); + return FromJSVal(cx, jsRet, ret); } template bool ScriptInterface::CallFunction(jsval val, const char* name, const T0& a0, const T1& a1, const T2& a2, R& ret) { - jsval jsRet; - jsval argv[3]; - ToJSVal(GetContext(), argv[0], a0); - ToJSVal(GetContext(), argv[1], a1); - ToJSVal(GetContext(), argv[2], a2); - bool ok = CallFunction_(val, name, 3, argv, jsRet); + JSContext* cx = GetContext(); + JSAutoRequest rq(cx); + JS::RootedValue jsRet(cx); + JS::RootedValue val1(cx, val); + JS::AutoValueVector argv(cx); + argv.resize(3); + ToJSVal(cx, argv[0], a0); + ToJSVal(cx, argv[1], a1); + ToJSVal(cx, argv[2], a2); + bool ok = CallFunction_(val1, name, 3, argv.begin(), &jsRet); if (!ok) return false; - return FromJSVal(GetContext(), jsRet, ret); + return FromJSVal(cx, jsRet, ret); } template bool ScriptInterface::CallFunction(jsval val, const char* name, const T0& a0, const T1& a1, const T2& a2, const T3& a3, R& ret) { - jsval jsRet; - jsval argv[4]; - ToJSVal(GetContext(), argv[0], a0); - ToJSVal(GetContext(), argv[1], a1); - ToJSVal(GetContext(), argv[2], a2); - ToJSVal(GetContext(), argv[3], a3); - bool ok = CallFunction_(val, name, 4, argv, jsRet); + JSContext* cx = GetContext(); + JSAutoRequest rq(cx); + JS::RootedValue jsRet(cx); + JS::RootedValue val1(cx, val); + JS::AutoValueVector argv(cx); + argv.resize(4); + ToJSVal(cx, argv[0], a0); + ToJSVal(cx, argv[1], a1); + ToJSVal(cx, argv[2], a2); + ToJSVal(cx, argv[3], a3); + bool ok = CallFunction_(val1, name, 4, argv.begin(), &jsRet); if (!ok) return false; - return FromJSVal(GetContext(), jsRet, ret); + return FromJSVal(cx, jsRet, ret); } template @@ -592,8 +623,9 @@ bool ScriptInterface::GetPropertyInt(jsval obj, int name, T& out) template bool ScriptInterface::Eval(const CHAR* code, T& ret) { - jsval rval; - if (! Eval_(code, rval)) + JSAutoRequest rq(GetContext()); + JS::RootedValue rval(GetContext()); + if (! Eval_(code, &rval)) return false; return FromJSVal(GetContext(), rval, ret); } diff --git a/source/scriptinterface/tests/test_ScriptConversions.h b/source/scriptinterface/tests/test_ScriptConversions.h index 79295430ce..b389c33507 100644 --- a/source/scriptinterface/tests/test_ScriptConversions.h +++ b/source/scriptinterface/tests/test_ScriptConversions.h @@ -52,8 +52,8 @@ class TestScriptConversions : public CxxTest::TestSuite JSContext* cx = script.GetContext(); JSAutoRequest rq(cx); - JS::Value v1; - ScriptInterface::ToJSVal(cx, v1, value); + JS::RootedValue v1(cx); + ScriptInterface::ToJSVal(cx, v1.get(), value); std::string source; TS_ASSERT(script.CallFunction(OBJECT_TO_JSVAL(JS_GetGlobalForScopeChain(cx)), "uneval", CScriptVal(v1), source)); @@ -62,7 +62,7 @@ class TestScriptConversions : public CxxTest::TestSuite TS_ASSERT_STR_EQUALS(source, expected); T v2 = T(); - TS_ASSERT(ScriptInterface::FromJSVal(script.GetContext(), v1, v2)); + TS_ASSERT(ScriptInterface::FromJSVal(cx, v1, v2)); TS_ASSERT_EQUALS(value, v2); } @@ -163,8 +163,8 @@ public: JSAutoRequest rq(cx); float f = 0; - JS::Value testNANVal; - ScriptInterface::ToJSVal(cx, testNANVal, NAN); + JS::RootedValue testNANVal(cx); + ScriptInterface::ToJSVal(cx, testNANVal.get(), NAN); TS_ASSERT(ScriptInterface::FromJSVal(cx, testNANVal, f)); TS_ASSERT(isnan(f)); } diff --git a/source/simulation2/scripting/EngineScriptConversions.cpp b/source/simulation2/scripting/EngineScriptConversions.cpp index 2319dfe18a..71d4166e8d 100644 --- a/source/simulation2/scripting/EngineScriptConversions.cpp +++ b/source/simulation2/scripting/EngineScriptConversions.cpp @@ -91,7 +91,7 @@ template<> void ScriptInterface::ToJSVal(JSContext* cx, JS::V ret = JSVAL_VOID; } -template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, CColor& out) +template<> bool ScriptInterface::FromJSVal(JSContext* cx, JS::HandleValue v, CColor& out) { if (!v.isObject()) FAIL("jsval not an object"); @@ -142,7 +142,7 @@ template<> void ScriptInterface::ToJSVal(JSContext* cx, JS::Value& ret, ret = JS::ObjectValue(*obj); } -template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, fixed& out) +template<> bool ScriptInterface::FromJSVal(JSContext* cx, JS::HandleValue v, fixed& out) { JSAutoRequest rq(cx); double ret; @@ -159,7 +159,7 @@ template<> void ScriptInterface::ToJSVal(JSContext* UNUSED(cx), JS::Value ret = JS::NumberValue(val.ToDouble()); } -template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, CFixedVector3D& out) +template<> bool ScriptInterface::FromJSVal(JSContext* cx, JS::HandleValue v, CFixedVector3D& out) { if (!v.isObject()) return false; // TODO: report type error @@ -210,7 +210,7 @@ template<> void ScriptInterface::ToJSVal(JSContext* cx, JS::Valu ret = JS::ObjectValue(*obj); } -template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, CFixedVector2D& out) +template<> bool ScriptInterface::FromJSVal(JSContext* cx, JS::HandleValue v, CFixedVector2D& out) { JSAutoRequest rq(cx); if (!v.isObject()) diff --git a/source/simulation2/scripting/MessageTypeConversions.cpp b/source/simulation2/scripting/MessageTypeConversions.cpp index 40b717eb82..b4f4b41f91 100644 --- a/source/simulation2/scripting/MessageTypeConversions.cpp +++ b/source/simulation2/scripting/MessageTypeConversions.cpp @@ -52,7 +52,7 @@ JSAutoRequest rq(scriptInterface.GetContext()); \ if (! JS_GetProperty(scriptInterface.GetContext(), obj, #name, prop.address())) \ return NULL; \ - if (! ScriptInterface::FromJSVal(scriptInterface.GetContext(), prop.get(), name)) \ + if (! ScriptInterface::FromJSVal(scriptInterface.GetContext(), prop, name)) \ return NULL; \ }