[SM78 2/2] Update to Spidermonkey 78 APIs
This ugprades 0 A.D. to the latest ESR at the moment of writing. Mostly straighforward API changes (see meta-Bug 1633145) - js::Class is merged with JSClass - JSNewArrayObject becomes JS::NewArrayObject - ArrayObject-functions are moved to a new public header Array.h - JSMSG error messages have again been changed, requiring some tweaks. - AutoValueArray becomes RootedBalueArray (Bug 1634435) - 'uneval' is behind a Realm flag (Bug 1565170), but no removal is planned in the short-term future. - Some minor GC API changes (Bugs 1569564 and 1633405) - Error reporting has had some tweaks, and error flags have been removed (Bug 1620583) - StructuredClone are now always thread-safe, simplifying an API change introduced in SM52 (Bug 1607791) Tested by: Stan, Freagarach, mammadori Closes #5861 Differential Revision: https://code.wildfiregames.com/D3168 This was SVN commit r24333.
This commit is contained in:
parent
6da64bf354
commit
d92a2118b0
@ -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, false);
|
||||
self->m_MapData = self->m_ScriptInterface->WriteStructuredClone(data);
|
||||
self->m_Progress = 0;
|
||||
}
|
||||
|
||||
|
@ -90,7 +90,7 @@ void CGUIManager::SwitchPage(const CStrW& pageName, ScriptInterface* srcScriptIn
|
||||
|
||||
ScriptInterface::StructuredClone initDataClone;
|
||||
if (!initData.isUndefined())
|
||||
initDataClone = srcScriptInterface->WriteStructuredClone(initData, true);
|
||||
initDataClone = srcScriptInterface->WriteStructuredClone(initData);
|
||||
|
||||
m_PageStack.clear();
|
||||
|
||||
@ -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, true);
|
||||
hotloadData = scriptInterface->WriteStructuredClone(hotloadDataVal);
|
||||
}
|
||||
|
||||
g_CursorName = g_DefaultCursor;
|
||||
|
@ -60,7 +60,7 @@ void CHotkeyPicker::FireEvent(const CStr& event)
|
||||
{
|
||||
ScriptRequest rq(*m_pGUI.GetScriptInterface());
|
||||
|
||||
JS::AutoValueArray<1> args(rq.cx);
|
||||
JS::RootedValueArray<1> args(rq.cx);
|
||||
JS::RootedValue keys(rq.cx);
|
||||
m_pGUI.GetScriptInterface()->ToJSVal(rq, &keys, m_KeysPressed);
|
||||
args[0].set(keys);
|
||||
|
@ -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, true), callbackFunction);
|
||||
g_GUI->PushPage(name, pCmptPrivate->pScriptInterface->WriteStructuredClone(initData), 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, true));
|
||||
g_GUI->PopPage(pCmptPrivate->pScriptInterface->WriteStructuredClone(args));
|
||||
}
|
||||
|
||||
JS::Value JSI_GUIManager::GetGUIObjectByName(ScriptInterface::CmptPrivate* pCmptPrivate, const std::string& name)
|
||||
|
@ -49,7 +49,7 @@ class JSI_GUIProxy : public js::BaseProxyHandler
|
||||
{
|
||||
public:
|
||||
// Access the js::Class of the Proxy.
|
||||
static js::Class& ClassDefinition();
|
||||
static JSClass& ClassDefinition();
|
||||
|
||||
// For convenience, this is the single instantiated JSI_GUIProxy.
|
||||
static JSI_GUIProxy& Singleton();
|
||||
|
@ -18,9 +18,9 @@
|
||||
// This file is included directly into actual implementation files.
|
||||
|
||||
template <typename T>
|
||||
js::Class& JSI_GUIProxy<T>::ClassDefinition()
|
||||
JSClass& JSI_GUIProxy<T>::ClassDefinition()
|
||||
{
|
||||
static js::Class c = PROXY_CLASS_DEF("GUIObjectProxy", JSCLASS_HAS_CACHED_PROTO(JSProto_Proxy) | JSCLASS_HAS_RESERVED_SLOTS(1));
|
||||
static JSClass c = PROXY_CLASS_DEF("GUIObjectProxy", JSCLASS_HAS_CACHED_PROTO(JSProto_Proxy) | JSCLASS_HAS_RESERVED_SLOTS(1));
|
||||
return c;
|
||||
}
|
||||
|
||||
@ -123,23 +123,26 @@ bool JSI_GUIProxy<T>::set(JSContext* cx, JS::HandleObject proxy, JS::HandleId id
|
||||
{
|
||||
T* e = static_cast<T*>(js::GetProxyPrivate(proxy.get()).toPrivate());
|
||||
if (!e)
|
||||
return result.fail(JSMSG_NOT_NONNULL_OBJECT);
|
||||
{
|
||||
LOGERROR("C++ GUI Object could not be found");
|
||||
return result.fail(JSMSG_OBJECT_REQUIRED);
|
||||
}
|
||||
|
||||
ScriptRequest rq(*ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface);
|
||||
|
||||
JS::RootedValue idval(rq.cx);
|
||||
if (!JS_IdToValue(rq.cx, id, &idval))
|
||||
return result.fail(JSMSG_NOT_NONNULL_OBJECT);
|
||||
return result.fail(JSMSG_BAD_PROP_ID);
|
||||
|
||||
std::string propName;
|
||||
if (!ScriptInterface::FromJSVal(rq, idval, propName))
|
||||
return result.fail(JSMSG_UNDEFINED_PROP);
|
||||
return result.fail(JSMSG_BAD_PROP_ID);
|
||||
|
||||
if (propName == "name")
|
||||
{
|
||||
std::string value;
|
||||
if (!ScriptInterface::FromJSVal(rq, vp, value))
|
||||
return result.fail(JSMSG_UNDEFINED_PROP);
|
||||
return result.fail(JSMSG_BAD_PROP_ID);
|
||||
e->SetName(value);
|
||||
return result.succeed();
|
||||
}
|
||||
@ -167,7 +170,7 @@ bool JSI_GUIProxy<T>::set(JSContext* cx, JS::HandleObject proxy, JS::HandleId id
|
||||
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);
|
||||
return result.fail(JSMSG_BAD_PROP_ID);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
@ -175,17 +178,20 @@ bool JSI_GUIProxy<T>::delete_(JSContext* cx, JS::HandleObject proxy, JS::HandleI
|
||||
{
|
||||
T* e = static_cast<T*>(js::GetProxyPrivate(proxy.get()).toPrivate());
|
||||
if (!e)
|
||||
return result.fail(JSMSG_NOT_NONNULL_OBJECT);
|
||||
{
|
||||
LOGERROR("C++ GUI Object could not be found");
|
||||
return result.fail(JSMSG_OBJECT_REQUIRED);
|
||||
}
|
||||
|
||||
ScriptRequest rq(*ScriptInterface::GetScriptInterfaceAndCBData(cx)->pScriptInterface);
|
||||
|
||||
JS::RootedValue idval(rq.cx);
|
||||
if (!JS_IdToValue(rq.cx, id, &idval))
|
||||
return result.fail(JSMSG_NOT_NONNULL_OBJECT);
|
||||
return result.fail(JSMSG_BAD_PROP_ID);
|
||||
|
||||
std::string propName;
|
||||
if (!ScriptInterface::FromJSVal(rq, idval, propName))
|
||||
return result.fail(JSMSG_UNDEFINED_PROP);
|
||||
return result.fail(JSMSG_BAD_PROP_ID);
|
||||
|
||||
// event handlers
|
||||
if (propName.substr(0, 2) == "on")
|
||||
@ -196,5 +202,5 @@ bool JSI_GUIProxy<T>::delete_(JSContext* cx, JS::HandleObject proxy, JS::HandleI
|
||||
}
|
||||
|
||||
LOGERROR("Only event handlers can be deleted from GUI objects!");
|
||||
return result.fail(JSMSG_UNDEFINED_PROP);
|
||||
return result.fail(JSMSG_BAD_PROP_ID);
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ public:
|
||||
JS::RootedValue val(rq.cx);
|
||||
scriptInterface.CreateObject(rq, &val);
|
||||
|
||||
ScriptInterface::StructuredClone data = scriptInterface.WriteStructuredClone(JS::NullHandleValue, true);
|
||||
ScriptInterface::StructuredClone data = scriptInterface.WriteStructuredClone(JS::NullHandleValue);
|
||||
g_GUI->PushPage(L"hotkey/page_hotkey.xml", data, JS::UndefinedHandleValue);
|
||||
|
||||
// Press 'a'.
|
||||
|
@ -737,7 +737,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, false);
|
||||
return scriptInterface.CloneValueFromOtherCompartment(*m_ScriptInterface, messages);
|
||||
}
|
||||
|
||||
JS::Value XmppClient::GuiPollHistoricMessages(const ScriptInterface& scriptInterface)
|
||||
@ -755,7 +755,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, false);
|
||||
return scriptInterface.CloneValueFromOtherCompartment(*m_ScriptInterface, messages);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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, false);
|
||||
return pCmptPrivate->pScriptInterface->CloneValueFromOtherCompartment(g_NetClient->GetScriptInterface(), pollNet);
|
||||
}
|
||||
|
||||
void JSI_Network::SetNetworkGameAttributes(ScriptInterface::CmptPrivate* pCmptPrivate, JS::HandleValue attribs1)
|
||||
|
@ -607,7 +607,7 @@ bool ModIo::ParseGameIdResponse(const ScriptInterface& scriptInterface, const st
|
||||
JS::RootedObject data(rq.cx, dataVal.toObjectOrNull());
|
||||
u32 length;
|
||||
bool isArray;
|
||||
if (!JS_IsArrayObject(rq.cx, data, &isArray) || !isArray || !JS_GetArrayLength(rq.cx, data, &length) || !length)
|
||||
if (!JS::IsArrayObject(rq.cx, data, &isArray) || !isArray || !JS::GetArrayLength(rq.cx, data, &length) || !length)
|
||||
FAIL("data property not an array with at least one element.");
|
||||
|
||||
// {"id": 42, ...}
|
||||
@ -678,7 +678,7 @@ bool ModIo::ParseModsResponse(const ScriptInterface& scriptInterface, const std:
|
||||
JS::RootedObject rData(rq.cx, dataVal.toObjectOrNull());
|
||||
u32 length;
|
||||
bool isArray;
|
||||
if (!JS_IsArrayObject(rq.cx, rData, &isArray) || !isArray || !JS_GetArrayLength(rq.cx, rData, &length) || !length)
|
||||
if (!JS::IsArrayObject(rq.cx, rData, &isArray) || !isArray || !JS::GetArrayLength(rq.cx, rData, &length) || !length)
|
||||
FAIL("data property not an array with at least one element.");
|
||||
|
||||
modData.clear();
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "ps/Replay.h"
|
||||
#include "ps/Util.h"
|
||||
#include "scriptinterface/ScriptInterface.h"
|
||||
#include "scriptinterface/ScriptExtraHeaders.h"
|
||||
|
||||
/**
|
||||
* Filter too short replays (value in seconds).
|
||||
@ -85,7 +86,7 @@ bool VisualReplay::ReadCacheFile(const ScriptInterface& scriptInterface, JS::Mut
|
||||
{
|
||||
cachedReplaysObject.set(&cachedReplays.toObject());
|
||||
bool isArray;
|
||||
if (JS_IsArrayObject(rq.cx, cachedReplaysObject, &isArray) && isArray)
|
||||
if (JS::IsArrayObject(rq.cx, cachedReplaysObject, &isArray) && isArray)
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -123,7 +124,7 @@ JS::HandleObject VisualReplay::ReloadReplayCache(const ScriptInterface& scriptIn
|
||||
{
|
||||
// Create list of files included in the cache
|
||||
u32 cacheLength = 0;
|
||||
JS_GetArrayLength(rq.cx, cachedReplaysObject, &cacheLength);
|
||||
JS::GetArrayLength(rq.cx, cachedReplaysObject, &cacheLength);
|
||||
for (u32 j = 0; j < cacheLength; ++j)
|
||||
{
|
||||
JS::RootedValue replay(rq.cx);
|
||||
@ -139,7 +140,7 @@ JS::HandleObject VisualReplay::ReloadReplayCache(const ScriptInterface& scriptIn
|
||||
}
|
||||
}
|
||||
|
||||
JS::RootedObject replays(rq.cx, JS_NewArrayObject(rq.cx, 0));
|
||||
JS::RootedObject replays(rq.cx, JS::NewArrayObject(rq.cx, 0));
|
||||
DirectoryNames directories;
|
||||
|
||||
if (GetDirectoryEntries(GetDirectoryPath(), nullptr, &directories) != INFO::OK)
|
||||
@ -236,7 +237,7 @@ JS::Value VisualReplay::GetReplays(const ScriptInterface& scriptInterface, bool
|
||||
ScriptInterface::CreateArray(rq, &replaysWithoutNullEntries);
|
||||
|
||||
u32 replaysLength = 0;
|
||||
JS_GetArrayLength(rq.cx, replays, &replaysLength);
|
||||
JS::GetArrayLength(rq.cx, replays, &replaysLength);
|
||||
for (u32 j = 0, i = 0; j < replaysLength; ++j)
|
||||
{
|
||||
JS::RootedValue replay(rq.cx);
|
||||
@ -458,10 +459,10 @@ void VisualReplay::AddReplayToCache(const ScriptInterface& scriptInterface, cons
|
||||
|
||||
JS::RootedObject cachedReplaysObject(rq.cx);
|
||||
if (!ReadCacheFile(scriptInterface, &cachedReplaysObject))
|
||||
cachedReplaysObject = JS_NewArrayObject(rq.cx, 0);
|
||||
cachedReplaysObject = JS::NewArrayObject(rq.cx, 0);
|
||||
|
||||
u32 cacheLength = 0;
|
||||
JS_GetArrayLength(rq.cx, cachedReplaysObject, &cacheLength);
|
||||
JS::GetArrayLength(rq.cx, cachedReplaysObject, &cacheLength);
|
||||
JS_SetElement(rq.cx, cachedReplaysObject, cacheLength, replayData);
|
||||
|
||||
StoreCacheFile(scriptInterface, cachedReplaysObject);
|
||||
|
@ -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, false));
|
||||
sim->GetScriptInterface().CloneValueFromOtherCompartment(*(pCmptPrivate->pScriptInterface), attribs));
|
||||
|
||||
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)
|
||||
{
|
||||
ScriptInterface::StructuredClone GUIMetadataClone = pCmptPrivate->pScriptInterface->WriteStructuredClone(GUIMetadata, false);
|
||||
ScriptInterface::StructuredClone GUIMetadataClone = pCmptPrivate->pScriptInterface->WriteStructuredClone(GUIMetadata);
|
||||
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)
|
||||
{
|
||||
ScriptInterface::StructuredClone GUIMetadataClone = pCmptPrivate->pScriptInterface->WriteStructuredClone(GUIMetadata, false);
|
||||
ScriptInterface::StructuredClone GUIMetadataClone = pCmptPrivate->pScriptInterface->WriteStructuredClone(GUIMetadata);
|
||||
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, false));
|
||||
sim->GetScriptInterface().CloneValueFromOtherCompartment(*(pCmptPrivate->pScriptInterface), guiContextMetadata));
|
||||
JS::RootedValue gameInitAttributes(rqGame.cx);
|
||||
sim->GetScriptInterface().GetProperty(gameContextMetadata, "initAttributes", &gameInitAttributes);
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "ps/CLogger.h"
|
||||
#include "ps/CStr.h"
|
||||
#include "ps/Filesystem.h"
|
||||
#include "scriptinterface/ScriptExtraHeaders.h"
|
||||
#include "scriptinterface/ScriptInterface.h"
|
||||
|
||||
#include <sstream>
|
||||
@ -58,7 +59,7 @@ struct BuildDirEntListState
|
||||
cur_idx(0)
|
||||
{
|
||||
ScriptRequest rq(pScriptInterface);
|
||||
filename_array = JS_NewArrayObject(rq.cx, JS::HandleValueArray::empty());
|
||||
filename_array = JS::NewArrayObject(rq.cx, JS::HandleValueArray::empty());
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -89,20 +89,15 @@ ScriptContext::ScriptContext(int contextSize, int heapGrowthBytesGCTrigger):
|
||||
{
|
||||
ENSURE(ScriptEngine::IsInitialised() && "The ScriptEngine must be initialized before constructing any ScriptContexts!");
|
||||
|
||||
m_cx = JS_NewContext(contextSize, JS::DefaultNurseryBytes, nullptr);
|
||||
m_cx = JS_NewContext(contextSize);
|
||||
ENSURE(m_cx); // TODO: error handling
|
||||
|
||||
ENSURE(JS::InitSelfHostedCode(m_cx));
|
||||
|
||||
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_cx, JSGC_DYNAMIC_HEAP_GROWTH, false);
|
||||
JS_SetGCParameter(m_cx, JSGC_MODE, JSGC_MODE_ZONE_INCREMENTAL);
|
||||
|
||||
JS_SetOffthreadIonCompilationEnabled(m_cx, true);
|
||||
|
||||
@ -114,10 +109,7 @@ ScriptContext::ScriptContext(int contextSize, int heapGrowthBytesGCTrigger):
|
||||
JS_SetGlobalJitCompilerOption(m_cx, JSJITCOMPILER_ION_ENABLE, 1);
|
||||
JS_SetGlobalJitCompilerOption(m_cx, JSJITCOMPILER_BASELINE_ENABLE, 1);
|
||||
|
||||
JS::ContextOptionsRef(m_cx)
|
||||
.setExtraWarnings(true)
|
||||
.setWerror(false)
|
||||
.setStrictMode(true);
|
||||
JS::ContextOptionsRef(m_cx).setStrictMode(true);
|
||||
|
||||
ScriptEngine::GetSingleton().RegisterContext(m_cx);
|
||||
}
|
||||
|
@ -25,7 +25,7 @@
|
||||
|
||||
template<typename T> static void ToJSVal_vector(const ScriptRequest& rq, JS::MutableHandleValue ret, const std::vector<T>& val)
|
||||
{
|
||||
JS::RootedObject obj(rq.cx, JS_NewArrayObject(rq.cx, 0));
|
||||
JS::RootedObject obj(rq.cx, JS::NewArrayObject(rq.cx, 0));
|
||||
if (!obj)
|
||||
{
|
||||
ret.setUndefined();
|
||||
@ -52,11 +52,11 @@ template<typename T> static bool FromJSVal_vector(const ScriptRequest& rq, JS::H
|
||||
|
||||
bool isArray;
|
||||
obj = &v.toObject();
|
||||
if ((!JS_IsArrayObject(rq.cx, obj, &isArray) || !isArray) && !JS_IsTypedArrayObject(obj))
|
||||
if ((!JS::IsArrayObject(rq.cx, obj, &isArray) || !isArray) && !JS_IsTypedArrayObject(obj))
|
||||
FAIL("Argument must be an array");
|
||||
|
||||
u32 length;
|
||||
if (!JS_GetArrayLength(rq.cx, obj, &length))
|
||||
if (!JS::GetArrayLength(rq.cx, obj, &length))
|
||||
FAIL("Failed to get array length");
|
||||
|
||||
out.reserve(length);
|
||||
|
@ -67,7 +67,7 @@ bool ScriptException::CatchPending(const ScriptRequest& rq)
|
||||
}
|
||||
|
||||
std::stringstream msg;
|
||||
msg << (JSREPORT_IS_EXCEPTION(report->flags) ? "JavaScript exception: " : "JavaScript error: ");
|
||||
msg << "JavaScript error: ";
|
||||
if (report->filename)
|
||||
{
|
||||
msg << report->filename;
|
||||
|
@ -47,20 +47,19 @@
|
||||
|
||||
#include "jsfriendapi.h"
|
||||
|
||||
#include "js/Array.h"
|
||||
#include "js/ArrayBuffer.h"
|
||||
#include "js/CompilationAndEvaluation.h"
|
||||
#include "js/Conversions.h"
|
||||
#include "js/ContextOptions.h"
|
||||
#include "js/ForOfIterator.h"
|
||||
#include "js/GCAPI.h"
|
||||
#include "js/JSON.h"
|
||||
#include "js/SourceText.h"
|
||||
#include "js/StructuredClone.h"
|
||||
#include "js/Proxy.h"
|
||||
#include "js/Warnings.h"
|
||||
|
||||
// CompileFunction & Evaluate
|
||||
#include "js/CompilationAndEvaluation.h"
|
||||
#include "js/SourceText.h"
|
||||
|
||||
#undef signbit
|
||||
|
||||
#if MSC_VERSION
|
||||
|
@ -324,6 +324,8 @@ ScriptInterface_impl::ScriptInterface_impl(const char* nativeScopeName, const sh
|
||||
JS::RealmCreationOptions creationOpt;
|
||||
// Keep JIT code during non-shrinking GCs. This brings a quite big performance improvement.
|
||||
creationOpt.setPreserveJitCode(true);
|
||||
// Enable uneval
|
||||
creationOpt.setToSourceEnabled(true);
|
||||
JS::RealmOptions opt(creationOpt, JS::RealmBehaviors{});
|
||||
|
||||
m_glob = JS_NewGlobalObject(m_cx, &global_class, nullptr, JS::OnNewGlobalHookOption::FireOnNewGlobalHook, opt);
|
||||
@ -543,7 +545,7 @@ bool ScriptInterface::CreateObject_(const ScriptRequest& rq, JS::MutableHandleOb
|
||||
|
||||
void ScriptInterface::CreateArray(const ScriptRequest& rq, JS::MutableHandleValue objectValue, size_t length)
|
||||
{
|
||||
objectValue.setObjectOrNull(JS_NewArrayObject(rq.cx, length));
|
||||
objectValue.setObjectOrNull(JS::NewArrayObject(rq.cx, length));
|
||||
if (!objectValue.isObject())
|
||||
throw PSERROR_Scripting_CreateObjectFailed();
|
||||
}
|
||||
@ -982,25 +984,22 @@ 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, bool sameThread) const
|
||||
JS::Value ScriptInterface::CloneValueFromOtherCompartment(const ScriptInterface& otherCompartment, JS::HandleValue val) const
|
||||
{
|
||||
PROFILE("CloneValueFromOtherCompartment");
|
||||
ScriptRequest rq(this);
|
||||
JS::RootedValue out(rq.cx);
|
||||
ScriptInterface::StructuredClone structuredClone = otherCompartment.WriteStructuredClone(val, sameThread);
|
||||
ScriptInterface::StructuredClone structuredClone = otherCompartment.WriteStructuredClone(val);
|
||||
ReadStructuredClone(structuredClone, &out);
|
||||
return out.get();
|
||||
}
|
||||
|
||||
ScriptInterface::StructuredClone ScriptInterface::WriteStructuredClone(JS::HandleValue v, bool sameThread) const
|
||||
ScriptInterface::StructuredClone ScriptInterface::WriteStructuredClone(JS::HandleValue v) const
|
||||
{
|
||||
ScriptRequest rq(this);
|
||||
|
||||
JS::StructuredCloneScope scope = sameThread ? JS::StructuredCloneScope::SameProcessSameThread : JS::StructuredCloneScope::SameProcessDifferentThread;
|
||||
ScriptInterface::StructuredClone ret(new JSStructuredCloneData(scope));
|
||||
ScriptInterface::StructuredClone ret(new JSStructuredCloneData(JS::StructuredCloneScope::SameProcess));
|
||||
JS::CloneDataPolicy policy;
|
||||
|
||||
if (!JS_WriteStructuredClone(rq.cx, v, ret.get(), scope, policy, nullptr, nullptr, JS::UndefinedHandleValue))
|
||||
if (!JS_WriteStructuredClone(rq.cx, v, ret.get(), JS::StructuredCloneScope::SameProcess, policy, nullptr, nullptr, JS::UndefinedHandleValue))
|
||||
{
|
||||
debug_warn(L"Writing a structured clone with JS_WriteStructuredClone failed!");
|
||||
ScriptException::CatchPending(rq);
|
||||
@ -1013,6 +1012,7 @@ ScriptInterface::StructuredClone ScriptInterface::WriteStructuredClone(JS::Handl
|
||||
void ScriptInterface::ReadStructuredClone(const ScriptInterface::StructuredClone& ptr, JS::MutableHandleValue ret) const
|
||||
{
|
||||
ScriptRequest rq(this);
|
||||
if (!JS_ReadStructuredClone(rq.cx, *ptr, JS_STRUCTURED_CLONE_VERSION, ptr->scope(), ret, nullptr, nullptr))
|
||||
JS::CloneDataPolicy policy;
|
||||
if (!JS_ReadStructuredClone(rq.cx, *ptr, JS_STRUCTURED_CLONE_VERSION, ptr->scope(), ret, policy, nullptr, nullptr))
|
||||
ScriptException::CatchPending(rq);
|
||||
}
|
||||
|
@ -337,7 +337,7 @@ public:
|
||||
*/
|
||||
using StructuredClone = shared_ptr<JSStructuredCloneData>;
|
||||
|
||||
StructuredClone WriteStructuredClone(JS::HandleValue v, bool sameThread) const;
|
||||
StructuredClone WriteStructuredClone(JS::HandleValue v) const;
|
||||
void ReadStructuredClone(const StructuredClone& ptr, JS::MutableHandleValue ret) const;
|
||||
|
||||
/**
|
||||
@ -346,7 +346,7 @@ public:
|
||||
* 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;
|
||||
JS::Value CloneValueFromOtherCompartment(const ScriptInterface& otherCompartment, JS::HandleValue val) const;
|
||||
|
||||
/**
|
||||
* Retrieve the private data field of a JSObject that is an instance of the given JSClass.
|
||||
|
@ -26,7 +26,6 @@ CScriptStatsTable* g_ScriptStatsTable;
|
||||
enum
|
||||
{
|
||||
Row_MaxBytes,
|
||||
Row_MaxMallocBytes,
|
||||
Row_Bytes,
|
||||
Row_NumberGC,
|
||||
NumberRows
|
||||
@ -87,13 +86,6 @@ CStr CScriptStatsTable::GetCellText(size_t row, size_t col)
|
||||
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->GetGeneralJSContext(), JSGC_MAX_MALLOC_BYTES);
|
||||
return CStr::FromUInt(n);
|
||||
}
|
||||
case Row_Bytes:
|
||||
{
|
||||
if (col == 0)
|
||||
|
@ -72,7 +72,7 @@ public:
|
||||
{
|
||||
ScriptRequest rq2(script2);
|
||||
|
||||
JS::RootedValue obj2(rq2.cx, script2.CloneValueFromOtherCompartment(script1, obj1, true));
|
||||
JS::RootedValue obj2(rq2.cx, script2.CloneValueFromOtherCompartment(script1, obj1));
|
||||
|
||||
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, true));
|
||||
JS::RootedValue obj2(rq2.cx, script2.CloneValueFromOtherCompartment(script1, obj1));
|
||||
|
||||
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, true));
|
||||
JS::RootedValue obj2(rq2.cx, script2.CloneValueFromOtherCompartment(script1, obj1));
|
||||
|
||||
// Use JSAPI function to check if the values of the properties "a", "b" are equals a.x[0]
|
||||
JS::RootedValue prop_a(rq2.cx);
|
||||
|
@ -173,7 +173,7 @@ public:
|
||||
ScriptRequest rqNew(newScript);
|
||||
for (const SimulationCommand& command : commands)
|
||||
{
|
||||
JS::RootedValue tmpCommand(rqNew.cx, newScript.CloneValueFromOtherCompartment(oldScript, command.data, true));
|
||||
JS::RootedValue tmpCommand(rqNew.cx, newScript.CloneValueFromOtherCompartment(oldScript, command.data));
|
||||
newScript.FreezeObject(tmpCommand, true);
|
||||
SimulationCommand cmd(command.player, rqNew.cx, tmpCommand);
|
||||
newCommands.emplace_back(std::move(cmd));
|
||||
@ -423,8 +423,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, true));
|
||||
m_SecondaryComponentManager->GetScriptInterface().CloneValueFromOtherCompartment(scriptInterface, m_MapSettings));
|
||||
ENSURE(LoadTriggerScripts(*m_SecondaryComponentManager, mapSettingsCloned, m_SecondaryLoadedScripts));
|
||||
}
|
||||
|
||||
|
@ -299,7 +299,7 @@ public:
|
||||
{
|
||||
if (m_Players[i]->m_Player == playerid)
|
||||
{
|
||||
m_Players[i]->m_Commands.push_back(m_ScriptInterface->WriteStructuredClone(cmd, false));
|
||||
m_Players[i]->m_Commands.push_back(m_ScriptInterface->WriteStructuredClone(cmd));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -557,7 +557,7 @@ public:
|
||||
JS::RootedObject dataObj(rq.cx, &mapData.toObject());
|
||||
|
||||
u32 length = 0;
|
||||
ENSURE(JS_GetArrayLength(rq.cx, dataObj, &length));
|
||||
ENSURE(JS::GetArrayLength(rq.cx, dataObj, &length));
|
||||
u32 nbytes = (u32)(length * sizeof(NavcellData));
|
||||
|
||||
bool sharedMemory;
|
||||
@ -585,7 +585,7 @@ public:
|
||||
JS::RootedObject dataObj(rq.cx, &mapData.toObject());
|
||||
|
||||
u32 length = 0;
|
||||
ENSURE(JS_GetArrayLength(rq.cx, dataObj, &length));
|
||||
ENSURE(JS::GetArrayLength(rq.cx, dataObj, &length));
|
||||
u32 nbytes = (u32)(length * sizeof(u8));
|
||||
|
||||
bool sharedMemory;
|
||||
@ -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, false));
|
||||
m_Players.back()->m_Commands.push_back(m_ScriptInterface->WriteStructuredClone(val));
|
||||
}
|
||||
|
||||
bool hasCustomDeserialize = m_ScriptInterface->HasProperty(m_Players.back()->m_Obj, "Deserialize");
|
||||
@ -1016,7 +1016,7 @@ public:
|
||||
if (cmpPathfinder)
|
||||
cmpPathfinder->GetPassabilityClasses(nonPathfindingPassClassMasks, pathfindingPassClassMasks);
|
||||
|
||||
m_Worker.RunGamestateInit(scriptInterface.WriteStructuredClone(state, false),
|
||||
m_Worker.RunGamestateInit(scriptInterface.WriteStructuredClone(state),
|
||||
*passabilityMap, *territoryMap, nonPathfindingPassClassMasks, pathfindingPassClassMasks);
|
||||
}
|
||||
|
||||
@ -1042,7 +1042,7 @@ public:
|
||||
LoadPathfinderClasses(state); // add the pathfinding classes to it
|
||||
|
||||
// Update the game state
|
||||
m_Worker.UpdateGameState(scriptInterface.WriteStructuredClone(state, false));
|
||||
m_Worker.UpdateGameState(scriptInterface.WriteStructuredClone(state));
|
||||
|
||||
// Update the pathfinding data
|
||||
CmpPtr<ICmpPathfinder> cmpPathfinder(GetSystemEntity());
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "ICmpAIManager.h"
|
||||
|
||||
#include "simulation2/system/InterfaceScripted.h"
|
||||
#include "scriptinterface/ScriptExtraHeaders.h"
|
||||
|
||||
#include "lib/file/vfs/vfs_util.h"
|
||||
#include "ps/Filesystem.h"
|
||||
@ -42,7 +43,7 @@ public:
|
||||
m_AIs(scriptInterface.GetGeneralJSContext())
|
||||
{
|
||||
ScriptRequest rq(m_ScriptInterface);
|
||||
m_AIs = JS_NewArrayObject(rq.cx, 0);
|
||||
m_AIs = JS::NewArrayObject(rq.cx, 0);
|
||||
}
|
||||
|
||||
void Run()
|
||||
@ -69,7 +70,7 @@ public:
|
||||
self->m_ScriptInterface.SetProperty(ai, "id", dirname, true);
|
||||
self->m_ScriptInterface.SetProperty(ai, "data", data, true);
|
||||
u32 length;
|
||||
JS_GetArrayLength(rq.cx, self->m_AIs, &length);
|
||||
JS::GetArrayLength(rq.cx, self->m_AIs, &length);
|
||||
JS_SetElement(rq.cx, self->m_AIs, length, ai);
|
||||
|
||||
return INFO::OK;
|
||||
|
@ -163,7 +163,7 @@ template<> void ScriptInterface::ToJSVal<CFixedVector3D>(const ScriptRequest& rq
|
||||
if (!JS_GetProperty(rq.cx, global, "Vector3D", &valueVector3D))
|
||||
FAIL_VOID("Failed to get Vector3D constructor");
|
||||
|
||||
JS::AutoValueArray<3> args(rq.cx);
|
||||
JS::RootedValueArray<3> args(rq.cx);
|
||||
args[0].setNumber(val.X.ToDouble());
|
||||
args[1].setNumber(val.Y.ToDouble());
|
||||
args[2].setNumber(val.Z.ToDouble());
|
||||
@ -199,7 +199,7 @@ template<> void ScriptInterface::ToJSVal<CFixedVector2D>(const ScriptRequest& rq
|
||||
if (!JS_GetProperty(rq.cx, global, "Vector2D", &valueVector2D))
|
||||
FAIL_VOID("Failed to get Vector2D constructor");
|
||||
|
||||
JS::AutoValueArray<2> args(rq.cx);
|
||||
JS::RootedValueArray<2> args(rq.cx);
|
||||
args[0].setNumber(val.X.ToDouble());
|
||||
args[1].setNumber(val.Y.ToDouble());
|
||||
|
||||
@ -259,11 +259,11 @@ template<> bool ScriptInterface::FromJSVal<TNSpline>(const ScriptRequest& rq, J
|
||||
|
||||
JS::RootedObject obj(rq.cx, &v.toObject());
|
||||
bool isArray;
|
||||
if (!JS_IsArrayObject(rq.cx, obj, &isArray) || !isArray)
|
||||
if (!JS::IsArrayObject(rq.cx, obj, &isArray) || !isArray)
|
||||
FAIL("Argument must be an array");
|
||||
|
||||
u32 numberOfNodes = 0;
|
||||
if (!JS_GetArrayLength(rq.cx, obj, &numberOfNodes))
|
||||
if (!JS::GetArrayLength(rq.cx, obj, &numberOfNodes))
|
||||
FAIL("Failed to get array length");
|
||||
|
||||
for (u32 i = 0; i < numberOfNodes; ++i)
|
||||
|
@ -52,11 +52,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, false));
|
||||
JS::RootedValue arg(rqSim.cx, sim->GetScriptInterface().CloneValueFromOtherCompartment(*(pCmptPrivate->pScriptInterface), data));
|
||||
JS::RootedValue ret(rqSim.cx);
|
||||
cmpGuiInterface->ScriptCall(g_Game->GetViewedPlayerID(), name, arg, &ret);
|
||||
|
||||
return pCmptPrivate->pScriptInterface->CloneValueFromOtherCompartment(sim->GetScriptInterface(), ret, false);
|
||||
return pCmptPrivate->pScriptInterface->CloneValueFromOtherCompartment(sim->GetScriptInterface(), ret);
|
||||
}
|
||||
|
||||
void JSI_Simulation::PostNetworkCommand(ScriptInterface::CmptPrivate* pCmptPrivate, JS::HandleValue cmd)
|
||||
@ -73,7 +73,7 @@ void JSI_Simulation::PostNetworkCommand(ScriptInterface::CmptPrivate* pCmptPriva
|
||||
|
||||
ScriptRequest rqSim(sim->GetScriptInterface());
|
||||
JS::RootedValue cmd2(rqSim.cx,
|
||||
sim->GetScriptInterface().CloneValueFromOtherCompartment(*(pCmptPrivate->pScriptInterface), cmd, false));
|
||||
sim->GetScriptInterface().CloneValueFromOtherCompartment(*(pCmptPrivate->pScriptInterface), cmd));
|
||||
|
||||
cmpCommandQueue->PostNetworkCommand(cmd2);
|
||||
}
|
||||
|
@ -102,7 +102,7 @@ void CBinarySerializerScriptImpl::HandleScriptVal(JS::HandleValue val)
|
||||
bool isMap;
|
||||
bool isSet;
|
||||
|
||||
if (JS_IsArrayObject(rq.cx, obj, &isArray) && isArray)
|
||||
if (JS::IsArrayObject(rq.cx, obj, &isArray) && isArray)
|
||||
{
|
||||
m_Serializer.NumberU8_Unbounded("type", SCRIPT_TYPE_ARRAY);
|
||||
// TODO: probably should have a more efficient storage format
|
||||
@ -110,8 +110,8 @@ void CBinarySerializerScriptImpl::HandleScriptVal(JS::HandleValue val)
|
||||
// Arrays like [1, 2, ] have an 'undefined' at the end which is part of the
|
||||
// length but seemingly isn't enumerated, so store the length explicitly
|
||||
uint length = 0;
|
||||
if (!JS_GetArrayLength(rq.cx, obj, &length))
|
||||
throw PSERROR_Serialize_ScriptError("JS_GetArrayLength failed");
|
||||
if (!JS::GetArrayLength(rq.cx, obj, &length))
|
||||
throw PSERROR_Serialize_ScriptError("JS::GetArrayLength failed");
|
||||
m_Serializer.NumberU32_Unbounded("array length", length);
|
||||
}
|
||||
else if (JS_IsTypedArrayObject(obj))
|
||||
|
@ -136,7 +136,7 @@ JS::Value CStdDeserializer::ReadScriptVal(const char* UNUSED(name), JS::HandleOb
|
||||
{
|
||||
u32 length;
|
||||
NumberU32_Unbounded("array length", length);
|
||||
obj.set(JS_NewArrayObject(rq.cx, length));
|
||||
obj.set(JS::NewArrayObject(rq.cx, length));
|
||||
}
|
||||
else // SCRIPT_TYPE_OBJECT
|
||||
{
|
||||
|
@ -354,7 +354,7 @@ void CTurnManager::QuickLoad()
|
||||
return;
|
||||
}
|
||||
|
||||
JS::AutoValueArray<1> paramData(rq.cx);
|
||||
JS::RootedValueArray<1> paramData(rq.cx);
|
||||
paramData[0].set(quickSaveMetadataClone);
|
||||
g_GUI->SendEventToAll(EventNameSavegameLoaded, paramData);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user