Index: source/scriptinterface/FunctionWrapper.h =================================================================== --- source/scriptinterface/FunctionWrapper.h +++ source/scriptinterface/FunctionWrapper.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -234,10 +234,9 @@ if (!JS_ValueToObject(rq.cx, val, &obj) || !obj) return false; - // Check that the named function actually exists, to avoid ugly JS error reports - // when calling an undefined value - bool found; - if (!JS_HasProperty(rq.cx, obj, name, &found) || !found) + // Fetch the property explicitly - this avoids converting the arguments if it doesn't exist. + JS::RootedValue func(rq.cx); + if (!JS_GetProperty(rq.cx, obj, name, &func)) return false; JS::RootedValueVector argv(rq.cx); @@ -246,11 +245,11 @@ bool success; if constexpr (std::is_same_v) - success = JS_CallFunctionName(rq.cx, obj, name, argv, ret); + success = JS_CallFunctionValue(rq.cx, obj, func, argv, ret); else { JS::RootedValue jsRet(rq.cx); - success = JS_CallFunctionName(rq.cx, obj, name, argv, &jsRet); + success = JS_CallFunctionValue(rq.cx, obj, func, argv, &jsRet); if constexpr (!std::is_same_v) { if (success) Index: source/simulation2/scripting/MessageTypeConversions.cpp =================================================================== --- source/simulation2/scripting/MessageTypeConversions.cpp +++ source/simulation2/scripting/MessageTypeConversions.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -50,9 +50,8 @@ return NULL; \ } -JS::Value CMessage::ToJSValCached(const ScriptInterface& scriptInterface) const +JS::Value CMessage::ToJSValCached(const ScriptRequest& rq, const ScriptInterface& scriptInterface) const { - ScriptRequest rq(scriptInterface); if (!m_Cached) m_Cached.reset(new JS::PersistentRootedValue(rq.cx, ToJSVal(scriptInterface))); Index: source/simulation2/scripting/ScriptComponent.cpp =================================================================== --- source/simulation2/scripting/ScriptComponent.cpp +++ source/simulation2/scripting/ScriptComponent.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -52,7 +52,7 @@ const char* name = global ? msg.GetScriptGlobalHandlerName() : msg.GetScriptHandlerName(); - JS::RootedValue msgVal(rq.cx, msg.ToJSValCached(m_ScriptInterface)); + JS::RootedValue msgVal(rq.cx, msg.ToJSValCached(rq, m_ScriptInterface)); if (!ScriptFunction::CallVoid(rq, m_Instance, name, msgVal)) LOGERROR("Script message handler %s failed", name); Index: source/simulation2/system/Message.h =================================================================== --- source/simulation2/system/Message.h +++ source/simulation2/system/Message.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2020 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -20,6 +20,8 @@ #include "scriptinterface/ScriptTypes.h" +class ScriptRequest; + class CMessage { NONCOPYABLE(CMessage); @@ -31,7 +33,7 @@ virtual const char* GetScriptHandlerName() const = 0; virtual const char* GetScriptGlobalHandlerName() const = 0; virtual JS::Value ToJSVal(const ScriptInterface&) const = 0; - JS::Value ToJSValCached(const ScriptInterface&) const; + JS::Value ToJSValCached(const ScriptRequest& rq, const ScriptInterface&) const; private: mutable std::unique_ptr m_Cached; };