Ticket #4244: deserializer-cleanup.patch
File deserializer-cleanup.patch, 7.8 KB (added by , 8 years ago) |
---|
-
source/simulation2/serialization/StdDeserializer.cpp
28 28 #include "lib/byte_order.h" 29 29 30 30 CStdDeserializer::CStdDeserializer(ScriptInterface& scriptInterface, std::istream& stream) : 31 m_ScriptInterface(scriptInterface), m_Stream(stream), 31 m_ScriptInterface(scriptInterface), m_Stream(stream), 32 32 m_dummyObject(scriptInterface.GetJSRuntime()) 33 33 { 34 34 JSContext* cx = m_ScriptInterface.GetContext(); … … 104 104 // but that doesn't work (at least on MSVC) since in_avail isn't 105 105 // guaranteed to return the actual number of bytes available; see e.g. 106 106 // http://social.msdn.microsoft.com/Forums/en/vclanguage/thread/13009a88-933f-4be7-bf3d-150e425e66a6#70ea562d-8605-4742-8851-1bae431ce6ce 107 107 108 108 // Instead we'll just verify that it's not an extremely large number: 109 109 if (numBytes > 64*MiB) 110 110 throw PSERROR_Deserialize_OutOfBounds("RequireBytesInStream"); … … 121 121 ret.set(m_ScriptBackrefs[tag]); 122 122 } 123 123 124 u32 CStdDeserializer::ReserveScriptBackref()125 {126 m_ScriptBackrefs.push_back(JS::Heap<JSObject*>(m_dummyObject));127 return m_ScriptBackrefs.size()-1;128 }129 130 void CStdDeserializer::SetReservedScriptBackref(u32 tag, JS::HandleObject obj)131 {132 ENSURE(m_ScriptBackrefs[tag] == m_dummyObject);133 m_ScriptBackrefs[tag] = JS::Heap<JSObject*>(obj);134 }135 136 124 void CStdDeserializer::FreeScriptBackrefs() 137 125 { 138 126 m_ScriptBackrefs.clear(); … … 202 190 203 191 if (hasCustomDeserialize) 204 192 { 193 AddScriptBackref(obj); 194 205 195 JS::RootedValue serialize(cx); 206 196 if (!JS_GetProperty(cx, obj, "Serialize", &serialize)) 207 197 throw PSERROR_Serialize_ScriptError("JS_GetProperty failed"); … … 214 204 215 205 JS::RootedValue objVal(cx, JS::ObjectValue(*obj)); 216 206 m_ScriptInterface.CallFunctionVoid(objVal, "Deserialize", data); 217 218 AddScriptBackref(obj); 219 207 220 208 return JS::ObjectValue(*obj); 221 209 } 222 210 } … … 352 340 NumberU32_Unbounded("length", length); 353 341 354 342 // To match the serializer order, we reserve the typed array's backref tag here 355 u32 arrayTag = ReserveScriptBackref(); 343 JS::RootedObject arrayObj(cx); 344 AddScriptBackref(arrayObj); 356 345 357 346 // Get buffer object 358 347 JS::RootedValue bufferVal(cx, ReadScriptVal("buffer", JS::NullPtr())); … … 364 353 if (!JS_IsArrayBufferObject(bufferObj)) 365 354 throw PSERROR_Deserialize_ScriptError("js_IsArrayBuffer failed"); 366 355 367 JS::RootedObject arrayObj(cx);368 356 switch(arrayType) 369 357 { 370 358 case SCRIPT_TYPED_ARRAY_INT8: … … 400 388 if (!arrayObj) 401 389 throw PSERROR_Deserialize_ScriptError("js_CreateTypedArrayWithBuffer failed"); 402 390 403 SetReservedScriptBackref(arrayTag, arrayObj);404 405 391 return JS::ObjectValue(*arrayObj); 406 392 } 407 393 case SCRIPT_TYPE_ARRAY_BUFFER: … … 423 409 case SCRIPT_TYPE_OBJECT_MAP: 424 410 { 425 411 JS::RootedObject obj(cx, JS::NewMapObject(cx)); 412 AddScriptBackref(obj); 413 426 414 u32 mapSize; 427 415 NumberU32_Unbounded("map size", mapSize); 428 416 429 // To match the serializer order, we reserve the map's backref tag here430 u32 mapTag = ReserveScriptBackref();431 432 417 for (u32 i=0; i<mapSize; ++i) 433 418 { 434 419 JS::RootedValue key(cx, ReadScriptVal("map key", JS::NullPtr())); … … 435 420 JS::RootedValue value(cx, ReadScriptVal("map value", JS::NullPtr())); 436 421 JS::MapSet(cx, obj, key, value); 437 422 } 438 SetReservedScriptBackref(mapTag, obj); 423 439 424 return JS::ObjectValue(*obj); 440 425 } 441 426 case SCRIPT_TYPE_OBJECT_SET: 442 427 { 443 u32 setSize;444 NumberU32_Unbounded("set size", setSize);445 428 JS::RootedValue setVal(cx); 446 429 m_ScriptInterface.Eval("(new Set())", &setVal); 447 430 448 // To match the serializer order, we reserve the set's backref tag here449 u32 setTag = ReserveScriptBackref();431 JS::RootedObject setObj(cx, &setVal.toObject()); 432 AddScriptBackref(setObj); 450 433 434 u32 setSize; 435 NumberU32_Unbounded("set size", setSize); 436 451 437 for (u32 i=0; i<setSize; ++i) 452 438 { 453 439 JS::RootedValue value(cx, ReadScriptVal("set value", JS::NullPtr())); 454 440 m_ScriptInterface.CallFunctionVoid(setVal, "add", value); 455 441 } 456 JS::RootedObject setObj(cx, &setVal.toObject()); 457 SetReservedScriptBackref(setTag, setObj); 442 458 443 return setVal; 459 444 } 460 445 default: … … 520 505 { 521 506 JSContext* cx = m_ScriptInterface.GetContext(); 522 507 JSAutoRequest rq(cx); 523 508 524 509 if (!objVal.isObject()) 525 510 throw PSERROR_Deserialize_ScriptError(); 526 511 -
source/simulation2/serialization/StdDeserializer.h
1 /* Copyright (C) 201 3Wildfire Games.1 /* Copyright (C) 2016 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 … … 54 54 55 55 virtual void AddScriptBackref(JS::HandleObject obj); 56 56 virtual void GetScriptBackref(u32 tag, JS::MutableHandleObject ret); 57 virtual u32 ReserveScriptBackref();58 virtual void SetReservedScriptBackref(u32 tag, JS::HandleObject obj);59 57 void FreeScriptBackrefs(); 60 58 std::vector<JS::Heap<JSObject*> > m_ScriptBackrefs; 61 59 JS::PersistentRooted<JSObject*> m_dummyObject; -
source/simulation2/tests/test_Serializer.h
1 /* Copyright (C) 201 5Wildfire Games.1 /* Copyright (C) 2016 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 … … 294 294 ScriptInterface script("Test", "Test", g_ScriptRuntime); 295 295 JSContext* cx = script.GetContext(); 296 296 JSAutoRequest rq(cx); 297 297 298 298 JS::RootedValue obj(cx); 299 299 TSM_ASSERT(msg, script.Eval(input, &obj)); 300 300 … … 467 467 "var arr=new Uint32Array(8);" 468 468 "for(var i=0; i<arr.length; ++i)" 469 469 " arr[i]=(i+1)*536870912;" 470 "arr", 470 "arr", 471 471 /* expected: */ 472 472 "({0:536870912, 1:1073741824, 2:1610612736, 3:2147483648, 4:2684354560, 5:3221225472, 6:3758096384, 7:0})" 473 473 ); … … 476 476 "var arr=new Float32Array(2);" 477 477 "arr[0]=3.4028234e38;" 478 478 "arr[1]=Infinity;" 479 "arr", 479 "arr", 480 480 /* expected: */ 481 481 "({0:3.4028234663852886e+38, 1:Infinity})" 482 482 ); … … 485 485 "var arr=new Float64Array(2);" 486 486 "arr[0]=1.7976931348623157e308;" 487 487 "arr[1]=-Infinity;" 488 "arr", 488 "arr", 489 489 /* expected: */ 490 490 "({0:1.7976931348623157e+308, 1:-Infinity})" 491 491 ); … … 594 594 "\x00\x00\x00\x00" // size 595 595 ); 596 596 597 helper_script_roundtrip("Set with elements and property", 597 helper_script_roundtrip("Set with elements and property", 598 598 "var a = new Set(); a.add(12); a.add(\"bar\"); a.foo = 27; a", 599 599 /* expected: */ 600 600 "({})", … … 673 673 ); 674 674 675 675 helper_script_roundtrip("Nested maps using backrefs", 676 "var a = new Map(); var b = new Map(); b.set(1, a); b.set(2, a); b",676 "var a = new Map(); var b = new Map(); a.set(1, b); a.set(2, b); a", 677 677 /* expected: */ 678 678 "({})", 679 679 /* expected stream: */ … … 689 689 "\x05" // SCRIPT_TYPE_INT 690 690 "\x02\0\0\0" // 2 691 691 "\x08" // SCRIPT_TYPE_BACKREF 692 "\x02\0\0\0" // ref. to object #2, i.e. " a", with #1 being "b"692 "\x02\0\0\0" // ref. to object #2, i.e. "b", with #1 being "a" 693 693 ); 694 694 } 695 695 … … 757 757 ScriptInterface script("Test", "Test", g_ScriptRuntime); 758 758 JSContext* cx = script.GetContext(); 759 759 JSAutoRequest rq(cx); 760 760 761 761 JS::RootedValue obj(cx); 762 762 763 763 std::stringstream stream; … … 792 792 ScriptInterface script("Test", "Test", g_ScriptRuntime); 793 793 JSContext* cx = script.GetContext(); 794 794 JSAutoRequest rq(cx); 795 795 796 796 JS::RootedValue obj(cx); 797 797 TS_ASSERT(script.Eval(input, &obj)); 798 798