mirror of
https://gitea.wildfiregames.com/0ad/0ad
synced 2026-06-16 05:13:58 -07:00
Cache property keys during component serialization
(cherry picked from commitab6a420f78) (fixed build on this commit by moving a change to commit originallyea34960249) Signed-off-by: Itms <itms@wildfiregames.com>
This commit is contained in:
parent
0fdd6005b8
commit
520c489b68
5 changed files with 32 additions and 22 deletions
|
|
@ -62,6 +62,8 @@ CBinarySerializerScriptImpl::CBinarySerializerScriptImpl(const ScriptInterface&
|
|||
{
|
||||
ScriptRequest rq(m_ScriptInterface);
|
||||
JS_AddExtraGCRootsTracer(rq.cx, Trace, this);
|
||||
m_SerializePropId = JS::PropertyKey::fromPinnedString(JS_AtomizeAndPinString(rq.cx, "Serialize"));
|
||||
m_DeserializePropId = JS::PropertyKey::fromPinnedString(JS_AtomizeAndPinString(rq.cx, "Deserialize"));
|
||||
}
|
||||
|
||||
CBinarySerializerScriptImpl::~CBinarySerializerScriptImpl()
|
||||
|
|
@ -227,7 +229,7 @@ void CBinarySerializerScriptImpl::HandleScriptVal(JS::HandleValue val)
|
|||
if (!JS_GetPrototype(rq.cx, obj, &proto))
|
||||
throw PSERROR_Serialize_ScriptError("JS_GetPrototype failed");
|
||||
|
||||
SPrototypeSerialization protoInfo = GetPrototypeInfo(rq, proto);
|
||||
SPrototypeSerialization protoInfo = GetPrototypeInfo(rq, proto, m_SerializePropId, m_DeserializePropId);
|
||||
|
||||
if (protoInfo.name == "Object")
|
||||
m_Serializer.NumberU8_Unbounded("type", SCRIPT_TYPE_OBJECT);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2024 Wildfire Games.
|
||||
/* Copyright (C) 2025 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
|
|
@ -98,6 +98,10 @@ private:
|
|||
ObjectTagMap m_ScriptBackrefTags;
|
||||
u32 m_ScriptBackrefsNext;
|
||||
u32 GetScriptBackrefTag(JS::HandleObject obj);
|
||||
|
||||
JS::PropertyKey m_SerializePropId;
|
||||
JS::PropertyKey m_DeserializePropId;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2023 Wildfire Games.
|
||||
/* Copyright (C) 2025 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
|
|
@ -63,7 +63,7 @@ struct SPrototypeSerialization
|
|||
bool hasNullSerialize = false;
|
||||
};
|
||||
|
||||
inline SPrototypeSerialization GetPrototypeInfo(const ScriptRequest& rq, JS::HandleObject prototype)
|
||||
inline SPrototypeSerialization GetPrototypeInfo(const ScriptRequest& rq, JS::HandleObject prototype, JS::PropertyKey ser, JS::PropertyKey deser)
|
||||
{
|
||||
SPrototypeSerialization ret;
|
||||
|
||||
|
|
@ -74,24 +74,23 @@ inline SPrototypeSerialization GetPrototypeInfo(const ScriptRequest& rq, JS::Han
|
|||
if (ret.name == "Object")
|
||||
return ret;
|
||||
|
||||
if (!JS_HasProperty(rq.cx, prototype, "Serialize", &ret.hasCustomSerialize) ||
|
||||
!JS_HasProperty(rq.cx, prototype, "Deserialize", &ret.hasCustomDeserialize))
|
||||
throw PSERROR_Serialize_ScriptError("JS_HasProperty failed");
|
||||
JS::RootedValue serialize(rq.cx);
|
||||
if (!JS_GetPropertyById(rq.cx, prototype, JS::Handle<jsid>::fromMarkedLocation(&ser), &serialize))
|
||||
throw PSERROR_Serialize_ScriptError("JS_GetProperty failed");
|
||||
|
||||
if (ret.hasCustomSerialize)
|
||||
if (serialize.isUndefined())
|
||||
return ret;
|
||||
|
||||
ret.hasCustomSerialize = true;
|
||||
if (serialize.isNull())
|
||||
ret.hasNullSerialize = true;
|
||||
if (!JS_HasPropertyById(rq.cx, prototype, JS::Handle<jsid>::fromMarkedLocation(&deser), &ret.hasCustomDeserialize) ||
|
||||
(!ret.hasNullSerialize && !ret.hasCustomDeserialize))
|
||||
{
|
||||
JS::RootedValue serialize(rq.cx);
|
||||
if (!JS_GetProperty(rq.cx, prototype, "Serialize", &serialize))
|
||||
throw PSERROR_Serialize_ScriptError("JS_GetProperty failed");
|
||||
|
||||
if (serialize.isNull())
|
||||
ret.hasNullSerialize = true;
|
||||
else if (!ret.hasCustomDeserialize)
|
||||
{
|
||||
// Don't throw for this error: mods might need updating and this crashes as exceptions are not correctly handled.
|
||||
LOGERROR("Error serializing object '%s': non-null Serialize() but no matching Deserialize().", ret.name);
|
||||
}
|
||||
// Don't throw for this error: mods might need updating and this crashes as exceptions are not correctly handled.
|
||||
LOGERROR("Error serializing object '%s': non-null Serialize() but no matching Deserialize().", ret.name);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2022 Wildfire Games.
|
||||
/* Copyright (C) 2025 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,9 @@ CStdDeserializer::CStdDeserializer(const ScriptInterface& scriptInterface, std::
|
|||
m_ScriptInterface(scriptInterface), m_Stream(stream)
|
||||
{
|
||||
JS_AddExtraGCRootsTracer(ScriptRequest(scriptInterface).cx, CStdDeserializer::Trace, this);
|
||||
m_SerializePropId = JS::PropertyKey::fromPinnedString(JS_AtomizeAndPinString(rq.cx, "Serialize"));
|
||||
m_DeserializePropId = JS::PropertyKey::fromPinnedString(JS_AtomizeAndPinString(rq.cx, "Deserialize"));
|
||||
|
||||
// Insert a dummy object in front, as valid tags start at 1.
|
||||
m_ScriptBackrefs.emplace_back(nullptr);
|
||||
}
|
||||
|
|
@ -168,7 +171,7 @@ JS::Value CStdDeserializer::ReadScriptVal(const char* UNUSED(name), JS::HandleOb
|
|||
|
||||
JS::RootedObject prototype(rq.cx);
|
||||
JS_GetPrototype(rq.cx, obj, &prototype);
|
||||
SPrototypeSerialization info = GetPrototypeInfo(rq, prototype);
|
||||
SPrototypeSerialization info = GetPrototypeInfo(rq, prototype, m_SerializePropId, m_DeserializePropId);
|
||||
|
||||
if (preexistingObject != nullptr && prototypeName != wstring_from_utf8(info.name))
|
||||
throw PSERROR_Deserialize_ScriptError("Deserializer failed: incorrect pre-existing object");
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2021 Wildfire Games.
|
||||
/* Copyright (C) 2025 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
|
|
@ -52,6 +52,8 @@ private:
|
|||
virtual void AddScriptBackref(JS::HandleObject obj);
|
||||
virtual void GetScriptBackref(size_t tag, JS::MutableHandleObject ret);
|
||||
std::vector<JS::Heap<JSObject*> > m_ScriptBackrefs;
|
||||
JS::PropertyKey m_SerializePropId;
|
||||
JS::PropertyKey m_DeserializePropId;
|
||||
|
||||
const ScriptInterface& m_ScriptInterface;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue