Changeset View
Changeset View
Standalone View
Standalone View
source/simulation2/serialization/BinarySerializer.cpp
Show First 20 Lines • Show All 213 Lines • ▼ Show 20 Lines | else | ||||
const JSClass* jsclass = JS_GetClass(obj); | const JSClass* jsclass = JS_GetClass(obj); | ||||
if (!jsclass) | if (!jsclass) | ||||
throw PSERROR_Serialize_ScriptError("JS_GetClass failed"); | throw PSERROR_Serialize_ScriptError("JS_GetClass failed"); | ||||
JSProtoKey protokey = JSCLASS_CACHED_PROTO_KEY(jsclass); | JSProtoKey protokey = JSCLASS_CACHED_PROTO_KEY(jsclass); | ||||
if (protokey == JSProto_Object) | if (protokey == JSProto_Object) | ||||
{ | { | ||||
// Standard Object prototype | // Object class - check for user-defined prototype | ||||
JS::RootedObject proto(rq.cx); | |||||
if (!JS_GetPrototype(rq.cx, obj, &proto)) | |||||
throw PSERROR_Serialize_ScriptError("JS_GetPrototype failed"); | |||||
SPrototypeSerialization protoInfo = GetPrototypeInfo(rq, proto); | |||||
if (protoInfo.name == "Object") | |||||
m_Serializer.NumberU8_Unbounded("type", SCRIPT_TYPE_OBJECT); | m_Serializer.NumberU8_Unbounded("type", SCRIPT_TYPE_OBJECT); | ||||
else | |||||
{ | |||||
m_Serializer.NumberU8_Unbounded("type", SCRIPT_TYPE_OBJECT_PROTOTYPE); | |||||
m_Serializer.String("proto", wstring_from_utf8(protoInfo.name), 0, 256); | |||||
// Does it have custom Serialize function? | |||||
// if so, we serialize the data it returns, rather than the object's properties directly | |||||
if (protoInfo.hasCustomSerialize) | |||||
{ | |||||
// If serialize is null, don't serialize anything more | |||||
if (!protoInfo.hasNullSerialize) | |||||
{ | |||||
JS::RootedValue data(rq.cx); | |||||
if (!m_ScriptInterface.CallFunction(val, "Serialize", &data)) | |||||
throw PSERROR_Serialize_ScriptError("Prototype Serialize function failed"); | |||||
m_Serializer.ScriptVal("data", &data); | |||||
} | |||||
// Break here to skip the custom object property serialization logic below. | |||||
break; | |||||
} | |||||
} | |||||
} | } | ||||
else if (protokey == JSProto_Number) | else if (protokey == JSProto_Number) | ||||
{ | { | ||||
// Standard Number object | // Standard Number object | ||||
m_Serializer.NumberU8_Unbounded("type", SCRIPT_TYPE_OBJECT_NUMBER); | m_Serializer.NumberU8_Unbounded("type", SCRIPT_TYPE_OBJECT_NUMBER); | ||||
// Get primitive value | // Get primitive value | ||||
double d; | double d; | ||||
if (!JS::ToNumber(rq.cx, val, &d)) | if (!JS::ToNumber(rq.cx, val, &d)) | ||||
▲ Show 20 Lines • Show All 201 Lines • ▼ Show 20 Lines | i32 CBinarySerializerScriptImpl::GetScriptBackrefTag(JS::HandleObject obj) | ||||
if (tagFound) | if (tagFound) | ||||
{ | { | ||||
ENSURE(JS_GetPropertyById(rq.cx, obj, symbolId, &tagValue)); | ENSURE(JS_GetPropertyById(rq.cx, obj, symbolId, &tagValue)); | ||||
ENSURE(tagValue.isInt32()); | ENSURE(tagValue.isInt32()); | ||||
return tagValue.toInt32(); | return tagValue.toInt32(); | ||||
} | } | ||||
tagValue = JS::Int32Value(m_ScriptBackrefsNext); | tagValue = JS::Int32Value(m_ScriptBackrefsNext); | ||||
JS_SetPropertyById(rq.cx, obj, symbolId, tagValue); | // TODO: this fails if the object cannot be written to. | ||||
// This means we could end up in an infinite loop... | |||||
if (!JS_DefinePropertyById(rq.cx, obj, symbolId, tagValue, JSPROP_READONLY)) | |||||
{ | |||||
// For now just warn, this should be user-fixable and may not actually error out. | |||||
JS::RootedValue objVal(rq.cx, JS::ObjectValue(*obj.get())); | |||||
LOGWARNING("Serialization symbol cannot be written on object %s", m_ScriptInterface.ToString(&objVal)); | |||||
} | |||||
++m_ScriptBackrefsNext; | ++m_ScriptBackrefsNext; | ||||
// Return a non-tag number so callers know they need to serialize the object | // Return a non-tag number so callers know they need to serialize the object | ||||
return -1; | return -1; | ||||
} | } |
Wildfire Games · Phabricator