Adds Serialization support for ES6 Maps.
Also includes the patch from Sanderd17 to use Maps and Sets for the Timer components. Sets can't be serialized yet, but in this case they don't require serialization. Refs #2475 This was SVN commit r15770.
This commit is contained in:
parent
6b2677a3fd
commit
f5336c42b8
@ -7,7 +7,7 @@ Timer.prototype.Init = function()
|
||||
{
|
||||
this.id = 0;
|
||||
this.time = 0;
|
||||
this.timers = {};
|
||||
this.timers = new Map();
|
||||
this.turnLength = 0;
|
||||
};
|
||||
|
||||
@ -33,7 +33,7 @@ Timer.prototype.GetLatestTurnLength = function()
|
||||
Timer.prototype.SetTimeout = function(ent, iid, funcname, time, data)
|
||||
{
|
||||
var id = ++this.id;
|
||||
this.timers[id] = [ent, iid, funcname, this.time + time, 0, data];
|
||||
this.timers.set(id, [ent, iid, funcname, this.time + time, 0, data]);
|
||||
return id;
|
||||
};
|
||||
|
||||
@ -51,7 +51,7 @@ Timer.prototype.SetInterval = function(ent, iid, funcname, time, repeattime, dat
|
||||
if (typeof repeattime != "number" || !(repeattime > 0))
|
||||
error("Invalid repeattime to SetInterval of "+funcname);
|
||||
var id = ++this.id;
|
||||
this.timers[id] = [ent, iid, funcname, this.time + time, repeattime, data];
|
||||
this.timers.set(id, [ent, iid, funcname, this.time + time, repeattime, data]);
|
||||
return id;
|
||||
};
|
||||
|
||||
@ -60,7 +60,7 @@ Timer.prototype.SetInterval = function(ent, iid, funcname, time, repeattime, dat
|
||||
*/
|
||||
Timer.prototype.CancelTimer = function(id)
|
||||
{
|
||||
delete this.timers[id];
|
||||
this.timers.delete(id);
|
||||
};
|
||||
|
||||
|
||||
@ -73,17 +73,15 @@ Timer.prototype.OnUpdate = function(msg)
|
||||
// Collect the timers that need to run
|
||||
// (We do this in two stages to avoid deleting from the timer list while
|
||||
// we're in the middle of iterating through it)
|
||||
var run = [];
|
||||
for (var id in this.timers)
|
||||
var run = new Set();
|
||||
for (let id of this.timers.keys())
|
||||
{
|
||||
if (this.timers[id][3] <= this.time)
|
||||
run.push(id);
|
||||
if (this.timers.get(id)[3] <= this.time)
|
||||
run.add(id);
|
||||
}
|
||||
for (var i = 0; i < run.length; ++i)
|
||||
for (let id of run)
|
||||
{
|
||||
var id = run[i];
|
||||
|
||||
var t = this.timers[id];
|
||||
var t = this.timers.get(id);
|
||||
if (!t)
|
||||
continue; // an earlier timer might have cancelled this one, so skip it
|
||||
|
||||
@ -91,7 +89,7 @@ Timer.prototype.OnUpdate = function(msg)
|
||||
if (!cmp)
|
||||
{
|
||||
// The entity was probably destroyed; clean up the timer
|
||||
delete this.timers[id];
|
||||
this.timers.delete(id);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -110,12 +108,12 @@ Timer.prototype.OnUpdate = function(msg)
|
||||
t[3] += t[4];
|
||||
// Add it to the list to get re-executed if it's soon enough
|
||||
if (t[3] <= this.time)
|
||||
run.push(id);
|
||||
run.add(id);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Non-repeating time - delete it
|
||||
delete this.timers[id];
|
||||
this.timers.delete(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -223,6 +223,38 @@ void CBinarySerializerScriptImpl::HandleScriptVal(JS::HandleValue val)
|
||||
m_Serializer.Bool("value", b);
|
||||
break;
|
||||
}
|
||||
else if (protokey == JSProto_Map)
|
||||
{
|
||||
// TODO: There's no C++ API (yet) to work with maps. This code relies on the internal
|
||||
// structure of the Iterator object returned by Map.entries(). This is not ideal
|
||||
// because the structure could change in the future (and actually does change with v31).
|
||||
// Change this code if SpiderMonkey gets such an API.
|
||||
u32 mapSize;
|
||||
m_ScriptInterface.GetProperty(val, "size", mapSize);
|
||||
|
||||
m_Serializer.NumberU8_Unbounded("type", SCRIPT_TYPE_OBJECT_MAP);
|
||||
m_Serializer.NumberU32_Unbounded("map size", mapSize);
|
||||
|
||||
JS::RootedValue keyValueIterator(cx);
|
||||
m_ScriptInterface.CallFunction(val, "entries", &keyValueIterator);
|
||||
for (u32 i=0; i<mapSize; ++i)
|
||||
{
|
||||
JS::RootedValue keyValuePair(cx);
|
||||
ENSURE(m_ScriptInterface.CallFunction(keyValueIterator, "next", &keyValuePair));
|
||||
|
||||
JS::RootedObject keyValuePairObj(cx, &keyValuePair.toObject());
|
||||
|
||||
JS::RootedValue key(cx);
|
||||
JS::RootedValue value(cx);
|
||||
ENSURE(JS_GetElement(cx, keyValuePairObj, 0, key.address()));
|
||||
ENSURE(JS_GetElement(cx, keyValuePairObj, 1, value.address()));
|
||||
|
||||
HandleScriptVal(key);
|
||||
HandleScriptVal(value);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unrecognized class
|
||||
|
@ -34,7 +34,8 @@ enum
|
||||
SCRIPT_TYPE_OBJECT_PROTOTYPE = 11, // user-defined prototype
|
||||
SCRIPT_TYPE_OBJECT_NUMBER = 12, // standard Number class
|
||||
SCRIPT_TYPE_OBJECT_STRING = 13, // standard String class
|
||||
SCRIPT_TYPE_OBJECT_BOOLEAN = 14 // standard Boolean class
|
||||
SCRIPT_TYPE_OBJECT_BOOLEAN = 14, // standard Boolean class
|
||||
SCRIPT_TYPE_OBJECT_MAP = 15 // Map class
|
||||
};
|
||||
|
||||
// ArrayBufferView subclasses (to avoid relying directly on the JSAPI enums)
|
||||
|
@ -389,6 +389,22 @@ jsval CStdDeserializer::ReadScriptVal(const char* UNUSED(name), JS::HandleObject
|
||||
|
||||
return JS::ObjectValue(*bufferObj);
|
||||
}
|
||||
case SCRIPT_TYPE_OBJECT_MAP:
|
||||
{
|
||||
u32 mapSize;
|
||||
NumberU32_Unbounded("map size", mapSize);
|
||||
JS::RootedValue mapVal(cx);
|
||||
m_ScriptInterface.Eval("(new Map())", &mapVal);
|
||||
|
||||
for (u32 i=0; i<mapSize; ++i)
|
||||
{
|
||||
JS::RootedValue key(cx, ReadScriptVal("map key", JS::NullPtr()));
|
||||
JS::RootedValue value(cx, ReadScriptVal("map value", JS::NullPtr()));
|
||||
m_ScriptInterface.CallFunctionVoid(mapVal, "set", key, value);
|
||||
}
|
||||
AddScriptBackref(&mapVal.toObject());
|
||||
return mapVal;
|
||||
}
|
||||
default:
|
||||
throw PSERROR_Deserialize_OutOfBounds();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user