Remove serializablePrototype code
The script interface has code to serialize/deserialize JS objects with a user-defined prototype. That code is usable in the AI, but currently unused (and there are no plans to use it in the long run). Removing it allows removing more code down the line, which helps with the SM45-52 migration. Collaboration with itms. Refs #4893 Differential Revision: https://code.wildfiregames.com/D2897 This was SVN commit r24157.
This commit is contained in:
parent
9c46062319
commit
f22449bf24
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2019 Wildfire Games.
|
||||
/* Copyright (C) 2020 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -216,7 +216,6 @@ public:
|
||||
m_CommandsComputed(true),
|
||||
m_HasLoadedEntityTemplates(false),
|
||||
m_HasSharedComponent(false),
|
||||
m_SerializablePrototypes(new ObjectIdCache<std::wstring>(g_ScriptRuntime)),
|
||||
m_EntityTemplates(g_ScriptRuntime->m_rt),
|
||||
m_SharedAIObj(g_ScriptRuntime->m_rt),
|
||||
m_PassabilityMapVal(g_ScriptRuntime->m_rt),
|
||||
@ -227,7 +226,6 @@ public:
|
||||
|
||||
m_ScriptInterface->SetCallbackData(static_cast<void*> (this));
|
||||
|
||||
m_SerializablePrototypes->init();
|
||||
JS_AddExtraGCRootsTracer(m_ScriptInterface->GetJSRuntime(), Trace, this);
|
||||
|
||||
m_ScriptInterface->RegisterFunction<void, int, JS::HandleValue, CAIWorker::PostCommand>("PostCommand");
|
||||
@ -660,8 +658,6 @@ public:
|
||||
else
|
||||
{
|
||||
CStdSerializer serializer(*m_ScriptInterface, stream);
|
||||
// TODO: see comment in Deserialize()
|
||||
serializer.SetSerializablePrototypes(m_SerializablePrototypes);
|
||||
SerializeState(serializer);
|
||||
}
|
||||
}
|
||||
@ -782,12 +778,6 @@ public:
|
||||
m_Players.back()->m_Commands.push_back(m_ScriptInterface->WriteStructuredClone(val));
|
||||
}
|
||||
|
||||
// TODO: this is yucky but necessary while the AIs are sharing data between contexts;
|
||||
// ideally a new (de)serializer instance would be created for each player
|
||||
// so they would have a single, consistent script context to use and serializable
|
||||
// prototypes could be stored in their ScriptInterface
|
||||
deserializer.SetSerializablePrototypes(m_DeserializablePrototypes);
|
||||
|
||||
bool hasCustomDeserialize = m_ScriptInterface->HasProperty(m_Players.back()->m_Obj, "Deserialize");
|
||||
if (hasCustomDeserialize)
|
||||
{
|
||||
@ -826,25 +816,6 @@ public:
|
||||
return m_Players.size();
|
||||
}
|
||||
|
||||
void RegisterSerializablePrototype(std::wstring name, JS::HandleValue proto)
|
||||
{
|
||||
// Require unique prototype and name (for reverse lookup)
|
||||
// TODO: this is yucky - see comment in Deserialize()
|
||||
ENSURE(proto.isObject() && "A serializable prototype has to be an object!");
|
||||
|
||||
JSContext* cx = m_ScriptInterface->GetContext();
|
||||
JSAutoRequest rq(cx);
|
||||
|
||||
JS::RootedObject obj(cx, &proto.toObject());
|
||||
if (m_SerializablePrototypes->has(obj) || m_DeserializablePrototypes.find(name) != m_DeserializablePrototypes.end())
|
||||
{
|
||||
LOGERROR("RegisterSerializablePrototype called with same prototype multiple times: p=%p n='%s'", (void *)obj.get(), utf8_from_wstring(name));
|
||||
return;
|
||||
}
|
||||
m_SerializablePrototypes->add(cx, obj, name);
|
||||
m_DeserializablePrototypes[name] = JS::Heap<JSObject*>(obj);
|
||||
}
|
||||
|
||||
private:
|
||||
static void Trace(JSTracer *trc, void *data)
|
||||
{
|
||||
@ -853,8 +824,6 @@ private:
|
||||
|
||||
void TraceMember(JSTracer *trc)
|
||||
{
|
||||
for (std::pair<const std::wstring, JS::Heap<JSObject*>>& prototype : m_DeserializablePrototypes)
|
||||
JS_CallObjectTracer(trc, &prototype.second, "CAIWorker::m_DeserializablePrototypes");
|
||||
for (std::pair<const VfsPath, JS::Heap<JS::Value>>& metadata : m_PlayerMetadata)
|
||||
JS_CallValueTracer(trc, &metadata.second, "CAIWorker::m_PlayerMetadata");
|
||||
}
|
||||
@ -943,8 +912,6 @@ private:
|
||||
|
||||
bool m_CommandsComputed;
|
||||
|
||||
shared_ptr<ObjectIdCache<std::wstring> > m_SerializablePrototypes;
|
||||
std::map<std::wstring, JS::Heap<JSObject*> > m_DeserializablePrototypes;
|
||||
CTemplateLoader m_TemplateLoader;
|
||||
};
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2019 Wildfire Games.
|
||||
/* Copyright (C) 2020 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -56,10 +56,9 @@ static u8 GetArrayType(js::Scalar::Type arrayType)
|
||||
|
||||
CBinarySerializerScriptImpl::CBinarySerializerScriptImpl(const ScriptInterface& scriptInterface, ISerializer& serializer) :
|
||||
m_ScriptInterface(scriptInterface), m_Serializer(serializer), m_ScriptBackrefs(scriptInterface.GetRuntime()),
|
||||
m_SerializablePrototypes(new ObjectIdCache<std::wstring>(scriptInterface.GetRuntime())), m_ScriptBackrefsNext(1)
|
||||
m_ScriptBackrefsNext(1)
|
||||
{
|
||||
m_ScriptBackrefs.init();
|
||||
m_SerializablePrototypes->init();
|
||||
}
|
||||
|
||||
void CBinarySerializerScriptImpl::HandleScriptVal(JS::HandleValue val)
|
||||
@ -153,51 +152,8 @@ void CBinarySerializerScriptImpl::HandleScriptVal(JS::HandleValue val)
|
||||
|
||||
if (protokey == JSProto_Object)
|
||||
{
|
||||
// Object class - check for user-defined prototype
|
||||
JS::RootedObject proto(cx);
|
||||
JS_GetPrototype(cx, obj, &proto);
|
||||
if (!proto)
|
||||
throw PSERROR_Serialize_ScriptError("JS_GetPrototype failed");
|
||||
|
||||
if (m_SerializablePrototypes->empty() || !IsSerializablePrototype(proto))
|
||||
{
|
||||
// Standard Object prototype
|
||||
m_Serializer.NumberU8_Unbounded("type", SCRIPT_TYPE_OBJECT);
|
||||
|
||||
// TODO: maybe we should throw an error for unrecognized non-Object prototypes?
|
||||
// (requires fixing AI serialization first and excluding component scripts)
|
||||
}
|
||||
else
|
||||
{
|
||||
// User-defined custom prototype
|
||||
m_Serializer.NumberU8_Unbounded("type", SCRIPT_TYPE_OBJECT_PROTOTYPE);
|
||||
|
||||
const std::wstring prototypeName = GetPrototypeName(proto);
|
||||
m_Serializer.String("proto name", prototypeName, 0, 256);
|
||||
|
||||
// Does it have custom Serialize function?
|
||||
// if so, we serialize the data it returns, rather than the object's properties directly
|
||||
bool hasCustomSerialize;
|
||||
if (!JS_HasProperty(cx, obj, "Serialize", &hasCustomSerialize))
|
||||
throw PSERROR_Serialize_ScriptError("JS_HasProperty failed");
|
||||
|
||||
if (hasCustomSerialize)
|
||||
{
|
||||
JS::RootedValue serialize(cx);
|
||||
if (!JS_GetProperty(cx, obj, "Serialize", &serialize))
|
||||
throw PSERROR_Serialize_ScriptError("JS_GetProperty failed");
|
||||
|
||||
// If serialize is null, so don't serialize anything more
|
||||
if (!serialize.isNull())
|
||||
{
|
||||
JS::RootedValue data(cx);
|
||||
if (!m_ScriptInterface.CallFunction(val, "Serialize", &data))
|
||||
throw PSERROR_Serialize_ScriptError("Prototype Serialize function failed");
|
||||
HandleScriptVal(data);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Standard Object prototype
|
||||
m_Serializer.NumberU8_Unbounded("type", SCRIPT_TYPE_OBJECT);
|
||||
}
|
||||
else if (protokey == JSProto_Number)
|
||||
{
|
||||
@ -474,21 +430,3 @@ u32 CBinarySerializerScriptImpl::GetScriptBackrefTag(JS::HandleObject obj)
|
||||
// Return a non-tag number so callers know they need to serialize the object
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool CBinarySerializerScriptImpl::IsSerializablePrototype(JS::HandleObject prototype)
|
||||
{
|
||||
return m_SerializablePrototypes->has(prototype);
|
||||
}
|
||||
|
||||
std::wstring CBinarySerializerScriptImpl::GetPrototypeName(JS::HandleObject prototype)
|
||||
{
|
||||
std::wstring ret;
|
||||
bool found = m_SerializablePrototypes->find(prototype, ret);
|
||||
ENSURE(found);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CBinarySerializerScriptImpl::SetSerializablePrototypes(shared_ptr<ObjectIdCache<std::wstring> > prototypes)
|
||||
{
|
||||
m_SerializablePrototypes = prototypes;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2017 Wildfire Games.
|
||||
/* Copyright (C) 2020 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -87,7 +87,6 @@ public:
|
||||
|
||||
void ScriptString(const char* name, JS::HandleString string);
|
||||
void HandleScriptVal(JS::HandleValue val);
|
||||
void SetSerializablePrototypes(shared_ptr<ObjectIdCache<std::wstring> > prototypes);
|
||||
private:
|
||||
const ScriptInterface& m_ScriptInterface;
|
||||
ISerializer& m_Serializer;
|
||||
@ -95,11 +94,6 @@ private:
|
||||
ObjectIdCache<u32> m_ScriptBackrefs;
|
||||
u32 m_ScriptBackrefsNext;
|
||||
u32 GetScriptBackrefTag(JS::HandleObject obj);
|
||||
|
||||
shared_ptr<ObjectIdCache<std::wstring> > m_SerializablePrototypes;
|
||||
|
||||
bool IsSerializablePrototype(JS::HandleObject prototype);
|
||||
std::wstring GetPrototypeName(JS::HandleObject prototype);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -127,11 +121,6 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
virtual void SetSerializablePrototypes(shared_ptr<ObjectIdCache<std::wstring> >& prototypes)
|
||||
{
|
||||
m_ScriptImpl->SetSerializablePrototypes(prototypes);
|
||||
}
|
||||
|
||||
protected:
|
||||
/*
|
||||
The Put* implementations here are designed for subclasses
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2015 Wildfire Games.
|
||||
/* Copyright (C) 2020 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -31,7 +31,7 @@ enum
|
||||
SCRIPT_TYPE_BACKREF = 8,
|
||||
SCRIPT_TYPE_TYPED_ARRAY = 9, // ArrayBufferView subclasses - see below
|
||||
SCRIPT_TYPE_ARRAY_BUFFER = 10, // ArrayBuffer containing actual typed array data (may be shared by multiple views)
|
||||
SCRIPT_TYPE_OBJECT_PROTOTYPE = 11, // user-defined prototype
|
||||
SCRIPT_TYPE_OBJECT_PROTOTYPE = 11, // user-defined prototype - currently unused
|
||||
SCRIPT_TYPE_OBJECT_NUMBER = 12, // standard Number class
|
||||
SCRIPT_TYPE_OBJECT_STRING = 13, // standard String class
|
||||
SCRIPT_TYPE_OBJECT_BOOLEAN = 14, // standard Boolean class
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2019 Wildfire Games.
|
||||
/* Copyright (C) 2020 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -56,9 +56,6 @@ void CStdDeserializer::TraceMember(JSTracer *trc)
|
||||
{
|
||||
for (size_t i=0; i<m_ScriptBackrefs.size(); ++i)
|
||||
JS_CallObjectTracer(trc, &m_ScriptBackrefs[i], "StdDeserializer::m_ScriptBackrefs");
|
||||
|
||||
for (std::pair<const std::wstring, JS::Heap<JSObject*>>& proto : m_SerializablePrototypes)
|
||||
JS_CallObjectTracer(trc, &proto.second, "StdDeserializer::m_SerializablePrototypes");
|
||||
}
|
||||
|
||||
void CStdDeserializer::Get(const char* name, u8* data, size_t len)
|
||||
@ -139,7 +136,6 @@ JS::Value CStdDeserializer::ReadScriptVal(const char* UNUSED(name), JS::HandleOb
|
||||
|
||||
case SCRIPT_TYPE_ARRAY:
|
||||
case SCRIPT_TYPE_OBJECT:
|
||||
case SCRIPT_TYPE_OBJECT_PROTOTYPE:
|
||||
{
|
||||
JS::RootedObject obj(cx);
|
||||
if (appendParent)
|
||||
@ -152,51 +148,10 @@ JS::Value CStdDeserializer::ReadScriptVal(const char* UNUSED(name), JS::HandleOb
|
||||
NumberU32_Unbounded("array length", length);
|
||||
obj.set(JS_NewArrayObject(cx, length));
|
||||
}
|
||||
else if (type == SCRIPT_TYPE_OBJECT)
|
||||
else // SCRIPT_TYPE_OBJECT
|
||||
{
|
||||
obj.set(JS_NewPlainObject(cx));
|
||||
}
|
||||
else // SCRIPT_TYPE_OBJECT_PROTOTYPE
|
||||
{
|
||||
std::wstring prototypeName;
|
||||
String("proto name", prototypeName, 0, 256);
|
||||
|
||||
// Get constructor object
|
||||
JS::RootedObject proto(cx);
|
||||
GetSerializablePrototype(prototypeName, &proto);
|
||||
if (!proto)
|
||||
throw PSERROR_Deserialize_ScriptError("Failed to find serializable prototype for object");
|
||||
|
||||
obj.set(JS_NewObjectWithGivenProto(cx, nullptr, proto));
|
||||
if (!obj)
|
||||
throw PSERROR_Deserialize_ScriptError("JS_NewObject failed");
|
||||
|
||||
// Does it have custom Deserialize function?
|
||||
// if so, we let it handle the deserialized data, rather than adding properties directly
|
||||
bool hasCustomDeserialize, hasCustomSerialize;
|
||||
if (!JS_HasProperty(cx, obj, "Serialize", &hasCustomSerialize) || !JS_HasProperty(cx, obj, "Deserialize", &hasCustomDeserialize))
|
||||
throw PSERROR_Serialize_ScriptError("JS_HasProperty failed");
|
||||
|
||||
if (hasCustomDeserialize)
|
||||
{
|
||||
AddScriptBackref(obj);
|
||||
|
||||
JS::RootedValue serialize(cx);
|
||||
if (!JS_GetProperty(cx, obj, "Serialize", &serialize))
|
||||
throw PSERROR_Serialize_ScriptError("JS_GetProperty failed");
|
||||
bool hasNullSerialize = hasCustomSerialize && serialize.isNull();
|
||||
|
||||
// If Serialize is null, we'll still call Deserialize but with undefined argument
|
||||
JS::RootedValue data(cx);
|
||||
if (!hasNullSerialize)
|
||||
ScriptVal("data", &data);
|
||||
|
||||
JS::RootedValue objVal(cx, JS::ObjectValue(*obj));
|
||||
m_ScriptInterface.CallFunctionVoid(objVal, "Deserialize", data);
|
||||
|
||||
return JS::ObjectValue(*obj);
|
||||
}
|
||||
}
|
||||
|
||||
if (!obj)
|
||||
throw PSERROR_Deserialize_ScriptError("Deserializer failed to create new object");
|
||||
@ -501,22 +456,3 @@ void CStdDeserializer::ScriptObjectAppend(const char* name, JS::HandleValue objV
|
||||
JS::RootedObject obj(cx, &objVal.toObject());
|
||||
ReadScriptVal(name, obj);
|
||||
}
|
||||
|
||||
void CStdDeserializer::SetSerializablePrototypes(std::map<std::wstring, JS::Heap<JSObject*> >& prototypes)
|
||||
{
|
||||
m_SerializablePrototypes = prototypes;
|
||||
}
|
||||
|
||||
bool CStdDeserializer::IsSerializablePrototype(const std::wstring& name)
|
||||
{
|
||||
return m_SerializablePrototypes.find(name) != m_SerializablePrototypes.end();
|
||||
}
|
||||
|
||||
void CStdDeserializer::GetSerializablePrototype(const std::wstring& name, JS::MutableHandleObject ret)
|
||||
{
|
||||
std::map<std::wstring, JS::Heap<JSObject*> >::iterator it = m_SerializablePrototypes.find(name);
|
||||
if (it != m_SerializablePrototypes.end())
|
||||
ret.set(it->second);
|
||||
else
|
||||
ret.set(NULL);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2017 Wildfire Games.
|
||||
/* Copyright (C) 2020 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@ -38,8 +38,6 @@ public:
|
||||
virtual std::istream& GetStream();
|
||||
virtual void RequireBytesInStream(size_t numBytes);
|
||||
|
||||
virtual void SetSerializablePrototypes(std::map<std::wstring, JS::Heap<JSObject*> >& prototypes);
|
||||
|
||||
static void Trace(JSTracer *trc, void *data);
|
||||
|
||||
void TraceMember(JSTracer *trc);
|
||||
@ -60,11 +58,6 @@ private:
|
||||
const ScriptInterface& m_ScriptInterface;
|
||||
|
||||
std::istream& m_Stream;
|
||||
|
||||
std::map<std::wstring, JS::Heap<JSObject*> > m_SerializablePrototypes;
|
||||
|
||||
bool IsSerializablePrototype(const std::wstring& name);
|
||||
void GetSerializablePrototype(const std::wstring& name, JS::MutableHandleObject ret);
|
||||
};
|
||||
|
||||
#endif // INCLUDED_STDDESERIALIZER
|
||||
|
Loading…
Reference in New Issue
Block a user