From fd8f5abd2ec2ad276393d0a0cecf3ac0b72d1e37 Mon Sep 17 00:00:00 2001 From: wraitii Date: Wed, 18 Nov 2020 14:39:04 +0000 Subject: [PATCH] [SM52 2/2] Update to Spidermonkey 52 APIs. No particularly noteworthy changes, as most complex API changes were already supported in SM45 and done. The addition of JSStructuredCloneData allows to remove our custom class. Changes: - InformalValueTypeName is back in the API, so remove our implementation. - Stop using JSRuntime entirely in favour of JSContext* - JSPropertyDescriptor is renamed. - CompartmentOptions are tweaked slightly (no functional changes) - JS::Construct - API update. - JSClass split - API update. - A js.msg error message was removed, so we had to use a different one. - Tests fix: fix comparison of union instances - Disable warning in spidermonkey Vector.h - Update error reporting to SM52 (minor API updates) - Ignore warnings about unused return values (would come from OOM, which isn't recoverable) Most of the patching was done by Itms. Tested by: Stan, Freagarach Fixes #4893 Differential Revision: https://code.wildfiregames.com/D3095 This was SVN commit r24203. --- source/graphics/MapGenerator.cpp | 8 +-- source/graphics/MapGenerator.h | 6 +- source/graphics/MapReader.cpp | 11 +-- source/graphics/MapReader.h | 6 +- source/gui/GUIManager.cpp | 18 ++--- source/gui/GUIManager.h | 12 ++-- source/gui/ObjectBases/IGUIObject.cpp | 8 +-- .../gui/Scripting/JSInterface_GUIManager.cpp | 4 +- source/gui/Scripting/JSInterface_GUISize.cpp | 7 +- source/gui/Scripting/JSInterface_GUISize.h | 3 +- .../gui/Scripting/JSInterface_IGUIObject.cpp | 7 +- source/gui/Scripting/JSInterface_IGUIObject.h | 3 +- source/gui/tests/test_GuiManager.h | 2 +- source/lobby/XmppClient.cpp | 8 +-- source/network/NetClient.cpp | 6 +- source/network/NetMessageSim.cpp | 12 ++-- source/network/NetServer.cpp | 2 +- .../network/scripting/JSInterface_Network.cpp | 2 +- source/ps/Game.cpp | 4 +- source/ps/Mod.cpp | 1 - source/ps/ProfileViewer.cpp | 4 +- source/ps/SavedGame.cpp | 6 +- source/ps/SavedGame.h | 6 +- source/ps/World.cpp | 10 +-- source/ps/World.h | 6 +- source/ps/scripting/JSInterface_Game.cpp | 2 +- source/ps/scripting/JSInterface_SavedGame.cpp | 6 +- source/ps/scripting/JSInterface_VFS.cpp | 2 +- source/scriptinterface/NativeWrapperDefns.h | 8 +-- source/scriptinterface/ScriptContext.cpp | 65 ++++++++--------- source/scriptinterface/ScriptContext.h | 11 +-- source/scriptinterface/ScriptConversions.cpp | 23 +------ source/scriptinterface/ScriptExceptions.cpp | 52 +------------- source/scriptinterface/ScriptExceptions.h | 2 - source/scriptinterface/ScriptInterface.cpp | 69 ++++++++----------- source/scriptinterface/ScriptInterface.h | 39 +++++------ source/scriptinterface/ScriptStats.cpp | 10 +-- source/scriptinterface/ScriptTypes.h | 2 + .../tests/test_ScriptInterface.h | 14 ++-- source/simulation2/Simulation2.cpp | 20 +++--- source/simulation2/Simulation2.h | 2 +- .../simulation2/components/CCmpAIManager.cpp | 33 ++++----- .../simulation2/components/ICmpAIManager.cpp | 2 +- .../components/tests/test_Pathfinder.h | 9 +-- .../scripting/EngineScriptConversions.cpp | 10 ++- .../scripting/JSInterface_Simulation.cpp | 7 +- .../scripting/MessageTypeConversions.cpp | 4 +- .../simulation2/scripting/ScriptComponent.cpp | 2 +- .../serialization/BinarySerializer.cpp | 2 +- .../serialization/StdDeserializer.cpp | 4 +- .../simulation2/system/ComponentManager.cpp | 6 +- source/simulation2/system/ComponentManager.h | 2 +- source/simulation2/system/TurnManager.cpp | 2 +- source/simulation2/tests/test_Serializer.h | 3 +- 54 files changed, 251 insertions(+), 324 deletions(-) diff --git a/source/graphics/MapGenerator.cpp b/source/graphics/MapGenerator.cpp index 9c6b1e7ad0..82400cb55e 100644 --- a/source/graphics/MapGenerator.cpp +++ b/source/graphics/MapGenerator.cpp @@ -92,7 +92,7 @@ void* CMapGeneratorWorker::RunThread(CMapGeneratorWorker* self) shared_ptr mapgenContext = ScriptContext::CreateContext(RMS_CONTEXT_SIZE); // Enable the script to be aborted - JS_SetInterruptCallback(mapgenContext->GetJSRuntime(), MapGeneratorInterruptCallback); + JS_AddInterruptCallback(mapgenContext->GetGeneralJSContext(), MapGeneratorInterruptCallback); self->m_ScriptInterface = new ScriptInterface("Engine", "MapGenerator", mapgenContext); @@ -214,7 +214,7 @@ double CMapGeneratorWorker::GetMicroseconds(ScriptInterface::CmptPrivate* UNUSED return JS_Now(); } -shared_ptr CMapGeneratorWorker::GetResults() +ScriptInterface::StructuredClone CMapGeneratorWorker::GetResults() { std::lock_guard lock(m_WorkerMutex); return m_MapData; @@ -232,7 +232,7 @@ void CMapGeneratorWorker::ExportMap(ScriptInterface::CmptPrivate* pCmptPrivate, // Copy results std::lock_guard lock(self->m_WorkerMutex); - self->m_MapData = self->m_ScriptInterface->WriteStructuredClone(data); + self->m_MapData = self->m_ScriptInterface->WriteStructuredClone(data, false); self->m_Progress = 0; } @@ -427,7 +427,7 @@ int CMapGenerator::GetProgress() return m_Worker->GetProgress(); } -shared_ptr CMapGenerator::GetResults() +ScriptInterface::StructuredClone CMapGenerator::GetResults() { return m_Worker->GetResults(); } diff --git a/source/graphics/MapGenerator.h b/source/graphics/MapGenerator.h index d398f2810b..353f9ef1a9 100644 --- a/source/graphics/MapGenerator.h +++ b/source/graphics/MapGenerator.h @@ -67,7 +67,7 @@ public: * * @return StructuredClone containing map data */ - shared_ptr GetResults(); + ScriptInterface::StructuredClone GetResults(); private: CMapGeneratorWorker* m_Worker; @@ -110,7 +110,7 @@ public: * * @return StructuredClone containing map data */ - shared_ptr GetResults(); + ScriptInterface::StructuredClone GetResults(); /** * Set initial seed, callback data. @@ -201,7 +201,7 @@ private: /** * Result of the mapscript generation including terrain, entities and environment settings. */ - shared_ptr m_MapData; + ScriptInterface::StructuredClone m_MapData; /** * Deterministic random number generator. diff --git a/source/graphics/MapReader.cpp b/source/graphics/MapReader.cpp index f616bd3a0d..65d7f5921f 100644 --- a/source/graphics/MapReader.cpp +++ b/source/graphics/MapReader.cpp @@ -39,6 +39,7 @@ #include "renderer/PostprocManager.h" #include "renderer/SkyManager.h" #include "renderer/WaterManager.h" +#include "scriptinterface/ScriptContext.h" #include "simulation2/Simulation2.h" #include "simulation2/components/ICmpCinemaManager.h" #include "simulation2/components/ICmpGarrisonHolder.h" @@ -62,7 +63,7 @@ CMapReader::CMapReader() } // LoadMap: try to load the map from given file; reinitialise the scene to new data if successful -void CMapReader::LoadMap(const VfsPath& pathname, JSRuntime* rt, JS::HandleValue settings, CTerrain *pTerrain_, +void CMapReader::LoadMap(const VfsPath& pathname, const ScriptContext& cx, JS::HandleValue settings, CTerrain *pTerrain_, WaterManager* pWaterMan_, SkyManager* pSkyMan_, CLightEnv *pLightEnv_, CGameView *pGameView_, CCinemaManager* pCinema_, CTriggerManager* pTrigMan_, CPostprocManager* pPostproc_, CSimulation2 *pSimulation2_, const CSimContext* pSimContext_, int playerID_, bool skipEntities) @@ -80,7 +81,7 @@ void CMapReader::LoadMap(const VfsPath& pathname, JSRuntime* rt, JS::HandleValu m_PlayerID = playerID_; m_SkipEntities = skipEntities; m_StartingCameraTarget = INVALID_ENTITY; - m_ScriptSettings.init(rt, settings); + m_ScriptSettings.init(cx.GetGeneralJSContext(), settings); filename_xml = pathname.ChangeExtension(L".xml"); @@ -144,7 +145,7 @@ void CMapReader::LoadMap(const VfsPath& pathname, JSRuntime* rt, JS::HandleValu } // LoadRandomMap: try to load the map data; reinitialise the scene to new data if successful -void CMapReader::LoadRandomMap(const CStrW& scriptFile, JSRuntime* rt, JS::HandleValue settings, CTerrain *pTerrain_, +void CMapReader::LoadRandomMap(const CStrW& scriptFile, const ScriptContext& cx, JS::HandleValue settings, CTerrain *pTerrain_, WaterManager* pWaterMan_, SkyManager* pSkyMan_, CLightEnv *pLightEnv_, CGameView *pGameView_, CCinemaManager* pCinema_, CTriggerManager* pTrigMan_, CPostprocManager* pPostproc_, CSimulation2 *pSimulation2_, int playerID_) @@ -152,7 +153,7 @@ void CMapReader::LoadRandomMap(const CStrW& scriptFile, JSRuntime* rt, JS::Handl m_ScriptFile = scriptFile; pSimulation2 = pSimulation2_; pSimContext = pSimulation2 ? &pSimulation2->GetSimContext() : NULL; - m_ScriptSettings.init(rt, settings); + m_ScriptSettings.init(cx.GetGeneralJSContext(), settings); pTerrain = pTerrain_; pLightEnv = pLightEnv_; pGameView = pGameView_; @@ -1295,7 +1296,7 @@ int CMapReader::GenerateMap() else if (progress == 0) { // Finished, get results as StructuredClone object, which must be read to obtain the JS::Value - shared_ptr results = m_MapGen->GetResults(); + ScriptInterface::StructuredClone results = m_MapGen->GetResults(); // Parse data into simulation context JS::RootedValue data(rq.cx); diff --git a/source/graphics/MapReader.h b/source/graphics/MapReader.h index 8c9f824b53..744c1da839 100644 --- a/source/graphics/MapReader.h +++ b/source/graphics/MapReader.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2017 Wildfire Games. +/* Copyright (C) 2020 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -52,11 +52,11 @@ public: ~CMapReader(); // LoadMap: try to load the map from given file; reinitialise the scene to new data if successful - void LoadMap(const VfsPath& pathname, JSRuntime* rt, JS::HandleValue settings, CTerrain*, WaterManager*, SkyManager*, CLightEnv*, CGameView*, + void LoadMap(const VfsPath& pathname, const ScriptContext& cx, JS::HandleValue settings, CTerrain*, WaterManager*, SkyManager*, CLightEnv*, CGameView*, CCinemaManager*, CTriggerManager*, CPostprocManager* pPostproc, CSimulation2*, const CSimContext*, int playerID, bool skipEntities); - void LoadRandomMap(const CStrW& scriptFile, JSRuntime* rt, JS::HandleValue settings, CTerrain*, WaterManager*, SkyManager*, CLightEnv*, CGameView*, CCinemaManager*, CTriggerManager*, CPostprocManager* pPostproc_, CSimulation2*, int playerID); + void LoadRandomMap(const CStrW& scriptFile, const ScriptContext& cx, JS::HandleValue settings, CTerrain*, WaterManager*, SkyManager*, CLightEnv*, CGameView*, CCinemaManager*, CTriggerManager*, CPostprocManager* pPostproc_, CSimulation2*, int playerID); private: // Load script settings for use by scripts diff --git a/source/gui/GUIManager.cpp b/source/gui/GUIManager.cpp index e36d314d36..81b76dceed 100644 --- a/source/gui/GUIManager.cpp +++ b/source/gui/GUIManager.cpp @@ -88,16 +88,16 @@ void CGUIManager::SwitchPage(const CStrW& pageName, ScriptInterface* srcScriptIn // The page stack is cleared (including the script context where initData came from), // therefore we have to clone initData. - shared_ptr initDataClone; + ScriptInterface::StructuredClone initDataClone; if (!initData.isUndefined()) - initDataClone = srcScriptInterface->WriteStructuredClone(initData); + initDataClone = srcScriptInterface->WriteStructuredClone(initData, true); m_PageStack.clear(); PushPage(pageName, initDataClone, JS::UndefinedHandleValue); } -void CGUIManager::PushPage(const CStrW& pageName, shared_ptr initData, JS::HandleValue callbackFunction) +void CGUIManager::PushPage(const CStrW& pageName, ScriptInterface::StructuredClone initData, JS::HandleValue callbackFunction) { // Store the callback handler in the current GUI page before opening the new one if (!m_PageStack.empty() && !callbackFunction.isUndefined()) @@ -109,7 +109,7 @@ void CGUIManager::PushPage(const CStrW& pageName, shared_ptr args) +void CGUIManager::PopPage(ScriptInterface::StructuredClone args) { if (m_PageStack.size() < 2) { @@ -121,7 +121,7 @@ void CGUIManager::PopPage(shared_ptr args) m_PageStack.back().PerformCallbackFunction(args); } -CGUIManager::SGUIPage::SGUIPage(const CStrW& pageName, const shared_ptr initData) +CGUIManager::SGUIPage::SGUIPage(const CStrW& pageName, const ScriptInterface::StructuredClone initData) : name(pageName), initData(initData), inputs(), gui(), callbackFunction() { } @@ -129,7 +129,7 @@ CGUIManager::SGUIPage::SGUIPage(const CStrW& pageName, const shared_ptr scriptContext) { // If we're hotloading then try to grab some data from the previous page - shared_ptr hotloadData; + ScriptInterface::StructuredClone hotloadData; if (gui) { shared_ptr scriptInterface = gui->GetScriptInterface(); @@ -138,7 +138,7 @@ void CGUIManager::SGUIPage::LoadPage(shared_ptr scriptContext) JS::RootedValue global(rq.cx, rq.globalValue()); JS::RootedValue hotloadDataVal(rq.cx); scriptInterface->CallFunction(global, "getHotloadData", &hotloadDataVal); - hotloadData = scriptInterface->WriteStructuredClone(hotloadDataVal); + hotloadData = scriptInterface->WriteStructuredClone(hotloadDataVal, true); } g_CursorName = g_DefaultCursor; @@ -232,10 +232,10 @@ void CGUIManager::SGUIPage::SetCallbackFunction(ScriptInterface& scriptInterface return; } - callbackFunction = std::make_shared(scriptInterface.GetJSRuntime(), callbackFunc); + callbackFunction = std::make_shared(scriptInterface.GetGeneralJSContext(), callbackFunc); } -void CGUIManager::SGUIPage::PerformCallbackFunction(shared_ptr args) +void CGUIManager::SGUIPage::PerformCallbackFunction(ScriptInterface::StructuredClone args) { if (!callbackFunction) return; diff --git a/source/gui/GUIManager.h b/source/gui/GUIManager.h index 20e9e54efd..b226f23506 100644 --- a/source/gui/GUIManager.h +++ b/source/gui/GUIManager.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2019 Wildfire Games. +/* Copyright (C) 2020 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -69,13 +69,13 @@ public: * user inputs. * If given, the callbackHandler function will be executed once this page is closed. */ - void PushPage(const CStrW& pageName, shared_ptr initData, JS::HandleValue callbackFunc); + void PushPage(const CStrW& pageName, ScriptInterface::StructuredClone initData, JS::HandleValue callbackFunc); /** * Unload the currently active GUI page, and make the previous page active. * (There must be at least two pages when you call this.) */ - void PopPage(shared_ptr args); + void PopPage(ScriptInterface::StructuredClone args); /** * Called when a file has been modified, to hotload changes. @@ -132,7 +132,7 @@ private: /** * Initializes the data that will be used to create the CGUI page one or multiple times (hotloading). */ - SGUIPage(const CStrW& pageName, const shared_ptr initData); + SGUIPage(const CStrW& pageName, const ScriptInterface::StructuredClone initData); /** * Create the CGUI with it's own ScriptInterface. Deletes the previous CGUI if it existed. @@ -147,11 +147,11 @@ private: /** * Execute the stored callback function with the given arguments. */ - void PerformCallbackFunction(shared_ptr args); + void PerformCallbackFunction(ScriptInterface::StructuredClone args); CStrW name; std::unordered_set inputs; // for hotloading - shared_ptr initData; // data to be passed to the init() function + ScriptInterface::StructuredClone initData; // data to be passed to the init() function shared_ptr gui; // the actual GUI page /** diff --git a/source/gui/ObjectBases/IGUIObject.cpp b/source/gui/ObjectBases/IGUIObject.cpp index 21c6d8269a..b6e9455918 100644 --- a/source/gui/ObjectBases/IGUIObject.cpp +++ b/source/gui/ObjectBases/IGUIObject.cpp @@ -76,7 +76,7 @@ IGUIObject::~IGUIObject() delete p.second; if (!m_ScriptHandlers.empty()) - JS_RemoveExtraGCRootsTracer(m_pGUI.GetScriptInterface()->GetJSRuntime(), Trace, this); + JS_RemoveExtraGCRootsTracer(m_pGUI.GetScriptInterface()->GetGeneralJSContext(), Trace, this); // m_Children is deleted along all other GUI Objects in the CGUI destructor } @@ -332,7 +332,7 @@ void IGUIObject::RegisterScriptHandler(const CStr& eventName, const CStr& Code, void IGUIObject::SetScriptHandler(const CStr& eventName, JS::HandleObject Function) { if (m_ScriptHandlers.empty()) - JS_AddExtraGCRootsTracer(m_pGUI.GetScriptInterface()->GetJSRuntime(), Trace, this); + JS_AddExtraGCRootsTracer(m_pGUI.GetScriptInterface()->GetGeneralJSContext(), Trace, this); m_ScriptHandlers[eventName] = JS::Heap(Function); @@ -353,7 +353,7 @@ void IGUIObject::UnsetScriptHandler(const CStr& eventName) m_ScriptHandlers.erase(it); if (m_ScriptHandlers.empty()) - JS_RemoveExtraGCRootsTracer(m_pGUI.GetScriptInterface()->GetJSRuntime(), Trace, this); + JS_RemoveExtraGCRootsTracer(m_pGUI.GetScriptInterface()->GetGeneralJSContext(), Trace, this); { auto it = m_pGUI.m_EventIGUIObjects.find(eventName); if (it != m_pGUI.m_EventIGUIObjects.end()) @@ -402,7 +402,7 @@ InReaction IGUIObject::SendMouseEvent(EGUIMessageType type, const CStr& eventNam "y", mousePos.y, "buttons", m_pGUI.GetMouseButtons()); JS::AutoValueVector paramData(rq.cx); - paramData.append(mouse); + (void)paramData.append(mouse); ScriptEvent(eventName, paramData); return msg.skipped ? IN_PASS : IN_HANDLED; diff --git a/source/gui/Scripting/JSInterface_GUIManager.cpp b/source/gui/Scripting/JSInterface_GUIManager.cpp index 6055461a16..380b2d96e3 100644 --- a/source/gui/Scripting/JSInterface_GUIManager.cpp +++ b/source/gui/Scripting/JSInterface_GUIManager.cpp @@ -29,7 +29,7 @@ // Functions aren't supported for example! void JSI_GUIManager::PushGuiPage(ScriptInterface::CmptPrivate* pCmptPrivate, const std::wstring& name, JS::HandleValue initData, JS::HandleValue callbackFunction) { - g_GUI->PushPage(name, pCmptPrivate->pScriptInterface->WriteStructuredClone(initData), callbackFunction); + g_GUI->PushPage(name, pCmptPrivate->pScriptInterface->WriteStructuredClone(initData, true), callbackFunction); } void JSI_GUIManager::SwitchGuiPage(ScriptInterface::CmptPrivate* pCmptPrivate, const std::wstring& name, JS::HandleValue initData) @@ -46,7 +46,7 @@ void JSI_GUIManager::PopGuiPage(ScriptInterface::CmptPrivate* pCmptPrivate, JS:: return; } - g_GUI->PopPage(pCmptPrivate->pScriptInterface->WriteStructuredClone(args)); + g_GUI->PopPage(pCmptPrivate->pScriptInterface->WriteStructuredClone(args, true)); } JS::Value JSI_GUIManager::GetGUIObjectByName(ScriptInterface::CmptPrivate* pCmptPrivate, const std::string& name) diff --git a/source/gui/Scripting/JSInterface_GUISize.cpp b/source/gui/Scripting/JSInterface_GUISize.cpp index 16c7291bcb..04212da81b 100644 --- a/source/gui/Scripting/JSInterface_GUISize.cpp +++ b/source/gui/Scripting/JSInterface_GUISize.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2019 Wildfire Games. +/* Copyright (C) 2020 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -23,7 +23,10 @@ #include "scriptinterface/ScriptInterface.h" JSClass JSI_GUISize::JSI_class = { - "GUISize", 0, + "GUISize", 0, &JSI_GUISize::JSI_classops +}; + +JSClassOps JSI_GUISize::JSI_classops = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, diff --git a/source/gui/Scripting/JSInterface_GUISize.h b/source/gui/Scripting/JSInterface_GUISize.h index bcf87e4f43..53050a863b 100644 --- a/source/gui/Scripting/JSInterface_GUISize.h +++ b/source/gui/Scripting/JSInterface_GUISize.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2019 Wildfire Games. +/* Copyright (C) 2020 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -24,6 +24,7 @@ namespace JSI_GUISize { extern JSClass JSI_class; + extern JSClassOps JSI_classops; extern JSPropertySpec JSI_props[]; extern JSFunctionSpec JSI_methods[]; diff --git a/source/gui/Scripting/JSInterface_IGUIObject.cpp b/source/gui/Scripting/JSInterface_IGUIObject.cpp index 2fdae17ba9..0b2062c702 100644 --- a/source/gui/Scripting/JSInterface_IGUIObject.cpp +++ b/source/gui/Scripting/JSInterface_IGUIObject.cpp @@ -27,7 +27,10 @@ #include "scriptinterface/ScriptInterface.h" JSClass JSI_IGUIObject::JSI_class = { - "GUIObject", JSCLASS_HAS_PRIVATE, + "GUIObject", JSCLASS_HAS_PRIVATE, &JSI_IGUIObject::JSI_classops +}; + +JSClassOps JSI_IGUIObject::JSI_classops = { nullptr, JSI_IGUIObject::deleteProperty, JSI_IGUIObject::getProperty, @@ -172,7 +175,7 @@ bool JSI_IGUIObject::setProperty(JSContext* cx, JS::HandleObject obj, JS::Handle } if (e->SettingExists(propName)) - return e->m_Settings[propName]->FromJSVal(rq, vp, true) ? result.succeed() : result.fail(JSMSG_TYPE_ERR_BAD_ARGS); + return e->m_Settings[propName]->FromJSVal(rq, vp, true) ? result.succeed() : result.fail(JSMSG_USER_DEFINED_ERROR); LOGERROR("Property '%s' does not exist!", propName.c_str()); return result.fail(JSMSG_UNDEFINED_PROP); diff --git a/source/gui/Scripting/JSInterface_IGUIObject.h b/source/gui/Scripting/JSInterface_IGUIObject.h index a90f827701..4a13e69aea 100644 --- a/source/gui/Scripting/JSInterface_IGUIObject.h +++ b/source/gui/Scripting/JSInterface_IGUIObject.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2019 Wildfire Games. +/* Copyright (C) 2020 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -23,6 +23,7 @@ namespace JSI_IGUIObject { extern JSClass JSI_class; + extern JSClassOps JSI_classops; extern JSFunctionSpec JSI_methods[]; void RegisterScriptClass(ScriptInterface& scriptInterface); diff --git a/source/gui/tests/test_GuiManager.h b/source/gui/tests/test_GuiManager.h index bfef132bf1..2957f6f575 100755 --- a/source/gui/tests/test_GuiManager.h +++ b/source/gui/tests/test_GuiManager.h @@ -66,7 +66,7 @@ public: JS::RootedValue val(rq.cx); scriptInterface.CreateObject(rq, &val); - std::shared_ptr data = scriptInterface.WriteStructuredClone(JS::NullHandleValue); + ScriptInterface::StructuredClone data = scriptInterface.WriteStructuredClone(JS::NullHandleValue, true); g_GUI->PushPage(L"hotkey/page_hotkey.xml", data, JS::UndefinedHandleValue); // Press 'a'. diff --git a/source/lobby/XmppClient.cpp b/source/lobby/XmppClient.cpp index 7da3de41c6..98bf494933 100644 --- a/source/lobby/XmppClient.cpp +++ b/source/lobby/XmppClient.cpp @@ -94,7 +94,7 @@ XmppClient::XmppClient(const ScriptInterface* scriptInterface, const std::string m_PlayerMapUpdate(false) { if (m_ScriptInterface) - JS_AddExtraGCRootsTracer(m_ScriptInterface->GetJSRuntime(), XmppClient::Trace, this); + JS_AddExtraGCRootsTracer(m_ScriptInterface->GetGeneralJSContext(), XmppClient::Trace, this); // Read lobby configuration from default.cfg std::string sXpartamupp; @@ -192,7 +192,7 @@ XmppClient::~XmppClient() glooxwrapper::Tag::free(t); if (m_ScriptInterface) - JS_RemoveExtraGCRootsTracer(m_ScriptInterface->GetJSRuntime(), XmppClient::Trace, this); + JS_RemoveExtraGCRootsTracer(m_ScriptInterface->GetGeneralJSContext(), XmppClient::Trace, this); } void XmppClient::TraceMember(JSTracer* trc) @@ -736,7 +736,7 @@ JS::Value XmppClient::GuiPollNewMessages(const ScriptInterface& scriptInterface) m_GuiMessageQueue.clear(); // Copy the messages over to the caller script interface. - return scriptInterface.CloneValueFromOtherCompartment(*m_ScriptInterface, messages); + return scriptInterface.CloneValueFromOtherCompartment(*m_ScriptInterface, messages, false); } JS::Value XmppClient::GuiPollHistoricMessages(const ScriptInterface& scriptInterface) @@ -754,7 +754,7 @@ JS::Value XmppClient::GuiPollHistoricMessages(const ScriptInterface& scriptInter m_ScriptInterface->SetPropertyInt(messages, j++, message); // Copy the messages over to the caller script interface. - return scriptInterface.CloneValueFromOtherCompartment(*m_ScriptInterface, messages); + return scriptInterface.CloneValueFromOtherCompartment(*m_ScriptInterface, messages, false); } /** diff --git a/source/network/NetClient.cpp b/source/network/NetClient.cpp index 5f06bf2145..124b390d0d 100644 --- a/source/network/NetClient.cpp +++ b/source/network/NetClient.cpp @@ -71,7 +71,7 @@ CNetClient::CNetClient(CGame* game, bool isLocalClient) : m_Session(NULL), m_UserName(L"anonymous"), m_HostID((u32)-1), m_ClientTurnManager(NULL), m_Game(game), - m_GameAttributes(game->GetSimulation2()->GetScriptInterface().GetJSRuntime()), + m_GameAttributes(game->GetSimulation2()->GetScriptInterface().GetGeneralJSContext()), m_IsLocalClient(isLocalClient), m_LastConnectionCheck(0), m_Rejoin(false) @@ -80,7 +80,7 @@ CNetClient::CNetClient(CGame* game, bool isLocalClient) : void* context = this; - JS_AddExtraGCRootsTracer(GetScriptInterface().GetJSRuntime(), CNetClient::Trace, this); + JS_AddExtraGCRootsTracer(GetScriptInterface().GetGeneralJSContext(), CNetClient::Trace, this); // Set up transitions for session AddTransition(NCS_UNCONNECTED, (uint)NMT_CONNECT_COMPLETE, NCS_CONNECT, (void*)&OnConnect, context); @@ -144,7 +144,7 @@ CNetClient::CNetClient(CGame* game, bool isLocalClient) : CNetClient::~CNetClient() { DestroyConnection(); - JS_RemoveExtraGCRootsTracer(GetScriptInterface().GetJSRuntime(), CNetClient::Trace, this); + JS_RemoveExtraGCRootsTracer(GetScriptInterface().GetGeneralJSContext(), CNetClient::Trace, this); } void CNetClient::TraceMember(JSTracer *trc) diff --git a/source/network/NetMessageSim.cpp b/source/network/NetMessageSim.cpp index 9ea45678c1..0876a4e179 100644 --- a/source/network/NetMessageSim.cpp +++ b/source/network/NetMessageSim.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2017 Wildfire Games. +/* Copyright (C) 2020 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -110,18 +110,18 @@ public: }; CSimulationMessage::CSimulationMessage(const ScriptInterface& scriptInterface) : - CNetMessage(NMT_SIMULATION_COMMAND), m_ScriptInterface(scriptInterface), m_Data(scriptInterface.GetJSRuntime()) + CNetMessage(NMT_SIMULATION_COMMAND), m_ScriptInterface(scriptInterface), m_Data(scriptInterface.GetGeneralJSContext()) { } CSimulationMessage::CSimulationMessage(const ScriptInterface& scriptInterface, u32 client, i32 player, u32 turn, JS::HandleValue data) : CNetMessage(NMT_SIMULATION_COMMAND), m_ScriptInterface(scriptInterface), - m_Client(client), m_Player(player), m_Turn(turn), m_Data(scriptInterface.GetJSRuntime(), data) + m_Client(client), m_Player(player), m_Turn(turn), m_Data(scriptInterface.GetGeneralJSContext(), data) { } CSimulationMessage::CSimulationMessage(const CSimulationMessage& orig) : - m_Data(orig.m_ScriptInterface.GetJSRuntime()), + m_Data(orig.m_ScriptInterface.GetGeneralJSContext()), m_Client(orig.m_Client), m_Player(orig.m_Player), m_ScriptInterface(orig.m_ScriptInterface), @@ -185,13 +185,13 @@ CStr CSimulationMessage::ToString() const CGameSetupMessage::CGameSetupMessage(const ScriptInterface& scriptInterface) : - CNetMessage(NMT_GAME_SETUP), m_ScriptInterface(scriptInterface), m_Data(scriptInterface.GetJSRuntime()) + CNetMessage(NMT_GAME_SETUP), m_ScriptInterface(scriptInterface), m_Data(scriptInterface.GetGeneralJSContext()) { } CGameSetupMessage::CGameSetupMessage(const ScriptInterface& scriptInterface, JS::HandleValue data) : CNetMessage(NMT_GAME_SETUP), m_ScriptInterface(scriptInterface), - m_Data(scriptInterface.GetJSRuntime(), data) + m_Data(scriptInterface.GetGeneralJSContext(), data) { } diff --git a/source/network/NetServer.cpp b/source/network/NetServer.cpp index a1abe071d7..8198a748aa 100644 --- a/source/network/NetServer.cpp +++ b/source/network/NetServer.cpp @@ -389,7 +389,7 @@ void CNetServerWorker::Run() // We create a new ScriptContext for this network thread, with a single ScriptInterface. shared_ptr netServerContext = ScriptContext::CreateContext(); m_ScriptInterface = new ScriptInterface("Engine", "Net server", netServerContext); - m_GameAttributes.init(m_ScriptInterface->GetJSRuntime(), JS::UndefinedValue()); + m_GameAttributes.init(m_ScriptInterface->GetGeneralJSContext(), JS::UndefinedValue()); while (true) { diff --git a/source/network/scripting/JSInterface_Network.cpp b/source/network/scripting/JSInterface_Network.cpp index 7de7b1266c..cc198f2724 100644 --- a/source/network/scripting/JSInterface_Network.cpp +++ b/source/network/scripting/JSInterface_Network.cpp @@ -163,7 +163,7 @@ JS::Value JSI_Network::PollNetworkClient(ScriptInterface::CmptPrivate* pCmptPriv ScriptRequest rqNet(g_NetClient->GetScriptInterface()); JS::RootedValue pollNet(rqNet.cx); g_NetClient->GuiPoll(&pollNet); - return pCmptPrivate->pScriptInterface->CloneValueFromOtherCompartment(g_NetClient->GetScriptInterface(), pollNet); + return pCmptPrivate->pScriptInterface->CloneValueFromOtherCompartment(g_NetClient->GetScriptInterface(), pollNet, false); } void JSI_Network::SetNetworkGameAttributes(ScriptInterface::CmptPrivate* pCmptPrivate, JS::HandleValue attribs1) diff --git a/source/ps/Game.cpp b/source/ps/Game.cpp index 295663874a..c2f7afffa9 100644 --- a/source/ps/Game.cpp +++ b/source/ps/Game.cpp @@ -243,7 +243,7 @@ void CGame::RegisterInit(const JS::HandleValue attribs, const std::string& saved scriptInterface.GetProperty(attribs, "script", scriptFile); scriptInterface.GetProperty(attribs, "settings", &settings); - m_World->RegisterInitRMS(scriptFile, scriptInterface.GetJSRuntime(), settings, m_PlayerID); + m_World->RegisterInitRMS(scriptFile, *scriptInterface.GetContext(), settings, m_PlayerID); } else { @@ -252,7 +252,7 @@ void CGame::RegisterInit(const JS::HandleValue attribs, const std::string& saved scriptInterface.GetProperty(attribs, "map", mapFile); scriptInterface.GetProperty(attribs, "settings", &settings); - m_World->RegisterInit(mapFile, scriptInterface.GetJSRuntime(), settings, m_PlayerID); + m_World->RegisterInit(mapFile, *scriptInterface.GetContext(), settings, m_PlayerID); } if (m_GameView) RegMemFun(g_Renderer.GetSingletonPtr()->GetWaterManager(), &WaterManager::LoadWaterTextures, L"LoadWaterTextures", 80); diff --git a/source/ps/Mod.cpp b/source/ps/Mod.cpp index 8ae3708ccc..0166282b31 100644 --- a/source/ps/Mod.cpp +++ b/source/ps/Mod.cpp @@ -28,7 +28,6 @@ #include "ps/GameSetup/GameSetup.h" #include "ps/GameSetup/Paths.h" #include "ps/Pyrogenesis.h" -#include "scriptinterface/ScriptContext.h" #include "scriptinterface/ScriptInterface.h" std::vector g_modsLoaded; diff --git a/source/ps/ProfileViewer.cpp b/source/ps/ProfileViewer.cpp index 572963b0b3..1aa4c2acbb 100644 --- a/source/ps/ProfileViewer.cpp +++ b/source/ps/ProfileViewer.cpp @@ -488,7 +488,7 @@ namespace const ScriptInterface& m_ScriptInterface; JS::PersistentRooted m_Root; DumpTable(const ScriptInterface& scriptInterface, JS::HandleValue root) : - m_ScriptInterface(scriptInterface), m_Root(scriptInterface.GetJSRuntime(), root) + m_ScriptInterface(scriptInterface), m_Root(scriptInterface.GetGeneralJSContext(), root) { } @@ -496,7 +496,7 @@ namespace // automatic move constructor DumpTable(DumpTable && original) : m_ScriptInterface(original.m_ScriptInterface), - m_Root(original.m_ScriptInterface.GetJSRuntime(), original.m_Root.get()) + m_Root(original.m_ScriptInterface.GetGeneralJSContext(), original.m_Root.get()) { } diff --git a/source/ps/SavedGame.cpp b/source/ps/SavedGame.cpp index 5fe1a97f1e..0253e573fa 100644 --- a/source/ps/SavedGame.cpp +++ b/source/ps/SavedGame.cpp @@ -35,7 +35,7 @@ // TODO: we ought to check version numbers when loading files -Status SavedGames::SavePrefix(const CStrW& prefix, const CStrW& description, CSimulation2& simulation, const shared_ptr& guiMetadataClone) +Status SavedGames::SavePrefix(const CStrW& prefix, const CStrW& description, CSimulation2& simulation, const ScriptInterface::StructuredClone& guiMetadataClone) { // Determine the filename to save under const VfsPath basenameFormat(L"saves/" + prefix + L"-%04d"); @@ -50,7 +50,7 @@ Status SavedGames::SavePrefix(const CStrW& prefix, const CStrW& description, CSi return Save(filename.Filename().string(), description, simulation, guiMetadataClone); } -Status SavedGames::Save(const CStrW& name, const CStrW& description, CSimulation2& simulation, const shared_ptr& guiMetadataClone) +Status SavedGames::Save(const CStrW& name, const CStrW& description, CSimulation2& simulation, const ScriptInterface::StructuredClone& guiMetadataClone) { ScriptRequest rq(simulation.GetScriptInterface()); @@ -161,7 +161,7 @@ public: */ CGameLoader(const ScriptInterface& scriptInterface, std::string* savedState) : m_ScriptInterface(scriptInterface), - m_Metadata(scriptInterface.GetJSRuntime()), + m_Metadata(scriptInterface.GetGeneralJSContext()), m_SavedState(savedState) { } diff --git a/source/ps/SavedGame.h b/source/ps/SavedGame.h index d4489da307..507eb691a0 100644 --- a/source/ps/SavedGame.h +++ b/source/ps/SavedGame.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2018 Wildfire Games. +/* Copyright (C) 2020 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -45,7 +45,7 @@ namespace SavedGames * @param guiMetadataClone if not NULL, store some UI-related data with the saved game * @return INFO::OK if successfully saved, else an error Status */ - Status Save(const CStrW& name, const CStrW& description, CSimulation2& simulation, const shared_ptr& guiMetadataClone); + Status Save(const CStrW& name, const CStrW& description, CSimulation2& simulation, const ScriptInterface::StructuredClone& guiMetadataClone); /** * Create new saved game archive with given prefix and simulation data @@ -56,7 +56,7 @@ namespace SavedGames * @param guiMetadataClone if not NULL, store some UI-related data with the saved game * @return INFO::OK if successfully saved, else an error Status */ - Status SavePrefix(const CStrW& prefix, const CStrW& description, CSimulation2& simulation, const shared_ptr& guiMetadataClone); + Status SavePrefix(const CStrW& prefix, const CStrW& description, CSimulation2& simulation, const ScriptInterface::StructuredClone& guiMetadataClone); /** * Load saved game archive with the given name diff --git a/source/ps/World.cpp b/source/ps/World.cpp index 8c87b4e508..36ba3c828a 100644 --- a/source/ps/World.cpp +++ b/source/ps/World.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2017 Wildfire Games. +/* Copyright (C) 2020 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -65,7 +65,7 @@ CWorld::CWorld(CGame *pGame): /** * Initializes the game world with the attributes provided. **/ -void CWorld::RegisterInit(const CStrW& mapFile, JSRuntime* rt, JS::HandleValue settings, int playerID) +void CWorld::RegisterInit(const CStrW& mapFile, const ScriptContext& cx, JS::HandleValue settings, int playerID) { // Load the map, if one was specified if (mapFile.length()) @@ -75,7 +75,7 @@ void CWorld::RegisterInit(const CStrW& mapFile, JSRuntime* rt, JS::HandleValue s try { CTriggerManager* pTriggerManager = NULL; - m_MapReader->LoadMap(mapfilename, rt, settings, m_Terrain, + m_MapReader->LoadMap(mapfilename, cx, settings, m_Terrain, CRenderer::IsInitialised() ? g_Renderer.GetWaterManager() : NULL, CRenderer::IsInitialised() ? g_Renderer.GetSkyManager() : NULL, &g_LightEnv, m_pGame->GetView(), @@ -94,11 +94,11 @@ void CWorld::RegisterInit(const CStrW& mapFile, JSRuntime* rt, JS::HandleValue s } } -void CWorld::RegisterInitRMS(const CStrW& scriptFile, JSRuntime* rt, JS::HandleValue settings, int playerID) +void CWorld::RegisterInitRMS(const CStrW& scriptFile, const ScriptContext& cx, JS::HandleValue settings, int playerID) { // If scriptFile is empty, a blank map will be generated using settings (no RMS run) CTriggerManager* pTriggerManager = NULL; - m_MapReader->LoadRandomMap(scriptFile, rt, settings, m_Terrain, + m_MapReader->LoadRandomMap(scriptFile, cx, settings, m_Terrain, CRenderer::IsInitialised() ? g_Renderer.GetWaterManager() : NULL, CRenderer::IsInitialised() ? g_Renderer.GetSkyManager() : NULL, &g_LightEnv, m_pGame->GetView(), diff --git a/source/ps/World.h b/source/ps/World.h index d563c809c3..2ad9feaa3e 100644 --- a/source/ps/World.h +++ b/source/ps/World.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2017 Wildfire Games. +/* Copyright (C) 2020 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -71,12 +71,12 @@ public: /* Initialize the World - load the map and all objects */ - void RegisterInit(const CStrW& mapFile, JSRuntime* rt, JS::HandleValue settings, int playerID); + void RegisterInit(const CStrW& mapFile, const ScriptContext& cx, JS::HandleValue settings, int playerID); /* Initialize the World - generate and load the random map */ - void RegisterInitRMS(const CStrW& scriptFile, JSRuntime* rt, JS::HandleValue settings, int playerID); + void RegisterInitRMS(const CStrW& scriptFile, const ScriptContext& cx, JS::HandleValue settings, int playerID); /** * Explicitly delete m_MapReader once the map has finished loading. diff --git a/source/ps/scripting/JSInterface_Game.cpp b/source/ps/scripting/JSInterface_Game.cpp index eb59a18d0b..6021ea6d45 100644 --- a/source/ps/scripting/JSInterface_Game.cpp +++ b/source/ps/scripting/JSInterface_Game.cpp @@ -51,7 +51,7 @@ void JSI_Game::StartGame(ScriptInterface::CmptPrivate* pCmptPrivate, JS::HandleV ScriptRequest rqSim(sim->GetScriptInterface()); JS::RootedValue gameAttribs(rqSim.cx, - sim->GetScriptInterface().CloneValueFromOtherCompartment(*(pCmptPrivate->pScriptInterface), attribs)); + sim->GetScriptInterface().CloneValueFromOtherCompartment(*(pCmptPrivate->pScriptInterface), attribs, false)); g_Game->SetPlayerID(playerID); g_Game->StartGame(&gameAttribs, ""); diff --git a/source/ps/scripting/JSInterface_SavedGame.cpp b/source/ps/scripting/JSInterface_SavedGame.cpp index 70d8efb5f9..8c11d004df 100644 --- a/source/ps/scripting/JSInterface_SavedGame.cpp +++ b/source/ps/scripting/JSInterface_SavedGame.cpp @@ -40,14 +40,14 @@ bool JSI_SavedGame::DeleteSavedGame(ScriptInterface::CmptPrivate* UNUSED(pCmptPr void JSI_SavedGame::SaveGame(ScriptInterface::CmptPrivate* pCmptPrivate, const std::wstring& filename, const std::wstring& description, JS::HandleValue GUIMetadata) { - shared_ptr GUIMetadataClone = pCmptPrivate->pScriptInterface->WriteStructuredClone(GUIMetadata); + ScriptInterface::StructuredClone GUIMetadataClone = pCmptPrivate->pScriptInterface->WriteStructuredClone(GUIMetadata, false); if (SavedGames::Save(filename, description, *g_Game->GetSimulation2(), GUIMetadataClone) < 0) LOGERROR("Failed to save game"); } void JSI_SavedGame::SaveGamePrefix(ScriptInterface::CmptPrivate* pCmptPrivate, const std::wstring& prefix, const std::wstring& description, JS::HandleValue GUIMetadata) { - shared_ptr GUIMetadataClone = pCmptPrivate->pScriptInterface->WriteStructuredClone(GUIMetadata); + ScriptInterface::StructuredClone GUIMetadataClone = pCmptPrivate->pScriptInterface->WriteStructuredClone(GUIMetadata, false); if (SavedGames::SavePrefix(prefix, description, *g_Game->GetSimulation2(), GUIMetadataClone) < 0) LOGERROR("Failed to save game"); } @@ -99,7 +99,7 @@ JS::Value JSI_SavedGame::StartSavedGame(ScriptInterface::CmptPrivate* pCmptPriva ScriptRequest rqGame(sim->GetScriptInterface()); JS::RootedValue gameContextMetadata(rqGame.cx, - sim->GetScriptInterface().CloneValueFromOtherCompartment(*(pCmptPrivate->pScriptInterface), guiContextMetadata)); + sim->GetScriptInterface().CloneValueFromOtherCompartment(*(pCmptPrivate->pScriptInterface), guiContextMetadata, false)); JS::RootedValue gameInitAttributes(rqGame.cx); sim->GetScriptInterface().GetProperty(gameContextMetadata, "initAttributes", &gameInitAttributes); diff --git a/source/ps/scripting/JSInterface_VFS.cpp b/source/ps/scripting/JSInterface_VFS.cpp index b35ad36e9e..6cf516eeb0 100644 --- a/source/ps/scripting/JSInterface_VFS.cpp +++ b/source/ps/scripting/JSInterface_VFS.cpp @@ -54,7 +54,7 @@ struct BuildDirEntListState BuildDirEntListState(ScriptInterface* scriptInterface) : pScriptInterface(scriptInterface), - filename_array(scriptInterface->GetJSRuntime()), + filename_array(scriptInterface->GetGeneralJSContext()), cur_idx(0) { ScriptRequest rq(pScriptInterface); diff --git a/source/scriptinterface/NativeWrapperDefns.h b/source/scriptinterface/NativeWrapperDefns.h index 462cb2c485..300643d7e1 100644 --- a/source/scriptinterface/NativeWrapperDefns.h +++ b/source/scriptinterface/NativeWrapperDefns.h @@ -180,7 +180,7 @@ bool ScriptInterface::CallFunction(JS::HandleValue val, const char* name, R& ret ScriptRequest rq(this); JS::RootedValue jsRet(rq.cx); JS::AutoValueVector argv(rq.cx); - argv.resize(sizeof...(Ts)); + (void)argv.resize(sizeof...(Ts)); AssignOrToJSValHelper<0>(rq, argv, params...); if (!CallFunction_(val, name, argv, &jsRet)) return false; @@ -193,7 +193,7 @@ bool ScriptInterface::CallFunction(JS::HandleValue val, const char* name, JS::Ro ScriptRequest rq(this); JS::MutableHandle jsRet(ret); JS::AutoValueVector argv(rq.cx); - argv.resize(sizeof...(Ts)); + (void)argv.resize(sizeof...(Ts)); AssignOrToJSValHelper<0>(rq, argv, params...); return CallFunction_(val, name, argv, jsRet); } @@ -203,7 +203,7 @@ bool ScriptInterface::CallFunction(JS::HandleValue val, const char* name, JS::Mu { ScriptRequest rq(this); JS::AutoValueVector argv(rq.cx); - argv.resize(sizeof...(Ts)); + (void)argv.resize(sizeof...(Ts)); AssignOrToJSValHelper<0>(rq, argv, params...); return CallFunction_(val, name, argv, ret); } @@ -215,7 +215,7 @@ bool ScriptInterface::CallFunctionVoid(JS::HandleValue val, const char* name, co ScriptRequest rq(this); JS::RootedValue jsRet(rq.cx); JS::AutoValueVector argv(rq.cx); - argv.resize(sizeof...(Ts)); + (void)argv.resize(sizeof...(Ts)); AssignOrToJSValHelper<0>(rq, argv, params...); return CallFunction_(val, name, argv, &jsRet); } diff --git a/source/scriptinterface/ScriptContext.cpp b/source/scriptinterface/ScriptContext.cpp index 7bb4509ccd..ec73a12105 100644 --- a/source/scriptinterface/ScriptContext.cpp +++ b/source/scriptinterface/ScriptContext.cpp @@ -25,7 +25,7 @@ #include "scriptinterface/ScriptInterface.h" -void GCSliceCallbackHook(JSRuntime* UNUSED(rt), JS::GCProgress progress, const JS::GCDescription& UNUSED(desc)) +void GCSliceCallbackHook(JSContext* UNUSED(cx), JS::GCProgress progress, const JS::GCDescription& UNUSED(desc)) { /* * During non-incremental GC, the GC is bracketed by JSGC_CYCLE_BEGIN/END @@ -69,7 +69,7 @@ void GCSliceCallbackHook(JSRuntime* UNUSED(rt), JS::GCProgress progress, const J if (progress == JS::GCProgress::GC_CYCLE_BEGIN) printf("starting cycle ===========================================\n"); - const char16_t* str = desc.formatMessage(rt); + const char16_t* str = desc.formatMessage(cx); int len = 0; for(int i = 0; i < 10000; i++) @@ -103,35 +103,32 @@ ScriptContext::ScriptContext(int contextSize, int heapGrowthBytesGCTrigger): { ENSURE(ScriptEngine::IsInitialised() && "The ScriptEngine must be initialized before constructing any ScriptContexts!"); - m_rt = JS_NewRuntime(contextSize, JS::DefaultNurseryBytes, nullptr); - ENSURE(m_rt); // TODO: error handling + m_cx = JS_NewContext(contextSize, JS::DefaultNurseryBytes, nullptr); + ENSURE(m_cx); // TODO: error handling - JS::SetGCSliceCallback(m_rt, GCSliceCallbackHook); + ENSURE(JS::InitSelfHostedCode(m_cx)); - JS_SetGCParameter(m_rt, JSGC_MAX_MALLOC_BYTES, m_ContextSize); - JS_SetGCParameter(m_rt, JSGC_MAX_BYTES, m_ContextSize); - JS_SetGCParameter(m_rt, JSGC_MODE, JSGC_MODE_INCREMENTAL); + JS::SetGCSliceCallback(m_cx, GCSliceCallbackHook); + + JS_SetGCParameter(m_cx, JSGC_MAX_MALLOC_BYTES, m_ContextSize); + JS_SetGCParameter(m_cx, JSGC_MAX_BYTES, m_ContextSize); + JS_SetGCParameter(m_cx, JSGC_MODE, JSGC_MODE_INCREMENTAL); // The whole heap-growth mechanism seems to work only for non-incremental GCs. // We disable it to make it more clear if full GCs happen triggered by this JSAPI internal mechanism. - JS_SetGCParameter(m_rt, JSGC_DYNAMIC_HEAP_GROWTH, false); + JS_SetGCParameter(m_cx, JSGC_DYNAMIC_HEAP_GROWTH, false); - JS_SetErrorReporter(m_rt, ScriptException::ErrorReporter); - - m_cx = JS_NewContext(m_rt, STACK_CHUNK_SIZE); - ENSURE(m_cx); // TODO: error handling - - JS_SetOffthreadIonCompilationEnabled(m_rt, true); + JS_SetOffthreadIonCompilationEnabled(m_cx, true); // For GC debugging: // JS_SetGCZeal(m_cx, 2, JS_DEFAULT_ZEAL_FREQ); JS_SetContextPrivate(m_cx, nullptr); - JS_SetGlobalJitCompilerOption(m_rt, JSJITCOMPILER_ION_ENABLE, 1); - JS_SetGlobalJitCompilerOption(m_rt, JSJITCOMPILER_BASELINE_ENABLE, 1); + JS_SetGlobalJitCompilerOption(m_cx, JSJITCOMPILER_ION_ENABLE, 1); + JS_SetGlobalJitCompilerOption(m_cx, JSJITCOMPILER_BASELINE_ENABLE, 1); - JS::RuntimeOptionsRef(m_cx) + JS::ContextOptionsRef(m_cx) .setExtraWarnings(true) .setWerror(false) .setStrictMode(true); @@ -144,8 +141,6 @@ ScriptContext::~ScriptContext() ENSURE(ScriptEngine::IsInitialised() && "The ScriptEngine must be active (initialized and not yet shut down) when destroying a ScriptContext!"); JS_DestroyContext(m_cx); - JS_DestroyRuntime(m_rt); - ScriptEngine::GetSingleton().UnRegisterContext(m_cx); } @@ -165,7 +160,7 @@ void ScriptContext::MaybeIncrementalGC(double delay) { PROFILE2("MaybeIncrementalGC"); - if (JS::IsIncrementalGCEnabled(m_rt)) + if (JS::IsIncrementalGCEnabled(m_cx)) { // The idea is to get the heap size after a completed GC and trigger the next GC when the heap size has // reached m_LastGCBytes + X. @@ -184,7 +179,7 @@ void ScriptContext::MaybeIncrementalGC(double delay) m_LastGCCheck = timer_Time(); - int gcBytes = JS_GetGCParameter(m_rt, JSGC_BYTES); + int gcBytes = JS_GetGCParameter(m_cx, JSGC_BYTES); #if GC_DEBUG_PRINT std::cout << "gcBytes: " << gcBytes / 1024 << " KB" << std::endl; @@ -201,10 +196,10 @@ void ScriptContext::MaybeIncrementalGC(double delay) // Run an additional incremental GC slice if the currently running incremental GC isn't over yet // ... or // start a new incremental GC if the JS heap size has grown enough for a GC to make sense - if (JS::IsIncrementalGCInProgress(m_rt) || (gcBytes - m_LastGCBytes > m_HeapGrowthBytesGCTrigger)) + if (JS::IsIncrementalGCInProgress(m_cx) || (gcBytes - m_LastGCBytes > m_HeapGrowthBytesGCTrigger)) { #if GC_DEBUG_PRINT - if (JS::IsIncrementalGCInProgress(m_rt)) + if (JS::IsIncrementalGCInProgress(m_cx)) printf("An incremental GC cycle is in progress. \n"); else printf("GC needed because JSGC_BYTES - m_LastGCBytes > m_HeapGrowthBytesGCTrigger \n" @@ -218,13 +213,13 @@ void ScriptContext::MaybeIncrementalGC(double delay) // fast enough. if (gcBytes > m_ContextSize / 2) { - if (JS::IsIncrementalGCInProgress(m_rt)) + if (JS::IsIncrementalGCInProgress(m_cx)) { #if GC_DEBUG_PRINT printf("Finishing incremental GC because gcBytes > m_ContextSize / 2. \n"); #endif PrepareCompartmentsForIncrementalGC(); - JS::FinishIncrementalGC(m_rt, JS::gcreason::REFRESH_FRAME); + JS::FinishIncrementalGC(m_cx, JS::gcreason::REFRESH_FRAME); } else { @@ -240,23 +235,23 @@ void ScriptContext::MaybeIncrementalGC(double delay) #if GC_DEBUG_PRINT printf("Running full GC because gcBytes > m_ContextSize / 2. \n"); #endif - JS_GC(m_rt); + JS_GC(m_cx); } } } else { #if GC_DEBUG_PRINT - if (!JS::IsIncrementalGCInProgress(m_rt)) + if (!JS::IsIncrementalGCInProgress(m_cx)) printf("Starting incremental GC \n"); else printf("Running incremental GC slice \n"); #endif PrepareCompartmentsForIncrementalGC(); - if (!JS::IsIncrementalGCInProgress(m_rt)) - JS::StartIncrementalGC(m_rt, GC_NORMAL, JS::gcreason::REFRESH_FRAME, GCSliceTimeBudget); + if (!JS::IsIncrementalGCInProgress(m_cx)) + JS::StartIncrementalGC(m_cx, GC_NORMAL, JS::gcreason::REFRESH_FRAME, GCSliceTimeBudget); else - JS::IncrementalGCSlice(m_rt, JS::gcreason::REFRESH_FRAME, GCSliceTimeBudget); + JS::IncrementalGCSlice(m_cx, JS::gcreason::REFRESH_FRAME, GCSliceTimeBudget); } m_LastGCBytes = gcBytes; } @@ -265,10 +260,10 @@ void ScriptContext::MaybeIncrementalGC(double delay) void ScriptContext::ShrinkingGC() { - JS_SetGCParameter(m_rt, JSGC_MODE, JSGC_MODE_COMPARTMENT); - JS::PrepareForFullGC(m_rt); - JS::GCForReason(m_rt, GC_SHRINK, JS::gcreason::REFRESH_FRAME); - JS_SetGCParameter(m_rt, JSGC_MODE, JSGC_MODE_INCREMENTAL); + JS_SetGCParameter(m_cx, JSGC_MODE, JSGC_MODE_ZONE); + JS::PrepareForFullGC(m_cx); + JS::GCForReason(m_cx, GC_SHRINK, JS::gcreason::REFRESH_FRAME); + JS_SetGCParameter(m_cx, JSGC_MODE, JSGC_MODE_INCREMENTAL); } void ScriptContext::PrepareCompartmentsForIncrementalGC() const diff --git a/source/scriptinterface/ScriptContext.h b/source/scriptinterface/ScriptContext.h index 8002752b8d..032d7da909 100644 --- a/source/scriptinterface/ScriptContext.h +++ b/source/scriptinterface/ScriptContext.h @@ -23,16 +23,14 @@ #include -constexpr int STACK_CHUNK_SIZE = 8192; - // Those are minimal defaults. The runtime for the main game is larger and GCs upon a larger growth. constexpr int DEFAULT_CONTEXT_SIZE = 16 * 1024 * 1024; constexpr int DEFAULT_HEAP_GROWTH_BYTES_GCTRIGGER = 2 * 1024 * 1024; /** - * Abstraction around a SpiderMonkey JSRuntime/JSContext. + * Abstraction around a SpiderMonkey JSContext. * - * A single ScriptContext, with the associated runtime and context, + * A single ScriptContext, with the associated context, * should only be used on a single thread. * * (One means to share data between threads and contexts is to create @@ -76,12 +74,10 @@ public: void RegisterCompartment(JSCompartment* cmpt); void UnRegisterCompartment(JSCompartment* cmpt); - JSRuntime* GetJSRuntime() const { return m_rt; } - /** * GetGeneralJSContext returns the context without starting a GC request and without * entering any compartment. It should only be used in specific situations, such as - * creating a new compartment, or as an unsafe alternative to GetJSRuntime. + * creating a new compartment, or when initializing a persistent rooted. * If you need the compartmented context of a ScriptInterface, you should create a * ScriptRequest and use the context from that. */ @@ -89,7 +85,6 @@ public: private: - JSRuntime* m_rt; JSContext* m_cx; void PrepareCompartmentsForIncrementalGC() const; diff --git a/source/scriptinterface/ScriptConversions.cpp b/source/scriptinterface/ScriptConversions.cpp index 26c4ce0073..054d920235 100644 --- a/source/scriptinterface/ScriptConversions.cpp +++ b/source/scriptinterface/ScriptConversions.cpp @@ -28,28 +28,7 @@ #define FAIL(msg) STMT(LOGERROR(msg); return false) // Implicit type conversions often hide bugs, so warn about them -#define WARN_IF_NOT(c, v) STMT(if (!(c)) { JS_ReportWarning(rq.cx, "Script value conversion check failed: %s (got type %s)", #c, InformalValueTypeName(v)); }) - -// TODO: SpiderMonkey: Follow upstream progresses about JS_InformalValueTypeName in the API -// https://bugzilla.mozilla.org/show_bug.cgi?id=1285917 -static const char* InformalValueTypeName(const JS::Value& v) -{ - if (v.isObject()) - return "object"; - if (v.isString()) - return "string"; - if (v.isSymbol()) - return "symbol"; - if (v.isNumber()) - return "number"; - if (v.isBoolean()) - return "boolean"; - if (v.isNull()) - return "null"; - if (v.isUndefined()) - return "undefined"; - return "value"; -} +#define WARN_IF_NOT(c, v) STMT(if (!(c)) { JS_ReportWarningUTF8(rq.cx, "Script value conversion check failed: %s (got type %s)", #c, JS::InformalValueTypeName(v)); }) template<> bool ScriptInterface::FromJSVal(const ScriptRequest& rq, JS::HandleValue v, bool& out) { diff --git a/source/scriptinterface/ScriptExceptions.cpp b/source/scriptinterface/ScriptExceptions.cpp index f15495d0fe..4a2fb5dd3d 100644 --- a/source/scriptinterface/ScriptExceptions.cpp +++ b/source/scriptinterface/ScriptExceptions.cpp @@ -73,10 +73,9 @@ bool ScriptException::CatchPending(const ScriptRequest& rq) msg << " line " << report->lineno << "\n"; } - // TODO SM52: - // msg << report->message(); + msg << report->message().c_str(); - JS::RootedObject stackObj(rq.cx, ExceptionStackOrNull(rq.cx, excnObj)); + JS::RootedObject stackObj(rq.cx, ExceptionStackOrNull(excnObj)); JS::RootedValue stackVal(rq.cx, JS::ObjectOrNullValue(stackObj)); if (!stackVal.isNull()) { @@ -97,55 +96,10 @@ bool ScriptException::CatchPending(const ScriptRequest& rq) return true; } -void ScriptException::ErrorReporter(JSContext* cx, const char* message, JSErrorReport* report) -{ - if (!ScriptInterface::GetScriptInterfaceAndCBData(cx)) - { - LOGERROR("Javascript - Out of Memory error"); - return; - } - ScriptRequest rq(*ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface); - - std::stringstream msg; - bool isWarning = JSREPORT_IS_WARNING(report->flags); - msg << (isWarning ? "JavaScript warning: " : "JavaScript error: "); - if (report->filename) - { - msg << report->filename; - msg << " line " << report->lineno << "\n"; - } - - msg << message; - - // If there is an exception, then print its stack trace - JS::RootedValue excn(rq.cx); - if (JS_GetPendingException(rq.cx, &excn) && excn.isObject()) - { - JS::RootedValue stackVal(rq.cx); - JS::RootedObject excnObj(rq.cx, &excn.toObject()); - JS_GetProperty(rq.cx, excnObj, "stack", &stackVal); - - std::string stackText; - ScriptInterface::FromJSVal(rq, stackVal, stackText); - - std::istringstream stream(stackText); - for (std::string line; std::getline(stream, line);) - msg << "\n " << line; - } - - if (isWarning) - LOGWARNING("%s", msg.str().c_str()); - else - LOGERROR("%s", msg.str().c_str()); - - // When running under Valgrind, print more information in the error message - // VALGRIND_PRINTF_BACKTRACE("->"); -} - void ScriptException::Raise(const ScriptRequest& rq, const char* format, ...) { va_list ap; va_start(ap, format); - JS_ReportError(rq.cx, format, ap); + JS_ReportErrorUTF8(rq.cx, format, ap); va_end(ap); } diff --git a/source/scriptinterface/ScriptExceptions.h b/source/scriptinterface/ScriptExceptions.h index d8fff7151d..d6bc7891c2 100644 --- a/source/scriptinterface/ScriptExceptions.h +++ b/source/scriptinterface/ScriptExceptions.h @@ -39,8 +39,6 @@ bool IsPending(const ScriptRequest& rq); */ bool CatchPending(const ScriptRequest& rq); -void ErrorReporter(JSContext* rt, const char* message, JSErrorReport* report); - /** * Raise a JS exception from C++ code. * This is only really relevant in JSNative functions that don't use ObjectOpResult, diff --git a/source/scriptinterface/ScriptInterface.cpp b/source/scriptinterface/ScriptInterface.cpp index 6a3a302985..5d7f7583d6 100644 --- a/source/scriptinterface/ScriptInterface.cpp +++ b/source/scriptinterface/ScriptInterface.cpp @@ -94,8 +94,7 @@ ScriptRequest::~ScriptRequest() namespace { -JSClass global_class = { - "global", JSCLASS_GLOBAL_FLAGS, +JSClassOps global_classops = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, @@ -103,6 +102,10 @@ JSClass global_class = { JS_GlobalObjectTraceHook }; +JSClass global_class = { + "global", JSCLASS_GLOBAL_FLAGS, &global_classops +}; + // Functions in the global namespace: bool print(JSContext* cx, uint argc, JS::Value* vp) @@ -319,12 +322,15 @@ bool ScriptInterface::MathRandom(double& nbr) } ScriptInterface_impl::ScriptInterface_impl(const char* nativeScopeName, const shared_ptr& context) : - m_context(context), m_cx(context->GetGeneralJSContext()), m_glob(context->GetJSRuntime()), m_nativeScope(context->GetJSRuntime()) + m_context(context), m_cx(context->GetGeneralJSContext()), m_glob(context->GetGeneralJSContext()), m_nativeScope(context->GetGeneralJSContext()) { - JS::CompartmentOptions opt; - opt.setVersion(JSVERSION_LATEST); + JS::CompartmentCreationOptions creationOpt; // Keep JIT code during non-shrinking GCs. This brings a quite big performance improvement. - opt.setPreserveJitCode(true); + creationOpt.setPreserveJitCode(true); + JS::CompartmentBehaviors behaviors; + behaviors.setVersion(JSVERSION_LATEST); + + JS::CompartmentOptions opt(creationOpt, behaviors); JSAutoRequest rq(m_cx); m_glob = JS_NewGlobalObject(m_cx, &global_class, nullptr, JS::OnNewGlobalHookOption::FireOnNewGlobalHook, opt); @@ -446,9 +452,9 @@ void ScriptInterface::Register(const char* name, JSNative fptr, size_t nargs) co m->Register(name, fptr, (uint)nargs); } -JSRuntime* ScriptInterface::GetJSRuntime() const +JSContext* ScriptInterface::GetGeneralJSContext() const { - return m->m_context->GetJSRuntime(); + return m->m_context->GetGeneralJSContext(); } shared_ptr ScriptInterface::GetContext() const @@ -560,7 +566,7 @@ bool ScriptInterface::SetGlobal_(const char* name, JS::HandleValue value, bool r return false; if (found) { - JS::Rooted desc(rq.cx); + JS::Rooted desc(rq.cx); if (!JS_GetOwnPropertyDescriptor(rq.cx, global, name, &desc)) return false; @@ -971,15 +977,7 @@ std::string ScriptInterface::ToString(JS::MutableHandleValue obj, bool pretty) c Stringifier str; JS::RootedValue indentVal(rq.cx, JS::Int32Value(2)); - // Temporary disable the error reporter, so we don't print complaints about cyclic values - JSErrorReporter er = JS_SetErrorReporter(GetJSRuntime(), nullptr); - - bool ok = JS_Stringify(rq.cx, obj, nullptr, indentVal, &Stringifier::callback, &str); - - // Restore error reporter - JS_SetErrorReporter(GetJSRuntime(), er); - - if (ok) + if (JS_Stringify(rq.cx, obj, nullptr, indentVal, &Stringifier::callback, &str)) return str.stream.str(); // Drop exceptions raised by cyclic values before trying something else @@ -994,48 +992,37 @@ std::string ScriptInterface::ToString(JS::MutableHandleValue obj, bool pretty) c return utf8_from_wstring(source); } -JS::Value ScriptInterface::CloneValueFromOtherCompartment(const ScriptInterface& otherCompartment, JS::HandleValue val) const +JS::Value ScriptInterface::CloneValueFromOtherCompartment(const ScriptInterface& otherCompartment, JS::HandleValue val, bool sameThread) const { PROFILE("CloneValueFromOtherCompartment"); ScriptRequest rq(this); JS::RootedValue out(rq.cx); - shared_ptr structuredClone = otherCompartment.WriteStructuredClone(val); + ScriptInterface::StructuredClone structuredClone = otherCompartment.WriteStructuredClone(val, sameThread); ReadStructuredClone(structuredClone, &out); return out.get(); } -ScriptInterface::StructuredClone::StructuredClone() : - m_Data(NULL), m_Size(0) -{ -} - -ScriptInterface::StructuredClone::~StructuredClone() -{ - if (m_Data) - JS_ClearStructuredClone(m_Data, m_Size, NULL, NULL); -} - -shared_ptr ScriptInterface::WriteStructuredClone(JS::HandleValue v) const +ScriptInterface::StructuredClone ScriptInterface::WriteStructuredClone(JS::HandleValue v, bool sameThread) const { ScriptRequest rq(this); - u64* data = NULL; - size_t nbytes = 0; - if (!JS_WriteStructuredClone(rq.cx, v, &data, &nbytes, NULL, NULL, JS::UndefinedHandleValue)) + + JS::StructuredCloneScope scope = sameThread ? JS::StructuredCloneScope::SameProcessSameThread : JS::StructuredCloneScope::SameProcessDifferentThread; + ScriptInterface::StructuredClone ret(new JSStructuredCloneData(scope)); + JS::CloneDataPolicy policy; + + if (!JS_WriteStructuredClone(rq.cx, v, ret.get(), scope, policy, nullptr, nullptr, JS::UndefinedHandleValue)) { debug_warn(L"Writing a structured clone with JS_WriteStructuredClone failed!"); ScriptException::CatchPending(rq); - return shared_ptr(); + return ScriptInterface::StructuredClone(); } - shared_ptr ret(new StructuredClone); - ret->m_Data = data; - ret->m_Size = nbytes; return ret; } -void ScriptInterface::ReadStructuredClone(const shared_ptr& ptr, JS::MutableHandleValue ret) const +void ScriptInterface::ReadStructuredClone(const ScriptInterface::StructuredClone& ptr, JS::MutableHandleValue ret) const { ScriptRequest rq(this); - if (!JS_ReadStructuredClone(rq.cx, ptr->m_Data, ptr->m_Size, JS_STRUCTURED_CLONE_VERSION, ret, NULL, NULL)) + if (!JS_ReadStructuredClone(rq.cx, *ptr, JS_STRUCTURED_CLONE_VERSION, ptr->scope(), ret, nullptr, nullptr)) ScriptException::CatchPending(rq); } diff --git a/source/scriptinterface/ScriptInterface.h b/source/scriptinterface/ScriptInterface.h index 76761c235a..3381aaeb27 100644 --- a/source/scriptinterface/ScriptInterface.h +++ b/source/scriptinterface/ScriptInterface.h @@ -119,7 +119,14 @@ public: void SetCallbackData(void* pCBData); static CmptPrivate* GetScriptInterfaceAndCBData(JSContext* cx); - JSRuntime* GetJSRuntime() const; + /** + * GetGeneralJSContext returns the context without starting a GC request and without + * entering the ScriptInterface compartment. It should only be used in specific situations, + * for instance when initializing a persistent rooted. + * If you need the compartmented context of the ScriptInterface, you should create a + * ScriptInterface::Request and use the context from that. + */ + JSContext* GetGeneralJSContext() const; shared_ptr GetContext() const; /** @@ -289,14 +296,6 @@ public: */ bool LoadGlobalScriptFile(const VfsPath& path) const; - /** - * Construct a new value (usable in this ScriptInterface's compartment) by cloning - * a value from a different compartment. - * Complex values (functions, XML, etc) won't be cloned correctly, but basic - * types and cyclic references should be fine. - */ - JS::Value CloneValueFromOtherCompartment(const ScriptInterface& otherCompartment, JS::HandleValue val) const; - /** * Convert a JS::Value to a C++ type. (This might trigger GC.) */ @@ -331,18 +330,18 @@ public: * We wrap them in shared_ptr so memory management is automatic and * thread-safe. */ - class StructuredClone - { - NONCOPYABLE(StructuredClone); - public: - StructuredClone(); - ~StructuredClone(); - u64* m_Data; - size_t m_Size; - }; + using StructuredClone = shared_ptr; - shared_ptr WriteStructuredClone(JS::HandleValue v) const; - void ReadStructuredClone(const shared_ptr& ptr, JS::MutableHandleValue ret) const; + StructuredClone WriteStructuredClone(JS::HandleValue v, bool sameThread) const; + void ReadStructuredClone(const StructuredClone& ptr, JS::MutableHandleValue ret) const; + + /** + * Construct a new value (usable in this ScriptInterface's compartment) by cloning + * a value from a different compartment. + * Complex values (functions, XML, etc) won't be cloned correctly, but basic + * types and cyclic references should be fine. + */ + JS::Value CloneValueFromOtherCompartment(const ScriptInterface& otherCompartment, JS::HandleValue val, bool sameThread) const; /** * Retrieve the private data field of a JSObject that is an instance of the given JSClass. diff --git a/source/scriptinterface/ScriptStats.cpp b/source/scriptinterface/ScriptStats.cpp index a680d00648..3304e72b8a 100644 --- a/source/scriptinterface/ScriptStats.cpp +++ b/source/scriptinterface/ScriptStats.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2015 Wildfire Games. +/* Copyright (C) 2020 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -84,28 +84,28 @@ CStr CScriptStatsTable::GetCellText(size_t row, size_t col) { if (col == 0) return "max nominal heap bytes"; - uint32_t n = JS_GetGCParameter(m_ScriptInterfaces.at(col-1).first->GetJSRuntime(), JSGC_MAX_BYTES); + uint32_t n = JS_GetGCParameter(m_ScriptInterfaces.at(col-1).first->GetGeneralJSContext(), JSGC_MAX_BYTES); return CStr::FromUInt(n); } case Row_MaxMallocBytes: { if (col == 0) return "max JS_malloc bytes"; - uint32_t n = JS_GetGCParameter(m_ScriptInterfaces.at(col-1).first->GetJSRuntime(), JSGC_MAX_MALLOC_BYTES); + uint32_t n = JS_GetGCParameter(m_ScriptInterfaces.at(col-1).first->GetGeneralJSContext(), JSGC_MAX_MALLOC_BYTES); return CStr::FromUInt(n); } case Row_Bytes: { if (col == 0) return "allocated bytes"; - uint32_t n = JS_GetGCParameter(m_ScriptInterfaces.at(col-1).first->GetJSRuntime(), JSGC_BYTES); + uint32_t n = JS_GetGCParameter(m_ScriptInterfaces.at(col-1).first->GetGeneralJSContext(), JSGC_BYTES); return CStr::FromUInt(n); } case Row_NumberGC: { if (col == 0) return "number of GCs"; - uint32_t n = JS_GetGCParameter(m_ScriptInterfaces.at(col-1).first->GetJSRuntime(), JSGC_NUMBER); + uint32_t n = JS_GetGCParameter(m_ScriptInterfaces.at(col-1).first->GetGeneralJSContext(), JSGC_NUMBER); return CStr::FromUInt(n); } default: diff --git a/source/scriptinterface/ScriptTypes.h b/source/scriptinterface/ScriptTypes.h index 4aa195e352..78be5a8e2b 100644 --- a/source/scriptinterface/ScriptTypes.h +++ b/source/scriptinterface/ScriptTypes.h @@ -55,6 +55,8 @@ #if MSC_VERSION // reduce the warning level for the SpiderMonkey headers # pragma warning(push, 1) +// ignore C4291 in +# pragma warning(disable: 4291) #endif #include "jspubtd.h" diff --git a/source/scriptinterface/tests/test_ScriptInterface.h b/source/scriptinterface/tests/test_ScriptInterface.h index ac06e967c5..d8c0d3359a 100644 --- a/source/scriptinterface/tests/test_ScriptInterface.h +++ b/source/scriptinterface/tests/test_ScriptInterface.h @@ -40,7 +40,7 @@ public: ScriptInterface script("Test", "Test", g_ScriptContext); TestLogger logger; TS_ASSERT(!script.LoadScript(L"test.js", "1+")); - TS_ASSERT_STR_CONTAINS(logger.GetOutput(), "ERROR: JavaScript error: test.js line 1\nSyntaxError: expected expression, got end of script"); + TS_ASSERT_STR_CONTAINS(logger.GetOutput(), "ERROR: JavaScript error: test.js line 1\nexpected expression, got end of script"); } void test_loadscript_strict_warning() @@ -57,7 +57,7 @@ public: ScriptInterface script("Test", "Test", g_ScriptContext); TestLogger logger; TS_ASSERT(!script.LoadScript(L"test.js", "with(1){}")); - TS_ASSERT_STR_CONTAINS(logger.GetOutput(), "ERROR: JavaScript error: test.js line 1\nSyntaxError: strict mode code may not contain \'with\' statements"); + TS_ASSERT_STR_CONTAINS(logger.GetOutput(), "ERROR: JavaScript error: test.js line 1\nstrict mode code may not contain \'with\' statements"); } void test_clone_basic() @@ -72,7 +72,7 @@ public: { ScriptRequest rq2(script2); - JS::RootedValue obj2(rq2.cx, script2.CloneValueFromOtherCompartment(script1, obj1)); + JS::RootedValue obj2(rq2.cx, script2.CloneValueFromOtherCompartment(script1, obj1, true)); std::string source; TS_ASSERT(script2.CallFunction(obj2, "toSource", source)); @@ -94,7 +94,7 @@ public: { ScriptRequest rq2(script2); - JS::RootedValue obj2(rq2.cx, script2.CloneValueFromOtherCompartment(script1, obj1)); + JS::RootedValue obj2(rq2.cx, script2.CloneValueFromOtherCompartment(script1, obj1, true)); std::string source; TS_ASSERT(script2.CallFunction(obj2, "toSource", source)); @@ -114,7 +114,7 @@ public: { ScriptRequest rq2(script2); - JS::RootedValue obj2(rq2.cx, script2.CloneValueFromOtherCompartment(script1, obj1)); + JS::RootedValue obj2(rq2.cx, script2.CloneValueFromOtherCompartment(script1, obj1, true)); // Use JSAPI function to check if the values of the properties "a", "b" are equals a.x[0] JS::RootedValue prop_a(rq2.cx); @@ -125,8 +125,8 @@ public: TS_ASSERT(prop_a.isObject()); TS_ASSERT(prop_b.isObject()); TS_ASSERT(script2.GetProperty(prop_a, "0", &prop_x1)); - TS_ASSERT_EQUALS(prop_x1.get(), prop_a.get()); - TS_ASSERT_EQUALS(prop_x1.get(), prop_b.get()); + TS_ASSERT(prop_x1.get() == prop_a.get()); + TS_ASSERT(prop_x1.get() == prop_b.get()); } } diff --git a/source/simulation2/Simulation2.cpp b/source/simulation2/Simulation2.cpp index a81c26c4a8..4def32622e 100644 --- a/source/simulation2/Simulation2.cpp +++ b/source/simulation2/Simulation2.cpp @@ -49,11 +49,11 @@ class CSimulation2Impl { public: - CSimulation2Impl(CUnitManager* unitManager, shared_ptr rt, CTerrain* terrain) : - m_SimContext(), m_ComponentManager(m_SimContext, rt), + CSimulation2Impl(CUnitManager* unitManager, shared_ptr cx, CTerrain* terrain) : + m_SimContext(), m_ComponentManager(m_SimContext, cx), m_EnableOOSLog(false), m_EnableSerializationTest(false), m_RejoinTestTurn(-1), m_TestingRejoin(false), m_SecondaryTerrain(nullptr), m_SecondaryContext(nullptr), m_SecondaryComponentManager(nullptr), m_SecondaryLoadedScripts(nullptr), - m_MapSettings(rt->GetJSRuntime()), m_InitAttributes(rt->GetJSRuntime()) + m_MapSettings(cx->GetGeneralJSContext()), m_InitAttributes(cx->GetGeneralJSContext()) { m_SimContext.m_UnitManager = unitManager; m_SimContext.m_Terrain = terrain; @@ -164,7 +164,7 @@ public: void InitRNGSeedSimulation(); void InitRNGSeedAI(); - static std::vector CloneCommandsFromOtherContext(const ScriptInterface& oldScript, const ScriptInterface& newScript, + static std::vector CloneCommandsFromOtherCompartment(const ScriptInterface& oldScript, const ScriptInterface& newScript, const std::vector& commands) { std::vector newCommands; @@ -173,7 +173,7 @@ public: ScriptRequest rqNew(newScript); for (const SimulationCommand& command : commands) { - JS::RootedValue tmpCommand(rqNew.cx, newScript.CloneValueFromOtherCompartment(oldScript, command.data)); + JS::RootedValue tmpCommand(rqNew.cx, newScript.CloneValueFromOtherCompartment(oldScript, command.data, true)); newScript.FreezeObject(tmpCommand, true); SimulationCommand cmd(command.player, rqNew.cx, tmpCommand); newCommands.emplace_back(std::move(cmd)); @@ -424,7 +424,7 @@ void CSimulation2Impl::Update(int turnLength, const std::vectorGetScriptInterface()); JS::RootedValue mapSettingsCloned(rq2.cx, m_SecondaryComponentManager->GetScriptInterface().CloneValueFromOtherCompartment( - scriptInterface, m_MapSettings)); + scriptInterface, m_MapSettings, true)); ENSURE(LoadTriggerScripts(*m_SecondaryComponentManager, mapSettingsCloned, m_SecondaryLoadedScripts)); } @@ -446,7 +446,7 @@ void CSimulation2Impl::Update(int turnLength, const std::vectorLoadMap(mapfilename, scriptInterface.GetJSRuntime(), JS::UndefinedHandleValue, + mapReader->LoadMap(mapfilename, *scriptInterface.GetContext(), JS::UndefinedHandleValue, m_SecondaryTerrain, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, m_SecondaryContext, INVALID_PLAYER, true); // throws exception on failure } @@ -477,7 +477,7 @@ void CSimulation2Impl::Update(int turnLength, const std::vectorGetScriptInterface(), commands)); + CloneCommandsFromOtherCompartment(scriptInterface, m_SecondaryComponentManager->GetScriptInterface(), commands)); SerializationTestState secondaryStateAfter; ENSURE(m_SecondaryComponentManager->SerializeState(secondaryStateAfter.state)); if (serializationTestHash) @@ -638,8 +638,8 @@ void CSimulation2Impl::DumpState() //////////////////////////////////////////////////////////////// -CSimulation2::CSimulation2(CUnitManager* unitManager, shared_ptr rt, CTerrain* terrain) : - m(new CSimulation2Impl(unitManager, rt, terrain)) +CSimulation2::CSimulation2(CUnitManager* unitManager, shared_ptr cx, CTerrain* terrain) : + m(new CSimulation2Impl(unitManager, cx, terrain)) { } diff --git a/source/simulation2/Simulation2.h b/source/simulation2/Simulation2.h index 907cfa2af4..6bc526cbfc 100644 --- a/source/simulation2/Simulation2.h +++ b/source/simulation2/Simulation2.h @@ -48,7 +48,7 @@ class CSimulation2 public: // TODO: CUnitManager should probably be handled automatically by this // module, but for now we'll have it passed in externally instead - CSimulation2(CUnitManager* unitManager, shared_ptr rt, CTerrain* terrain); + CSimulation2(CUnitManager* unitManager, shared_ptr cx, CTerrain* terrain); ~CSimulation2(); void EnableSerializationTest(); diff --git a/source/simulation2/components/CCmpAIManager.cpp b/source/simulation2/components/CCmpAIManager.cpp index ee7599a50e..e0edc1e938 100644 --- a/source/simulation2/components/CCmpAIManager.cpp +++ b/source/simulation2/components/CCmpAIManager.cpp @@ -86,7 +86,7 @@ private: CAIPlayer(CAIWorker& worker, const std::wstring& aiName, player_id_t player, u8 difficulty, const std::wstring& behavior, shared_ptr scriptInterface) : m_Worker(worker), m_AIName(aiName), m_Player(player), m_Difficulty(difficulty), m_Behavior(behavior), - m_ScriptInterface(scriptInterface), m_Obj(scriptInterface->GetJSRuntime()) + m_ScriptInterface(scriptInterface), m_Obj(scriptInterface->GetGeneralJSContext()) { } @@ -200,14 +200,14 @@ private: shared_ptr m_ScriptInterface; JS::PersistentRootedValue m_Obj; - std::vector > m_Commands; + std::vector m_Commands; }; public: struct SCommandSets { player_id_t player; - std::vector > commands; + std::vector commands; }; CAIWorker() : @@ -216,17 +216,17 @@ public: m_CommandsComputed(true), m_HasLoadedEntityTemplates(false), m_HasSharedComponent(false), - m_EntityTemplates(g_ScriptContext->GetJSRuntime()), - m_SharedAIObj(g_ScriptContext->GetJSRuntime()), - m_PassabilityMapVal(g_ScriptContext->GetJSRuntime()), - m_TerritoryMapVal(g_ScriptContext->GetJSRuntime()) + m_EntityTemplates(g_ScriptContext->GetGeneralJSContext()), + m_SharedAIObj(g_ScriptContext->GetGeneralJSContext()), + m_PassabilityMapVal(g_ScriptContext->GetGeneralJSContext()), + m_TerritoryMapVal(g_ScriptContext->GetGeneralJSContext()) { m_ScriptInterface->ReplaceNondeterministicRNG(m_RNG); m_ScriptInterface->SetCallbackData(static_cast (this)); - JS_AddExtraGCRootsTracer(m_ScriptInterface->GetJSRuntime(), Trace, this); + JS_AddExtraGCRootsTracer(m_ScriptInterface->GetGeneralJSContext(), Trace, this); m_ScriptInterface->RegisterFunction("PostCommand"); m_ScriptInterface->RegisterFunction("IncludeModule"); @@ -245,7 +245,7 @@ public: ~CAIWorker() { - JS_RemoveExtraGCRootsTracer(m_ScriptInterface->GetJSRuntime(), Trace, this); + JS_RemoveExtraGCRootsTracer(m_ScriptInterface->GetGeneralJSContext(), Trace, this); } bool HasLoadedEntityTemplates() const { return m_HasLoadedEntityTemplates; } @@ -299,7 +299,7 @@ public: { if (m_Players[i]->m_Player == playerid) { - m_Players[i]->m_Commands.push_back(m_ScriptInterface->WriteStructuredClone(cmd)); + m_Players[i]->m_Commands.push_back(m_ScriptInterface->WriteStructuredClone(cmd, false)); return; } } @@ -485,7 +485,7 @@ public: return true; } - bool RunGamestateInit(const shared_ptr& gameState, const Grid& passabilityMap, const Grid& territoryMap, + bool RunGamestateInit(const ScriptInterface::StructuredClone& gameState, const Grid& passabilityMap, const Grid& territoryMap, const std::map& nonPathfindingPassClassMasks, const std::map& pathfindingPassClassMasks) { // this will be run last by InitGame.js, passing the full game representation. @@ -521,7 +521,7 @@ public: return true; } - void UpdateGameState(const shared_ptr& gameState) + void UpdateGameState(const ScriptInterface::StructuredClone& gameState) { ENSURE(m_CommandsComputed); m_GameState = gameState; @@ -765,7 +765,7 @@ public: { JS::RootedValue val(rq.cx); deserializer.ScriptVal("command", &val); - m_Players.back()->m_Commands.push_back(m_ScriptInterface->WriteStructuredClone(val)); + m_Players.back()->m_Commands.push_back(m_ScriptInterface->WriteStructuredClone(val, false)); } bool hasCustomDeserialize = m_ScriptInterface->HasProperty(m_Players.back()->m_Obj, "Deserialize"); @@ -888,7 +888,7 @@ private: std::set m_LoadedModules; - shared_ptr m_GameState; + ScriptInterface::StructuredClone m_GameState; Grid m_PassabilityMap; JS::PersistentRootedValue m_PassabilityMapVal; Grid m_TerritoryMap; @@ -1016,7 +1016,8 @@ public: if (cmpPathfinder) cmpPathfinder->GetPassabilityClasses(nonPathfindingPassClassMasks, pathfindingPassClassMasks); - m_Worker.RunGamestateInit(scriptInterface.WriteStructuredClone(state), *passabilityMap, *territoryMap, nonPathfindingPassClassMasks, pathfindingPassClassMasks); + m_Worker.RunGamestateInit(scriptInterface.WriteStructuredClone(state, false), + *passabilityMap, *territoryMap, nonPathfindingPassClassMasks, pathfindingPassClassMasks); } virtual void StartComputation() @@ -1041,7 +1042,7 @@ public: LoadPathfinderClasses(state); // add the pathfinding classes to it // Update the game state - m_Worker.UpdateGameState(scriptInterface.WriteStructuredClone(state)); + m_Worker.UpdateGameState(scriptInterface.WriteStructuredClone(state, false)); // Update the pathfinding data CmpPtr cmpPathfinder(GetSystemEntity()); diff --git a/source/simulation2/components/ICmpAIManager.cpp b/source/simulation2/components/ICmpAIManager.cpp index 9b1ba1a060..54ba0312ac 100644 --- a/source/simulation2/components/ICmpAIManager.cpp +++ b/source/simulation2/components/ICmpAIManager.cpp @@ -39,7 +39,7 @@ struct GetAIsHelper public: GetAIsHelper(const ScriptInterface& scriptInterface) : m_ScriptInterface(scriptInterface), - m_AIs(scriptInterface.GetJSRuntime()) + m_AIs(scriptInterface.GetGeneralJSContext()) { ScriptRequest rq(m_ScriptInterface); m_AIs = JS_NewArrayObject(rq.cx, 0); diff --git a/source/simulation2/components/tests/test_Pathfinder.h b/source/simulation2/components/tests/test_Pathfinder.h index 3cb0a3c692..7bd459f6d8 100644 --- a/source/simulation2/components/tests/test_Pathfinder.h +++ b/source/simulation2/components/tests/test_Pathfinder.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2019 Wildfire Games. +/* Copyright (C) 2020 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -28,6 +28,7 @@ #include "lib/tex/tex.h" #include "ps/Loader.h" #include "ps/Pyrogenesis.h" +#include "scriptinterface/ScriptContext.h" #include "simulation2/Simulation2.h" class TestCmpPathfinder : public CxxTest::TestSuite @@ -147,7 +148,7 @@ public: LDR_BeginRegistering(); mapReader->LoadMap(L"maps/skirmishes/Median Oasis (2).pmp", - sim2.GetScriptInterface().GetJSRuntime(), JS::UndefinedHandleValue, + *sim2.GetScriptInterface().GetContext(), JS::UndefinedHandleValue, &terrain, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &sim2, &sim2.GetSimContext(), -1, false); LDR_EndRegistering(); @@ -258,7 +259,7 @@ public: LDR_BeginRegistering(); mapReader->LoadMap(L"maps/scenarios/Peloponnese.pmp", - sim2.GetScriptInterface().GetJSRuntime(), JS::UndefinedHandleValue, + *sim2.GetScriptInterface().GetContext(), JS::UndefinedHandleValue, &terrain, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &sim2, &sim2.GetSimContext(), -1, false); LDR_EndRegistering(); @@ -315,7 +316,7 @@ public: LDR_BeginRegistering(); mapReader->LoadMap(L"maps/scenarios/Peloponnese.pmp", - sim2.GetScriptInterface().GetJSRuntime(), JS::UndefinedHandleValue, + *sim2.GetScriptInterface().GetContext(), JS::UndefinedHandleValue, &terrain, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &sim2, &sim2.GetSimContext(), -1, false); LDR_EndRegistering(); diff --git a/source/simulation2/scripting/EngineScriptConversions.cpp b/source/simulation2/scripting/EngineScriptConversions.cpp index f75110b438..3c28a1d174 100644 --- a/source/simulation2/scripting/EngineScriptConversions.cpp +++ b/source/simulation2/scripting/EngineScriptConversions.cpp @@ -168,8 +168,11 @@ template<> void ScriptInterface::ToJSVal(const ScriptRequest& rq args[1].setNumber(val.Y.ToDouble()); args[2].setNumber(val.Z.ToDouble()); - if (!JS::Construct(rq.cx, valueVector3D, args, ret)) + JS::RootedObject objVec(rq.cx); + if (!JS::Construct(rq.cx, valueVector3D, args, &objVec)) FAIL_VOID("Failed to construct Vector3D object"); + + ret.setObject(*objVec); } template<> bool ScriptInterface::FromJSVal(const ScriptRequest& rq, JS::HandleValue v, CFixedVector2D& out) @@ -200,8 +203,11 @@ template<> void ScriptInterface::ToJSVal(const ScriptRequest& rq args[0].setNumber(val.X.ToDouble()); args[1].setNumber(val.Y.ToDouble()); - if (!JS::Construct(rq.cx, valueVector2D, args, ret)) + JS::RootedObject objVec(rq.cx); + if (!JS::Construct(rq.cx, valueVector2D, args, &objVec)) FAIL_VOID("Failed to construct Vector2D object"); + + ret.setObject(*objVec); } template<> void ScriptInterface::ToJSVal >(const ScriptRequest& rq, JS::MutableHandleValue ret, const Grid& val) diff --git a/source/simulation2/scripting/JSInterface_Simulation.cpp b/source/simulation2/scripting/JSInterface_Simulation.cpp index b1dce48ce3..b006fceee9 100644 --- a/source/simulation2/scripting/JSInterface_Simulation.cpp +++ b/source/simulation2/scripting/JSInterface_Simulation.cpp @@ -51,11 +51,11 @@ JS::Value JSI_Simulation::GuiInterfaceCall(ScriptInterface::CmptPrivate* pCmptPr return JS::UndefinedValue(); ScriptRequest rqSim(sim->GetScriptInterface()); - JS::RootedValue arg(rqSim.cx, sim->GetScriptInterface().CloneValueFromOtherCompartment(*(pCmptPrivate->pScriptInterface), data)); + JS::RootedValue arg(rqSim.cx, sim->GetScriptInterface().CloneValueFromOtherCompartment(*(pCmptPrivate->pScriptInterface), data, false)); JS::RootedValue ret(rqSim.cx); cmpGuiInterface->ScriptCall(g_Game->GetViewedPlayerID(), name, arg, &ret); - return pCmptPrivate->pScriptInterface->CloneValueFromOtherCompartment(sim->GetScriptInterface(), ret); + return pCmptPrivate->pScriptInterface->CloneValueFromOtherCompartment(sim->GetScriptInterface(), ret, false); } void JSI_Simulation::PostNetworkCommand(ScriptInterface::CmptPrivate* pCmptPrivate, JS::HandleValue cmd) @@ -71,7 +71,8 @@ void JSI_Simulation::PostNetworkCommand(ScriptInterface::CmptPrivate* pCmptPriva return; ScriptRequest rqSim(sim->GetScriptInterface()); - JS::RootedValue cmd2(rqSim.cx, sim->GetScriptInterface().CloneValueFromOtherCompartment(*(pCmptPrivate->pScriptInterface), cmd)); + JS::RootedValue cmd2(rqSim.cx, + sim->GetScriptInterface().CloneValueFromOtherCompartment(*(pCmptPrivate->pScriptInterface), cmd, false)); cmpCommandQueue->PostNetworkCommand(cmd2); } diff --git a/source/simulation2/scripting/MessageTypeConversions.cpp b/source/simulation2/scripting/MessageTypeConversions.cpp index 2eee3d6a8d..344e318c48 100644 --- a/source/simulation2/scripting/MessageTypeConversions.cpp +++ b/source/simulation2/scripting/MessageTypeConversions.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2019 Wildfire Games. +/* Copyright (C) 2020 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -53,7 +53,7 @@ JS::Value CMessage::ToJSValCached(const ScriptInterface& scriptInterface) const { if (!m_Cached) - m_Cached.reset(new JS::PersistentRootedValue(scriptInterface.GetJSRuntime(), ToJSVal(scriptInterface))); + m_Cached.reset(new JS::PersistentRootedValue(scriptInterface.GetGeneralJSContext(), ToJSVal(scriptInterface))); return m_Cached->get(); } diff --git a/source/simulation2/scripting/ScriptComponent.cpp b/source/simulation2/scripting/ScriptComponent.cpp index b30340b4a8..17202a64af 100644 --- a/source/simulation2/scripting/ScriptComponent.cpp +++ b/source/simulation2/scripting/ScriptComponent.cpp @@ -23,7 +23,7 @@ #include "simulation2/serialization/IDeserializer.h" CComponentTypeScript::CComponentTypeScript(const ScriptInterface& scriptInterface, JS::HandleValue instance) : - m_ScriptInterface(scriptInterface), m_Instance(scriptInterface.GetJSRuntime(), instance) + m_ScriptInterface(scriptInterface), m_Instance(scriptInterface.GetGeneralJSContext(), instance) { // Cache the property detection for efficiency ScriptRequest rq(m_ScriptInterface); diff --git a/source/simulation2/serialization/BinarySerializer.cpp b/source/simulation2/serialization/BinarySerializer.cpp index 7dff1e636f..c8909e725b 100644 --- a/source/simulation2/serialization/BinarySerializer.cpp +++ b/source/simulation2/serialization/BinarySerializer.cpp @@ -272,7 +272,7 @@ void CBinarySerializerScriptImpl::HandleScriptVal(JS::HandleValue val) JS::RootedValue propval(rq.cx); // Forbid getters, which might delete values and mess things up. - JS::Rooted desc(rq.cx); + JS::Rooted desc(rq.cx); if (!JS_GetPropertyDescriptorById(rq.cx, obj, id, &desc)) throw PSERROR_Serialize_ScriptError("JS_GetPropertyDescriptorById failed"); if (desc.hasGetterObject()) diff --git a/source/simulation2/serialization/StdDeserializer.cpp b/source/simulation2/serialization/StdDeserializer.cpp index 9c4689a795..1635aa7427 100644 --- a/source/simulation2/serialization/StdDeserializer.cpp +++ b/source/simulation2/serialization/StdDeserializer.cpp @@ -30,12 +30,12 @@ CStdDeserializer::CStdDeserializer(const ScriptInterface& scriptInterface, std::istream& stream) : m_ScriptInterface(scriptInterface), m_Stream(stream) { - JS_AddExtraGCRootsTracer(m_ScriptInterface.GetJSRuntime(), CStdDeserializer::Trace, this); + JS_AddExtraGCRootsTracer(m_ScriptInterface.GetGeneralJSContext(), CStdDeserializer::Trace, this); } CStdDeserializer::~CStdDeserializer() { - JS_RemoveExtraGCRootsTracer(m_ScriptInterface.GetJSRuntime(), CStdDeserializer::Trace, this); + JS_RemoveExtraGCRootsTracer(m_ScriptInterface.GetGeneralJSContext(), CStdDeserializer::Trace, this); } void CStdDeserializer::Trace(JSTracer *trc, void *data) diff --git a/source/simulation2/system/ComponentManager.cpp b/source/simulation2/system/ComponentManager.cpp index 8bba681c96..cfcfb390a9 100644 --- a/source/simulation2/system/ComponentManager.cpp +++ b/source/simulation2/system/ComponentManager.cpp @@ -43,7 +43,7 @@ public: virtual JS::Value ToJSVal(const ScriptInterface& UNUSED(scriptInterface)) const { return msg.get(); } CMessageScripted(const ScriptInterface& scriptInterface, int mtid, const std::string& name, JS::HandleValue msg) : - mtid(mtid), handlerName("On" + name), globalHandlerName("OnGlobal" + name), msg(scriptInterface.GetJSRuntime(), msg) + mtid(mtid), handlerName("On" + name), globalHandlerName("OnGlobal" + name), msg(scriptInterface.GetGeneralJSContext(), msg) { } @@ -53,9 +53,9 @@ public: JS::PersistentRootedValue msg; }; -CComponentManager::CComponentManager(CSimContext& context, shared_ptr rt, bool skipScriptFunctions) : +CComponentManager::CComponentManager(CSimContext& context, shared_ptr cx, bool skipScriptFunctions) : m_NextScriptComponentTypeId(CID__LastNative), - m_ScriptInterface("Engine", "Simulation", rt), + m_ScriptInterface("Engine", "Simulation", cx), m_SimContext(context), m_CurrentlyHotloading(false) { context.SetComponentManager(this); diff --git a/source/simulation2/system/ComponentManager.h b/source/simulation2/system/ComponentManager.h index 07089d1b21..70fd7be5ad 100644 --- a/source/simulation2/system/ComponentManager.h +++ b/source/simulation2/system/ComponentManager.h @@ -74,7 +74,7 @@ private: }; public: - CComponentManager(CSimContext&, shared_ptr rt, bool skipScriptFunctions = false); + CComponentManager(CSimContext&, shared_ptr cx, bool skipScriptFunctions = false); ~CComponentManager(); void LoadComponentTypes(); diff --git a/source/simulation2/system/TurnManager.cpp b/source/simulation2/system/TurnManager.cpp index 80e946fccb..e78c54f06c 100644 --- a/source/simulation2/system/TurnManager.cpp +++ b/source/simulation2/system/TurnManager.cpp @@ -46,7 +46,7 @@ CTurnManager::CTurnManager(CSimulation2& simulation, u32 defaultTurnLength, int : m_Simulation2(simulation), m_CurrentTurn(0), m_ReadyTurn(1), m_TurnLength(defaultTurnLength), m_PlayerId(-1), m_ClientId(clientId), m_DeltaSimTime(0), m_HasSyncError(false), m_Replay(replay), m_FinalTurn(std::numeric_limits::max()), m_TimeWarpNumTurns(0), - m_QuickSaveMetadata(m_Simulation2.GetScriptInterface().GetJSRuntime()) + m_QuickSaveMetadata(m_Simulation2.GetScriptInterface().GetGeneralJSContext()) { // When we are on turn n, we schedule new commands for n+2. // We know that all other clients have finished scheduling commands for n (else we couldn't have got here). diff --git a/source/simulation2/tests/test_Serializer.h b/source/simulation2/tests/test_Serializer.h index 593c02d5d6..98005999cc 100644 --- a/source/simulation2/tests/test_Serializer.h +++ b/source/simulation2/tests/test_Serializer.h @@ -21,6 +21,7 @@ #include "simulation2/serialization/HashSerializer.h" #include "simulation2/serialization/StdSerializer.h" #include "simulation2/serialization/StdDeserializer.h" +#include "scriptinterface/ScriptContext.h" #include "scriptinterface/ScriptInterface.h" #include "graphics/MapReader.h" @@ -841,7 +842,7 @@ public: LDR_BeginRegistering(); mapReader->LoadMap(L"maps/skirmishes/Greek Acropolis (2).pmp", - sim2.GetScriptInterface().GetJSRuntime(), JS::UndefinedHandleValue, + *sim2.GetScriptInterface().GetContext(), JS::UndefinedHandleValue, &terrain, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &sim2, &sim2.GetSimContext(), -1, false); LDR_EndRegistering();