Index: source/scriptinterface/ScriptInterface.h =================================================================== --- source/scriptinterface/ScriptInterface.h +++ source/scriptinterface/ScriptInterface.h @@ -24,7 +24,7 @@ #include "scriptinterface/ScriptRequest.h" #include "scriptinterface/ScriptTypes.h" -#include +#include ERROR_GROUP(Scripting); ERROR_TYPE(Scripting, SetupFailed); @@ -278,7 +278,7 @@ // members have to be called before the custom destructor of ScriptInterface_impl. std::unique_ptr m; - std::map m_CustomObjectTypes; + std::unordered_map m_CustomObjectTypes; }; // Explicitly instantiate void* as that is used for the generic template, Index: source/scriptinterface/ScriptInterface.cpp =================================================================== --- source/scriptinterface/ScriptInterface.cpp +++ source/scriptinterface/ScriptInterface.cpp @@ -516,7 +516,7 @@ JSObject* ScriptInterface::CreateCustomObject(const std::string& typeName) const { - std::map::const_iterator it = m_CustomObjectTypes.find(typeName); + std::unordered_map::const_iterator it = m_CustomObjectTypes.find(typeName); if (it == m_CustomObjectTypes.end()) throw PSERROR_Scripting_TypeDoesNotExist(); Index: source/simulation2/components/CCmpFootprint.cpp =================================================================== --- source/simulation2/components/CCmpFootprint.cpp +++ source/simulation2/components/CCmpFootprint.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -39,6 +39,7 @@ } DEFAULT_COMPONENT_ALLOCATOR(Footprint) + CACHE_WRAPPED_SCRIPT(Footprint); EShape m_Shape; entity_pos_t m_Size0; // width/radius Index: source/simulation2/components/CCmpObstruction.cpp =================================================================== --- source/simulation2/components/CCmpObstruction.cpp +++ source/simulation2/components/CCmpObstruction.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -53,6 +53,7 @@ } DEFAULT_COMPONENT_ALLOCATOR(Obstruction) + CACHE_WRAPPED_SCRIPT(Obstruction); typedef ICmpObstructionManager::tag_t tag_t; typedef ICmpObstructionManager::flags_t flags_t; Index: source/simulation2/components/CCmpObstructionManager.cpp =================================================================== --- source/simulation2/components/CCmpObstructionManager.cpp +++ source/simulation2/components/CCmpObstructionManager.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -132,6 +132,7 @@ } DEFAULT_COMPONENT_ALLOCATOR(ObstructionManager) + CACHE_WRAPPED_SCRIPT(ObstructionManager); bool m_DebugOverlayEnabled; bool m_DebugOverlayDirty; Index: source/simulation2/components/CCmpOwnership.cpp =================================================================== --- source/simulation2/components/CCmpOwnership.cpp +++ source/simulation2/components/CCmpOwnership.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -34,6 +34,7 @@ } DEFAULT_COMPONENT_ALLOCATOR(Ownership) + CACHE_WRAPPED_SCRIPT(Ownership); player_id_t m_Owner; Index: source/simulation2/components/CCmpPosition.cpp =================================================================== --- source/simulation2/components/CCmpPosition.cpp +++ source/simulation2/components/CCmpPosition.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -57,6 +57,7 @@ } DEFAULT_COMPONENT_ALLOCATOR(Position) + CACHE_WRAPPED_SCRIPT(Position); // Template state: Index: source/simulation2/components/CCmpProjectileManager.cpp =================================================================== --- source/simulation2/components/CCmpProjectileManager.cpp +++ source/simulation2/components/CCmpProjectileManager.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -51,6 +51,7 @@ } DEFAULT_COMPONENT_ALLOCATOR(ProjectileManager) + CACHE_WRAPPED_SCRIPT(ProjectileManager); static std::string GetSchema() { Index: source/simulation2/components/CCmpRangeManager.cpp =================================================================== --- source/simulation2/components/CCmpRangeManager.cpp +++ source/simulation2/components/CCmpRangeManager.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -367,6 +367,7 @@ } DEFAULT_COMPONENT_ALLOCATOR(RangeManager) + CACHE_WRAPPED_SCRIPT(RangeManager); bool m_DebugOverlayEnabled; bool m_DebugOverlayDirty; Index: source/simulation2/components/CCmpRangeOverlayRenderer.cpp =================================================================== --- source/simulation2/components/CCmpRangeOverlayRenderer.cpp +++ source/simulation2/components/CCmpRangeOverlayRenderer.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -43,6 +43,7 @@ } DEFAULT_COMPONENT_ALLOCATOR(RangeOverlayRenderer) + CACHE_WRAPPED_SCRIPT(RangeOverlayRenderer); CCmpRangeOverlayRenderer() : m_RangeOverlayData() { @@ -62,7 +63,9 @@ UpdateMessageSubscriptions(); } - void Deinit() override { } + void Deinit() override + { + } void Serialize(ISerializer& UNUSED(serialize)) override { Index: source/simulation2/components/CCmpSoundManager.cpp =================================================================== --- source/simulation2/components/CCmpSoundManager.cpp +++ source/simulation2/components/CCmpSoundManager.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -35,6 +35,7 @@ } DEFAULT_COMPONENT_ALLOCATOR(SoundManager) + CACHE_WRAPPED_SCRIPT(SoundManager); static std::string GetSchema() { Index: source/simulation2/components/CCmpTemplateManager.cpp =================================================================== --- source/simulation2/components/CCmpTemplateManager.cpp +++ source/simulation2/components/CCmpTemplateManager.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -37,6 +37,7 @@ } DEFAULT_COMPONENT_ALLOCATOR(TemplateManager) + CACHE_WRAPPED_SCRIPT(TemplateManager); static std::string GetSchema() { Index: source/simulation2/components/CCmpTerritoryManager.cpp =================================================================== --- source/simulation2/components/CCmpTerritoryManager.cpp +++ source/simulation2/components/CCmpTerritoryManager.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -73,6 +73,7 @@ } DEFAULT_COMPONENT_ALLOCATOR(TerritoryManager) + CACHE_WRAPPED_SCRIPT(TerritoryManager); static std::string GetSchema() { Index: source/simulation2/components/CCmpUnitMotion.h =================================================================== --- source/simulation2/components/CCmpUnitMotion.h +++ source/simulation2/components/CCmpUnitMotion.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -146,6 +146,7 @@ } DEFAULT_COMPONENT_ALLOCATOR(UnitMotion) + CACHE_WRAPPED_SCRIPT(UnitMotion); bool m_DebugOverlayEnabled; std::vector m_DebugOverlayLongPathLines; Index: source/simulation2/components/CCmpVision.cpp =================================================================== --- source/simulation2/components/CCmpVision.cpp +++ source/simulation2/components/CCmpVision.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -36,6 +36,7 @@ } DEFAULT_COMPONENT_ALLOCATOR(Vision) + CACHE_WRAPPED_SCRIPT(Vision); // Template state: Index: source/simulation2/components/CCmpVisualActor.cpp =================================================================== --- source/simulation2/components/CCmpVisualActor.cpp +++ source/simulation2/components/CCmpVisualActor.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -64,6 +64,7 @@ } DEFAULT_COMPONENT_ALLOCATOR(VisualActor) + CACHE_WRAPPED_SCRIPT_2(Visual, VisualActor); private: std::wstring m_BaseActorName, m_ActorName; Index: source/simulation2/scripting/EngineScriptConversions.cpp =================================================================== --- source/simulation2/scripting/EngineScriptConversions.cpp +++ source/simulation2/scripting/EngineScriptConversions.cpp @@ -44,7 +44,7 @@ } // If this is a scripted component, just return the JS object directly - JS::RootedValue instance(rq.cx, val->GetJSInstance()); + JS::HandleValue instance(val->GetJSInstance()); if (!instance.isNull()) { ret.set(instance); Index: source/simulation2/scripting/ScriptComponent.h =================================================================== --- source/simulation2/scripting/ScriptComponent.h +++ source/simulation2/scripting/ScriptComponent.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -37,21 +37,23 @@ public: CComponentTypeScript(const ScriptInterface& scriptInterface, JS::HandleValue instance); - JS::Value GetInstance() const { return m_Instance.get(); } + JS::HandleValue GetInstance() const { return JS::HandleValue::fromMarkedLocation(m_Instance.address()); } + JS::MutableHandleValue GetMutInstance() { return JS::MutableHandleValue::fromMarkedLocation(const_cast(m_Instance.address())); } + static void Trace(JSTracer* trc, void* data); - void Init(const CParamNode& paramNode, entity_id_t ent); + void Init(CComponentManager& cmpMgr, const CParamNode& paramNode, entity_id_t ent); void Deinit(); void HandleMessage(const CMessage& msg, bool global); void Serialize(ISerializer& serialize); - void Deserialize(const CParamNode& paramNode, IDeserializer& deserialize, entity_id_t ent); + void Deserialize(CComponentManager& cmpMgr, const CParamNode& paramNode, IDeserializer& deserialize, entity_id_t ent); template R Call(const char* funcname, const Ts&... params) const { R ret; ScriptRequest rq(m_ScriptInterface); - if (ScriptFunction::Call(rq, m_Instance, funcname, ret, params...)) + if (ScriptFunction::Call(rq, GetInstance(), funcname, ret, params...)) return ret; LOGERROR("Error calling component script function %s", funcname); return R(); @@ -62,7 +64,7 @@ void CallRef(const char* funcname, R ret, const Ts&... params) const { ScriptRequest rq(m_ScriptInterface); - if (!ScriptFunction::Call(rq, m_Instance, funcname, ret, params...)) + if (!ScriptFunction::Call(rq, GetInstance(), funcname, ret, params...)) LOGERROR("Error calling component script function %s", funcname); } @@ -70,13 +72,13 @@ void CallVoid(const char* funcname, const Ts&... params) const { ScriptRequest rq(m_ScriptInterface); - if (!ScriptFunction::CallVoid(rq, m_Instance, funcname, params...)) + if (!ScriptFunction::CallVoid(rq, GetInstance(), funcname, params...)) LOGERROR("Error calling component script function %s", funcname); } private: const ScriptInterface& m_ScriptInterface; - JS::PersistentRootedValue m_Instance; + JS::Heap m_Instance; }; #define REGISTER_COMPONENT_SCRIPT_WRAPPER(cname) \ @@ -104,7 +106,7 @@ } \ void Init(const CParamNode& paramNode) override \ { \ - m_Script.Init(paramNode, GetEntityId()); \ + m_Script.Init(GetSimContext().GetComponentManager(), paramNode, GetEntityId()); \ } \ void Deinit() override \ { \ @@ -120,9 +122,9 @@ } \ void Deserialize(const CParamNode& paramNode, IDeserializer& deserialize) override \ { \ - m_Script.Deserialize(paramNode, deserialize, GetEntityId()); \ + m_Script.Deserialize(GetSimContext().GetComponentManager(), paramNode, deserialize, GetEntityId()); \ } \ - JS::Value GetJSInstance() const override \ + JS::HandleValue GetJSInstance() const override \ { \ return m_Script.GetInstance(); \ } \ Index: source/simulation2/scripting/ScriptComponent.cpp =================================================================== --- source/simulation2/scripting/ScriptComponent.cpp +++ source/simulation2/scripting/ScriptComponent.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -25,25 +25,26 @@ #include "scriptinterface/Object.h" #include "simulation2/serialization/ISerializer.h" #include "simulation2/serialization/IDeserializer.h" +#include "simulation2/system/ComponentManager.h" CComponentTypeScript::CComponentTypeScript(const ScriptInterface& scriptInterface, JS::HandleValue instance) : - m_ScriptInterface(scriptInterface) + m_ScriptInterface(scriptInterface), m_Instance(instance) { - m_Instance.init(ScriptRequest(m_ScriptInterface).cx, instance); } -void CComponentTypeScript::Init(const CParamNode& paramNode, entity_id_t ent) +void CComponentTypeScript::Init(CComponentManager& cmpMgr, const CParamNode& paramNode, entity_id_t ent) { + cmpMgr.RegisterTrace(ent, m_Instance); ScriptRequest rq(m_ScriptInterface); - Script::SetProperty(rq, m_Instance, "entity", (int)ent, true, false); - Script::SetProperty(rq, m_Instance, "template", paramNode, true, false); - ScriptFunction::CallVoid(rq, m_Instance, "Init"); + Script::SetProperty(rq, GetInstance(), "entity", (int)ent, true, false); + Script::SetProperty(rq, GetInstance(), "template", paramNode, true, false); + ScriptFunction::CallVoid(rq, GetInstance(), "Init"); } void CComponentTypeScript::Deinit() { ScriptRequest rq(m_ScriptInterface); - ScriptFunction::CallVoid(rq, m_Instance, "Deinit"); + ScriptFunction::CallVoid(rq, GetInstance(), "Deinit"); } void CComponentTypeScript::HandleMessage(const CMessage& msg, bool global) @@ -54,7 +55,7 @@ JS::RootedValue msgVal(rq.cx, msg.ToJSValCached(m_ScriptInterface)); - if (!ScriptFunction::CallVoid(rq, m_Instance, name, msgVal)) + if (!ScriptFunction::CallVoid(rq, GetInstance(), name, msgVal)) LOGERROR("Script message handler %s failed", name); } @@ -64,26 +65,28 @@ try { - serialize.ScriptVal("comp", &m_Instance); + serialize.ScriptVal("comp", GetMutInstance()); } catch(PSERROR_Serialize& err) { int ent = INVALID_ENTITY; - Script::GetProperty(rq, m_Instance, "entity", ent); + Script::GetProperty(rq, GetInstance(), "entity", ent); std::string name = "(error)"; - Script::GetObjectClassName(rq, m_Instance, name); - LOGERROR("Script component %s of entity %i failed to serialize: %s\nSerializing:\n%s", name, ent, err.what(), Script::ToString(rq, &m_Instance)); + Script::GetObjectClassName(rq, GetInstance(), name); + LOGERROR("Script component %s of entity %i failed to serialize: %s\nSerializing:\n%s", name, ent, err.what(), Script::ToString(rq, GetMutInstance())); // Rethrow now that we added more details throw; } } -void CComponentTypeScript::Deserialize(const CParamNode& paramNode, IDeserializer& deserialize, entity_id_t ent) +void CComponentTypeScript::Deserialize(CComponentManager& cmpMgr, const CParamNode& paramNode, IDeserializer& deserialize, entity_id_t ent) { + cmpMgr.RegisterTrace(ent, m_Instance); + ScriptRequest rq(m_ScriptInterface); - Script::SetProperty(rq, m_Instance, "entity", (int)ent, true, false); - Script::SetProperty(rq, m_Instance, "template", paramNode, true, false); + Script::SetProperty(rq, GetInstance(), "entity", (int)ent, true, false); + Script::SetProperty(rq, GetInstance(), "template", paramNode, true, false); - deserialize.ScriptObjectAssign("comp", m_Instance); + deserialize.ScriptObjectAssign("comp", GetInstance()); } Index: source/simulation2/system/Component.h =================================================================== --- source/simulation2/system/Component.h +++ source/simulation2/system/Component.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -44,6 +44,33 @@ return CID_##cname; \ } +#define CACHE_WRAPPED_SCRIPT(iname) CACHE_WRAPPED_SCRIPT_2(iname, iname) + +#define CACHE_WRAPPED_SCRIPT_2(iname, cname) \ + mutable JS::Heap m_Instance; \ + JS::HandleValue GetJSInstance() const override \ + { \ + if (m_Instance) \ + return JS::HandleValue::fromMarkedLocation(m_Instance.address()); \ + const ScriptInterface& si = GetSimContext().GetScriptInterface(); \ + ScriptRequest rq(si); \ + \ + JS::RootedObject obj(rq.cx); \ + if (!NewJSObject(rq.GetScriptInterface(), &obj)) \ + { \ + /* Report as an error, since scripts really shouldn't try to use unscriptable interfaces*/ \ + LOGERROR("CCmp##cname does not have a scriptable interface"); \ + return JS::UndefinedHandleValue; \ + } \ + \ + JS::SetPrivate(obj, static_cast(static_cast(const_cast(this)))); \ + JS::RootedValue objVal(rq.cx); \ + objVal.setObject(*obj); \ + m_Instance.set(objVal); \ + GetSimContext().GetComponentManager().RegisterTrace(GetEntityId(), m_Instance); \ + return JS::HandleValue::fromMarkedLocation(m_Instance.address()); \ + } + #define DEFAULT_MOCK_COMPONENT() \ int GetComponentTypeId() const override \ { \ Index: source/simulation2/system/ComponentManager.h =================================================================== --- source/simulation2/system/ComponentManager.h +++ source/simulation2/system/ComponentManager.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -226,6 +226,16 @@ */ void FlushDestroyedComponents(); + /** + * Called during GC tracing of our components. + */ + static void Trace(JSTracer* trc, void* data); + /** + * Call this from components when they need to save their JS instance. + * Not done by the component manager because C++ components do it lazily. + */ + void RegisterTrace(entity_id_t ent, const JS::Heap& instance); + IComponent* QueryInterface(entity_id_t ent, InterfaceId iid) const; using InterfacePair = std::pair; @@ -322,6 +332,7 @@ std::map > m_DynamicMessageSubscriptionsNonsyncByComponent; std::unordered_map m_ComponentCaches; + std::unordered_map*>> m_TraceCache; // TODO: maintaining both ComponentsBy* is nasty; can we get rid of one, // while keeping QueryInterface and PostMessage sufficiently efficient? Index: source/simulation2/system/ComponentManager.cpp =================================================================== --- source/simulation2/system/ComponentManager.cpp +++ source/simulation2/system/ComponentManager.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -66,6 +66,8 @@ m_ScriptInterface.SetCallbackData(static_cast (this)); m_ScriptInterface.ReplaceNondeterministicRNG(m_RNG); + JS_AddExtraGCRootsTracer(m_ScriptInterface.GetGeneralJSContext(), Trace, (void*)this); + // For component script tests, the test system sets up its own scripted implementation of // these functions, so we skip registering them here in those cases if (!skipScriptFunctions) @@ -117,6 +119,7 @@ CComponentManager::~CComponentManager() { + JS_RemoveExtraGCRootsTracer(m_ScriptInterface.GetGeneralJSContext(), Trace, (void*)this); ResetState(); } @@ -481,6 +484,9 @@ m_DynamicMessageSubscriptionsNonsync.clear(); m_DynamicMessageSubscriptionsNonsyncByComponent.clear(); + // Remove all items we were tracing. + m_TraceCache.clear(); + // Delete all IComponents in reverse order of creation. std::map >::reverse_iterator iit = m_ComponentsByTypeId.rbegin(); for (; iit != m_ComponentsByTypeId.rend(); ++iit) @@ -788,6 +794,19 @@ cache->interfaces[iid] = &component; } +void CComponentManager::Trace(JSTracer* trc, void* data) +{ + CComponentManager& cmpMgr = *(static_cast(data)); + for (auto& traceByEnt : cmpMgr.m_TraceCache) + for (JS::Heap* ptr : traceByEnt.second) + JS::TraceEdge(trc, ptr, "ComponentManager::Trace"); +} + +void CComponentManager::RegisterTrace(entity_id_t ent, const JS::Heap& instance) +{ + m_TraceCache.try_emplace(ent).first->second.push_back(const_cast*>(std::addressof(instance))); +} + CEntityHandle CComponentManager::AllocateEntityHandle(entity_id_t ent) { ENSURE(!EntityExists(ent)); @@ -928,6 +947,10 @@ free(handle.GetComponentCache()); m_ComponentCaches.erase(ent); + auto hit = m_TraceCache.find(ent); + if (hit != m_TraceCache.end()) + m_TraceCache.erase(hit); + // Remove from m_ComponentsByInterface std::vector >::iterator ifcit = m_ComponentsByInterface.begin(); for (; ifcit != m_ComponentsByInterface.end(); ++ifcit) Index: source/simulation2/system/IComponent.h =================================================================== --- source/simulation2/system/IComponent.h +++ source/simulation2/system/IComponent.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -67,7 +67,7 @@ * Derrived classes should return true if they implement such a wrapper. */ virtual bool NewJSObject(const ScriptInterface& scriptInterface, JS::MutableHandleObject out) const; - virtual JS::Value GetJSInstance() const; + virtual JS::HandleValue GetJSInstance() const; virtual int GetComponentTypeId() const = 0; private: Index: source/simulation2/system/IComponent.cpp =================================================================== --- source/simulation2/system/IComponent.cpp +++ source/simulation2/system/IComponent.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -52,7 +52,7 @@ return false; } -JS::Value IComponent::GetJSInstance() const +JS::HandleValue IComponent::GetJSInstance() const { - return JS::NullValue(); + return JS::NullHandleValue; }