Index: ps/trunk/source/gui/scripting/JSInterface_GUITypes.cpp =================================================================== --- ps/trunk/source/gui/scripting/JSInterface_GUITypes.cpp +++ ps/trunk/source/gui/scripting/JSInterface_GUITypes.cpp @@ -94,8 +94,8 @@ bool JSI_GUISize::toString(JSContext* cx, uint argc, JS::Value* vp) { - UNUSED2(argc); - JS::CallReceiver rec = JS::CallReceiverFromVp(vp); + // JSAutoRequest not needed for the calls below + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); CStr buffer; try @@ -103,8 +103,8 @@ ScriptInterface* pScriptInterface = ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface; double val, valr; #define SIDE(side) \ - pScriptInterface->GetProperty(rec.thisv(), #side, val); \ - pScriptInterface->GetProperty(rec.thisv(), "r"#side, valr); \ + pScriptInterface->GetProperty(args.thisv(), #side, val); \ + pScriptInterface->GetProperty(args.thisv(), "r"#side, valr); \ buffer += ToPercentString(val, valr); SIDE(left); @@ -118,10 +118,10 @@ } catch (PSERROR_Scripting_ConversionFailed&) { - ScriptInterface::ToJSVal(cx, rec.rval(), std::string("")); + ScriptInterface::ToJSVal(cx, args.rval(), std::string("")); return true; } - ScriptInterface::ToJSVal(cx, rec.rval(), buffer); + ScriptInterface::ToJSVal(cx, args.rval(), buffer); return true; } Index: ps/trunk/source/gui/scripting/JSInterface_IGUIObject.cpp =================================================================== --- ps/trunk/source/gui/scripting/JSInterface_IGUIObject.cpp +++ ps/trunk/source/gui/scripting/JSInterface_IGUIObject.cpp @@ -52,7 +52,7 @@ JSAutoRequest rq(cx); ScriptInterface* pScriptInterface = ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface; - IGUIObject* e = (IGUIObject*)JS_GetInstancePrivate(cx, obj, &JSI_IGUIObject::JSI_class, NULL); + IGUIObject* e = ScriptInterface::GetPrivate(cx, obj, &JSI_IGUIObject::JSI_class); if (!e) return false; @@ -126,7 +126,7 @@ bool JSI_IGUIObject::setProperty(JSContext* cx, JS::HandleObject obj, JS::HandleId id, JS::MutableHandleValue vp, JS::ObjectOpResult& result) { - IGUIObject* e = (IGUIObject*)JS_GetInstancePrivate(cx, obj, &JSI_IGUIObject::JSI_class, NULL); + IGUIObject* e = ScriptInterface::GetPrivate(cx, obj, &JSI_IGUIObject::JSI_class); if (!e) return result.fail(JSMSG_NOT_NONNULL_OBJECT); @@ -179,63 +179,50 @@ scriptInterface.DefineCustomObjectType(&JSI_class, nullptr, 1, nullptr, JSI_methods, nullptr, nullptr); } -bool JSI_IGUIObject::toString(JSContext* cx, uint UNUSED(argc), JS::Value* vp) +bool JSI_IGUIObject::toString(JSContext* cx, uint argc, JS::Value* vp) { - JSAutoRequest rq(cx); - JS::CallReceiver rec = JS::CallReceiverFromVp(vp); - - JS::RootedObject thisObj(cx, JS_THIS_OBJECT(cx, vp)); - - IGUIObject* e = (IGUIObject*)JS_GetInstancePrivate(cx, thisObj, &JSI_IGUIObject::JSI_class, NULL); + // No JSAutoRequest needed for these calls + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + IGUIObject* e = ScriptInterface::GetPrivate(cx, args, &JSI_IGUIObject::JSI_class); if (!e) return false; - ScriptInterface::ToJSVal(cx, rec.rval(), "[GUIObject: " + e->GetName() + "]"); + ScriptInterface::ToJSVal(cx, args.rval(), "[GUIObject: " + e->GetName() + "]"); return true; } -bool JSI_IGUIObject::focus(JSContext* cx, uint UNUSED(argc), JS::Value* vp) +bool JSI_IGUIObject::focus(JSContext* cx, uint argc, JS::Value* vp) { - JSAutoRequest rq(cx); - JS::CallReceiver rec = JS::CallReceiverFromVp(vp); - - JS::RootedObject thisObj(cx, JS_THIS_OBJECT(cx, vp)); - - IGUIObject* e = (IGUIObject*)JS_GetInstancePrivate(cx, thisObj, &JSI_IGUIObject::JSI_class, NULL); + // No JSAutoRequest needed for these calls + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + IGUIObject* e = ScriptInterface::GetPrivate(cx, args, &JSI_IGUIObject::JSI_class); if (!e) return false; e->GetGUI()->SetFocusedObject(e); - - rec.rval().setUndefined(); + args.rval().setUndefined(); return true; } -bool JSI_IGUIObject::blur(JSContext* cx, uint UNUSED(argc), JS::Value* vp) +bool JSI_IGUIObject::blur(JSContext* cx, uint argc, JS::Value* vp) { - JSAutoRequest rq(cx); - JS::CallReceiver rec = JS::CallReceiverFromVp(vp); - - JS::RootedObject thisObj(cx, JS_THIS_OBJECT(cx, vp)); - - IGUIObject* e = (IGUIObject*)JS_GetInstancePrivate(cx, thisObj, &JSI_IGUIObject::JSI_class, NULL); + // No JSAutoRequest needed for these calls + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + IGUIObject* e = ScriptInterface::GetPrivate(cx, args, &JSI_IGUIObject::JSI_class); if (!e) return false; e->GetGUI()->SetFocusedObject(NULL); - - rec.rval().setUndefined(); + args.rval().setUndefined(); return true; } -bool JSI_IGUIObject::getComputedSize(JSContext* cx, uint UNUSED(argc), JS::Value* vp) +bool JSI_IGUIObject::getComputedSize(JSContext* cx, uint argc, JS::Value* vp) { JSAutoRequest rq(cx); - JS::CallReceiver rec = JS::CallReceiverFromVp(vp); - - JS::RootedObject thisObj(cx, JS_THIS_OBJECT(cx, vp)); + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); - IGUIObject* e = (IGUIObject*)JS_GetInstancePrivate(cx, thisObj, &JSI_IGUIObject::JSI_class, NULL); + IGUIObject* e = ScriptInterface::GetPrivate(cx, args, &JSI_IGUIObject::JSI_class); if (!e) return false; @@ -258,6 +245,6 @@ return false; } - rec.rval().set(objVal); + args.rval().set(objVal); return true; } Index: ps/trunk/source/gui/scripting/JSInterface_IGUITextOwner.cpp =================================================================== --- ps/trunk/source/gui/scripting/JSInterface_IGUITextOwner.cpp +++ ps/trunk/source/gui/scripting/JSInterface_IGUITextOwner.cpp @@ -33,27 +33,23 @@ JS_DefineFunctions(cx, obj, JSI_methods); } -bool JSI_IGUITextOwner::GetTextSize(JSContext* cx, uint UNUSED(argc), JS::Value* vp) +bool JSI_IGUITextOwner::GetTextSize(JSContext* cx, uint argc, JS::Value* vp) { - JSAutoRequest rq(cx); - JS::CallReceiver rec = JS::CallReceiverFromVp(vp); - JS::RootedObject thisObj(cx, &rec.thisv().toObject()); - - IGUIObject* obj = static_cast(JS_GetInstancePrivate(cx, thisObj, &JSI_IGUIObject::JSI_class, nullptr)); + // No JSAutoRequest needed for these calls + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + IGUIObject* obj = ScriptInterface::GetPrivate(cx, args, &JSI_IGUIObject::JSI_class); if (!obj) - { - JS_ReportError(cx, "This is not an IGUIObject!"); return false; - } // Avoid dynamic_cast for performance reasons IGUITextOwner* objText = static_cast(obj->GetTextOwner()); if (!objText) { + JSAutoRequest rq(cx); JS_ReportError(cx, "This IGUIObject is not an IGUITextOwner!"); return false; } - ScriptInterface::ToJSVal(cx, rec.rval(), objText->CalculateTextSize()); + ScriptInterface::ToJSVal(cx, args.rval(), objText->CalculateTextSize()); return true; } Index: ps/trunk/source/scriptinterface/NativeWrapperDefns.h =================================================================== --- ps/trunk/source/scriptinterface/NativeWrapperDefns.h +++ ps/trunk/source/scriptinterface/NativeWrapperDefns.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2017 Wildfire Games. +/* Copyright (C) 2019 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -132,9 +132,7 @@ { \ JS::CallArgs args = JS::CallArgsFromVp(argc, vp); \ JSAutoRequest rq(cx); \ - JS::RootedObject thisObj(cx, JS_THIS_OBJECT(cx, vp)); \ - if (ScriptInterface::GetClass(thisObj) != CLS) return false; \ - TC* c = static_cast(ScriptInterface::GetPrivate(thisObj)); \ + TC* c = ScriptInterface::GetPrivate(cx, args, CLS); \ if (! c) return false; \ BOOST_PP_REPEAT_##z (i, CONVERT_ARG, ~) \ JS::RootedValue rval(cx); \ @@ -152,9 +150,7 @@ { \ JS::CallArgs args = JS::CallArgsFromVp(argc, vp); \ JSAutoRequest rq(cx); \ - JS::RootedObject thisObj(cx, JS_THIS_OBJECT(cx, vp)); \ - if (ScriptInterface::GetClass(thisObj) != CLS) return false; \ - TC* c = static_cast(ScriptInterface::GetPrivate(thisObj)); \ + TC* c = ScriptInterface::GetPrivate(cx, args, CLS); \ if (! c) return false; \ BOOST_PP_REPEAT_##z (i, CONVERT_ARG, ~) \ JS::RootedValue rval(cx); \ Index: ps/trunk/source/scriptinterface/ScriptInterface.h =================================================================== --- ps/trunk/source/scriptinterface/ScriptInterface.h +++ ps/trunk/source/scriptinterface/ScriptInterface.h @@ -337,6 +337,39 @@ void ReadStructuredClone(const shared_ptr& ptr, JS::MutableHandleValue ret) const; /** + * Retrieve the private data field of a JSObject that is an instance of the given JSClass. + */ + template + static T* GetPrivate(JSContext* cx, JS::HandleObject thisobj, JSClass* jsClass) + { + JSAutoRequest rq(cx); + T* value = static_cast(JS_GetInstancePrivate(cx, thisobj, jsClass, nullptr)); + if (value == nullptr && !JS_IsExceptionPending(cx)) + JS_ReportError(cx, "Private data of the given object is null!"); + return value; + } + + /** + * Retrieve the private data field of a JS Object that is an instance of the given JSClass. + * If an error occurs, GetPrivate will report it with the according stack. + */ + template + static T* GetPrivate(JSContext* cx, JS::CallArgs& callArgs, JSClass* jsClass) + { + JSAutoRequest rq(cx); + if (!callArgs.thisv().isObject()) + { + JS_ReportError(cx, "Cannot retrieve private JS class data because from a non-object value!"); + return nullptr; + } + JS::RootedObject thisObj(cx, &callArgs.thisv().toObject()); + T* value = static_cast(JS_GetInstancePrivate(cx, thisObj, jsClass, &callArgs)); + if (value == nullptr && !JS_IsExceptionPending(cx)) + JS_ReportError(cx, "Private data of the given object is null!"); + return value; + } + + /** * Converts |a| if needed and assigns it to |handle|. * This is meant for use in other templates where we want to use the same code for JS::RootedValue&/JS::HandleValue and * other types. Note that functions are meant to take JS::HandleValue instead of JS::RootedValue&, but this implicit @@ -380,8 +413,6 @@ bool GetProperty_(JS::HandleValue obj, const char* name, JS::MutableHandleValue out) const; bool GetPropertyInt_(JS::HandleValue obj, int name, JS::MutableHandleValue value) const; static bool IsExceptionPending(JSContext* cx); - static const JSClass* GetClass(JS::HandleObject obj); - static void* GetPrivate(JS::HandleObject obj); struct CustomType { Index: ps/trunk/source/scriptinterface/ScriptInterface.cpp =================================================================== --- ps/trunk/source/scriptinterface/ScriptInterface.cpp +++ ps/trunk/source/scriptinterface/ScriptInterface.cpp @@ -252,15 +252,15 @@ return true; } -bool ProfileStop(JSContext* UNUSED(cx), uint UNUSED(argc), JS::Value* vp) +bool ProfileStop(JSContext* UNUSED(cx), uint argc, JS::Value* vp) { - JS::CallReceiver rec = JS::CallReceiverFromVp(vp); + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); if (CProfileManager::IsInitialised() && ThreadUtil::IsMainThread()) g_Profiler.Stop(); g_Profiler2.RecordRegionLeave(); - rec.rval().setUndefined(); + args.rval().setUndefined(); return true; } @@ -308,14 +308,14 @@ } } -bool Math_random(JSContext* cx, uint UNUSED(argc), JS::Value* vp) +bool Math_random(JSContext* cx, uint argc, JS::Value* vp) { - JS::CallReceiver rec = JS::CallReceiverFromVp(vp); + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); double r; if (!ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface->MathRandom(r)) return false; - rec.rval().setNumber(r); + args.rval().setNumber(r); return true; } @@ -1104,17 +1104,6 @@ return JS_IsExceptionPending(cx) ? true : false; } -const JSClass* ScriptInterface::GetClass(JS::HandleObject obj) -{ - return JS_GetClass(obj); -} - -void* ScriptInterface::GetPrivate(JS::HandleObject obj) -{ - // TODO: use JS_GetInstancePrivate - return JS_GetPrivate(obj); -} - JS::Value ScriptInterface::CloneValueFromOtherContext(const ScriptInterface& otherContext, JS::HandleValue val) const { PROFILE("CloneValueFromOtherContext");