More crap, some new discoveries, backtracking, annoyance.
git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@3918 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
@@ -16,9 +16,10 @@ Design decisions
|
|||||||
|
|
||||||
- We need a realistic HashMap implementation. Using Object properties
|
- We need a realistic HashMap implementation. Using Object properties
|
||||||
(a-la my SimpleMap) is not going to cut it because keys must always
|
(a-la my SimpleMap) is not going to cut it because keys must always
|
||||||
be Strings and there's no way to *really* remove a value from an Object
|
be Strings.<strike>and there's no way to *really* remove a value from
|
||||||
(you can set the property to null, but now the property is forever defined:
|
an Object (you can set the property to null, but now the property is
|
||||||
the key is not cleared)
|
forever defined: the key is not cleared)</strike>
|
||||||
|
***Update: the 'delete' operator removes properties.
|
||||||
|
|
||||||
mx.utils.UIDUtil.getUID() can be used to generate a (huge) unique String
|
mx.utils.UIDUtil.getUID() can be used to generate a (huge) unique String
|
||||||
for any object for use as a key or something.
|
for any object for use as a key or something.
|
||||||
@@ -81,10 +82,9 @@ Notes
|
|||||||
and accessing only public properties of the main class from the helper.
|
and accessing only public properties of the main class from the helper.
|
||||||
|
|
||||||
|
|
||||||
- Similarly, I'm unclear about sandboxes. If a user-created .swf is playing
|
- Sandboxing classes is done with ApplicationDomains. When we load a sub-swf
|
||||||
inside ours, I don't know if it can interact with our classes, and if so,
|
we'll want to put it into a different domain so that nothing malicious
|
||||||
what happens if it proceeds to define a class like
|
can be done to our classes.
|
||||||
com.threerings.presents.client.Client?
|
|
||||||
|
|
||||||
- <strike>constructors do not defaultly call super()- be sure to do it explicitely.
|
- <strike>constructors do not defaultly call super()- be sure to do it explicitely.
|
||||||
Maybe we should get in the habit of doing it in Java for consistency and
|
Maybe we should get in the habit of doing it in Java for consistency and
|
||||||
@@ -169,6 +169,14 @@ ActionScript
|
|||||||
Perhaps we'll want a util method that always generates an error if the
|
Perhaps we'll want a util method that always generates an error if the
|
||||||
object's type is not identical or a subclass of the casted-to type.
|
object's type is not identical or a subclass of the casted-to type.
|
||||||
|
|
||||||
|
***Update:
|
||||||
|
var o1 :String = null;
|
||||||
|
var o2 :String = String(o1); // ends up being "" or something
|
||||||
|
|
||||||
|
The 2nd kind of cast destroys null, at least for String. So fuck that,
|
||||||
|
I was trying to use it when pulling a value out of a hash, but if it
|
||||||
|
wasn't there it got booched.
|
||||||
|
|
||||||
|
|
||||||
- Pitfall! This is perfectly legal:
|
- Pitfall! This is perfectly legal:
|
||||||
var b :int = 3;
|
var b :int = 3;
|
||||||
@@ -198,5 +206,10 @@ ActionScript
|
|||||||
me from correctly streaming arrays, as we need to know if the class
|
me from correctly streaming arrays, as we need to know if the class
|
||||||
is final. I can't just pass an instance in because it may be a pain
|
is final. I can't just pass an instance in because it may be a pain
|
||||||
to construct, it may even be unconstructable if the type of the array
|
to construct, it may even be unconstructable if the type of the array
|
||||||
is an interface. The adobe forums are broken right now, but I'm going
|
is an interface. Posted as a request for enhancement on the AS3.0 forums.
|
||||||
to post a request for enhancement so that we can get this information.
|
|
||||||
|
|
||||||
|
- Actionscript's property accessors are a cool feature, but beware hidden
|
||||||
|
performance issues: accessing a simple property of a variable
|
||||||
|
(like myArray.length) may actually be executing arbitrary code, possibly
|
||||||
|
creating many objects, each time.
|
||||||
|
|||||||
@@ -28,14 +28,6 @@ public class ObjectInputStream
|
|||||||
_source = source;
|
_source = source;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a translation that should be used when writing objects.
|
|
||||||
*/
|
|
||||||
public function addTranslation (oldName :String, newName :String) :void
|
|
||||||
{
|
|
||||||
_translations[oldName] = newName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function readObject () :Object
|
public function readObject () :Object
|
||||||
//throws IOError
|
//throws IOError
|
||||||
{
|
{
|
||||||
@@ -57,13 +49,8 @@ public class ObjectInputStream
|
|||||||
code *= -1;
|
code *= -1;
|
||||||
|
|
||||||
// read in the class metadata
|
// read in the class metadata
|
||||||
var cname :String = readUTF();
|
var cname :String = Translations.getFromServer(readUTF());
|
||||||
Log.debug("read cname: " + cname);
|
Log.debug("read cname: " + cname);
|
||||||
// if we have a translation, use it
|
|
||||||
var tname :String = _translations[cname];
|
|
||||||
if (tname != null) {
|
|
||||||
cname = tname;
|
|
||||||
}
|
|
||||||
var streamer :Streamer = Streamer.getStreamerByJavaName(cname);
|
var streamer :Streamer = Streamer.getStreamerByJavaName(cname);
|
||||||
|
|
||||||
cmap = new ClassMapping(code, cname, streamer);
|
cmap = new ClassMapping(code, cname, streamer);
|
||||||
@@ -215,9 +202,5 @@ public class ObjectInputStream
|
|||||||
|
|
||||||
/** A map of short class code to ClassMapping info. */
|
/** A map of short class code to ClassMapping info. */
|
||||||
protected var _classMap :Array = new Array();
|
protected var _classMap :Array = new Array();
|
||||||
|
|
||||||
/** An collection of class name translations to use when unserializing
|
|
||||||
* objects. */
|
|
||||||
protected var _translations :SimpleMap = new SimpleMap();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,15 +15,6 @@ public class ObjectOutputStream
|
|||||||
_targ = targ;
|
_targ = targ;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a classname translation for rewriting the names of objects
|
|
||||||
* that we send to the server.
|
|
||||||
*/
|
|
||||||
public function addTranslation (oldName :String, newName :String) :void
|
|
||||||
{
|
|
||||||
_translations[oldName] = newName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function writeObject (obj :Object) :void
|
public function writeObject (obj :Object) :void
|
||||||
//throws IOError
|
//throws IOError
|
||||||
{
|
{
|
||||||
@@ -35,7 +26,7 @@ public class ObjectOutputStream
|
|||||||
|
|
||||||
var cname :String = ClassUtil.getClassName(obj);
|
var cname :String = ClassUtil.getClassName(obj);
|
||||||
// look up the class mapping record
|
// look up the class mapping record
|
||||||
var cmap :ClassMapping = _classMap[cname];
|
var cmap :ClassMapping = (_classMap.get(cname) as ClassMapping);
|
||||||
|
|
||||||
// create a class mapping if we've not got one
|
// create a class mapping if we've not got one
|
||||||
if (cmap == null) {
|
if (cmap == null) {
|
||||||
@@ -48,18 +39,13 @@ public class ObjectOutputStream
|
|||||||
}
|
}
|
||||||
|
|
||||||
cmap = new ClassMapping(_nextCode++, cname, streamer);
|
cmap = new ClassMapping(_nextCode++, cname, streamer);
|
||||||
_classMap[cname] = cmap;
|
_classMap.put(cname, cmap);
|
||||||
|
|
||||||
// TODO: if _nextCode blows short, log an error
|
// TODO: if _nextCode blows short, log an error
|
||||||
|
|
||||||
// see if there's a translation we should use
|
|
||||||
var tname :String = _translations[cname];
|
|
||||||
if (tname != null) {
|
|
||||||
cname = tname;
|
|
||||||
}
|
|
||||||
|
|
||||||
writeShort(-cmap.code);
|
writeShort(-cmap.code);
|
||||||
writeUTF((streamer == null) ? cname : streamer.getJavaClassName());
|
writeUTF((streamer == null) ? Translations.getToServer(cname)
|
||||||
|
: streamer.getJavaClassName());
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
writeShort(cmap.code);
|
writeShort(cmap.code);
|
||||||
@@ -200,8 +186,5 @@ public class ObjectOutputStream
|
|||||||
|
|
||||||
/** A map of classname to ClassMapping info. */
|
/** A map of classname to ClassMapping info. */
|
||||||
protected var _classMap :SimpleMap = new SimpleMap();
|
protected var _classMap :SimpleMap = new SimpleMap();
|
||||||
|
|
||||||
/** A map of classname translations. */
|
|
||||||
protected var _translations :SimpleMap = new SimpleMap();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,6 +48,10 @@ public class Streamer
|
|||||||
{
|
{
|
||||||
initStreamers();
|
initStreamers();
|
||||||
|
|
||||||
|
if (jname.charAt(0) === "[") {
|
||||||
|
// Oh ghod
|
||||||
|
}
|
||||||
|
|
||||||
for each (var streamer :Streamer in _streamers) {
|
for each (var streamer :Streamer in _streamers) {
|
||||||
if (streamer.getJavaClassName() === jname) {
|
if (streamer.getJavaClassName() === jname) {
|
||||||
return streamer;
|
return streamer;
|
||||||
@@ -86,7 +90,7 @@ public class Streamer
|
|||||||
if (obj is Array) {
|
if (obj is Array) {
|
||||||
trace("Arrays not yet done. Crap!");
|
trace("Arrays not yet done. Crap!");
|
||||||
/**
|
/**
|
||||||
var arr :Array = (obj as Array); // not strictly necessary
|
var arr :Array = Array(obj); // not strictly necessary
|
||||||
var length :int = arr.length;
|
var length :int = arr.length;
|
||||||
out.writeInt(length);
|
out.writeInt(length);
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -208,14 +208,13 @@ public class ClientDObjectMgr
|
|||||||
|
|
||||||
} else if (obj is UnsubscribeResponse) {
|
} else if (obj is UnsubscribeResponse) {
|
||||||
var oid :int = obj.getOid();
|
var oid :int = obj.getOid();
|
||||||
if (_dead[oid] == null) {
|
if (_dead.remove(oid) == null) {
|
||||||
Log.warning("Received unsub ACK from unknown object " +
|
Log.warning("Received unsub ACK from unknown object " +
|
||||||
"[oid=" + oid + "].");
|
"[oid=" + oid + "].");
|
||||||
}
|
}
|
||||||
_dead[oid] = undefined;
|
|
||||||
|
|
||||||
} else if (obj is FailureResponse) {
|
} else if (obj is FailureResponse) {
|
||||||
var oid :int = obj.getOid();
|
var oid :int = (obj as FailureResponse).getOid();
|
||||||
notifyFailure(oid);
|
notifyFailure(oid);
|
||||||
|
|
||||||
} else if (obj is PongResponse) {
|
} else if (obj is PongResponse) {
|
||||||
@@ -250,9 +249,9 @@ public class ClientDObjectMgr
|
|||||||
|
|
||||||
// look up the object on which we're dispatching this event
|
// look up the object on which we're dispatching this event
|
||||||
var toid :int = event.getTargetOid();
|
var toid :int = event.getTargetOid();
|
||||||
var target :DObject = _ocache[toid];
|
var target :DObject = (_ocache.get(toid) as DEvent);
|
||||||
if (target == null) {
|
if (target == null) {
|
||||||
if (_dead[toid] === undefined) {
|
if (_dead.get(toid) == null) {
|
||||||
Log.warning("Unable to dispatch event on non-proxied " +
|
Log.warning("Unable to dispatch event on non-proxied " +
|
||||||
"object [event=" + event + "].");
|
"object [event=" + event + "].");
|
||||||
}
|
}
|
||||||
@@ -269,7 +268,7 @@ public class ClientDObjectMgr
|
|||||||
// Log.info("Pitching destroyed object " +
|
// Log.info("Pitching destroyed object " +
|
||||||
// "[oid=" + toid + ", class=" +
|
// "[oid=" + toid + ", class=" +
|
||||||
// StringUtil.shortClassName(target) + "].");
|
// StringUtil.shortClassName(target) + "].");
|
||||||
_ocache[toid] = undefined;
|
_ocache.remove(toid);
|
||||||
}
|
}
|
||||||
|
|
||||||
// have the object pass this event on to its listeners
|
// have the object pass this event on to its listeners
|
||||||
@@ -295,7 +294,7 @@ public class ClientDObjectMgr
|
|||||||
|
|
||||||
var oid :int = obj.getOid();
|
var oid :int = obj.getOid();
|
||||||
// stick the object into the proxy object table
|
// stick the object into the proxy object table
|
||||||
_ocache[oid] = obj;
|
_ocache.put(oid, obj);
|
||||||
|
|
||||||
// let the penders know that the object is available
|
// let the penders know that the object is available
|
||||||
var req :PendingRequest = (_penders.remove(oid) as PendingRequest);
|
var req :PendingRequest = (_penders.remove(oid) as PendingRequest);
|
||||||
@@ -321,8 +320,7 @@ public class ClientDObjectMgr
|
|||||||
protected function notifyFailure (oid :int) :void
|
protected function notifyFailure (oid :int) :void
|
||||||
{
|
{
|
||||||
// let the penders know that the object is not available
|
// let the penders know that the object is not available
|
||||||
var req :PendingRequest = _penders[oid];
|
var req :PendingRequest = (_penders.remove(oid) as PendingRequest);
|
||||||
_penders[oid] = undefined;
|
|
||||||
if (req == null) {
|
if (req == null) {
|
||||||
Log.warning("Failed to get object, but no one cares?! " +
|
Log.warning("Failed to get object, but no one cares?! " +
|
||||||
"[oid=" + oid + "].");
|
"[oid=" + oid + "].");
|
||||||
@@ -345,10 +343,10 @@ public class ClientDObjectMgr
|
|||||||
// Log.info("doSubscribe: " + oid + ": " + target);
|
// Log.info("doSubscribe: " + oid + ": " + target);
|
||||||
|
|
||||||
// first see if we've already got the object in our table
|
// first see if we've already got the object in our table
|
||||||
var obj :DObject = _ocache[oid];
|
var obj :DObject = (_ocache.get(oid) as DObject);
|
||||||
if (obj != null) {
|
if (obj != null) {
|
||||||
// clear the object out of the flush table if it's in there
|
// clear the object out of the flush table if it's in there
|
||||||
_flushes[oid] = undefined;
|
_flushes.remove(oid);
|
||||||
// add the subscriber and call them back straight away
|
// add the subscriber and call them back straight away
|
||||||
obj.addSubscriber(target);
|
obj.addSubscriber(target);
|
||||||
target.objectAvailable(obj);
|
target.objectAvailable(obj);
|
||||||
@@ -356,7 +354,7 @@ public class ClientDObjectMgr
|
|||||||
}
|
}
|
||||||
|
|
||||||
// see if we've already got an outstanding request for this object
|
// see if we've already got an outstanding request for this object
|
||||||
var req :PendingRequest = _penders[oid];
|
var req :PendingRequest = (_penders.get(oid) as PendingRequest);
|
||||||
if (req != null) {
|
if (req != null) {
|
||||||
// add this subscriber to the list of subscribers to be
|
// add this subscriber to the list of subscribers to be
|
||||||
// notified when the request is satisfied
|
// notified when the request is satisfied
|
||||||
@@ -367,7 +365,7 @@ public class ClientDObjectMgr
|
|||||||
// otherwise we need to create a new request
|
// otherwise we need to create a new request
|
||||||
req = new PendingRequest(oid);
|
req = new PendingRequest(oid);
|
||||||
req.addTarget(target);
|
req.addTarget(target);
|
||||||
_penders[oid] = req;
|
_penders.put(oid, req);
|
||||||
// Log.info("Registering pending request [oid=" + oid + "].");
|
// Log.info("Registering pending request [oid=" + oid + "].");
|
||||||
|
|
||||||
// and issue a request to get things rolling
|
// and issue a request to get things rolling
|
||||||
@@ -380,7 +378,7 @@ public class ClientDObjectMgr
|
|||||||
*/
|
*/
|
||||||
protected function doUnsubscribe (oid :int, target :Subscriber) :void
|
protected function doUnsubscribe (oid :int, target :Subscriber) :void
|
||||||
{
|
{
|
||||||
var dobj :DObject = _ocache[oid];
|
var dobj :DObject = (_ocache.get(oid) as DObject);
|
||||||
if (dobj != null) {
|
if (dobj != null) {
|
||||||
dobj.removeSubscriber(target);
|
dobj.removeSubscriber(target);
|
||||||
|
|
||||||
@@ -401,8 +399,8 @@ public class ClientDObjectMgr
|
|||||||
// have it around anymore; once our unsubscribe message is
|
// have it around anymore; once our unsubscribe message is
|
||||||
// processed, it'll be 86ed
|
// processed, it'll be 86ed
|
||||||
var ooid :int = obj.getOid();
|
var ooid :int = obj.getOid();
|
||||||
_ocache[ooid] = undefined;
|
_ocache.remove(ooid);
|
||||||
_dead[ooid] = obj;
|
_dead.put(ooid, obj);
|
||||||
|
|
||||||
// ship off an unsubscribe message to the server; we'll remove the
|
// ship off an unsubscribe message to the server; we'll remove the
|
||||||
// object from our table when we get the unsub ack
|
// object from our table when we get the unsub ack
|
||||||
@@ -416,10 +414,10 @@ public class ClientDObjectMgr
|
|||||||
protected function flushObjects () :void
|
protected function flushObjects () :void
|
||||||
{
|
{
|
||||||
var now :Number = new Date().getTime();
|
var now :Number = new Date().getTime();
|
||||||
for (var oid :String in _flushes) {
|
for (var oid :String in _flushes.keys()) {
|
||||||
var rec :FlushRecord = _flushes[oid];
|
var rec :FlushRecord = (_flushes.get(oid) as FlushRecord);
|
||||||
if (rec.expire <= now) {
|
if (rec.expire <= now) {
|
||||||
_flushes[oid] = undefined;
|
_flushes.remove(oid);
|
||||||
flushObject(rec.obj);
|
flushObject(rec.obj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import com.threerings.io.FrameAvailableEvent;
|
|||||||
import com.threerings.io.FrameReader;
|
import com.threerings.io.FrameReader;
|
||||||
import com.threerings.io.ObjectInputStream;
|
import com.threerings.io.ObjectInputStream;
|
||||||
import com.threerings.io.ObjectOutputStream;
|
import com.threerings.io.ObjectOutputStream;
|
||||||
|
import com.threerings.io.Translations;
|
||||||
|
|
||||||
import com.threerings.presents.Log;
|
import com.threerings.presents.Log;
|
||||||
|
|
||||||
@@ -57,9 +58,8 @@ public class Communicator
|
|||||||
|
|
||||||
private function addClassTranslations () :void
|
private function addClassTranslations () :void
|
||||||
{
|
{
|
||||||
_inStream.addTranslation("com.threerings.presents.dobj.DSet$Entry",
|
Translations.addTranslation(
|
||||||
"com.threerings.presents.dobj.DSetEntry");
|
"com.threerings.presents.dobj.DSetEntry",
|
||||||
_outStream.addTranslation("com.threerings.presents.dobj.DSetEntry",
|
|
||||||
"com.threerings.presents.dobj.DSet$Entry");
|
"com.threerings.presents.dobj.DSet$Entry");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,7 +102,7 @@ public class Communicator
|
|||||||
// write the message (ends up in _outBuffer)
|
// write the message (ends up in _outBuffer)
|
||||||
_outStream.writeObject(msg);
|
_outStream.writeObject(msg);
|
||||||
|
|
||||||
//Log.debug("outBuffer: " + Util.bytesToString(_outBuffer));
|
Log.debug("outBuffer: " + Util.bytesToString(_outBuffer));
|
||||||
|
|
||||||
// Frame it by writing the length, then the bytes.
|
// Frame it by writing the length, then the bytes.
|
||||||
// We add 4 to the length, because the length is of the entire frame
|
// We add 4 to the length, because the length is of the entire frame
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ public class InvocationDirector
|
|||||||
var reg :InvocationRegistration = new InvocationRegistration(
|
var reg :InvocationRegistration = new InvocationRegistration(
|
||||||
decoder.getReceiverCode(), nextReceiverId());
|
decoder.getReceiverCode(), nextReceiverId());
|
||||||
_clobj.addToReceivers(reg);
|
_clobj.addToReceivers(reg);
|
||||||
_receivers[reg.receiverId] = decoder;
|
_receivers.put(reg.receiverId, decoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -139,7 +139,7 @@ public class InvocationDirector
|
|||||||
|
|
||||||
// create a mapping for this marshaller so that we can
|
// create a mapping for this marshaller so that we can
|
||||||
// properly dispatch responses sent to it
|
// properly dispatch responses sent to it
|
||||||
_listeners[lm.requestId] = lm;
|
_listeners.put(lm.requestId, lm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,7 +187,7 @@ public class InvocationDirector
|
|||||||
(reqId :int, methodId :int, args :Array) :void
|
(reqId :int, methodId :int, args :Array) :void
|
||||||
{
|
{
|
||||||
var listener :ListenerMarshaller =
|
var listener :ListenerMarshaller =
|
||||||
(_listeners.remove(reqId) as ListenerMarshaller);
|
(_listeners.remove(reqId) as ListenerMarshaller);
|
||||||
if (listener == null) {
|
if (listener == null) {
|
||||||
Log.warning("Received invocation response for which we have " +
|
Log.warning("Received invocation response for which we have " +
|
||||||
"no registered listener [reqId=" + reqId +
|
"no registered listener [reqId=" + reqId +
|
||||||
@@ -229,7 +229,7 @@ public class InvocationDirector
|
|||||||
{
|
{
|
||||||
// look up the decoder registered for this receiver
|
// look up the decoder registered for this receiver
|
||||||
var decoder :InvocationDecoder =
|
var decoder :InvocationDecoder =
|
||||||
(_receivers[receiverId] as InvocationDecoder);
|
(_receivers.get(receiverId) as InvocationDecoder);
|
||||||
if (decoder == null) {
|
if (decoder == null) {
|
||||||
Log.warning("Received notification for which we have no " +
|
Log.warning("Received notification for which we have no " +
|
||||||
"registered receiver [recvId=" + receiverId +
|
"registered receiver [recvId=" + receiverId +
|
||||||
@@ -268,11 +268,11 @@ public class InvocationDirector
|
|||||||
protected function flushListeners (now :Number) :void
|
protected function flushListeners (now :Number) :void
|
||||||
{
|
{
|
||||||
var then :Number = now - LISTENER_MAX_AGE;
|
var then :Number = now - LISTENER_MAX_AGE;
|
||||||
for (var skey :String in _listeners) {
|
for (var skey :String in _listeners.keys()) {
|
||||||
var lm :ListenerMarshaller =
|
var lm :ListenerMarshaller =
|
||||||
(_listeners[skey] as ListenerMarshaller);
|
(_listeners.get(skey) as ListenerMarshaller);
|
||||||
if (lm.mapStamp < then) {
|
if (lm.mapStamp < then) {
|
||||||
_listeners.clear(skey);
|
_listeners.remove(skey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,13 +15,41 @@ public class TestClient extends Client
|
|||||||
setServer("tasman.sea.earth.threerings.net", DEFAULT_SERVER_PORT);
|
setServer("tasman.sea.earth.threerings.net", DEFAULT_SERVER_PORT);
|
||||||
logon();
|
logon();
|
||||||
|
|
||||||
var a :Object = new HelperClass(this);
|
var g1 :String = null;
|
||||||
|
var g2 :String = String(g1);
|
||||||
|
Log.debug("foo: " + (g1 === g2));
|
||||||
|
|
||||||
Log.debug("instance: " + describeType(a).toXMLString());
|
var duckie :Duck = new Goose();
|
||||||
Log.debug("class : " + describeType(HelperClass).toXMLString());
|
duckie.screw();
|
||||||
|
|
||||||
|
var arr :Array = new Array();
|
||||||
|
arr[0] = "Florp";
|
||||||
|
arr[1] = "Blanger";
|
||||||
|
arr[2] = "Swissbrat";
|
||||||
|
|
||||||
|
for (var key:* in arr) {
|
||||||
|
Log.debug("a key=" + key + " -> " + arr[key]);
|
||||||
|
}
|
||||||
|
delete arr[1];
|
||||||
|
arr["1"] = "oinkenheimer";
|
||||||
|
for (var key:* in arr) {
|
||||||
|
Log.debug("a key=" + key + " -> " + arr[key]);
|
||||||
|
}
|
||||||
|
Log.debug("length: " + arr.length);
|
||||||
|
Log.debug("arr[0]: " + arr[0]);
|
||||||
|
Log.debug("arr[1]: " + arr[1]);
|
||||||
|
Log.debug("arr[2]: " + arr[2]);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
var b :Object = new PooperClass();
|
var a :Object = new OldClass();
|
||||||
|
var c :Class = OldClass;
|
||||||
|
|
||||||
|
Log.debug("instance: " + describeType(a).toXMLString());
|
||||||
|
Log.debug("class : " + describeType(Pork).toXMLString());
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
var b :Object = new OldClass();
|
||||||
var c :Object = 2.4;
|
var c :Object = 2.4;
|
||||||
var d :Object = new HooperClass(this);
|
var d :Object = new HooperClass(this);
|
||||||
|
|
||||||
@@ -74,6 +102,13 @@ public class TestClient extends Client
|
|||||||
import com.threerings.presents.Log;
|
import com.threerings.presents.Log;
|
||||||
import com.threerings.presents.client.TestClient;
|
import com.threerings.presents.client.TestClient;
|
||||||
|
|
||||||
|
dynamic class OldClass
|
||||||
|
{
|
||||||
|
public function OldClass ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class HelperClass
|
class HelperClass
|
||||||
{
|
{
|
||||||
public function HelperClass (cli :TestClient)
|
public function HelperClass (cli :TestClient)
|
||||||
@@ -113,10 +148,3 @@ final class HooperClass extends HelperClass
|
|||||||
// nada
|
// nada
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class PooperClass
|
|
||||||
{
|
|
||||||
public function PooperClass ()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import flash.util.StringBuilder;
|
|||||||
import com.threerings.io.ObjectInputStream;
|
import com.threerings.io.ObjectInputStream;
|
||||||
import com.threerings.io.ObjectOutputStream;
|
import com.threerings.io.ObjectOutputStream;
|
||||||
|
|
||||||
import com.threerings.util.Comparable;
|
|
||||||
|
|
||||||
import com.threerings.presents.Log;
|
import com.threerings.presents.Log;
|
||||||
|
|
||||||
@@ -31,7 +30,7 @@ public class EntryRemovedEvent extends NamedEvent
|
|||||||
* @param oldEntry the previous value of the entry.
|
* @param oldEntry the previous value of the entry.
|
||||||
*/
|
*/
|
||||||
public function EntryRemovedEvent (
|
public function EntryRemovedEvent (
|
||||||
targetOid :int, name :String, key :Comparable, oldEntry :DSetEntry)
|
targetOid :int, name :String, key :Object, oldEntry :DSetEntry)
|
||||||
{
|
{
|
||||||
super(targetOid, name);
|
super(targetOid, name);
|
||||||
_key = key;
|
_key = key;
|
||||||
@@ -41,7 +40,7 @@ public class EntryRemovedEvent extends NamedEvent
|
|||||||
/**
|
/**
|
||||||
* Returns the key that identifies the entry that has been removed.
|
* Returns the key that identifies the entry that has been removed.
|
||||||
*/
|
*/
|
||||||
public function getKey () :Comparable
|
public function getKey () :Object
|
||||||
{
|
{
|
||||||
return _key;
|
return _key;
|
||||||
}
|
}
|
||||||
@@ -99,10 +98,10 @@ public class EntryRemovedEvent extends NamedEvent
|
|||||||
public override function readObject (ins :ObjectInputStream) :void
|
public override function readObject (ins :ObjectInputStream) :void
|
||||||
{
|
{
|
||||||
super.readObject(ins);
|
super.readObject(ins);
|
||||||
_key = (ins.readObject() as Comparable);
|
_key = ins.readObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected var _key :Comparable;
|
protected var _key :Object;
|
||||||
protected var _oldEntry :DSetEntry = UNSET_OLD_ENTRY;
|
protected var _oldEntry :DSetEntry = UNSET_OLD_ENTRY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ public class ClassUtil
|
|||||||
|
|
||||||
public static function getClassByName (cname :String) :Class
|
public static function getClassByName (cname :String) :Class
|
||||||
{
|
{
|
||||||
|
// see also ApplicationDomain.currentDomain.getClass(cname)
|
||||||
return flash.util.getClassByName(cname);
|
return flash.util.getClassByName(cname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,15 +4,44 @@ package com.threerings.util {
|
|||||||
* Marker class that allows us to use ActionScript's built-in hashing
|
* Marker class that allows us to use ActionScript's built-in hashing
|
||||||
* function without hassle.
|
* function without hassle.
|
||||||
*/
|
*/
|
||||||
public dynamic class SimpleMap extends Object
|
public class SimpleMap extends Object
|
||||||
{
|
{
|
||||||
|
public function clear () :void
|
||||||
|
{
|
||||||
|
_data = new Object();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function get (key :Object) :Object
|
||||||
|
{
|
||||||
|
var skey :String = key.toString();
|
||||||
|
return _data[skey];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function keys () :Array
|
||||||
|
{
|
||||||
|
var arr :Array = new Array();
|
||||||
|
for (var skey :String in _data) {
|
||||||
|
arr.push(skey);
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function put (key :Object, value :Object) :Object
|
||||||
|
{
|
||||||
|
var skey :String = key.toString();
|
||||||
|
var oldValue :Object = _data[skey];
|
||||||
|
_data[skey] = value;
|
||||||
|
return oldValue;
|
||||||
|
}
|
||||||
|
|
||||||
public function remove (key :Object) :Object
|
public function remove (key :Object) :Object
|
||||||
{
|
{
|
||||||
// I'm not sure this really works
|
|
||||||
var skey :String = key.toString();
|
var skey :String = key.toString();
|
||||||
var value :Object = this[skey];
|
var value :Object = _data[skey];
|
||||||
this[skey] = undefined;
|
delete _data[skey];
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var _data :Object = new Object();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
package com.threerings.util {
|
package com.threerings.util {
|
||||||
|
|
||||||
import flash.util.describeType;
|
|
||||||
|
|
||||||
import mx.utils.ObjectUtil;
|
import mx.utils.ObjectUtil;
|
||||||
|
|
||||||
import com.threerings.io.ArrayMask;
|
import com.threerings.io.ArrayMask;
|
||||||
@@ -83,6 +81,7 @@ public dynamic class TypedArray extends Array
|
|||||||
* except gives it a clue as to how to stream to our server. */
|
* except gives it a clue as to how to stream to our server. */
|
||||||
protected var _type :Class;
|
protected var _type :Class;
|
||||||
|
|
||||||
|
/** Whether or not the type of the array represents a final class. */
|
||||||
protected var _final :Boolean;
|
protected var _final :Boolean;
|
||||||
|
|
||||||
protected var _delegate :Streamer;
|
protected var _delegate :Streamer;
|
||||||
|
|||||||
Reference in New Issue
Block a user