mirror of
https://gitea.wildfiregames.com/0ad/0ad.git
synced 2026-06-21 01:04:06 +00:00
[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.
This commit is contained in:
@@ -92,7 +92,7 @@ void* CMapGeneratorWorker::RunThread(CMapGeneratorWorker* self)
|
||||
shared_ptr<ScriptContext> 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<ScriptInterface::StructuredClone> CMapGeneratorWorker::GetResults()
|
||||
ScriptInterface::StructuredClone CMapGeneratorWorker::GetResults()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_WorkerMutex);
|
||||
return m_MapData;
|
||||
@@ -232,7 +232,7 @@ void CMapGeneratorWorker::ExportMap(ScriptInterface::CmptPrivate* pCmptPrivate,
|
||||
|
||||
// Copy results
|
||||
std::lock_guard<std::mutex> 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<ScriptInterface::StructuredClone> CMapGenerator::GetResults()
|
||||
ScriptInterface::StructuredClone CMapGenerator::GetResults()
|
||||
{
|
||||
return m_Worker->GetResults();
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ public:
|
||||
*
|
||||
* @return StructuredClone containing map data
|
||||
*/
|
||||
shared_ptr<ScriptInterface::StructuredClone> GetResults();
|
||||
ScriptInterface::StructuredClone GetResults();
|
||||
|
||||
private:
|
||||
CMapGeneratorWorker* m_Worker;
|
||||
@@ -110,7 +110,7 @@ public:
|
||||
*
|
||||
* @return StructuredClone containing map data
|
||||
*/
|
||||
shared_ptr<ScriptInterface::StructuredClone> 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<ScriptInterface::StructuredClone> m_MapData;
|
||||
ScriptInterface::StructuredClone m_MapData;
|
||||
|
||||
/**
|
||||
* Deterministic random number generator.
|
||||
|
||||
@@ -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<ScriptInterface::StructuredClone> results = m_MapGen->GetResults();
|
||||
ScriptInterface::StructuredClone results = m_MapGen->GetResults();
|
||||
|
||||
// Parse data into simulation context
|
||||
JS::RootedValue data(rq.cx);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<ScriptInterface::StructuredClone> 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<ScriptInterface::StructuredClone> 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<ScriptInterface::St
|
||||
m_PageStack.back().LoadPage(m_ScriptContext);
|
||||
}
|
||||
|
||||
void CGUIManager::PopPage(shared_ptr<ScriptInterface::StructuredClone> args)
|
||||
void CGUIManager::PopPage(ScriptInterface::StructuredClone args)
|
||||
{
|
||||
if (m_PageStack.size() < 2)
|
||||
{
|
||||
@@ -121,7 +121,7 @@ void CGUIManager::PopPage(shared_ptr<ScriptInterface::StructuredClone> args)
|
||||
m_PageStack.back().PerformCallbackFunction(args);
|
||||
}
|
||||
|
||||
CGUIManager::SGUIPage::SGUIPage(const CStrW& pageName, const shared_ptr<ScriptInterface::StructuredClone> 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<ScriptIn
|
||||
void CGUIManager::SGUIPage::LoadPage(shared_ptr<ScriptContext> scriptContext)
|
||||
{
|
||||
// If we're hotloading then try to grab some data from the previous page
|
||||
shared_ptr<ScriptInterface::StructuredClone> hotloadData;
|
||||
ScriptInterface::StructuredClone hotloadData;
|
||||
if (gui)
|
||||
{
|
||||
shared_ptr<ScriptInterface> scriptInterface = gui->GetScriptInterface();
|
||||
@@ -138,7 +138,7 @@ void CGUIManager::SGUIPage::LoadPage(shared_ptr<ScriptContext> 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<JS::PersistentRootedValue>(scriptInterface.GetJSRuntime(), callbackFunc);
|
||||
callbackFunction = std::make_shared<JS::PersistentRootedValue>(scriptInterface.GetGeneralJSContext(), callbackFunc);
|
||||
}
|
||||
|
||||
void CGUIManager::SGUIPage::PerformCallbackFunction(shared_ptr<ScriptInterface::StructuredClone> args)
|
||||
void CGUIManager::SGUIPage::PerformCallbackFunction(ScriptInterface::StructuredClone args)
|
||||
{
|
||||
if (!callbackFunction)
|
||||
return;
|
||||
|
||||
@@ -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<ScriptInterface::StructuredClone> 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<ScriptInterface::StructuredClone> 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<ScriptInterface::StructuredClone> 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<ScriptInterface::StructuredClone> args);
|
||||
void PerformCallbackFunction(ScriptInterface::StructuredClone args);
|
||||
|
||||
CStrW name;
|
||||
std::unordered_set<VfsPath> inputs; // for hotloading
|
||||
shared_ptr<ScriptInterface::StructuredClone> initData; // data to be passed to the init() function
|
||||
ScriptInterface::StructuredClone initData; // data to be passed to the init() function
|
||||
shared_ptr<CGUI> gui; // the actual GUI page
|
||||
|
||||
/**
|
||||
|
||||
@@ -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<JSObject*>(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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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[];
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -66,7 +66,7 @@ public:
|
||||
JS::RootedValue val(rq.cx);
|
||||
scriptInterface.CreateObject(rq, &val);
|
||||
|
||||
std::shared_ptr<ScriptInterface::StructuredClone> 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'.
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -389,7 +389,7 @@ void CNetServerWorker::Run()
|
||||
// We create a new ScriptContext for this network thread, with a single ScriptInterface.
|
||||
shared_ptr<ScriptContext> 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)
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
|
||||
+2
-2
@@ -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);
|
||||
|
||||
@@ -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<CStr> g_modsLoaded;
|
||||
|
||||
@@ -488,7 +488,7 @@ namespace
|
||||
const ScriptInterface& m_ScriptInterface;
|
||||
JS::PersistentRooted<JS::Value> 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())
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -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<ScriptInterface::StructuredClone>& 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<ScriptInterface::StructuredClone>& 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)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -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<ScriptInterface::StructuredClone>& 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<ScriptInterface::StructuredClone>& guiMetadataClone);
|
||||
Status SavePrefix(const CStrW& prefix, const CStrW& description, CSimulation2& simulation, const ScriptInterface::StructuredClone& guiMetadataClone);
|
||||
|
||||
/**
|
||||
* Load saved game archive with the given name
|
||||
|
||||
+5
-5
@@ -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(),
|
||||
|
||||
+3
-3
@@ -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.
|
||||
|
||||
@@ -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, "");
|
||||
|
||||
@@ -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<ScriptInterface::StructuredClone> 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<ScriptInterface::StructuredClone> 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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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<R> 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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -23,16 +23,14 @@
|
||||
|
||||
#include <sstream>
|
||||
|
||||
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;
|
||||
|
||||
@@ -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<bool>(const ScriptRequest& rq, JS::HandleValue v, bool& out)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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<ScriptContext>& 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<ScriptContext> ScriptInterface::GetContext() const
|
||||
@@ -560,7 +566,7 @@ bool ScriptInterface::SetGlobal_(const char* name, JS::HandleValue value, bool r
|
||||
return false;
|
||||
if (found)
|
||||
{
|
||||
JS::Rooted<JSPropertyDescriptor> desc(rq.cx);
|
||||
JS::Rooted<JS::PropertyDescriptor> 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> 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::StructuredClone> 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<StructuredClone>();
|
||||
return ScriptInterface::StructuredClone();
|
||||
}
|
||||
|
||||
shared_ptr<StructuredClone> ret(new StructuredClone);
|
||||
ret->m_Data = data;
|
||||
ret->m_Size = nbytes;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ScriptInterface::ReadStructuredClone(const shared_ptr<ScriptInterface::StructuredClone>& 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);
|
||||
}
|
||||
|
||||
@@ -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<ScriptContext> 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<JSStructuredCloneData>;
|
||||
|
||||
shared_ptr<StructuredClone> WriteStructuredClone(JS::HandleValue v) const;
|
||||
void ReadStructuredClone(const shared_ptr<StructuredClone>& 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.
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -55,6 +55,8 @@
|
||||
#if MSC_VERSION
|
||||
// reduce the warning level for the SpiderMonkey headers
|
||||
# pragma warning(push, 1)
|
||||
// ignore C4291 in <mozilla/Vector.h>
|
||||
# pragma warning(disable: 4291)
|
||||
#endif
|
||||
|
||||
#include "jspubtd.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());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -49,11 +49,11 @@
|
||||
class CSimulation2Impl
|
||||
{
|
||||
public:
|
||||
CSimulation2Impl(CUnitManager* unitManager, shared_ptr<ScriptContext> rt, CTerrain* terrain) :
|
||||
m_SimContext(), m_ComponentManager(m_SimContext, rt),
|
||||
CSimulation2Impl(CUnitManager* unitManager, shared_ptr<ScriptContext> 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<SimulationCommand> CloneCommandsFromOtherContext(const ScriptInterface& oldScript, const ScriptInterface& newScript,
|
||||
static std::vector<SimulationCommand> CloneCommandsFromOtherCompartment(const ScriptInterface& oldScript, const ScriptInterface& newScript,
|
||||
const std::vector<SimulationCommand>& commands)
|
||||
{
|
||||
std::vector<SimulationCommand> 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::vector<SimulationComman
|
||||
ScriptRequest rq2(m_SecondaryComponentManager->GetScriptInterface());
|
||||
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::vector<SimulationComman
|
||||
scriptInterface.GetProperty(m_InitAttributes, "map", mapFile);
|
||||
|
||||
VfsPath mapfilename = VfsPath(mapFile).ChangeExtension(L".pmp");
|
||||
mapReader->LoadMap(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::vector<SimulationComman
|
||||
ENSURE(m_ComponentManager.ComputeStateHash(primaryStateAfter.hash, false));
|
||||
|
||||
UpdateComponents(*m_SecondaryContext, turnLengthFixed,
|
||||
CloneCommandsFromOtherContext(scriptInterface, m_SecondaryComponentManager->GetScriptInterface(), 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<ScriptContext> rt, CTerrain* terrain) :
|
||||
m(new CSimulation2Impl(unitManager, rt, terrain))
|
||||
CSimulation2::CSimulation2(CUnitManager* unitManager, shared_ptr<ScriptContext> cx, CTerrain* terrain) :
|
||||
m(new CSimulation2Impl(unitManager, cx, terrain))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -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<ScriptContext> rt, CTerrain* terrain);
|
||||
CSimulation2(CUnitManager* unitManager, shared_ptr<ScriptContext> cx, CTerrain* terrain);
|
||||
~CSimulation2();
|
||||
|
||||
void EnableSerializationTest();
|
||||
|
||||
@@ -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> 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<ScriptInterface> m_ScriptInterface;
|
||||
|
||||
JS::PersistentRootedValue m_Obj;
|
||||
std::vector<shared_ptr<ScriptInterface::StructuredClone> > m_Commands;
|
||||
std::vector<ScriptInterface::StructuredClone > m_Commands;
|
||||
};
|
||||
|
||||
public:
|
||||
struct SCommandSets
|
||||
{
|
||||
player_id_t player;
|
||||
std::vector<shared_ptr<ScriptInterface::StructuredClone> > commands;
|
||||
std::vector<ScriptInterface::StructuredClone > 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<void*> (this));
|
||||
|
||||
JS_AddExtraGCRootsTracer(m_ScriptInterface->GetJSRuntime(), Trace, this);
|
||||
JS_AddExtraGCRootsTracer(m_ScriptInterface->GetGeneralJSContext(), Trace, this);
|
||||
|
||||
m_ScriptInterface->RegisterFunction<void, int, JS::HandleValue, CAIWorker::PostCommand>("PostCommand");
|
||||
m_ScriptInterface->RegisterFunction<void, std::wstring, CAIWorker::IncludeModule>("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<ScriptInterface::StructuredClone>& gameState, const Grid<NavcellData>& passabilityMap, const Grid<u8>& territoryMap,
|
||||
bool RunGamestateInit(const ScriptInterface::StructuredClone& gameState, const Grid<NavcellData>& passabilityMap, const Grid<u8>& territoryMap,
|
||||
const std::map<std::string, pass_class_t>& nonPathfindingPassClassMasks, const std::map<std::string, pass_class_t>& 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<ScriptInterface::StructuredClone>& 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<std::wstring> m_LoadedModules;
|
||||
|
||||
shared_ptr<ScriptInterface::StructuredClone> m_GameState;
|
||||
ScriptInterface::StructuredClone m_GameState;
|
||||
Grid<NavcellData> m_PassabilityMap;
|
||||
JS::PersistentRootedValue m_PassabilityMapVal;
|
||||
Grid<u8> 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<ICmpPathfinder> cmpPathfinder(GetSystemEntity());
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -168,8 +168,11 @@ template<> void ScriptInterface::ToJSVal<CFixedVector3D>(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<CFixedVector2D>(const ScriptRequest& rq, JS::HandleValue v, CFixedVector2D& out)
|
||||
@@ -200,8 +203,11 @@ template<> void ScriptInterface::ToJSVal<CFixedVector2D>(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<Grid<u8> >(const ScriptRequest& rq, JS::MutableHandleValue ret, const Grid<u8>& val)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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<JSPropertyDescriptor> desc(rq.cx);
|
||||
JS::Rooted<JS::PropertyDescriptor> desc(rq.cx);
|
||||
if (!JS_GetPropertyDescriptorById(rq.cx, obj, id, &desc))
|
||||
throw PSERROR_Serialize_ScriptError("JS_GetPropertyDescriptorById failed");
|
||||
if (desc.hasGetterObject())
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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<ScriptContext> rt, bool skipScriptFunctions) :
|
||||
CComponentManager::CComponentManager(CSimContext& context, shared_ptr<ScriptContext> 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);
|
||||
|
||||
@@ -74,7 +74,7 @@ private:
|
||||
};
|
||||
|
||||
public:
|
||||
CComponentManager(CSimContext&, shared_ptr<ScriptContext> rt, bool skipScriptFunctions = false);
|
||||
CComponentManager(CSimContext&, shared_ptr<ScriptContext> cx, bool skipScriptFunctions = false);
|
||||
~CComponentManager();
|
||||
|
||||
void LoadComponentTypes();
|
||||
|
||||
@@ -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<u32>::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).
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user