Remove Script::CreateArray

It's better to construct a js-array from a `JS::RootedValueVector`.
Because it is more strongly typed and the index doesn't has to be
specified when appending an element.
Some usages are replaced with `JS::RootedValueArray`.

Fixes: #8702
This commit is contained in:
phosit 2026-02-02 18:24:57 +01:00
parent fe9c0f6c2f
commit df18e22277
No known key found for this signature in database
GPG key ID: C9430B600671C268
14 changed files with 146 additions and 136 deletions

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2025 Wildfire Games.
/* Copyright (C) 2026 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -244,11 +244,16 @@ bool JSI_GUIProxy<T>::get(JSContext* cx, JS::HandleObject proxy, JS::HandleValue
}
else if (propName == "children")
{
Script::CreateArray(rq, vp);
for (size_t i = 0; i < e->m_Children.size(); ++i)
Script::SetPropertyInt(rq, vp, i, e->m_Children[i]);
JS::RootedValueVector children{rq.cx};
for (const auto& child : e->m_Children)
{
JS::RootedValue rootedChild{rq.cx};
Script::ToJSVal(rq, &rootedChild, child);
if (!children.append(rootedChild))
throw std::runtime_error{"Append failed"};
}
vp.set(JS::ObjectValue(*JS::NewArrayObject(rq.cx, children)));
return true;
}
else if (propName == "name")

View file

@ -573,9 +573,7 @@ void XmppClient::handleOOB(const gloox::JID&, const gloox::OOB&)
*/
JS::Value XmppClient::GUIGetPlayerList(const ScriptRequest& rq)
{
JS::RootedValue ret(rq.cx);
Script::CreateArray(rq, &ret);
int j = 0;
JS::RootedValueVector players{rq.cx};
for (const std::pair<const std::string, SPlayer>& p : m_PlayerMap)
{
@ -589,9 +587,10 @@ JS::Value XmppClient::GUIGetPlayerList(const ScriptRequest& rq)
"rating", p.second.m_Rating,
"role", p.second.m_Role);
Script::SetPropertyInt(rq, ret, j++, player);
if (!players.append(player))
throw std::runtime_error{"Append failed"};
}
return ret;
return JS::ObjectValue(*JS::NewArrayObject(rq.cx, players));
}
/**
@ -601,9 +600,7 @@ JS::Value XmppClient::GUIGetPlayerList(const ScriptRequest& rq)
*/
JS::Value XmppClient::GUIGetGameList(const ScriptRequest& rq)
{
JS::RootedValue ret(rq.cx);
Script::CreateArray(rq, &ret);
int j = 0;
JS::RootedValueVector games{rq.cx};
const char* stats[] = { "name", "hostUsername", "hostJID", "state", "hasPassword",
"nbp", "maxnbp", "players", "mapName", "niceMapName", "mapSize", "mapType",
@ -617,9 +614,10 @@ JS::Value XmppClient::GUIGetGameList(const ScriptRequest& rq)
for (size_t i = 0; i < ARRAY_SIZE(stats); ++i)
Script::SetProperty(rq, game, stats[i], t->findAttribute(stats[i]));
Script::SetPropertyInt(rq, ret, j++, game);
if (!games.append(game))
throw std::runtime_error{"Append failed"};
}
return ret;
return JS::ObjectValue(*JS::NewArrayObject(rq.cx, games));
}
/**
@ -629,9 +627,7 @@ JS::Value XmppClient::GUIGetGameList(const ScriptRequest& rq)
*/
JS::Value XmppClient::GUIGetBoardList(const ScriptRequest& rq)
{
JS::RootedValue ret(rq.cx);
Script::CreateArray(rq, &ret);
int j = 0;
JS::RootedValueVector boardList{rq.cx};
const char* attributes[] = { "name", "rank", "rating" };
@ -643,9 +639,10 @@ JS::Value XmppClient::GUIGetBoardList(const ScriptRequest& rq)
for (size_t i = 0; i < ARRAY_SIZE(attributes); ++i)
Script::SetProperty(rq, board, attributes[i], t->findAttribute(attributes[i]));
Script::SetPropertyInt(rq, ret, j++, board);
if (!boardList.append(board))
throw std::runtime_error{"Append failed"};
}
return ret;
return JS::ObjectValue(*JS::NewArrayObject(rq.cx, boardList));
}
/**
@ -655,9 +652,7 @@ JS::Value XmppClient::GUIGetBoardList(const ScriptRequest& rq)
*/
JS::Value XmppClient::GUIGetProfile(const ScriptRequest& rq)
{
JS::RootedValue ret(rq.cx);
Script::CreateArray(rq, &ret);
int j = 0;
JS::RootedValueVector profileData{rq.cx};
const char* stats[] = { "player", "rating", "totalGamesPlayed", "highestRating", "wins", "losses", "rank" };
@ -669,9 +664,10 @@ JS::Value XmppClient::GUIGetProfile(const ScriptRequest& rq)
for (size_t i = 0; i < ARRAY_SIZE(stats); ++i)
Script::SetProperty(rq, profile, stats[i], t->findAttribute(stats[i]));
Script::SetPropertyInt(rq, ret, j++, profile);
if (!profileData.append(profile))
throw std::runtime_error{"Append failed"};
}
return ret;
return JS::ObjectValue(*JS::NewArrayObject(rq.cx, profileData));
}
/*****************************************************
@ -735,14 +731,12 @@ JS::Value XmppClient::GuiPollNewMessages(const ScriptInterface& guiInterface)
// Optimize for batch message processing that is more
// performance demanding than processing a lone message.
JS::RootedValue messages(rq.cx);
Script::CreateArray(rq, &messages);
int j = 0;
JS::RootedValueVector messages{rq.cx};
for (const JS::Heap<JS::Value>& message : m_GuiMessageQueue)
{
Script::SetPropertyInt(rq, messages, j++, message);
if (!messages.append(message))
throw std::runtime_error{"Append failed"};
// Store historic chat messages.
// Only store relevant messages to minimize memory footprint.
@ -770,7 +764,8 @@ JS::Value XmppClient::GuiPollNewMessages(const ScriptInterface& guiInterface)
m_GuiMessageQueue.clear();
// Copy the messages over to the caller script interface.
return Script::CloneValueFromOtherCompartment(guiInterface, *m_ScriptInterface, messages);
return Script::CloneValueFromOtherCompartment(guiInterface, *m_ScriptInterface,
JS::RootedValue{rq.cx, JS::ObjectValue(*JS::NewArrayObject(rq.cx, messages))});
}
JS::Value XmppClient::GuiPollHistoricMessages(const ScriptInterface& guiInterface)
@ -780,15 +775,17 @@ JS::Value XmppClient::GuiPollHistoricMessages(const ScriptInterface& guiInterfac
ScriptRequest rq(m_ScriptInterface);
JS::RootedValue messages(rq.cx);
Script::CreateArray(rq, &messages);
JS::RootedValueVector messages{rq.cx};
int j = 0;
for (const JS::Heap<JS::Value>& message : m_HistoricGuiMessages)
Script::SetPropertyInt(rq, messages, j++, message);
{
if (!messages.append(message))
throw std::runtime_error{"Append failed"};
}
// Copy the messages over to the caller script interface.
return Script::CloneValueFromOtherCompartment(guiInterface, *m_ScriptInterface, messages);
return Script::CloneValueFromOtherCompartment(guiInterface, *m_ScriptInterface,
JS::RootedValue{rq.cx, JS::ObjectValue(*JS::NewArrayObject(rq.cx, messages))});
}
/**

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2025 Wildfire Games.
/* Copyright (C) 2026 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -37,11 +37,9 @@ public:
ScriptInterface script("Test", "Test", g_ScriptContext);
ScriptRequest rq(script);
JS::RootedValue val(rq.cx);
Script::CreateArray(rq, &val);
Script::SetPropertyInt(rq, val, 0, 4);
CSimulationMessage msg(script, 1, 2, 3, val);
JS::RootedValueArray<1> val{rq.cx, JS::ValueArray<1>{JS::NumberValue(4)}};
CSimulationMessage msg(script, 1, 2, 3,
JS::RootedValue{rq.cx, JS::ObjectValue(*JS::NewArrayObject(rq.cx, val))});
TS_ASSERT_STR_EQUALS(msg.ToString(), "CSimulationMessage { m_Client: 1, m_Player: 2, m_Turn: 3, m_Data: [4] }");
size_t len = msg.GetSerializedLength();

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2025 Wildfire Games.
/* Copyright (C) 2026 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -193,14 +193,13 @@ JS::Value MakeFreeTypeReport(const ScriptRequest& rq)
void ReportLibraries(const ScriptRequest& rq, JS::HandleValue settings)
{
JS::RootedValue librariesSettings(rq.cx);
Script::CreateArray(rq, &librariesSettings);
int libraryCount = 0;
JS::RootedValueVector librariesSettings{rq.cx};
auto appendLibrary = [&rq, &librariesSettings, &libraryCount](const JS::Value& librarySettings)
auto appendLibrary = [&rq, &librariesSettings](const JS::Value& librarySettings)
{
JS::RootedValue value(rq.cx, librarySettings);
Script::SetPropertyInt(rq, librariesSettings, libraryCount++, value);
if (!librariesSettings.append(value))
throw std::runtime_error{"Append failed"};
};
appendLibrary(MakeSDLReport(rq));
@ -230,7 +229,8 @@ void ReportLibraries(const ScriptRequest& rq, JS::HandleValue settings)
.MakeReport());
#endif
Script::SetProperty(rq, settings, "libraries", librariesSettings);
Script::SetProperty(rq, settings, "libraries",
JS::RootedValue{rq.cx, JS::ObjectValue(*JS::NewArrayObject(rq.cx, librariesSettings))});
}
void WriteSystemInfo(Renderer::Backend::IDevice* device, const utsname& un)

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2025 Wildfire Games.
/* Copyright (C) 2026 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -494,19 +494,23 @@ namespace
for (size_t r = 0; r < table->GetNumberRows(); ++r)
{
JS::RootedValue row(rq.cx);
Script::CreateArray(rq, &row);
JS::RootedValueVector row{rq.cx};
if (!row.resize(columns.size() + 1))
throw std::runtime_error{"Resize failed"};
Script::SetProperty(rq, data, table->GetCellText(r, 0).c_str(), row);
if (table->GetChild(r))
{
JS::RootedValue childRows(rq.cx, DumpRows(table->GetChild(r)));
Script::SetPropertyInt(rq, row, 0, childRows);
row[0].set(childRows);
}
for (size_t c = 1; c < columns.size(); ++c)
Script::SetPropertyInt(rq, row, c, table->GetCellText(r, c));
{
row[c].set(JS::StringValue(
JS_NewStringCopyZ(rq.cx, table->GetCellText(r, c).c_str())));
}
}
return data;

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2025 Wildfire Games.
/* Copyright (C) 2026 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -279,8 +279,7 @@ JS::Value SavedGames::GetSavedGames(const ScriptInterface& scriptInterface)
PROFILE2("GetSavedGames");
ScriptRequest rq(scriptInterface);
JS::RootedValue games(rq.cx);
Script::CreateArray(rq, &games);
JS::RootedValueVector games{rq.cx};
Status err;
@ -288,10 +287,10 @@ JS::Value SavedGames::GetSavedGames(const ScriptInterface& scriptInterface)
err = vfs::GetPathnames(g_VFS, "saves/", L"*.0adsave", pathnames);
WARN_IF_ERR(err);
for (size_t i = 0; i < pathnames.size(); ++i)
for (const VfsPath& pathname : pathnames)
{
OsPath realPath;
err = g_VFS->GetRealPath(pathnames[i], realPath);
err = g_VFS->GetRealPath(pathname, realPath);
if (err < 0)
{
DEBUG_WARN_ERR(err);
@ -319,13 +318,14 @@ JS::Value SavedGames::GetSavedGames(const ScriptInterface& scriptInterface)
Script::CreateObject(
rq,
&game,
"id", pathnames[i].Basename(),
"id", pathname.Basename(),
"metadata", metadata);
Script::SetPropertyInt(rq, games, i, game);
if (!games.append(game))
throw std::runtime_error{"Append failed"};
}
return games;
return JS::ObjectValue(*JS::NewArrayObject(rq.cx, games));
}
bool SavedGames::DeleteSavedGame(const std::wstring& name)

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2025 Wildfire Games.
/* Copyright (C) 2026 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -255,19 +255,20 @@ JS::Value VisualReplay::GetReplays(const ScriptInterface& scriptInterface, bool
ScriptRequest rq(scriptInterface);
JS::RootedObject replays(rq.cx, ReloadReplayCache(scriptInterface, compareFiles));
// Only take entries with data
JS::RootedValue replaysWithoutNullEntries(rq.cx);
Script::CreateArray(rq, &replaysWithoutNullEntries);
JS::RootedValueVector replaysWithoutNullEntries{rq.cx};
u32 replaysLength = 0;
JS::GetArrayLength(rq.cx, replays, &replaysLength);
for (u32 j = 0, i = 0; j < replaysLength; ++j)
for (u32 j = 0; j < replaysLength; ++j)
{
JS::RootedValue replay(rq.cx);
JS_GetElement(rq.cx, replays, j, &replay);
if (Script::HasProperty(rq, replay, "attribs"))
Script::SetPropertyInt(rq, replaysWithoutNullEntries, i++, replay);
if (!Script::HasProperty(rq, replay, "attribs"))
continue;
if (!replaysWithoutNullEntries.append(replay))
throw std::runtime_error{"Append failed"};
}
return replaysWithoutNullEntries;
return JS::ObjectValue(*JS::NewArrayObject(rq.cx, replaysWithoutNullEntries));
}
/**

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2025 Wildfire Games.
/* Copyright (C) 2026 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -70,10 +70,10 @@ JS::Value GetMods(const ScriptRequest& rq)
const std::vector<ModIoModData>& availableMods = g_ModIo->GetMods();
JS::RootedValue mods(rq.cx);
Script::CreateArray(rq, &mods, availableMods.size());
JS::RootedValueVector mods{rq.cx};
if (!mods.reserve(availableMods.size()))
throw std::runtime_error{"Reserve failed"};
u32 i = 0;
for (const ModIoModData& mod : availableMods)
{
JS::RootedValue m(rq.cx);
@ -83,10 +83,11 @@ JS::Value GetMods(const ScriptRequest& rq)
Script::SetProperty(rq, m, prop.first.c_str(), prop.second, true);
Script::SetProperty(rq, m, "dependencies", mod.dependencies, true);
Script::SetPropertyInt(rq, mods, i++, m);
if (!mods.append(m))
throw std::runtime_error{"Append failed"};
}
return mods;
return JS::ObjectValue(*JS::NewArrayObject(rq.cx, mods));
}
const std::map<DownloadProgressStatus, std::string> statusStrings = {

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2025 Wildfire Games.
/* Copyright (C) 2026 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -227,21 +227,20 @@ JS::Value ReadFileLines(const ScriptRequest& rq, const std::wstring& filename)
// split into array of strings (one per line)
std::stringstream ss(contents);
JS::RootedValue line_array(rq.cx);
Script::CreateArray(rq, &line_array);
JS::RootedValueVector lineArray{rq.cx};
std::string line;
int cur_line = 0;
while (std::getline(ss, line))
{
// Decode each line as UTF-8
JS::RootedValue val(rq.cx);
Script::ToJSVal(rq, &val, CStr(line).FromUTF8());
Script::SetPropertyInt(rq, line_array, cur_line++, val);
if (!lineArray.append(val))
throw std::runtime_error{"Append failed"};
}
return line_array;
return JS::ObjectValue(*JS::NewArrayObject(rq.cx, lineArray));
}
// Return file contents parsed as a JS Object

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2025 Wildfire Games.
/* Copyright (C) 2026 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -726,16 +726,19 @@ void CDevice::Report(const ScriptRequest& rq, JS::HandleValue settings)
ReportAvailablePhysicalDevice(m_ChoosenDevice, rq, device);
Script::SetProperty(rq, settings, "choosen_device", device);
JS::RootedValue availableDevices(rq.cx);
Script::CreateArray(rq, &availableDevices, m_AvailablePhysicalDevices.size());
for (size_t index = 0; index < m_AvailablePhysicalDevices.size(); ++index)
JS::RootedValueVector availableDevices{rq.cx};
if (!availableDevices.reserve(m_AvailablePhysicalDevices.size()))
throw std::runtime_error{"Reserve failed"};
for (const SAvailablePhysicalDevice& d : m_AvailablePhysicalDevices)
{
JS::RootedValue device(rq.cx);
Script::CreateObject(rq, &device);
ReportAvailablePhysicalDevice(m_AvailablePhysicalDevices[index], rq, device);
Script::SetPropertyInt(rq, availableDevices, index, device);
ReportAvailablePhysicalDevice(d, rq, device);
if (!availableDevices.append(device))
throw std::runtime_error{"Append failed"};
}
Script::SetProperty(rq, settings, "available_devices", availableDevices);
Script::SetProperty(rq, settings, "available_devices",
JS::RootedValue{rq.cx, JS::ObjectValue(*JS::NewArrayObject(rq.cx, availableDevices))});
Script::SetProperty(rq, settings, "instance_extensions", m_InstanceExtensions);
Script::SetProperty(rq, settings, "validation_layers", m_ValidationLayers);

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2025 Wildfire Games.
/* Copyright (C) 2026 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -29,6 +29,7 @@
#include <js/RootingAPI.h>
#include <js/Value.h>
#include <limits>
#include <span>
#include <string>
#include <type_traits>
#include <vector>
@ -353,32 +354,38 @@ void ReportAvailablePhysicalDevice(const SAvailablePhysicalDevice& device,
JS::RootedValue memory(rq.cx);
Script::CreateObject(rq, &memory);
JS::RootedValue memoryTypes(rq.cx);
Script::CreateArray(rq, &memoryTypes, device.memoryProperties.memoryTypeCount);
for (uint32_t memoryTypeIndex = 0; memoryTypeIndex < device.memoryProperties.memoryTypeCount; ++memoryTypeIndex)
JS::RootedValueVector memoryTypes{rq.cx};
if (!memoryTypes.reserve(device.memoryProperties.memoryTypeCount))
throw std::runtime_error{"Reserve failed"};
for (const VkMemoryType& type : std::span{device.memoryProperties.memoryTypes,
device.memoryProperties.memoryTypeCount})
{
const VkMemoryType& type = device.memoryProperties.memoryTypes[memoryTypeIndex];
JS::RootedValue memoryType(rq.cx);
Script::CreateObject(rq, &memoryType);
Script::SetProperty(rq, memoryType, "propertyFlags", static_cast<uint32_t>(type.propertyFlags));
Script::SetProperty(rq, memoryType, "heapIndex", type.heapIndex);
Script::SetPropertyInt(rq, memoryTypes, memoryTypeIndex, memoryType);
if (!memoryTypes.append(memoryType))
throw std::runtime_error{"Append failed"};
}
JS::RootedValue memoryHeaps(rq.cx);
Script::CreateArray(rq, &memoryHeaps, device.memoryProperties.memoryHeapCount);
for (uint32_t memoryHeapIndex = 0; memoryHeapIndex < device.memoryProperties.memoryHeapCount; ++memoryHeapIndex)
JS::RootedValueVector memoryHeaps{rq.cx};
if (!memoryHeaps.reserve(device.memoryProperties.memoryHeapCount))
throw std::runtime_error{"Reserve failed"};
for (const VkMemoryHeap& heap : std::span{device.memoryProperties.memoryHeaps,
device.memoryProperties.memoryHeapCount})
{
const VkMemoryHeap& heap = device.memoryProperties.memoryHeaps[memoryHeapIndex];
JS::RootedValue memoryHeap(rq.cx);
Script::CreateObject(rq, &memoryHeap);
// We can't serialize uint64_t in JS, so put data in KiB.
Script::SetProperty(rq, memoryHeap, "size", static_cast<uint32_t>(heap.size / 1024));
Script::SetProperty(rq, memoryHeap, "flags", static_cast<uint32_t>(heap.flags));
Script::SetPropertyInt(rq, memoryHeaps, memoryHeapIndex, memoryHeap);
if (!memoryHeaps.append(memoryHeap))
throw std::runtime_error{"Append failed"};
}
Script::SetProperty(rq, memory, "types", memoryTypes);
Script::SetProperty(rq, memory, "heaps", memoryHeaps);
Script::SetProperty(rq, memory, "types",
JS::RootedValue{rq.cx, JS::ObjectValue(*JS::NewArrayObject(rq.cx, memoryTypes))});
Script::SetProperty(rq, memory, "heaps",
JS::RootedValue{rq.cx, JS::ObjectValue(*JS::NewArrayObject(rq.cx, memoryHeaps))});
Script::SetProperty(rq, settings, "memory", memory);
JS::RootedValue constants(rq.cx);
@ -513,28 +520,33 @@ void ReportAvailablePhysicalDevice(const SAvailablePhysicalDevice& device,
Script::SetProperty(rq, settings, "features", features);
JS::RootedValue presentModes(rq.cx);
Script::CreateArray(rq, &presentModes, device.presentModes.size());
for (size_t index = 0; index < device.presentModes.size(); ++index)
JS::RootedValueVector presentModes{rq.cx};
if (!presentModes.reserve(device.presentModes.size()))
throw std::runtime_error{"Reserve failed"};
for (const VkPresentModeKHR& mode : device.presentModes)
{
Script::SetPropertyInt(
rq, presentModes, index, static_cast<uint32_t>(device.presentModes[index]));
if (!presentModes.append(JS::NumberValue(static_cast<uint32_t>(mode))))
throw std::runtime_error{"Append failed"};
}
Script::SetProperty(rq, settings, "present_modes", presentModes);
Script::SetProperty(rq, settings, "present_modes",
JS::RootedValue{rq.cx, JS::ObjectValue(*JS::NewArrayObject(rq.cx, presentModes))});
JS::RootedValue surfaceFormats(rq.cx);
Script::CreateArray(rq, &surfaceFormats, device.surfaceFormats.size());
for (size_t index = 0; index < device.surfaceFormats.size(); ++index)
JS::RootedValueVector surfaceFormats{rq.cx};
if (!surfaceFormats.reserve(device.surfaceFormats.size()))
throw std::runtime_error{"Reserve failed"};
for (const VkSurfaceFormatKHR& format : device.surfaceFormats)
{
JS::RootedValue surfaceFormat(rq.cx);
Script::CreateObject(rq, &surfaceFormat);
Script::SetProperty(
rq, surfaceFormat, "format", static_cast<uint32_t>(device.surfaceFormats[index].format));
rq, surfaceFormat, "format", static_cast<uint32_t>(format.format));
Script::SetProperty(
rq, surfaceFormat, "color_space", static_cast<uint32_t>(device.surfaceFormats[index].colorSpace));
Script::SetPropertyInt(rq, surfaceFormats, index, surfaceFormat);
rq, surfaceFormat, "color_space", static_cast<uint32_t>(format.colorSpace));
if (!surfaceFormats.append(surfaceFormat))
throw std::runtime_error{"Append failed"};
}
Script::SetProperty(rq, settings, "surface_formats", surfaceFormats);
Script::SetProperty(rq, settings, "surface_formats",
JS::RootedValue{rq.cx, JS::ObjectValue(*JS::NewArrayObject(rq.cx, surfaceFormats))});
JS::RootedValue surfaceCapabilities(rq.cx);
Script::CreateObject(rq, &surfaceCapabilities);

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2025 Wildfire Games.
/* Copyright (C) 2026 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -271,15 +271,6 @@ inline bool CreateObject(const ScriptRequest& rq, JS::MutableHandleValue objectV
return CreateObject(rq, objectValue, args...) && SetProperty(rq, objectValue, propertyName, val, false, true);
}
/**
* Sets the given value to a new JS object or Null Value in case of out-of-memory.
*/
inline bool CreateArray(const ScriptRequest& rq, JS::MutableHandleValue objectValue, size_t length = 0)
{
objectValue.setObjectOrNull(JS::NewArrayObject(rq.cx, length));
return !objectValue.isNullOrUndefined();
}
} // namespace Script
#endif // INCLUDED_SCRIPTINTERFACE_Object

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2025 Wildfire Games.
/* Copyright (C) 2026 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -148,9 +148,7 @@ JS::Value GetEdgesOfStaticObstructionsOnScreenNearTo(const ScriptInterface& scri
ENSURE(sim);
ScriptRequest rq(scriptInterface);
JS::RootedValue edgeList(rq.cx);
Script::CreateArray(rq, &edgeList);
int edgeListIndex = 0;
JS::RootedValueVector edgeList{rq.cx};
const float distanceThreshold{g_ConfigDB.Get("gui.session.snaptoedgesdistancethreshold", 10.0f)};
CFixedVector2D entityPos(x, z);
@ -202,10 +200,11 @@ JS::Value GetEdgesOfStaticObstructionsOnScreenNearTo(const ScriptInterface& scri
"normal", normal,
"order", "cw");
Script::SetPropertyInt(rq, edgeList, edgeListIndex++, edge);
if (!edgeList.append(edge))
throw std::runtime_error{"Append failed"};
}
}
return edgeList;
return JS::ObjectValue(*JS::NewArrayObject(rq.cx, edgeList));
}
std::vector<entity_id_t> PickSimilarPlayerEntities(const std::string& templateName, bool includeOffScreen, bool matchRank, bool allowFoundations)

View file

@ -1,4 +1,4 @@
/* Copyright (C) 2025 Wildfire Games.
/* Copyright (C) 2026 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -163,14 +163,13 @@ QUERYHANDLER(GenerateMap)
ScriptRequest rq(scriptInterface);
// Set up 8-element array of empty objects to satisfy init
JS::RootedValue playerData(rq.cx);
Script::CreateArray(rq, &playerData);
JS::RootedValueArray<8> playerData{rq.cx};
for (int i = 0; i < 8; ++i)
for (JS::Value& p : playerData.get().elements)
{
JS::RootedValue player(rq.cx);
Script::CreateObject(rq, &player);
Script::SetPropertyInt(rq, playerData, i, player);
p = player;
}
JS::RootedValue settings(rq.cx);
@ -178,7 +177,8 @@ QUERYHANDLER(GenerateMap)
rq,
&settings,
"mapType", "scenario",
"PlayerData", playerData);
"PlayerData",
JS::RootedValue{rq.cx, JS::ObjectValue(*JS::NewArrayObject(rq.cx, playerData))});
JS::RootedValue attrs(rq.cx);
Script::CreateObject(