Index: source/lobby/IXmppClient.h =================================================================== --- source/lobby/IXmppClient.h +++ source/lobby/IXmppClient.h @@ -50,10 +50,11 @@ virtual const char* GetPresence(const std::string& nickname) = 0; virtual const char* GetRole(const std::string& nickname) = 0; virtual const std::wstring& GetSubject() = 0; - virtual void GUIGetPlayerList(const ScriptInterface& scriptInterface, JS::MutableHandleValue ret) = 0; - virtual void GUIGetGameList(const ScriptInterface& scriptInterface, JS::MutableHandleValue ret) = 0; - virtual void GUIGetBoardList(const ScriptInterface& scriptInterface, JS::MutableHandleValue ret) = 0; - virtual void GUIGetProfile(const ScriptInterface& scriptInterface, JS::MutableHandleValue ret) = 0; + + virtual JS::Value GUIGetPlayerList(const ScriptInterface& scriptInterface) = 0; + virtual JS::Value GUIGetGameList(const ScriptInterface& scriptInterface) = 0; + virtual JS::Value GUIGetBoardList(const ScriptInterface& scriptInterface) = 0; + virtual JS::Value GUIGetProfile(const ScriptInterface& scriptInterface) = 0; virtual JS::Value GuiPollNewMessage(const ScriptInterface& scriptInterface) = 0; virtual JS::Value GuiPollHistoricMessages(const ScriptInterface& scriptInterface) = 0; Index: source/lobby/XmppClient.h =================================================================== --- source/lobby/XmppClient.h +++ source/lobby/XmppClient.h @@ -92,10 +92,10 @@ const char* GetRole(const std::string& nickname); const std::wstring& GetSubject(); - void GUIGetPlayerList(const ScriptInterface& scriptInterface, JS::MutableHandleValue ret); - void GUIGetGameList(const ScriptInterface& scriptInterface, JS::MutableHandleValue ret); - void GUIGetBoardList(const ScriptInterface& scriptInterface, JS::MutableHandleValue ret); - void GUIGetProfile(const ScriptInterface& scriptInterface, JS::MutableHandleValue ret); + JS::Value GUIGetPlayerList(const ScriptInterface& scriptInterface); + JS::Value GUIGetGameList(const ScriptInterface& scriptInterface); + JS::Value GUIGetBoardList(const ScriptInterface& scriptInterface); + JS::Value GUIGetProfile(const ScriptInterface& scriptInterface); void SendStunEndpointToHost(const StunClient::StunEndpoint& stunEndpoint, const std::string& hostJID); @@ -179,18 +179,25 @@ PlayerMap m_PlayerMap; /// Whether or not the playermap has changed since the last time the GUI checked. bool m_PlayerMapUpdate; + + using GlooxwrapperTags = std::vector; + /// List of games - std::vector m_GameList; + GlooxwrapperTags m_GameList; /// List of rankings - std::vector m_BoardList; + GlooxwrapperTags m_BoardList; /// Profile data - std::vector m_Profile; + GlooxwrapperTags m_Profile; + /// ScriptInterface to root the values const ScriptInterface* m_ScriptInterface; + /// Queue of messages for the GUI std::deque > m_GuiMessageQueue; + /// Cache of all GUI messages received since the login std::vector > m_HistoricGuiMessages; + /// Current room subject/topic. std::wstring m_Subject; }; Index: source/lobby/XmppClient.cpp =================================================================== --- source/lobby/XmppClient.cpp +++ source/lobby/XmppClient.cpp @@ -535,12 +535,13 @@ * * @return A JS array containing all known players and their presences */ -void XmppClient::GUIGetPlayerList(const ScriptInterface& scriptInterface, JS::MutableHandleValue ret) +JS::Value XmppClient::GUIGetPlayerList(const ScriptInterface& scriptInterface) { JSContext* cx = scriptInterface.GetContext(); JSAutoRequest rq(cx); - ScriptInterface::CreateArray(cx, ret); + JS::RootedValue ret(cx); + ScriptInterface::CreateArray(cx, &ret); int j = 0; for (const std::pair& p : m_PlayerMap) @@ -557,6 +558,8 @@ scriptInterface.SetPropertyInt(ret, j++, player); } + + return ret; } /** @@ -564,28 +567,13 @@ * * @return A JS array containing all known games */ -void XmppClient::GUIGetGameList(const ScriptInterface& scriptInterface, JS::MutableHandleValue ret) +JS::Value XmppClient::GUIGetGameList(const ScriptInterface& scriptInterface) { JSContext* cx = scriptInterface.GetContext(); JSAutoRequest rq(cx); - - ScriptInterface::CreateArray(cx, ret); - int j = 0; - - const char* stats[] = { "name", "ip", "port", "stunIP", "stunPort", "hostUsername", "state", - "nbp", "maxnbp", "players", "mapName", "niceMapName", "mapSize", "mapType", - "victoryCondition", "startTime", "mods" }; - - for(const glooxwrapper::Tag* const& t : m_GameList) - { - JS::RootedValue game(cx); - ScriptInterface::CreateObject(cx, &game); - - for (size_t i = 0; i < ARRAY_SIZE(stats); ++i) - scriptInterface.SetProperty(game, stats[i], t->findAttribute(stats[i])); - - scriptInterface.SetPropertyInt(ret, j++, game); - } + JS::RootedValue ret(cx); + ScriptInterface::ToJSVal(cx, &ret, m_GameList); + return ret; } /** @@ -593,26 +581,13 @@ * * @return A JS array containing all known leaderboard data */ -void XmppClient::GUIGetBoardList(const ScriptInterface& scriptInterface, JS::MutableHandleValue ret) +JS::Value XmppClient::GUIGetBoardList(const ScriptInterface& scriptInterface) { JSContext* cx = scriptInterface.GetContext(); JSAutoRequest rq(cx); - - ScriptInterface::CreateArray(cx, ret); - int j = 0; - - const char* attributes[] = { "name", "rank", "rating" }; - - for(const glooxwrapper::Tag* const& t : m_BoardList) - { - JS::RootedValue board(cx); - ScriptInterface::CreateObject(cx, &board); - - for (size_t i = 0; i < ARRAY_SIZE(attributes); ++i) - scriptInterface.SetProperty(board, attributes[i], t->findAttribute(attributes[i])); - - scriptInterface.SetPropertyInt(ret, j++, board); - } + JS::RootedValue ret(cx); + ScriptInterface::ToJSVal(cx, &ret, m_BoardList); + return ret; } /** @@ -620,26 +595,13 @@ * * @return A JS array containing the specific user's profile data */ -void XmppClient::GUIGetProfile(const ScriptInterface& scriptInterface, JS::MutableHandleValue ret) +JS::Value XmppClient::GUIGetProfile(const ScriptInterface& scriptInterface) { JSContext* cx = scriptInterface.GetContext(); JSAutoRequest rq(cx); - - ScriptInterface::CreateArray(cx, ret); - int j = 0; - - const char* stats[] = { "player", "rating", "totalGamesPlayed", "highestRating", "wins", "losses", "rank" }; - - for (const glooxwrapper::Tag* const& t : m_Profile) - { - JS::RootedValue profile(cx); - ScriptInterface::CreateObject(cx, &profile); - - for (size_t i = 0; i < ARRAY_SIZE(stats); ++i) - scriptInterface.SetProperty(profile, stats[i], t->findAttribute(stats[i])); - - scriptInterface.SetPropertyInt(ret, j++, profile); - } + JS::RootedValue ret(cx); + ScriptInterface::ToJSVal(cx, &ret, m_Profile); + return ret; } /***************************************************** Index: source/lobby/glooxwrapper/glooxwrapper.h =================================================================== --- source/lobby/glooxwrapper/glooxwrapper.h +++ source/lobby/glooxwrapper/glooxwrapper.h @@ -591,6 +591,7 @@ bool addAttribute(const string& name, const string& value); string findAttribute(const string& name) const; + std::vector attributeNames() const; Tag* clone() const; string xmlns() const; bool setXmlns(const string& xmlns); Index: source/lobby/glooxwrapper/glooxwrapper.cpp =================================================================== --- source/lobby/glooxwrapper/glooxwrapper.cpp +++ source/lobby/glooxwrapper/glooxwrapper.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #if OS_WIN @@ -749,6 +750,16 @@ return m_Wrapped->findAttribute(name.to_string()); } +std::vector glooxwrapper::Tag::attributeNames() const +{ + const gloox::Tag::AttributeList& attributes = m_Wrapped->attributes(); + std::vector names; + names.reserve(attributes.size()); + for (gloox::Tag::Attribute* attribute : attributes) + names.push_back(attribute->name()); + return names; +} + glooxwrapper::Tag* glooxwrapper::Tag::clone() const { return new glooxwrapper::Tag(m_Wrapped->clone(), true); Index: source/lobby/scripting/GlooxScriptConversions.cpp =================================================================== --- source/lobby/scripting/GlooxScriptConversions.cpp +++ source/lobby/scripting/GlooxScriptConversions.cpp @@ -21,6 +21,7 @@ #if CONFIG2_LOBBY #include "lobby/XmppClient.h" +#include "scriptinterface/ScriptConversions.h" #include "scriptinterface/ScriptInterface.h" template<> void ScriptInterface::ToJSVal(JSContext* cx, JS::MutableHandleValue ret, const glooxwrapper::string& val) @@ -58,4 +59,24 @@ ToJSVal(cx, ret, wstring_from_utf8(XmppClient::CertificateErrorToString(val))); } +template<> void ScriptInterface::ToJSVal(JSContext* cx, JS::MutableHandleValue ret, const glooxwrapper::Tag* const& val) +{ + JSAutoRequest rq(cx); + JS::RootedObject obj(cx, JS_NewPlainObject(cx)); + if (!obj) + { + JS_ReportError(cx, "Failed to create glooxwrapper::Tag value"); + return; + } + for (const glooxwrapper::string& attributeName : val->attributeNames()) + { + JS::RootedValue stringVal(cx); + ToJSVal(cx, &stringVal, wstring_from_utf8(val->findAttribute(attributeName).to_string())); + JS_SetProperty(cx, obj, attributeName.c_str(), stringVal); + } + ret.set(JS::ObjectValue(*obj)); +} + +TOJSVAL_VECTOR(const glooxwrapper::Tag*) + #endif // CONFIG2_LOBBY Index: source/lobby/scripting/JSInterface_Lobby.cpp =================================================================== --- source/lobby/scripting/JSInterface_Lobby.cpp +++ source/lobby/scripting/JSInterface_Lobby.cpp @@ -187,13 +187,7 @@ if (!g_XmppClient) return JS::UndefinedValue(); - JSContext* cx = pCxPrivate->pScriptInterface->GetContext(); - JSAutoRequest rq(cx); - - JS::RootedValue playerList(cx); - g_XmppClient->GUIGetPlayerList(*(pCxPrivate->pScriptInterface), &playerList); - - return playerList; + return g_XmppClient->GUIGetPlayerList(*(pCxPrivate->pScriptInterface)); } JS::Value JSI_Lobby::GetGameList(ScriptInterface::CxPrivate* pCxPrivate) @@ -201,13 +195,7 @@ if (!g_XmppClient) return JS::UndefinedValue(); - JSContext* cx = pCxPrivate->pScriptInterface->GetContext(); - JSAutoRequest rq(cx); - - JS::RootedValue gameList(cx); - g_XmppClient->GUIGetGameList(*(pCxPrivate->pScriptInterface), &gameList); - - return gameList; + return g_XmppClient->GUIGetGameList(*(pCxPrivate->pScriptInterface)); } JS::Value JSI_Lobby::GetBoardList(ScriptInterface::CxPrivate* pCxPrivate) @@ -215,13 +203,7 @@ if (!g_XmppClient) return JS::UndefinedValue(); - JSContext* cx = pCxPrivate->pScriptInterface->GetContext(); - JSAutoRequest rq(cx); - - JS::RootedValue boardList(cx); - g_XmppClient->GUIGetBoardList(*(pCxPrivate->pScriptInterface), &boardList); - - return boardList; + return g_XmppClient->GUIGetBoardList(*(pCxPrivate->pScriptInterface)); } JS::Value JSI_Lobby::GetProfile(ScriptInterface::CxPrivate* pCxPrivate) @@ -229,13 +211,7 @@ if (!g_XmppClient) return JS::UndefinedValue(); - JSContext* cx = pCxPrivate->pScriptInterface->GetContext(); - JSAutoRequest rq(cx); - - JS::RootedValue profileFetch(cx); - g_XmppClient->GUIGetProfile(*(pCxPrivate->pScriptInterface), &profileFetch); - - return profileFetch; + return g_XmppClient->GUIGetProfile(*(pCxPrivate->pScriptInterface)); } bool JSI_Lobby::LobbyGuiPollHasPlayerListUpdate(ScriptInterface::CxPrivate* UNUSED(pCxPrivate)) Index: source/scriptinterface/ScriptConversions.h =================================================================== --- source/scriptinterface/ScriptConversions.h +++ source/scriptinterface/ScriptConversions.h @@ -77,16 +77,20 @@ #undef FAIL -#define JSVAL_VECTOR(T) \ +#define TOJSVAL_VECTOR(T) \ template<> void ScriptInterface::ToJSVal >(JSContext* cx, JS::MutableHandleValue ret, const std::vector& val) \ { \ ToJSVal_vector(cx, ret, val); \ -} \ +} + +#define FROMJSVAL_VECTOR(T) \ template<> bool ScriptInterface::FromJSVal >(JSContext* cx, JS::HandleValue v, std::vector& out) \ { \ return FromJSVal_vector(cx, v, out); \ } +#define JSVAL_VECTOR(T) TOJSVAL_VECTOR(T) FROMJSVAL_VECTOR(T) + template bool ScriptInterface::FromJSProperty(JSContext* cx, const JS::HandleValue val, const char* name, T& ret) { if (!val.isObject())