[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:
wraitii 2020-12-06 14:03:02 +00:00
parent 6da64bf354
commit d92a2118b0
30 changed files with 91 additions and 100 deletions

View File

@ -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;
}

View File

@ -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;

View File

@ -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);

View File

@ -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)

View File

@ -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();

View File

@ -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);
}

View File

@ -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'.

View File

@ -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);
}
/**

View File

@ -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)

View File

@ -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();

View File

@ -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);

View File

@ -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, "");

View File

@ -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);

View File

@ -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());
}
};

View File

@ -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);
}

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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);
}

View File

@ -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.

View File

@ -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)

View File

@ -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);

View File

@ -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));
}

View File

@ -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());

View File

@ -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;

View File

@ -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)

View File

@ -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);
}

View File

@ -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))

View File

@ -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
{

View File

@ -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);