diff --git a/binaries/data/mods/_test.sim/globalscripts/test-global-helper.js b/binaries/data/mods/_test.sim/globalscripts/test-global-helper.js
index 884d084927..ace5e854a9 100644
a
|
b
|
Vector2D.prototype.add = function(v)
|
21 | 21 | return this; |
22 | 22 | }; |
23 | 23 | |
| 24 | Vector2D.prototype.lengthSquared = function() |
| 25 | { |
| 26 | return this.x*this.x + this.y*this.y |
| 27 | }; |
| 28 | |
| 29 | Vector2D.prototype.nop = function() |
| 30 | { |
| 31 | return "working"; |
| 32 | }; |
| 33 | |
24 | 34 | function Vector3D(x, y, z) |
25 | 35 | { |
26 | 36 | if (arguments.length == 3) |
diff --git a/binaries/data/mods/_test.sim/simulation/components/test-serialize.js b/binaries/data/mods/_test.sim/simulation/components/test-serialize.js
index 9893d6d794..87e458da81 100644
a
|
b
|
TestScript1_consts.prototype.GetX = function() {
|
88 | 88 | }; |
89 | 89 | |
90 | 90 | Engine.RegisterComponentType(IID_Test1, "TestScript1_consts", TestScript1_consts); |
| 91 | |
| 92 | // -------- // |
| 93 | |
| 94 | function TestScript1_vector() {} |
| 95 | |
| 96 | TestScript1_vector.prototype.Init = function() { |
| 97 | this.list = [ {pos: new Vector2D(1, 2)}]; |
| 98 | }; |
| 99 | |
| 100 | TestScript1_vector.prototype.GetX = function() { |
| 101 | return this.list[0].pos.lengthSquared(); |
| 102 | }; |
| 103 | |
| 104 | Engine.RegisterComponentType(IID_Test1, "TestScript1_vector", TestScript1_vector); |
diff --git a/source/network/NetMessageSim.cpp b/source/network/NetMessageSim.cpp
index 28b0dfeb33..6efda7f535 100644
a
|
b
|
u8* CSimulationMessage::Serialize(u8* pBuffer) const
|
141 | 141 | serializer.NumberI32_Unbounded("player", m_Player); |
142 | 142 | serializer.NumberU32_Unbounded("turn", m_Turn); |
143 | 143 | |
144 | | serializer.ScriptVal("command", const_cast<JS::PersistentRootedValue*>(&m_Data)); |
| 144 | serializer.ScriptVal("command", const_cast<JS::PersistentRootedValue*>(&m_Data), false); |
145 | 145 | return serializer.GetBuffer(); |
146 | 146 | } |
147 | 147 | |
… |
… |
size_t CSimulationMessage::GetSerializedLength() const
|
170 | 170 | |
171 | 171 | // TODO: The cast can probably be removed if and when ScriptVal can take a JS::HandleValue instead of |
172 | 172 | // a JS::MutableHandleValue (relies on JSAPI change). Also search for other casts like this one in that case. |
173 | | serializer.ScriptVal("command", const_cast<JS::PersistentRootedValue*>(&m_Data)); |
| 173 | serializer.ScriptVal("command", const_cast<JS::PersistentRootedValue*>(&m_Data), false); |
174 | 174 | return CNetMessage::GetSerializedLength() + serializer.GetLength(); |
175 | 175 | } |
176 | 176 | |
… |
… |
u8* CGameSetupMessage::Serialize(u8* pBuffer) const
|
200 | 200 | // TODO: ought to handle serialization exceptions |
201 | 201 | u8* pos = CNetMessage::Serialize(pBuffer); |
202 | 202 | CBufferBinarySerializer serializer(m_ScriptInterface, pos); |
203 | | serializer.ScriptVal("command", const_cast<JS::PersistentRootedValue*>(&m_Data)); |
| 203 | serializer.ScriptVal("command", const_cast<JS::PersistentRootedValue*>(&m_Data), false); |
204 | 204 | return serializer.GetBuffer(); |
205 | 205 | } |
206 | 206 | |
… |
… |
const u8* CGameSetupMessage::Deserialize(const u8* pStart, const u8* pEnd)
|
217 | 217 | size_t CGameSetupMessage::GetSerializedLength() const |
218 | 218 | { |
219 | 219 | CLengthBinarySerializer serializer(m_ScriptInterface); |
220 | | serializer.ScriptVal("command", const_cast<JS::PersistentRootedValue*>(&m_Data)); |
| 220 | serializer.ScriptVal("command", const_cast<JS::PersistentRootedValue*>(&m_Data), false); |
221 | 221 | return CNetMessage::GetSerializedLength() + serializer.GetLength(); |
222 | 222 | } |
223 | 223 | |
diff --git a/source/simulation2/components/CCmpAIManager.cpp b/source/simulation2/components/CCmpAIManager.cpp
index d62ee29205..ddf22bf9b0 100644
a
|
b
|
public:
|
671 | 671 | JS::RootedValue sharedData(cx); |
672 | 672 | if (!m_ScriptInterface->CallFunction(m_SharedAIObj, "Serialize", &sharedData)) |
673 | 673 | LOGERROR("AI shared script Serialize call failed"); |
674 | | serializer.ScriptVal("sharedData", &sharedData); |
| 674 | serializer.ScriptVal("sharedData", &sharedData, false); |
675 | 675 | } |
676 | 676 | for (size_t i = 0; i < m_Players.size(); ++i) |
677 | 677 | { |
… |
… |
public:
|
684 | 684 | { |
685 | 685 | JS::RootedValue val(cx); |
686 | 686 | m_ScriptInterface->ReadStructuredClone(m_Players[i]->m_Commands[j], &val); |
687 | | serializer.ScriptVal("command", &val); |
| 687 | serializer.ScriptVal("command", &val, false); |
688 | 688 | } |
689 | 689 | |
690 | 690 | bool hasCustomSerialize = m_ScriptInterface->HasProperty(m_Players[i]->m_Obj, "Serialize"); |
… |
… |
public:
|
693 | 693 | JS::RootedValue scriptData(cx); |
694 | 694 | if (!m_ScriptInterface->CallFunction(m_Players[i]->m_Obj, "Serialize", &scriptData)) |
695 | 695 | LOGERROR("AI script Serialize call failed"); |
696 | | serializer.ScriptVal("data", &scriptData); |
| 696 | serializer.ScriptVal("data", &scriptData, false); |
697 | 697 | } |
698 | 698 | else |
699 | 699 | { |
700 | | serializer.ScriptVal("data", &m_Players[i]->m_Obj); |
| 700 | serializer.ScriptVal("data", &m_Players[i]->m_Obj, false); |
701 | 701 | } |
702 | 702 | } |
703 | 703 | |
diff --git a/source/simulation2/components/CCmpCommandQueue.cpp b/source/simulation2/components/CCmpCommandQueue.cpp
index 90d4d3e5eb..fdf8ee4a2a 100644
a
|
b
|
public:
|
58 | 58 | for (size_t i = 0; i < m_LocalQueue.size(); ++i) |
59 | 59 | { |
60 | 60 | serialize.NumberI32_Unbounded("player", m_LocalQueue[i].player); |
61 | | serialize.ScriptVal("data", &m_LocalQueue[i].data); |
| 61 | serialize.ScriptVal("data", &m_LocalQueue[i].data, false); |
62 | 62 | } |
63 | 63 | } |
64 | 64 | |
diff --git a/source/simulation2/scripting/ScriptComponent.cpp b/source/simulation2/scripting/ScriptComponent.cpp
index 4e96c7bdf5..39580e9994 100644
a
|
b
|
void CComponentTypeScript::Serialize(ISerializer& serialize)
|
82 | 82 | JS::RootedValue val(cx); |
83 | 83 | if (!m_ScriptInterface.CallFunction(m_Instance, "Serialize", &val)) |
84 | 84 | LOGERROR("Script Serialize call failed"); |
85 | | serialize.ScriptVal("object", &val); |
| 85 | serialize.ScriptVal("object", &val, false); // TODO: make this new parameter optional |
| 86 | // TODO: or (maybe even better) provide another serialize function for it |
| 87 | // then we just need to make both call the right binaryserializer one in the end |
86 | 88 | } |
87 | 89 | else |
88 | 90 | { |
89 | | serialize.ScriptVal("object", &m_Instance); |
| 91 | // We want to ignore the prototype of the top level object for components. |
| 92 | serialize.ScriptVal("object", &m_Instance, true); |
90 | 93 | } |
91 | 94 | } |
92 | 95 | |
diff --git a/source/simulation2/serialization/BinarySerializer.cpp b/source/simulation2/serialization/BinarySerializer.cpp
index 2f1e737132..5f959e687b 100644
a
|
b
|
|
26 | 26 | #include "scriptinterface/ScriptExtraHeaders.h" |
27 | 27 | #include "SerializedScriptTypes.h" |
28 | 28 | |
| 29 | #include "ps/Filesystem.h" // TODO part fo the gvfs hack |
| 30 | |
29 | 31 | static u8 GetArrayType(js::Scalar::Type arrayType) |
30 | 32 | { |
31 | 33 | switch(arrayType) |
… |
… |
CBinarySerializerScriptImpl::CBinarySerializerScriptImpl(const ScriptInterface&
|
60 | 62 | { |
61 | 63 | m_ScriptBackrefs.init(); |
62 | 64 | m_SerializablePrototypes->init(); |
| 65 | |
| 66 | // TODO fix/remove the set functions for these prototypes, and let them just add things |
| 67 | // TODO call into the scriptinterface to let that add it |
| 68 | // TODO do the same thing for the deserializer |
| 69 | if (g_VFS) // TODO hack for tests |
| 70 | { |
| 71 | m_SerializablePrototypes->add(m_ScriptInterface.GetContext(), &m_ScriptInterface.GetCachedValue(ScriptInterface::CACHE_VECTOR2DPROTO).toObject(), L"Vector2D"); |
| 72 | m_SerializablePrototypes->add(m_ScriptInterface.GetContext(), &m_ScriptInterface.GetCachedValue(ScriptInterface::CACHE_VECTOR3DPROTO).toObject(), L"Vector3D"); |
| 73 | } |
63 | 74 | } |
64 | 75 | |
65 | | void CBinarySerializerScriptImpl::HandleScriptVal(JS::HandleValue val) |
| 76 | void CBinarySerializerScriptImpl::HandleScriptVal(JS::HandleValue val, bool ignoreCustomPrototype) |
66 | 77 | { |
67 | 78 | JSContext* cx = m_ScriptInterface.GetContext(); |
68 | 79 | JSAutoRequest rq(cx); |
… |
… |
void CBinarySerializerScriptImpl::HandleScriptVal(JS::HandleValue val)
|
159 | 170 | if (!proto) |
160 | 171 | throw PSERROR_Serialize_ScriptError("JS_GetPrototype failed"); |
161 | 172 | |
162 | | if (m_SerializablePrototypes->empty() || !IsSerializablePrototype(proto)) |
| 173 | if (IdentifyStandardPrototype(proto) == JSProto_Object || ignoreCustomPrototype) |
163 | 174 | { |
| 175 | debug_printf("default proto\n"); |
| 176 | |
164 | 177 | // Standard Object prototype |
165 | 178 | m_Serializer.NumberU8_Unbounded("type", SCRIPT_TYPE_OBJECT); |
| 179 | } |
| 180 | else if (/*IdentifyStandardPrototype(proto) == JSProto_Null && */!IsSerializablePrototype(proto)) |
| 181 | { |
| 182 | // TODO we could print the current value |
166 | 183 | |
167 | | // TODO: maybe we should throw an error for unrecognized non-Object prototypes? |
168 | | // (requires fixing AI serialization first and excluding component scripts) |
| 184 | // TODO: Can we get some more data about what the prototype is? (apart from null that is) |
| 185 | throw PSERROR_Serialize_ScriptError("Unhandled custom prototype"); |
169 | 186 | } |
170 | 187 | else |
171 | 188 | { |
… |
… |
void CBinarySerializerScriptImpl::HandleScriptVal(JS::HandleValue val)
|
174 | 191 | |
175 | 192 | const std::wstring prototypeName = GetPrototypeName(proto); |
176 | 193 | m_Serializer.String("proto name", prototypeName, 0, 256); |
| 194 | debug_printf("other %ls\n", prototypeName.c_str()); |
177 | 195 | |
178 | 196 | // Does it have custom Serialize function? |
179 | 197 | // if so, we serialize the data it returns, rather than the object's properties directly |
diff --git a/source/simulation2/serialization/BinarySerializer.h b/source/simulation2/serialization/BinarySerializer.h
index 235b69a278..11a18c3c06 100644
a
|
b
|
public:
|
86 | 86 | CBinarySerializerScriptImpl(const ScriptInterface& scriptInterface, ISerializer& serializer); |
87 | 87 | |
88 | 88 | void ScriptString(const char* name, JS::HandleString string); |
89 | | void HandleScriptVal(JS::HandleValue val); |
| 89 | void HandleScriptVal(JS::HandleValue val, bool ignoreCustomObjectPrototype = true); |
90 | 90 | void SetSerializablePrototypes(shared_ptr<ObjectIdCache<std::wstring> > prototypes); |
91 | 91 | private: |
92 | 92 | const ScriptInterface& m_ScriptInterface; |
… |
… |
protected:
|
206 | 206 | m_Impl.Put(name, (u8*)value.data(), value.length()); |
207 | 207 | } |
208 | 208 | |
209 | | virtual void PutScriptVal(const char* UNUSED(name), JS::MutableHandleValue value) |
| 209 | virtual void PutScriptVal(const char* UNUSED(name), JS::MutableHandleValue value, bool isComponentObject) |
210 | 210 | { |
211 | | m_ScriptImpl->HandleScriptVal(value); |
| 211 | m_ScriptImpl->HandleScriptVal(value, isComponentObject); |
212 | 212 | } |
213 | 213 | |
214 | 214 | virtual void PutRaw(const char* name, const u8* data, size_t len) |
diff --git a/source/simulation2/serialization/DebugSerializer.cpp b/source/simulation2/serialization/DebugSerializer.cpp
index 7f1f49f1ec..ffff9bc492 100644
a
|
b
|
void CDebugSerializer::PutString(const char* name, const std::string& value)
|
147 | 147 | m_Stream << INDENT << name << ": " << "\"" << escaped << "\"\n"; |
148 | 148 | } |
149 | 149 | |
150 | | void CDebugSerializer::PutScriptVal(const char* name, JS::MutableHandleValue value) |
| 150 | void CDebugSerializer::PutScriptVal(const char* name, JS::MutableHandleValue value, bool) |
151 | 151 | { |
152 | 152 | std::string source = m_ScriptInterface.ToString(value, true); |
153 | 153 | |
diff --git a/source/simulation2/serialization/DebugSerializer.h b/source/simulation2/serialization/DebugSerializer.h
index 7ad4871540..e30e6ba20d 100644
a
|
b
|
protected:
|
54 | 54 | virtual void PutNumber(const char* name, fixed value); |
55 | 55 | virtual void PutBool(const char* name, bool value); |
56 | 56 | virtual void PutString(const char* name, const std::string& value); |
57 | | virtual void PutScriptVal(const char* name, JS::MutableHandleValue value); |
| 57 | virtual void PutScriptVal(const char* name, JS::MutableHandleValue value, bool); |
58 | 58 | virtual void PutRaw(const char* name, const u8* data, size_t len); |
59 | 59 | |
60 | 60 | private: |
diff --git a/source/simulation2/serialization/ISerializer.cpp b/source/simulation2/serialization/ISerializer.cpp
index 92b9124e88..10c379fca7 100644
a
|
b
|
void ISerializer::String(const char* name, const std::wstring& value, uint32_t m
|
92 | 92 | PutString(name, str); |
93 | 93 | } |
94 | 94 | |
95 | | void ISerializer::ScriptVal(const char* name, JS::MutableHandleValue value) |
| 95 | void ISerializer::ScriptVal(const char* name, JS::MutableHandleValue value, bool a) |
96 | 96 | { |
97 | | PutScriptVal(name, value); |
| 97 | PutScriptVal(name, value, a); |
98 | 98 | } |
99 | 99 | |
100 | 100 | void ISerializer::RawBytes(const char* name, const u8* data, size_t len) |
diff --git a/source/simulation2/serialization/ISerializer.h b/source/simulation2/serialization/ISerializer.h
index 4ab47bb0b7..4ca1016bab 100644
a
|
b
|
public:
|
220 | 220 | * The value must not contain any unserializable values (like functions). |
221 | 221 | * NOTE: We have to use a mutable handle because JS_Stringify requires that for unknown reasons. |
222 | 222 | */ |
223 | | void ScriptVal(const char* name, JS::MutableHandleValue value); |
| 223 | void ScriptVal(const char* name, JS::MutableHandleValue value, bool); |
224 | 224 | |
225 | 225 | /** |
226 | 226 | * Serialize a stream of bytes. |
… |
… |
protected:
|
257 | 257 | virtual void PutBool(const char* name, bool value) = 0; |
258 | 258 | virtual void PutString(const char* name, const std::string& value) = 0; |
259 | 259 | // We have to use a mutable handle because JS_Stringify requires that for unknown reasons. |
260 | | virtual void PutScriptVal(const char* name, JS::MutableHandleValue value) = 0; |
| 260 | virtual void PutScriptVal(const char* name, JS::MutableHandleValue value, bool) = 0; |
261 | 261 | virtual void PutRaw(const char* name, const u8* data, size_t len) = 0; |
262 | 262 | }; |
263 | 263 | |
diff --git a/source/simulation2/serialization/StdDeserializer.cpp b/source/simulation2/serialization/StdDeserializer.cpp
index 131898ccd9..6a1097841c 100644
a
|
b
|
|
1 | | /* Copyright (C) 2016 Wildfire Games. |
| 1 | /* Copyright (C) 2017 Wildfire Games. |
2 | 2 | * This file is part of 0 A.D. |
3 | 3 | * |
4 | 4 | * 0 A.D. is free software: you can redistribute it and/or modify |
… |
… |
|
27 | 27 | |
28 | 28 | #include "lib/byte_order.h" |
29 | 29 | |
| 30 | #include "ps/Filesystem.h" // gvfs hack |
| 31 | |
30 | 32 | CStdDeserializer::CStdDeserializer(ScriptInterface& scriptInterface, std::istream& stream) : |
31 | 33 | m_ScriptInterface(scriptInterface), m_Stream(stream), |
32 | 34 | m_dummyObject(scriptInterface.GetJSRuntime()) |
… |
… |
CStdDeserializer::CStdDeserializer(ScriptInterface& scriptInterface, std::istrea
|
40 | 42 | // needs to be serialized and then tagged |
41 | 43 | m_dummyObject = JS_NewPlainObject(cx); |
42 | 44 | m_ScriptBackrefs.push_back(JS::Heap<JSObject*>(m_dummyObject)); |
| 45 | |
| 46 | if (g_VFS) |
| 47 | { |
| 48 | JS::Heap<JSObject*> v2proto(&m_ScriptInterface.GetCachedValue(ScriptInterface::CACHE_VECTOR2DPROTO).toObject()); |
| 49 | m_SerializablePrototypes.insert(std::make_pair(L"Vector2D", v2proto)); |
| 50 | JS::Heap<JSObject*> v3proto(&m_ScriptInterface.GetCachedValue(ScriptInterface::CACHE_VECTOR3DPROTO).toObject()); |
| 51 | m_SerializablePrototypes.insert(std::make_pair(L"Vector2D", v3proto)); |
| 52 | } |
43 | 53 | } |
44 | 54 | |
45 | 55 | CStdDeserializer::~CStdDeserializer() |
… |
… |
void CStdDeserializer::SetSerializablePrototypes(std::map<std::wstring, JS::Heap
|
512 | 522 | m_SerializablePrototypes = prototypes; |
513 | 523 | } |
514 | 524 | |
515 | | bool CStdDeserializer::IsSerializablePrototype(const std::wstring& name) |
| 525 | bool CStdDeserializer::IsSerializablePrototype(const std::wstring& name) const |
516 | 526 | { |
517 | 527 | return m_SerializablePrototypes.find(name) != m_SerializablePrototypes.end(); |
518 | 528 | } |
519 | 529 | |
520 | | void CStdDeserializer::GetSerializablePrototype(const std::wstring& name, JS::MutableHandleObject ret) |
| 530 | void CStdDeserializer::GetSerializablePrototype(const std::wstring& name, JS::MutableHandleObject ret) const |
521 | 531 | { |
522 | | std::map<std::wstring, JS::Heap<JSObject*> >::iterator it = m_SerializablePrototypes.find(name); |
| 532 | std::map<std::wstring, JS::Heap<JSObject*> >::const_iterator it = m_SerializablePrototypes.find(name); |
523 | 533 | if (it != m_SerializablePrototypes.end()) |
524 | 534 | ret.set(it->second); |
525 | 535 | else |
526 | | ret.set(NULL); |
| 536 | ret.set(nullptr); |
527 | 537 | } |
diff --git a/source/simulation2/serialization/StdDeserializer.h b/source/simulation2/serialization/StdDeserializer.h
index 1d16e56993..d2c3f48655 100644
a
|
b
|
|
1 | | /* Copyright (C) 2016 Wildfire Games. |
| 1 | /* Copyright (C) 2017 Wildfire Games. |
2 | 2 | * This file is part of 0 A.D. |
3 | 3 | * |
4 | 4 | * 0 A.D. is free software: you can redistribute it and/or modify |
… |
… |
private:
|
63 | 63 | |
64 | 64 | std::map<std::wstring, JS::Heap<JSObject*> > m_SerializablePrototypes; |
65 | 65 | |
66 | | bool IsSerializablePrototype(const std::wstring& name); |
67 | | void GetSerializablePrototype(const std::wstring& name, JS::MutableHandleObject ret); |
| 66 | bool IsSerializablePrototype(const std::wstring& name) const; |
| 67 | void GetSerializablePrototype(const std::wstring& name, JS::MutableHandleObject ret) const; |
68 | 68 | }; |
69 | 69 | |
70 | 70 | #endif // INCLUDED_STDDESERIALIZER |
diff --git a/source/simulation2/tests/test_ComponentManager.h b/source/simulation2/tests/test_ComponentManager.h
index 1cbffd1602..735ecbb53b 100644
a
|
b
|
public:
|
716 | 716 | man.LoadComponentTypes(); |
717 | 717 | TS_ASSERT(man.LoadScript(L"simulation/components/test-serialize.js")); |
718 | 718 | |
719 | | entity_id_t ent1 = 1, ent2 = 2, ent3 = 3, ent4 = 4; |
| 719 | entity_id_t ent1 = 1, ent2 = 2, ent3 = 3, ent4 = 4, ent5 = 5; |
720 | 720 | CEntityHandle hnd1 = man.AllocateEntityHandle(ent1); |
721 | 721 | CEntityHandle hnd2 = man.AllocateEntityHandle(ent2); |
722 | 722 | CEntityHandle hnd3 = man.AllocateEntityHandle(ent3); |
723 | 723 | CEntityHandle hnd4 = man.AllocateEntityHandle(ent4); |
| 724 | CEntityHandle hnd5 = man.AllocateEntityHandle(ent5); |
724 | 725 | CParamNode noParam; |
725 | 726 | |
726 | 727 | CParamNode testParam; |
… |
… |
public:
|
729 | 730 | man.AddComponent(hnd1, man.LookupCID("TestScript1_values"), testParam); |
730 | 731 | man.AddComponent(hnd2, man.LookupCID("TestScript1_entity"), testParam); |
731 | 732 | |
| 733 | // TODO is this actually accurate? |
732 | 734 | // TODO: Since the upgrade to SpiderMonkey v24 this test won't be able to correctly represent |
733 | 735 | // non-tree structures because sharp variables were removed (bug 566700). |
734 | 736 | // This also affects the debug serializer and it could make sense to implement correct serialization again. |
… |
… |
public:
|
736 | 738 | |
737 | 739 | man.AddComponent(hnd4, man.LookupCID("TestScript1_custom"), testParam); |
738 | 740 | |
| 741 | man.AddComponent(hnd5, man.LookupCID("TestScript1_vector"), testParam); |
| 742 | |
739 | 743 | TS_ASSERT_EQUALS(static_cast<ICmpTest1*> (man.QueryInterface(ent1, IID_Test1))->GetX(), 1234); |
740 | 744 | { |
741 | 745 | TestLogger log; // swallow warnings about this.entity being read-only |
742 | 746 | TS_ASSERT_EQUALS(static_cast<ICmpTest1*> (man.QueryInterface(ent2, IID_Test1))->GetX(), (int)ent2); |
743 | 747 | } |
744 | 748 | TS_ASSERT_EQUALS(static_cast<ICmpTest1*> (man.QueryInterface(ent3, IID_Test1))->GetX(), 8); |
| 749 | TS_ASSERT_EQUALS(static_cast<ICmpTest1*> (man.QueryInterface(ent5, IID_Test1))->GetX(), 5); |
745 | 750 | |
746 | 751 | std::stringstream debugStream; |
747 | 752 | TS_ASSERT(man.DumpDebugState(debugStream, true)); |
… |
… |
entities:\n\
|
780 | 785 | object: {\n\ |
781 | 786 | \"c\": 1\n\ |
782 | 787 | }\n\ |
| 788 | \n\ |
| 789 | - id: 5\n\ |
| 790 | TestScript1_vector:\n\ |
| 791 | object: {\n\ |
| 792 | \"list\": [\n\ |
| 793 | {\n\ |
| 794 | \"pos\": {\n\ |
| 795 | \"x\": 1,\n\ |
| 796 | \"y\": 2\n\ |
| 797 | }\n\ |
| 798 | }\n\ |
| 799 | ]\n\ |
| 800 | }\n\ |
783 | 801 | \n" |
784 | 802 | ); |
785 | 803 | |
… |
… |
entities:\n\
|
799 | 817 | TS_ASSERT_EQUALS(static_cast<ICmpTest1*> (man2.QueryInterface(ent2, IID_Test1))->GetX(), (int)ent2); |
800 | 818 | } |
801 | 819 | TS_ASSERT_EQUALS(static_cast<ICmpTest1*> (man2.QueryInterface(ent3, IID_Test1))->GetX(), 12); |
| 820 | TS_ASSERT_EQUALS(static_cast<ICmpTest1*> (man.QueryInterface(ent5, IID_Test1))->GetX(), 5); |
802 | 821 | } |
803 | 822 | |
804 | 823 | void test_script_serialization_errors() |
diff --git a/source/simulation2/tests/test_Serializer.h b/source/simulation2/tests/test_Serializer.h
index d9aee50552..4d160fc1cb 100644
a
|
b
|
public:
|
289 | 289 | |
290 | 290 | // TODO: test exceptions more thoroughly |
291 | 291 | |
292 | | void helper_script_roundtrip(const char* msg, const char* input, const char* expected, size_t expstreamlen = 0, const char* expstream = NULL, const char* debug = NULL) |
| 292 | void helper_script_roundtrip(const char* msg, const char* input, const char* expected, size_t expstreamlen = 0, const char* expstream = NULL, const char* debug = NULL, bool loadglobalscripts = false) |
293 | 293 | { |
294 | 294 | ScriptInterface script("Test", "Test", g_ScriptRuntime); |
| 295 | |
| 296 | if (loadglobalscripts) |
| 297 | script.LoadGlobalScripts(); |
| 298 | |
295 | 299 | JSContext* cx = script.GetContext(); |
296 | 300 | JSAutoRequest rq(cx); |
297 | 301 | |
… |
… |
public:
|
302 | 306 | { |
303 | 307 | std::stringstream dbgstream; |
304 | 308 | CDebugSerializer serialize(script, dbgstream); |
305 | | serialize.ScriptVal("script", &obj); |
| 309 | serialize.ScriptVal("script", &obj, false); |
306 | 310 | TS_ASSERT_STR_EQUALS(dbgstream.str(), debug); |
307 | 311 | } |
308 | 312 | |
309 | 313 | std::stringstream stream; |
310 | 314 | CStdSerializer serialize(script, stream); |
311 | 315 | |
312 | | serialize.ScriptVal("script", &obj); |
| 316 | serialize.ScriptVal("script", &obj, false); |
| 317 | |
| 318 | // TODO hack |
| 319 | if (loadglobalscripts) { |
| 320 | std::string foo_; |
| 321 | TSM_ASSERT(msg, script.CallFunction(obj, "nop", foo_)); |
| 322 | TS_ASSERT_STR_EQUALS(foo_, "working"); |
| 323 | } |
313 | 324 | |
314 | 325 | if (expstream) |
315 | 326 | { |
… |
… |
public:
|
327 | 338 | std::string source; |
328 | 339 | TSM_ASSERT(msg, script.CallFunction(newobj, "toSource", source)); |
329 | 340 | TS_ASSERT_STR_EQUALS(source, expected); |
| 341 | |
| 342 | // TODO hack |
| 343 | if (loadglobalscripts) { |
| 344 | std::string foo; |
| 345 | TSM_ASSERT(msg, script.CallFunction(newobj, "nop", foo)); |
| 346 | TS_ASSERT_STR_EQUALS(foo, "working"); |
| 347 | } |
330 | 348 | } |
331 | 349 | |
332 | 350 | void test_script_basic() |
… |
… |
public:
|
717 | 735 | |
718 | 736 | // TODO: prototype objects |
719 | 737 | |
| 738 | void test_script_vector() |
| 739 | { |
| 740 | g_VFS = CreateVfs(20 * MiB); |
| 741 | TS_ASSERT_OK(g_VFS->Mount(L"", DataDir()/"mods"/"_test.sim", VFS_MOUNT_MUST_EXIST)); |
| 742 | TS_ASSERT_OK(g_VFS->Mount(L"cache", DataDir()/"_testcache")); |
| 743 | |
| 744 | helper_script_roundtrip("Vector2D", |
| 745 | "var a = new Vector2D(1, 2); a.add({x:1, y:1}); warn(\"\"+(a instanceof Vector2D)); a", |
| 746 | /* expected: */ |
| 747 | "({x:2, y:3})", |
| 748 | /* expected stream */ |
| 749 | 39, |
| 750 | "\x0B" // SCRIPT_TYPE_OBJECT_PROTOTYPE |
| 751 | "\x08\0\0\0" // len of prototype name |
| 752 | "Vector2D" // prototype name |
| 753 | "\x02\0\0\0" // num props |
| 754 | "\x01\x01\0\0\0" "x" // "x" |
| 755 | "\x05" // SCRIPT_TYPE_INT |
| 756 | "\x02\0\0\0" // 2 |
| 757 | |
| 758 | "\x01\x01\0\0\0" "y" // "y" |
| 759 | "\x05" // SCRIPT_TYPE_INT |
| 760 | "\x03\0\0\0" // 3 |
| 761 | , |
| 762 | NULL, |
| 763 | true |
| 764 | |
| 765 | ); |
| 766 | g_VFS.reset(); |
| 767 | } |
| 768 | |
720 | 769 | void test_script_nonfinite() |
721 | 770 | { |
722 | 771 | helper_script_roundtrip("nonfinite", "[0, Infinity, -Infinity, NaN, -1/Infinity]", "[0, Infinity, -Infinity, NaN, -0]"); |
… |
… |
public:
|
766 | 815 | TestLogger logger; |
767 | 816 | |
768 | 817 | TS_ASSERT(script.Eval("([1, 2, function () { }])", &obj)); |
769 | | TS_ASSERT_THROWS(serialize.ScriptVal("script", &obj), PSERROR_Serialize_InvalidScriptValue); |
| 818 | TS_ASSERT_THROWS(serialize.ScriptVal("script", &obj, false), PSERROR_Serialize_InvalidScriptValue); |
770 | 819 | } |
771 | 820 | |
772 | 821 | void test_script_splice() |
… |
… |
public:
|
801 | 850 | std::stringstream stream; |
802 | 851 | CStdSerializer serialize(script, stream); |
803 | 852 | |
804 | | serialize.ScriptVal("script", &obj); |
| 853 | serialize.ScriptVal("script", &obj, false); |
805 | 854 | |
806 | 855 | CStdDeserializer deserialize(script, stream); |
807 | 856 | |
… |
… |
public:
|
882 | 931 | DeleteDirectory(DataDir()/"_testcache"); |
883 | 932 | CXeromyces::Terminate(); |
884 | 933 | } |
885 | | |
886 | 934 | }; |