This is an automated email from the ASF dual-hosted git repository.

gregdove pushed a commit to branch amf_updates
in repository https://gitbox.apache.org/repos/asf/royale-asjs.git

commit bcc4467f4febf8a279b374db86724742fada0eff
Author: greg-dove <[email protected]>
AuthorDate: Fri Mar 1 18:14:15 2019 +1300

    Getting WIP updates in for AMFBinaryData
    
    Support for dynamic classes (with constraints based on compile settings : 
needs js-default-initializers)
    Support for IExternalizable. Will try to improve things here for 
IDataInput/IDataOutput imports in implementing classes. These currently needs 
COMPILE::JS and COMPILE::SWF variants in imports - to discuss on dev list
    (See mx.collections/ArrayCollection.as for example)
    Numerous fixes and improvements to amf serialization as a result of 
AMFBinaryDataTesterTest testing in UnitTests manual test project.
    Updates to mxroyale/RemoteObjectAMFTest to use ArrayCollection as the 
collection for amf serialization (instead of ArrayList)
    
    still to do:
    IDynamicPropertyWriter (easy)
    test Vectors
    XML
    Dictionary (Map ?)
    Decide whether ByteArray decodes to ArrayBuffer or AMFBinaryData in 
javascript. To discuss on dev list.
---
 examples/amf/SampleAmfWebApp/pom.xml               |   28 +-
 .../RemoteObjectAMFTest/src/main/royale/App.mxml   |    8 +-
 .../src/main/royale/valueObjects/Product.as        |   18 +-
 .../org/apache/royale/collections/ArrayList.as     |   11 +-
 .../main/royale/mx/collections/ArrayCollection.as  |   10 +-
 .../src/main/royale/mx/collections/ArrayList.as    |   12 +-
 .../royale/net/remoting/amf/AMFBinaryData.as       | 1221 ++++++++++++++++++++
 .../royale/net/remoting/amf/AMFNetConnection.as    |    6 +-
 .../utils/{IExternalizable.as => IDataInput.as}    |   21 +-
 .../utils/{IExternalizable.as => IDataOutput.as}   |   25 +-
 .../org/apache/royale/net/utils/IExternalizable.as |   13 +
 .../UnitTests/src/main/royale/TestClasses.as       |    5 +-
 .../{JiraIssuesTester.as => GithubIssuesTester.as} |    6 +-
 .../{JiraIssuesTester.as => NetworkTester.as}      |   20 +-
 .../GithubTesterTest.as}                           |   12 +-
 .../network/AMFBinaryDataTesterTest.as             |  335 ++++++
 .../network/support/DynamicTestClass.as}           |   28 +-
 .../network/support/TestClass1.as}                 |   27 +-
 .../network/support/TestClass2.as}                 |   25 +-
 .../network/support/TestClass3.as}                 |   39 +-
 .../testsview/image/apache-royale-main-logo.png    |  Bin 0 -> 58758 bytes
 manualtests/UnitTests/testsview/index.html         |    3 +-
 22 files changed, 1771 insertions(+), 102 deletions(-)

diff --git a/examples/amf/SampleAmfWebApp/pom.xml 
b/examples/amf/SampleAmfWebApp/pom.xml
index 8cf7b3f..1a05d8b 100644
--- a/examples/amf/SampleAmfWebApp/pom.xml
+++ b/examples/amf/SampleAmfWebApp/pom.xml
@@ -24,7 +24,7 @@
     <artifactId>examples-amf-webapps</artifactId>
     <version>0.9.6-SNAPSHOT</version>
   </parent>
-  
+
   <artifactId>SampleAmfWebApp</artifactId>
   <version>0.9.6-SNAPSHOT</version>
   <packaging>war</packaging>
@@ -34,7 +34,7 @@
   <properties>
     <java.version>1.7</java.version>
   </properties>
-  
+
   <build>
     <sourceDirectory>src/main/java</sourceDirectory>
     <plugins>
@@ -47,7 +47,7 @@
           <target>${java.version}</target>
         </configuration>
       </plugin>
-        
+
       <!-- Make Spring-Boot build an executable war -->
       <plugin>
         <groupId>org.springframework.boot</groupId>
@@ -84,7 +84,25 @@
           </overlays>
         </configuration>
       </plugin>
-
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-antrun-plugin</artifactId>
+        <version>1.1</version>
+        <executions>
+          <execution>
+            <phase>install</phase>
+            <goals>
+              <goal>run</goal>
+            </goals>
+            <configuration>
+              <tasks>
+                <echo>To run, use:</echo>
+                <echo>java -jar 
target/${project.artifactId}-${project.version}-exec.war</echo>
+              </tasks>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
       <!-- Test create javadocs -->
       <!-- <plugin>
           <groupId>org.apache.maven.plugins</groupId>
@@ -131,7 +149,7 @@
       <version>0.9.6-SNAPSHOT</version>
       <type>war</type>
     </dependency> -->
-    
+
     <dependency>
       <groupId>org.apache.royale.examples</groupId>
       <artifactId>RemoteObjectAMFTest-MXRoyale</artifactId>
diff --git a/examples/mxroyale/RemoteObjectAMFTest/src/main/royale/App.mxml 
b/examples/mxroyale/RemoteObjectAMFTest/src/main/royale/App.mxml
index 7fa241a..ac5911e 100644
--- a/examples/mxroyale/RemoteObjectAMFTest/src/main/royale/App.mxml
+++ b/examples/mxroyale/RemoteObjectAMFTest/src/main/royale/App.mxml
@@ -34,7 +34,7 @@ limitations under the License.
             import mx.rpc.remoting.Operation;
             import mx.collections.ArrayCollection;
 
-            import org.apache.royale.collections.ArrayList;
+      //      import org.apache.royale.collections.ArrayList;
             import org.apache.royale.events.Event;
             import org.apache.royale.reflection.registerClassAlias;
             import org.apache.royale.reflection.getAliasByClass;
@@ -47,7 +47,7 @@ limitations under the License.
 
             private function iniApp(event:Event):void{
                 //swap in ArrayCollection for ArrayList
-                registerClassAlias(getAliasByClass(ArrayCollection), 
ArrayList);
+   //             registerClassAlias(getAliasByClass(ArrayCollection), 
ArrayList);
 
                 // Test CompressedRemoteObject
                 // trace("init CompressedRemoteObject.includePackages");
@@ -126,7 +126,7 @@ limitations under the License.
 
                 product.taxonomy = taxonomy;
 
-                var zones:ArrayList = new ArrayList();
+                var zones:ArrayCollection = new ArrayCollection();
 
                 var zone:Zone= new Zone();
                 zone.id = 1;
@@ -145,7 +145,7 @@ limitations under the License.
 
                 zones.addItem(zone);
 
-                var flavors:ArrayList = new ArrayList();
+                var flavors:ArrayCollection = new ArrayCollection();
 
                 flavors.addItem('X');
                 flavors.addItem('Y');
diff --git 
a/examples/mxroyale/RemoteObjectAMFTest/src/main/royale/valueObjects/Product.as 
b/examples/mxroyale/RemoteObjectAMFTest/src/main/royale/valueObjects/Product.as
index cfb045d..66adadc 100644
--- 
a/examples/mxroyale/RemoteObjectAMFTest/src/main/royale/valueObjects/Product.as
+++ 
b/examples/mxroyale/RemoteObjectAMFTest/src/main/royale/valueObjects/Product.as
@@ -18,7 +18,9 @@
 
////////////////////////////////////////////////////////////////////////////////
 package valueObjects
 {
-    import org.apache.royale.collections.ArrayList;
+  //  import org.apache.royale.collections.ArrayList;
+    
+    import mx.collections.ArrayCollection;
 
     [RemoteClass(alias="org.apache.royale.amfsamples.valueobjects.Product")]
        public class Product
@@ -66,29 +68,29 @@ package valueObjects
             _taxonomy = value;
         }
 
-        // collection of zones (Zone), we can use Array and ArrayList
-        private var _zones:ArrayList;
+        // collection of zones (Zone), we can use ArrayCollection
+        private var _zones:ArrayCollection;
 
         [Bindable("__NoChangeEvent__")]
-        public function get zones():ArrayList
+        public function get zones():ArrayCollection
         {
             return _zones;
         }
 
-        public function set zones(value:ArrayList):void
+        public function set zones(value:ArrayCollection):void
         {
             _zones = value;
         }
 
-        private var _flavors:ArrayList = null;
+        private var _flavors:ArrayCollection = null;
 
         [Bindable("__NoChangeEvent__")]
-        public function get flavors():ArrayList
+        public function get flavors():ArrayCollection
         {
             return _flavors;
         }
 
-        public function set flavors(value:ArrayList):void
+        public function set flavors(value:ArrayCollection):void
         {
             _flavors = value;
         }
diff --git 
a/frameworks/projects/Collections/src/main/royale/org/apache/royale/collections/ArrayList.as
 
b/frameworks/projects/Collections/src/main/royale/org/apache/royale/collections/ArrayList.as
index 0281628..04e536d 100644
--- 
a/frameworks/projects/Collections/src/main/royale/org/apache/royale/collections/ArrayList.as
+++ 
b/frameworks/projects/Collections/src/main/royale/org/apache/royale/collections/ArrayList.as
@@ -26,8 +26,15 @@ package org.apache.royale.collections
     import org.apache.royale.events.CollectionEvent;
        
        import org.apache.royale.net.utils.IExternalizable;
-       import org.apache.royale.net.utils.IDataInput;
-       import org.apache.royale.net.utils.IDataOutput;
+       COMPILE::JS{
+               import org.apache.royale.net.utils.IDataInput;
+               import org.apache.royale.net.utils.IDataOutput;
+       }
+       COMPILE::SWF{
+               import flash.utils.IDataInput;
+               import flash.utils.IDataOutput;
+       }
+       
 
     //--------------------------------------
     //  Events
diff --git 
a/frameworks/projects/MXRoyale/src/main/royale/mx/collections/ArrayCollection.as
 
b/frameworks/projects/MXRoyale/src/main/royale/mx/collections/ArrayCollection.as
index 1dc975e..0807354 100644
--- 
a/frameworks/projects/MXRoyale/src/main/royale/mx/collections/ArrayCollection.as
+++ 
b/frameworks/projects/MXRoyale/src/main/royale/mx/collections/ArrayCollection.as
@@ -31,8 +31,14 @@ use namespace mx_internal;
 */
 
 import org.apache.royale.net.utils.IExternalizable;
-import org.apache.royale.net.utils.IDataInput;
-import org.apache.royale.net.utils.IDataOutput;
+COMPILE::JS {
+       import org.apache.royale.net.utils.IDataInput;
+       import org.apache.royale.net.utils.IDataOutput;
+}
+COMPILE::SWF{
+       import flash.utils.IDataInput;
+       import flash.utils.IDataOutput;
+}
 
 
 [DefaultProperty("source")]
diff --git 
a/frameworks/projects/MXRoyale/src/main/royale/mx/collections/ArrayList.as 
b/frameworks/projects/MXRoyale/src/main/royale/mx/collections/ArrayList.as
index 763f54b..540ca0b 100644
--- a/frameworks/projects/MXRoyale/src/main/royale/mx/collections/ArrayList.as
+++ b/frameworks/projects/MXRoyale/src/main/royale/mx/collections/ArrayList.as
@@ -39,8 +39,14 @@ import org.apache.royale.utils.UIDUtil;
 import org.apache.royale.reflection.getQualifiedClassName;
 
 import org.apache.royale.net.utils.IExternalizable;
-import org.apache.royale.net.utils.IDataInput;
-import org.apache.royale.net.utils.IDataOutput;
+       COMPILE::JS {
+               import org.apache.royale.net.utils.IDataInput;
+               import org.apache.royale.net.utils.IDataOutput;
+       }
+       COMPILE::SWF{
+               import flash.utils.IDataInput;
+               import flash.utils.IDataOutput;
+       }
 
 //--------------------------------------
 //  Events
@@ -95,7 +101,7 @@ import org.apache.royale.net.utils.IDataOutput;
  *  @productversion Flex 4
  */
 public class ArrayList extends EventDispatcher
-       implements IList//, IExternalizable, IPropertyChangeNotifier
+       implements IList, IExternalizable//, IPropertyChangeNotifier
 {
     
//--------------------------------------------------------------------------
     //
diff --git 
a/frameworks/projects/Network/src/main/royale/org/apache/royale/net/remoting/amf/AMFBinaryData.as
 
b/frameworks/projects/Network/src/main/royale/org/apache/royale/net/remoting/amf/AMFBinaryData.as
new file mode 100644
index 0000000..dac9976
--- /dev/null
+++ 
b/frameworks/projects/Network/src/main/royale/org/apache/royale/net/remoting/amf/AMFBinaryData.as
@@ -0,0 +1,1221 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed under the Apache License, Version 2.0 (the "License");
+//  you may not use this file except in compliance with the License.
+//  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+/***
+ * Based on the
+ * AMF JavaScript library by Emil Malinov https://github.com/emilkm/amfjs
+ */
+package org.apache.royale.net.remoting.amf {
+       import org.apache.royale.net.utils.IDataInput;
+       import org.apache.royale.net.utils.IDataOutput;
+       import org.apache.royale.net.utils.IExternalizable;
+       import org.apache.royale.utils.BinaryData;
+       
+       /**
+        *  A version of BinaryData specific to AMF.
+        *
+        *  @langversion 3.0
+        *  @playerversion Flash 9
+        *  @playerversion AIR 1.1
+        *  @productversion BlazeDS 4
+        *  @productversion LCDS 3
+        *
+        *  @royalesuppresspublicvarwarning
+        */
+       public class AMFBinaryData extends BinaryData implements IDataInput, 
IDataOutput {
+               
//--------------------------------------------------------------------------
+               //
+               // Class Constants
+               //
+               
//--------------------------------------------------------------------------
+               
+               
+               public function AMFBinaryData(bytes:Object = null) {
+                       super(bytes);
+               }
+               
+               COMPILE::SWF
+               public function get objectEncoding():uint{
+                       return 3;
+               }
+               COMPILE::SWF
+               public function set objectEncoding(value:uint):void{
+                       trace('objectEncoding is always AMF3, setter is 
ignored');
+               }
+               
+               
+               
+               COMPILE::JS
+               private var serializationContext:SerializationContext;
+               
+               COMPILE::JS
+               public function writeObject(v:*):void {
+                       if (!serializationContext) serializationContext = new 
SerializationContext(this);
+                       _position = serializationContext.writeObjectExternal(v, 
_position, mergeInToArrayBuffer);
+                       var err:Error = serializationContext.getError();
+                       if (err) {
+                               throw new Error(err.message);
+                       }
+               }
+               
+               COMPILE::JS
+               public function readObject():* {
+                       if (!serializationContext) serializationContext = new 
SerializationContext(this);
+                       var value:* = serializationContext.readObjectExternal();
+                       var err:Error = serializationContext.getError();
+                       if (err) {
+                               throw new Error(err.message);
+                       }
+                       return value;
+               }
+               
+               COMPILE::SWF
+               public function writeObject(v:*):void {
+                       ba.writeObject(v);
+               }
+               
+               COMPILE::SWF
+               public function readObject():* {
+                       return ba.readObject();
+               }
+       }
+}
+
+import org.apache.royale.net.remoting.amf.AMFBinaryData;
+import org.apache.royale.reflection.getAliasByClass;
+import org.apache.royale.reflection.getClassByAlias;
+import org.apache.royale.reflection.getDynamicFields;
+import org.apache.royale.reflection.isDynamicObject;
+import org.apache.royale.net.utils.IDataInput;
+import org.apache.royale.net.utils.IDataOutput;
+import org.apache.royale.utils.BinaryData;
+import org.apache.royale.net.utils.IExternalizable;
+import org.apache.royale.net.utils.IDataInput;
+import org.apache.royale.net.utils.IDataOutput;
+
+
+COMPILE::JS
+class SerializationContext extends BinaryData  implements IDataInput, 
IDataOutput {
+       import goog.DEBUG;
+       
+       
+       private static const AMF0_AMF3:int = 0x11;
+       private static const AMF3_OBJECT_ENCODING:int = 0x03;
+       
+       private static const AMF3_UNDEFINED:int = 0x00;
+       private static const AMF3_NULL:int = 0x01;
+       private static const AMF3_BOOLEAN_FALSE:int = 0x02;
+       private static const AMF3_BOOLEAN_TRUE:int = 0x03;
+       private static const AMF3_INTEGER:int = 0x04;
+       private static const AMF3_DOUBLE:int = 0x05;
+       private static const AMF3_STRING:int = 0x06;
+       private static const AMF3_XMLDOCUMENT:int = 0x07;
+       private static const AMF3_DATE:int = 0x08;
+       private static const AMF3_ARRAY:int = 0x09;
+       private static const AMF3_OBJECT:int = 0x0A;
+       private static const AMF3_XML:int = 0x0B;
+       private static const AMF3_BYTEARRAY:int = 0x0C;
+       private static const AMF3_VECTOR_INT:int = 0x0D;
+       private static const AMF3_VECTOR_UINT:int = 0x0E;
+       private static const AMF3_VECTOR_DOUBLE:int = 0x0F;
+       private static const AMF3_VECTOR_OBJECT:int = 0x10;
+       private static const AMF3_DICTIONARY:int = 0x11;
+       
+       
+       private static const UINT29_MASK:int = 0x1FFFFFFF;
+       private static const INT28_MAX_VALUE:int = 268435455;
+       private static const INT28_MIN_VALUE:int = -268435456;
+       
+       private static const EMPTY_STRING:String = "";
+       
+       private var owner:AMFBinaryData;
+       private var writeBuffer:Array;
+       
+       private var objects:Array ;
+       
+       private var traits:Object;
+       
+       private var strings:Object;
+       
+       private var stringCount:uint;
+       private var traitCount:uint;
+       private var objectCount:uint;
+       
+       
+       private var writeMode:Boolean = false;
+       
+       
+
+       private var _numbers:ArrayBuffer;
+
+       private var _numberView:DataView;
+
+       private var _numberBytes:Uint8Array;
+       
+       private var _error:Error;
+       public function getError():Error{
+               var _err:Error = _error;
+               _error = null;
+               return _err;
+       }
+       
+       
+       public function SerializationContext(ownerReference:AMFBinaryData){
+               owner = ownerReference;
+               reset();
+               super();
+       }
+       
+       public function reset():void{
+               writeBuffer = [];
+               objects = [];
+               traits = {};
+               strings = {};
+               stringCount = 0;
+               traitCount = 0;
+               objectCount = 0;
+       }
+       
+
+       /**
+        * used internally as an override to return the writeBuffer Array for 
use to mimic Uint8Array during writing.
+        * Array is used because it is not usually known what the byte 
allocation should be in advance,
+        * and length is not mutable with javascript typed arrays, so 'growing' 
the buffer with each write is not
+        * a good strategy for performance.
+        * The assumption is that, while write access is slower for individual 
elements, increasing the length of
+        * the 'buffer' is not, and that using Array will be more performant.
+        * @royaleignorecoercion Uint8Array
+        */
+       override protected function getTypedArray():Uint8Array{
+               return writeMode ? writeBuffer as Uint8Array : 
super.getTypedArray();
+       }
+       
+
+       override protected function getDataView():DataView
+       {
+               if(!writeMode) return super.getDataView();
+               //in write mode, return a utility version
+               if (!_numberView) {
+                       _numbers = new ArrayBuffer(8);
+                       _numberView = new DataView(_numbers);
+                       _numberBytes = new Uint8Array(_numbers);
+               }
+               return _numberView;
+       }
+       
+       
+
+       override protected function setBufferSize(newSize:uint):void
+       {
+               //writing variation: in this subclass, writing  is always using 
'Array' so length is not fixed
+               _len = newSize;
+       }
+       
+
+       override public function writeByte(byte:int):void
+       {
+               writeBuffer[_position++] = byte & 255;
+       }
+       
+       override public function writeByteAt(idx:uint, byte:int):void
+       {
+               while (idx > _len) {
+                       writeBuffer[_len++] = 0;
+               }
+               writeBuffer[idx] = byte & 255;
+       }
+       
+       public function writeUInt29(v:uint):void {
+               const write:Function = writeByte;
+               if (v < 128) {
+                       write(v);
+               } else if (v < 16384) {
+                       write(((v >> 7) & 127) | 128);
+                       write(v & 127);
+               } else if (v < 2097152) {
+                       write(((v >> 14) & 127) | 128);
+                       write(((v >> 7) & 127) | 128);
+                       write(v & 127);
+               } else if (v < 0x40000000) {
+                       write(((v >> 22) & 127) | 128);
+                       write(((v >> 15) & 127) | 128);
+                       write(((v >> 8) & 127) | 128);
+                       write(v & 255);
+               } else {
+                       throw "Integer out of range: " + v;
+               }
+       }
+       
+       public function writeAll(bytes:Array):void {
+               for (var i:uint = 0; i < bytes.length; i++) {
+                       writeByte(bytes[i]);
+               }
+       }
+       
+       protected function addByteSequence(array:Array):void{
+               var length:uint = array.length;
+               if (_position == _len) {
+                       writeBuffer = writeBuffer.concat(array);
+                       _len = _len + length;
+                       if (_len != writeBuffer.length) {
+                               throw new Error('code review')
+                       }
+               } else {
+                       if (_position + length > _len) {
+                               //overwrite beyond
+                               //first truncate to _position
+                               writeBuffer.length = _position;
+                               //then append the new content
+                               writeBuffer = writeBuffer.concat(array);
+                               _len = _position + length;
+                               if (_len != writeBuffer.length) {
+                                       throw new Error('code review')
+                               }
+                               
+                       } else {
+                               //overwrite within - concatenate left and right 
slices with the new content between
+                               writeBuffer = writeBuffer.slice(0, 
_position).concat(array, writeBuffer.slice(_position + length));
+                               
+                               if (_len != writeBuffer.length) {
+                                       throw new Error('code review')
+                               }
+                               
+                       }
+               }
+               _position += length;
+       }
+       
+       
+       override public function writeBytes(bytes:ArrayBuffer, offset:uint = 0, 
length:uint = 0):void
+       {
+               if (length == 0) length = bytes.byteLength - offset ;
+               if (!length) return;
+               var src:Uint8Array = new Uint8Array(bytes, offset, offset + 
length);
+               var srcArray:Array = [].slice.call(src);
+               addByteSequence(srcArray);
+       }
+       
+       override public function writeUTF(str:String):void
+       {
+               var utcBytes:Uint8Array = getUTFBytes(str , true);
+               var srcArray:Array = [].slice.call(utcBytes);
+               addByteSequence(srcArray);
+       }
+       
+       override public function writeUTFBytes(str:String):void
+       {
+               var utcBytes:Uint8Array = getUTFBytes(str, false);
+               var srcArray:Array = [].slice.call(utcBytes);
+               addByteSequence(srcArray);
+       }
+       
+       protected function copyNumericBytes(byteCount:uint):void{
+               //arr here is actually an Array, not Uint8Array
+               var arr:Uint8Array = getTypedArray();
+               var numbers:Uint8Array = _numberBytes;
+               var idx:uint = 0;
+               while(byteCount--) {
+                       arr[_position++] = numbers[idx++];
+               }
+       }
+       
+       override public function writeFloat(val:Number):void
+       {
+               //always big endian
+               getDataView().setFloat32(0,val,false);
+               copyNumericBytes(4);
+       }
+       
+       override public function writeDouble(val:Number):void
+       {
+               //always big endian
+               getDataView().setFloat64(0,val,false);
+               copyNumericBytes(8);
+       }
+       
+       private function writeAMF_UTF(string:String):void{
+               var utcBytes:Uint8Array = getUTFBytes(string , false);
+               var srcArray:Array = [].slice.call(utcBytes);
+               writeUInt29((srcArray.length << 1) | 1);
+               addByteSequence(srcArray);
+       }
+       
+       private function writeStringWithoutType(v:String):void {
+               if (v.length == 0) {
+                       writeUInt29(1);
+               } else {
+                       if (!this.stringByReference(v)) {
+                               writeAMF_UTF(v);
+                       }
+               }
+       }
+       
+       private function stringByReference(v:String):Boolean {
+               const strIndex:* = strings[v];
+               const found:Boolean = strIndex !== undefined;
+               if (found) {
+                       const ref:uint = strIndex;
+                       writeUInt29(ref << 1);
+               } else {
+                       strings[v] = stringCount++;
+               }
+               return found;
+       }
+       
+       public function objectByReference(v:Object):Boolean {
+               const ref:int = objects.indexOf(v);
+               const found:Boolean = ref !== -1;
+               if (found) {
+                       writeUInt29(ref << 1);
+               } else {
+                       objects.push(v);
+                       objectCount++;
+               }
+               return found;
+       }
+       
+       private function traitsByReference(props:Array, alias:String):Boolean {
+               //@todo review this. Don't think it is necessary to do the long 
joins with the props
+               //maybe alias alone is enough...?
+               const s:String = alias + "|" + props.join("|");
+               const traitsIndex:* = traits[s];
+               const found:Boolean = traitsIndex !== undefined;
+               if (found) {
+                       const ref:uint = traitsIndex;
+                       writeUInt29((ref << 2) | 1);
+               } else {
+                       traits[s] = traitCount++;
+               }
+               return found;
+       }
+       
+       private function writeAmfInt(v:int):void {
+               if (v >= INT28_MIN_VALUE && v <= INT28_MAX_VALUE) {
+                       v = v & UINT29_MASK;
+                       writeByte(AMF3_INTEGER);
+                       writeUInt29(v);
+               } else {
+                       writeByte(AMF3_DOUBLE);
+                       writeDouble(v);
+               }
+       }
+       
+       private function writeDate(v:Date):void {
+               writeByte(AMF3_DATE);
+               if (!objectByReference(v)) {
+                       writeUInt29(1);
+                       writeDouble(v.getTime());
+               }
+       }
+       
+       private function filterSerializableMembers(fieldSet:Object, 
accessChecks:Object, localTraits:Traits, asAccessors:Boolean = false, 
excludeTransient:Boolean = true):Array {
+               var l:uint;
+               var metas:Array;
+               var exclude:Boolean;
+               var fieldName:String;
+               const into:Array = localTraits.props;
+               
+               for (fieldName in fieldSet) {
+                       //exclude all static props
+                       if (fieldName.charAt(0) == '|') continue;
+                       var field:Object = fieldSet[fieldName];
+                       exclude = false;
+                       if (asAccessors) {
+                               exclude = field.access != 'readwrite';
+                               if (exclude && into.indexOf(fieldName) == -1) { 
//<-- if at some level we already have read-write access, then that wins
+                                       //check: does it combine to provide 
'readwrite' permissions via accessChecks through inheritance chain
+                                       if (accessChecks[fieldName] && 
accessChecks[fieldName] != field.access) {
+                                               //readonly or writeonly 
overridde at one level and different at another == readwrite
+                                               exclude = false;
+                                       } else {
+                                               if (!accessChecks[fieldName]) {
+                                                       //cache for subsequent 
cross-checks as above
+                                                       accessChecks[fieldName] 
= field.access;
+                                               }
+                                       }
+                               }
+                       }
+                       if (!exclude && excludeTransient && field.metadata != 
null) {
+                               //exclude anything marked as Transient
+                               metas = field.metadata();
+                               l = metas.length;
+                               while (l--) {
+                                       if (metas[l].name == 'Transient') {
+                                               exclude = true;
+                                       }
+                               }
+                               if (exclude && into.indexOf(fieldName) != -1) {
+                                       //?possible case where it is marked 
transient on an ancestor but not in a subclass override
+                                       //it will not have been excluded when 
processing the subclass, which occurs first, so remove it now
+                                       //@todo untested : check this scenario, 
assume it should be removed
+                                       into.splice(into.indexOf(fieldName), 1);
+                               }
+                       }
+                       if (!exclude) {
+                               //set up null/undefined value lookups for 
undefined field values (when encoding)
+                               var nullValues:Object = localTraits.nullValues;
+                               if (field.type == 'Number') {
+                                       nullValues[fieldName] = Number.NaN;
+                               } else if (field.type == 'Boolean') {
+                                       nullValues[fieldName] = false;
+                               } else if (field.type == 'int' || field.type == 
'uint') {
+                                       nullValues[fieldName] = 0;
+                               } else if (field.type == '*') {
+                                       nullValues[fieldName] = undefined;
+                               } else {
+                                       nullValues[fieldName] = null;
+                               }
+                               into.push(fieldName);
+                               if (asAccessors) {
+                                       localTraits.getterSetters[fieldName] = 
Traits.createInstanceAccessorGetterSetter(fieldName);
+                               } else {
+                                       //variable
+                                       localTraits.getterSetters[fieldName] = 
Traits.createInstanceVariableGetterSetter(field.get_set, field.type);
+                               }
+                       }
+               }
+               return into;
+       }
+       
+       private function populateSerializableMembers(reflectionInfo:Object, 
accessChecks:Object, localTraits:Traits):Array {
+               if (!reflectionInfo) return localTraits.props;
+               var fields:Object = reflectionInfo.variables();
+               filterSerializableMembers(fields, accessChecks, localTraits, 
false, true);
+               fields = reflectionInfo.accessors();
+               filterSerializableMembers(fields, accessChecks, localTraits, 
true, true);
+               return localTraits.props;
+       }
+       
+       private function getLocalTraitsInfo(instance:Object):Traits {
+               var classInfo:Object = instance.ROYALE_CLASS_INFO;
+               var originalClassInfo:Object;
+               var localTraits:Traits;
+               if (classInfo) {
+                       localTraits = classInfo.localTraits;
+                       if (localTraits) {
+                               //implementation note: @todo a class may have 
more than one alias point to it
+                               //update alias, in case of registration of 
alias changed since traits was last cached.
+                               localTraits.alias = classInfo.alias || '';
+                               return classInfo.localTraits;
+                       }
+                       originalClassInfo = classInfo;
+                       localTraits = new Traits();
+                       var alias:String = classInfo.alias;// 
getAliasByClass(instance.constructor as Class); //<- @todo possible 
optimization: registerClassAlias implementation stores in the classInfo Object, 
access directly
+                       if (alias) localTraits.alias = alias;
+                       else localTraits.alias = '';
+                       localTraits.qName = classInfo.names[0].qName;
+                       localTraits.isDynamic = 
Boolean(classInfo.names[0].isDynamic);
+                       localTraits.externalizable = instance is 
IExternalizable;
+                       
+                       if (localTraits.externalizable) {
+                               localTraits.count = 0;
+                       } else {
+                               var accessChecks:Object = {};
+                               var c:Object = instance;
+                               while (classInfo) {
+                                       var reflectionInfo:Object = 
c.ROYALE_REFLECTION_INFO();
+                                       
populateSerializableMembers(reflectionInfo, accessChecks, localTraits);
+                                       if (!c.constructor.superClass_ || 
!c.constructor.superClass_.ROYALE_CLASS_INFO)
+                                               break;
+                                       classInfo = 
c.constructor.superClass_.ROYALE_CLASS_INFO;
+                                       c = c.constructor.superClass_;
+                               }
+                               localTraits.count = localTraits.props.length;
+                               //not required, but useful when testing:
+                               localTraits.props.sort();
+                       }
+                       //cache in the classInfo for faster lookups next time
+                       originalClassInfo.localTraits = localTraits;
+               } else {
+                       //assume dynamic, anon object
+                       if (Object == instance.constructor) {
+                               localTraits = Traits.getBaseObjectTraits();
+                       } else {
+                               //could be a class object
+                               var anonFields:Array = [];
+                               for (var key:String in instance) {
+                                       if (key !== "") {
+                                               anonFields.push(key);
+                                       }
+                               }
+                               localTraits = 
Traits.getDynObjectTraits(anonFields);
+                       }
+                       //not required, but useful when testing:
+                       localTraits.props.sort();
+                       
+               }
+               return localTraits;
+       }
+       
+       public function writeObjectExternal(v:*, position:uint, 
mergeIntoOwner:Function):uint {
+               writeMode = true;
+               _position = 0;
+               _len = 0;
+               try{
+                       writeObject(v);
+               } catch (e:Error) {
+                       _error = e;
+               }
+               var output:Uint8Array = new Uint8Array(writeBuffer);
+               reset();
+               writeMode = false;
+               return mergeIntoOwner(position, output);
+       }
+       
+       /**
+        * @royaleignorecoercion Class
+        * @royaleignorecoercion String
+        * @royaleignorecoercion Number
+        * @royaleignorecoercion Array
+        */
+       public function writeObject(v:*):void {
+               if (v == null) {
+                       writeByte(AMF3_NULL);
+                       return;
+               }
+               if (v is Function) {
+                       //output function value as undefined
+                       writeByte(AMF3_UNDEFINED);
+                       return;
+               }
+               if (v is String) {
+                       writeByte(AMF3_STRING);
+                       writeStringWithoutType(v as String);
+               } else if (v is Number) {
+                       var n:Number = v as Number;
+                       if (n === +n && n === (n | 0)) {
+                               writeAmfInt(n);
+                       } else {
+                               writeByte(AMF3_DOUBLE);
+                               writeDouble(n);
+                       }
+               } else if (v is Boolean)
+                       writeByte((v
+                                       ? AMF3_BOOLEAN_TRUE
+                                       : AMF3_BOOLEAN_FALSE));
+               else if (v is Date)
+                       writeDate(v as Date);
+               else {
+                       if (v is Array) {
+                               if (v.toString().indexOf("[Vector") == 0)
+                                       writeVector(v);
+                               else
+                                       writeArray(v as Array);
+                       } else writeObjectVariant(v);
+               }
+       }
+       
+       /**
+        *
+        * @royaleignorecoercion BinaryData
+        */
+       private function writeObjectVariant(v:Object):void {
+               if (v is AMFBinaryData || v is BinaryData) {
+                       writeByte(AMF3_BYTEARRAY);
+                       var binaryData:BinaryData = v as BinaryData;
+                       var len:uint = binaryData.length;
+                       writeUInt29(len);
+                       writeBinaryData(binaryData, 0, len);
+                       return;
+               }
+               
+               writeByte(AMF3_OBJECT);
+               if (!this.objectByReference(v)) {
+                       const localTraits:Traits = getLocalTraitsInfo(v);
+                       if (localTraits.externalizable && !localTraits.alias) {
+                               //in flash player if you try to write an object 
with no alias that is externalizable it does this:
+                               throw new Error("ArgumentError: Error #2004: 
One of the parameters is invalid.");
+                       }
+                       writeTypedObject(v, localTraits);
+               }
+       }
+       
+       
+       private function writeTypedObject(v:Object, localTraits:Traits):void {
+               var encodedName:String = localTraits.alias && 
localTraits.alias.length ? localTraits.alias : ']:' + localTraits.qName + ":[";
+               
+               if (!traitsByReference(localTraits.props, encodedName)) {
+                       this.writeUInt29(3 | (localTraits.externalizable ? 4 : 
0) | (localTraits.isDynamic ? 8 : 0) | (localTraits.count << 4));
+                       this.writeStringWithoutType(localTraits.alias);
+                       
+                       if (!localTraits.externalizable) {
+                               var l:uint = localTraits.count;
+                               for (var i:uint = 0; i < l; i++) {
+                                       
this.writeStringWithoutType(localTraits.props[i]);
+                               }
+                       }
+               }
+               
+               if (localTraits.externalizable) {
+                       v.writeExternal(this);
+               } else {
+                       l = localTraits.count;
+                       for (i = 0; i < l; i++) {
+                               //sealed props
+                               var val:* = 
localTraits.getterSetters[localTraits.props[i]].getValue(v);
+                               if (val === null || val === undefined) {
+                                       //coerce null values to the 'correct' 
types
+                                       val = 
localTraits.nullValues[localTraits.props[i]];
+                                       
+                                       //handle '*' type which can be 
undefined or explicitly null
+                                       if (val === undefined && 
localTraits.getterSetters[localTraits.props[i]].getValue(v) === null) {
+                                               val = null;
+                                       }
+                               }
+                               this.writeObject(val);
+                       }
+                       
+                       if (localTraits.isDynamic) {
+                               var dynFields:Array = getDynamicFields(v);
+                               i = 0;
+                               l = dynFields.length;
+                               for (; i < l; i++) {
+                                       
this.writeStringWithoutType(dynFields[i]);
+                                       this.writeObject(v[dynFields[i]]);
+                               }
+                               this.writeStringWithoutType(EMPTY_STRING);
+                       }
+               }
+       }
+       
+       /*private function writeDynamicObject(v:Object, 
localTraits:Traits):void {
+               if (!this.traitsByReference([], '$DynObject$')) { //<-something 
to represent an anonymous object
+                       this.writeUInt29(11 /!* 3 | 8 == dynamic *!/);
+                       this.writeStringWithoutType(EMPTY_STRING); //class name
+               }
+               var i:uint = 0;
+               var l:uint = localTraits.props.length;
+               for (; i < l; i++) {
+                       this.writeStringWithoutType(localTraits.props[i]);
+                       this.writeObject(v[localTraits.props[i]]);
+               }
+               this.writeStringWithoutType(EMPTY_STRING);
+       }*/
+       
+       /**
+        *
+        * @royaleignorecoercion String
+        */
+       private function writeArray(v:Array):void {
+               writeByte(AMF3_ARRAY);
+               var len:uint = v.length;
+               var i:uint = 0;
+               var akl:uint = 0; //associative keys length
+               if (!this.objectByReference(v)) {
+                       var denseLength:uint = len;
+                       var keys:Array = Object.keys(v);
+                       var associativeKeys:Array;
+                       //profile the array
+                       if (keys.length != len) {
+                               //Array is not strict
+                               if (len) {
+                                       associativeKeys = [];
+                                       var kl:uint = keys.length;
+                                       //find denseLength
+                                       for (i=0;i<len;i++) {
+                                               if (keys.indexOf(''+i) == -1) 
break;
+                                       }
+                                       denseLength = i;
+                                       
+                                       for (i=0;i<kl;i++) {
+                                               
+                                               var key:String = keys[i] as 
String;
+                                               var numKey:Number = Number(key);
+                                               if (isNaN(numKey) || numKey > 
denseLength || numKey<0 || uint(numKey) != numKey) {
+                                                       associativeKeys[akl++] 
= key;
+                                               }
+                                       }
+                                       
+                               } else associativeKeys = keys;
+                       }
+                       this.writeUInt29((denseLength << 1) | 1);
+                       
+                       if (akl) {
+                               //name-value pairs of associative keys
+                               for (i = 0; i < akl; i++) {
+                                       
this.writeStringWithoutType(associativeKeys[i] as String);
+                                       this.writeObject(v[associativeKeys[i]]);
+                               }
+                       }
+                       //empty string 'terminates' associative keys block - no 
more associative keys (if there were any)
+                       writeStringWithoutType(EMPTY_STRING);
+                       if (denseLength) {
+                               for (i = 0; i < denseLength; i++) {
+                                       writeObject(v[i]);
+                               }
+                       }
+               }
+       }
+       
+       private function writeVector(v:Object):void {
+               writeByte(v.type);
+               var i:uint;
+               var len:uint = v.length;
+               if (!this.objectByReference(v)) {
+                       this.writeUInt29((len << 1) | 1);
+                       this.writeBoolean(v.fixed);
+               }
+               if (v.type == AMF3_VECTOR_OBJECT) {
+                       var className:String = "";
+                       if (len > 0) {
+                               // TODO: how much of the PHP logic can we do 
here
+                               className = v[0].constructor.name;
+                       }
+                       this.writeStringWithoutType(className);
+                       for (i = 0; i < len; i++) {
+                               writeObject(v[i]);
+                       }
+               } else if (v.type == AMF3_VECTOR_INT) {
+                       for (i = 0; i < len; i++) {
+                               writeInt(v[i]);
+                       }
+               } else if (v.type == AMF3_VECTOR_UINT) {
+                       for (i = 0; i < len; i++) {
+                               writeUnsignedInt(v[i]);
+                       }
+               } else if (v.type == AMF3_VECTOR_DOUBLE) {
+                       for (i = 0; i < len; i++) {
+                               writeDouble(v[i]);
+                       }
+               }
+       }
+       
+       public function readUInt29():int {
+               const read:Function = readUnsignedByte;
+               var b:uint = read() & 255;
+               if (b < 128) {
+                       return b;
+               }
+               var value:uint = (b & 127) << 7;
+               b = read() & 255;
+               if (b < 128)
+                       return (value | b);
+               value = (value | (b & 127)) << 7;
+               b = read() & 255;
+               if (b < 128)
+                       return (value | b);
+               value = (value | (b & 127)) << 8;
+               b = read() & 255;
+               return (value | b);
+       }
+       
+       /**
+        *
+        * @royaleignorecoercion ArrayBuffer
+        */
+       public function readObjectExternal():* {
+               if (ba != owner.data) {
+                       ba = owner.data as ArrayBuffer;
+                       _typedArray = new Uint8Array(ba);
+               }
+               _position = owner.position;
+               _len = owner.length;
+               try{
+                       var result:* = readObject();
+               } catch (e:Error) {
+                       _error = e;
+               }
+               reset();
+               owner.position = _position;
+               return result;
+       }
+       
+       public function readObject():* {
+               var amfType:uint = readUnsignedByte();
+               return readObjectValue(amfType);
+       }
+       
+       public function readString():String {
+               var ref:uint = readUInt29();
+               if ((ref & 1) == 0) {
+                       return getString(ref >> 1);
+               } else {
+                       var len:uint = (ref >> 1);
+                       if (len == 0) {
+                               return EMPTY_STRING;
+                       }
+                       var str:String = readUTFBytes(len);
+                       rememberString(str);
+                       return str;
+               }
+       }
+       
+       private function rememberString(v:String):void {
+               strings[stringCount++] = v;
+       }
+       
+       private function getString(v:uint):String {
+               return strings[v];
+       }
+       
+       private function getObject(v:uint):Object {
+               
+               return objects[v];
+       }
+       
+       
+       private function getTraits(v:uint):Traits {
+               return traits[v] as Traits;
+       }
+       
+       private function rememberTraits(v:Traits):void {
+               traits[traitCount++] = v;
+       }
+       
+       
+       private function rememberObject(v:Object):void {
+               objects.push(v);
+       }
+       
+       private function readTraits(ref:uint):Traits {
+               var ti:Traits;
+               if ((ref & 3) == 1) {
+                       ti = getTraits(ref >> 2);
+                       return ti;
+               } else {
+                       ti = new Traits();
+                       ti.externalizable = ((ref & 4) == 4);
+                       ti.isDynamic = ((ref & 8) == 8);
+                       ti.count = (ref >> 4);
+                       var className:String = readString();
+                       if (className != null && className != "") {
+                               ti.alias = className;
+                       }
+                       
+                       for (var i:int = 0; i < ti.count; i++) {
+                               ti.props.push(readString());
+                       }
+                       
+                       rememberTraits(ti);
+                       return ti;
+               }
+       }
+       
+       private function readScriptObject():Object {
+               var ref:uint = readUInt29();
+               if ((ref & 1) == 0) {
+                       //retrieve object from object reference table
+                       return getObject(ref >> 1);
+               } else {
+                       var decodedTraits:Traits = readTraits(ref);
+                       var obj:Object;
+                       var localTraits:Traits;
+                       if (decodedTraits.alias) {
+                               var c:Class = 
getClassByAlias(decodedTraits.alias);
+                               if (c) {
+                                       obj = new c();
+                                       localTraits = getLocalTraitsInfo(obj);
+                               } else {
+                                       obj = {};
+                               }
+                       } else {
+                               obj = {};
+                       }
+                       rememberObject(obj);
+                       if (decodedTraits.externalizable) {
+                               obj.readExternal(this);
+                       } else {
+                               const l:uint = decodedTraits.props.length;
+                               var hasProp:Boolean;
+                               for (var i:uint = 0; i < l; i++) {
+                                       var fieldValue:* = readObject();
+                                       var prop:String = 
decodedTraits.props[i];
+                                       hasProp = localTraits &&  
(localTraits.hasProp(prop) || localTraits.isDynamic);
+                                       if (hasProp) {
+                                               
localTraits.getterSetters[prop].setValue(obj, fieldValue);
+                                       } else {
+                                               if (!localTraits) {
+                                                       obj[prop] = fieldValue;
+                                               } else {
+                                                       //@todo add debug-only 
logging for error checks (e.g. ReferenceError: Error #1074: Illegal write to 
read-only property)
+                                                       if (goog.DEBUG) {
+                                                               
trace('ReferenceError: Error #1056: Cannot create property ' + prop + ' on ' + 
decodedTraits.alias);
+                                                       }
+                                               }
+                                       }
+                               }
+                               if (decodedTraits.isDynamic) {
+                                       for (; ;) {
+                                               var name:String = readString();
+                                               if (name == null || name.length 
== 0) {
+                                                       break;
+                                               }
+                                               obj[name] = readObject();
+                                       }
+                               }
+                       }
+                       return obj;
+               }
+       }
+       
+       /**
+        * @royaleignorecoercion Array
+        */
+       public function readArray():Array {
+               var ref:uint = readUInt29();
+               if ((ref & 1) == 0)
+                       return getObject(ref >> 1) as Array;
+               var denseLength:uint = (ref >> 1);
+               var array:Array = [];
+               rememberObject(array);
+               while (true) {
+                       var name:String = readString();
+                       if (!name)
+                               break;
+                       //associative keys first
+                       array[name] = readObject();
+               }
+               //then dense array keys
+               for (var i:uint = 0; i < denseLength; i++) {
+                       array[i] = readObject();
+               }
+               return array;
+       }
+       
+       /**
+        * @royaleignorecoercion Array
+        */
+       public function readDate():Date {
+               var ref:uint = readUInt29();
+               if ((ref & 1) == 0)
+                       return getObject(ref >> 1) as Date;
+               var time:Number = readDouble();
+               var date:Date = new Date(time);
+               rememberObject(date);
+               return date;
+       }
+       
+       public function readByteArray():AMFBinaryData {
+               var ref:uint = readUInt29();
+               if ((ref & 1) == 0)
+                       return getObject(ref >> 1) as AMFBinaryData;
+               else {
+                       var len:uint = (ref >> 1);
+                       var bytes:Uint8Array = new Uint8Array(len);
+                       bytes.set(new Uint8Array(getTypedArray(), _position, 
len));
+                       _position += len;
+                       var ba:AMFBinaryData = new AMFBinaryData(bytes.buffer);
+                       rememberObject(ba);
+                       return ba;
+               }
+       }
+       
+       private function toVector(type:uint, array:Array, fixed:Boolean):Array {
+               // TODO (aharui) handle vectors
+               return array;
+       }
+       
+       private function readAmf3Vector(amfType:uint):Object {
+               var ref:uint = readUInt29();
+               if ((ref & 1) == 0)
+                       return getObject(ref >> 1);
+               var len:uint = (ref >> 1);
+               var vector:Array = toVector(amfType, [], readBoolean());
+               var i:uint;
+               if (amfType === AMF3_VECTOR_OBJECT) {
+                       readString(); //className
+                       for (i = 0; i < len; i++)
+                               vector.push(readObject());
+               } else if (amfType === AMF3_VECTOR_INT) {
+                       for (i = 0; i < len; i++)
+                               vector.push(readInt());
+               } else if (amfType === AMF3_VECTOR_UINT) {
+                       for (i = 0; i < len; i++)
+                               vector.push(readUnsignedInt());
+               } else if (amfType === AMF3_VECTOR_DOUBLE) {
+                       for (i = 0; i < len; i++)
+                               vector.push(readDouble());
+               }
+               rememberObject(vector);
+               return vector;
+       }
+       
+       private function readObjectValue(amfType:uint):Object {
+               var value:Object = null;
+               var u:uint;
+               
+               switch (amfType) {
+                       case AMF3_STRING:
+                               value = readString();
+                               break;
+                       case AMF3_OBJECT:
+                               try {
+                                       value = readScriptObject();
+                               } catch (e:Error) {
+                                       throw new Error("Failed to deserialize: 
" + e);
+                               }
+                               break;
+                       case AMF3_ARRAY:
+                               value = readArray();
+                               break;
+                       case AMF3_BOOLEAN_FALSE:
+                               value = false;
+                               break;
+                       case AMF3_BOOLEAN_TRUE:
+                               value = true;
+                               break;
+                       case AMF3_INTEGER:
+                               u = readUInt29();
+                               // Symmetric with writing an integer to fix 
sign bits for
+                               // negative values...
+                               value = (u << 3) >> 3;
+                               break;
+                       case AMF3_DOUBLE:
+                               value = readDouble();
+                               break;
+                       case AMF3_UNDEFINED:
+                       case AMF3_NULL:
+                               break;
+                       case AMF3_DATE:
+                               value = readDate();
+                               break;
+                       case AMF3_BYTEARRAY:
+                               value = readByteArray();
+                               break;
+                       case AMF3_VECTOR_INT:
+                       case AMF3_VECTOR_UINT:
+                       case AMF3_VECTOR_DOUBLE:
+                       case AMF3_VECTOR_OBJECT:
+                               value = readAmf3Vector(amfType);
+                               break;
+                       case AMF0_AMF3:
+                               value = readObject();
+                               break;
+                       default:
+                               throw new Error("Unsupported AMF type: " + 
amfType);
+               }
+               return value;
+       }
+}
+
+COMPILE::JS
+/**
+ *  @royalesuppresspublicvarwarning
+ */
+class Traits {
+       import goog.DEBUG;
+       
+/*     public static function createInstanceVariableGetter(fromFunc:Function, 
type:String):Function{
+               if (type == "*") {
+                       return function(inst:Object):* {
+                               return fromFunc(inst, fromFunc);
+                       }
+               } else {
+                       return function(inst:Object):* {
+                               fromFunc(inst);
+                       }
+               }
+       }
+       
+       public static function createInstanceVariableSetter(toFunc:Function, 
type:String):Function{
+               return function(inst:Object, value:*):void {
+                       toFunc(inst, value);
+               }
+       }*/
+       
+       public static function 
createInstanceVariableGetterSetter(reflectionFunction:Function, 
type:String):Object{
+               var ret:Object = {
+                       setValue: function(inst:Object, value:*):void {
+                               reflectionFunction(inst, value);
+                       }
+               };
+               
+               if (type == "*") {
+                       ret.getValue =
+                               function(inst:Object):* {
+                                       return reflectionFunction(inst, 
reflectionFunction);
+                               }
+               } else {
+                       ret.getValue =
+                               function(inst:Object):* {
+                                       return reflectionFunction(inst);
+                               }
+               }
+               return ret;
+       }
+       
+       public static function 
createInstanceAccessorGetterSetter(fieldName:String):Object{
+               return {
+                       getValue: function(inst:Object):* {
+                               return inst[fieldName];
+                       },
+                       setValue: function(inst:Object, value:*):void {
+                               inst[fieldName] = value;
+                       }
+               };
+       }
+       
+       private static var _emtpy_object:Traits;
+       
+       
+       
+       public static function getClassTraits(fields:Array, 
qName:String):Traits{
+               var traits:Traits = new Traits();
+               traits.qName = '[Class] '+ qName;
+               traits.isDynamic = true;
+               traits.externalizable = false;
+               traits.props = fields;
+               
+               return traits;
+       }
+       
+       public static function getBaseObjectTraits():Traits {
+               if (_emtpy_object) return _emtpy_object;
+               var traits:Traits = _emtpy_object = new Traits();
+               traits.qName = 'Object';
+               traits.externalizable = false;
+               traits.isDynamic = true;
+               return traits;
+       }
+       
+       public static function getDynObjectTraits(fields:Array):Traits {
+               var traits:Traits;
+               traits = new Traits();
+               traits.qName = 'Object';
+               traits.externalizable = false;
+               traits.isDynamic = true;
+               traits.props = fields;
+               return traits;
+       }
+       
+       public var alias:String = '';
+       public var qName:String;
+       public var externalizable:Boolean;
+       public var isDynamic:Boolean;
+       public var count:uint = 0;
+       public var props:Array = [];
+       public var nullValues:Object = {};
+       
+       public var getterSetters:Object = {};
+       
+       public function hasProp(prop:String):Boolean {
+               return props.indexOf(prop) != -1;
+       }
+       
+       public function toString():String {
+               if (goog.DEBUG) {
+                       return 'Traits for \'' + qName + '\'\n'
+                                       + 'alias: \'' + alias + '\'\n'
+                                       + 'externalizable:' + 
Boolean(externalizable) + '\n'
+                                       + 'isDynamic:' + Boolean(isDynamic) + 
'\n'
+                                       + 'count:' + count + '\n'
+                                       + 'props:\n\t' + props.join('\n\t');
+               } else {
+                       return 'Traits';
+               }
+       }
+}
+
+
diff --git 
a/frameworks/projects/Network/src/main/royale/org/apache/royale/net/remoting/amf/AMFNetConnection.as
 
b/frameworks/projects/Network/src/main/royale/org/apache/royale/net/remoting/amf/AMFNetConnection.as
index e845098..d176fcc 100644
--- 
a/frameworks/projects/Network/src/main/royale/org/apache/royale/net/remoting/amf/AMFNetConnection.as
+++ 
b/frameworks/projects/Network/src/main/royale/org/apache/royale/net/remoting/amf/AMFNetConnection.as
@@ -467,13 +467,13 @@ public class AMFNetConnection
         //reader.pos += 4; //length
         //reader.reset();
                var len:uint = reader.readUnsignedInt();
-               trace('readHeader len',len);
+               //trace('readHeader len',len);
         var type:uint = reader.readUnsignedByte();
         if (type != 2) { //amf0 string
             throw "Only string header data supported.";
         }
         header.data = reader.readUTF();
-        trace('readHeader data:',header.data);
+        //trace('readHeader data:',header.data);
         return header;
     }
 
@@ -485,7 +485,7 @@ public class AMFNetConnection
         body.responseURI = reader.readUTF();
         //reader.pos += 4; //length
         var len:uint = reader.readUnsignedInt();
-        trace('readBody len',len);
+        //trace('readBody len',len);
        //reader.reset();
         body.data = reader.readObject();
         return body;
diff --git 
a/frameworks/projects/Network/src/main/royale/org/apache/royale/net/utils/IExternalizable.as
 
b/frameworks/projects/Network/src/main/royale/org/apache/royale/net/utils/IDataInput.as
similarity index 72%
copy from 
frameworks/projects/Network/src/main/royale/org/apache/royale/net/utils/IExternalizable.as
copy to 
frameworks/projects/Network/src/main/royale/org/apache/royale/net/utils/IDataInput.as
index 19364f4..f3e4ce4 100644
--- 
a/frameworks/projects/Network/src/main/royale/org/apache/royale/net/utils/IExternalizable.as
+++ 
b/frameworks/projects/Network/src/main/royale/org/apache/royale/net/utils/IDataInput.as
@@ -18,13 +18,24 @@
 
////////////////////////////////////////////////////////////////////////////////
 package org.apache.royale.net.utils
 {
+    import org.apache.royale.utils.IBinaryDataInput;
+    COMPILE::SWF{
+        import flash.utils.IDataInput
+    }
+    
     /**
-     * replacement for flash.utils.IExternalizable
+     * initial work on replacement for flash.utils.IDataInput
      */
-    public interface IExternalizable
+    COMPILE::JS
+    public interface IDataInput extends IBinaryDataInput
     {
-        function readExternal(input:IDataInput):void;
-        
-        function writeExternal(output:IDataOutput):void;
+        function readObject():*;
     }
+       
+       COMPILE::SWF
+       public interface IDataInput extends IBinaryDataInput, 
flash.utils.IDataInput
+       {
+
+       }
+
 }
diff --git 
a/frameworks/projects/Network/src/main/royale/org/apache/royale/net/utils/IExternalizable.as
 
b/frameworks/projects/Network/src/main/royale/org/apache/royale/net/utils/IDataOutput.as
similarity index 66%
copy from 
frameworks/projects/Network/src/main/royale/org/apache/royale/net/utils/IExternalizable.as
copy to 
frameworks/projects/Network/src/main/royale/org/apache/royale/net/utils/IDataOutput.as
index 19364f4..98edd55 100644
--- 
a/frameworks/projects/Network/src/main/royale/org/apache/royale/net/utils/IExternalizable.as
+++ 
b/frameworks/projects/Network/src/main/royale/org/apache/royale/net/utils/IDataOutput.as
@@ -18,13 +18,28 @@
 
////////////////////////////////////////////////////////////////////////////////
 package org.apache.royale.net.utils
 {
+       import org.apache.royale.utils.IBinaryDataOutput;
+    COMPILE::SWF{
+        import flash.utils.IDataOutput
+    }
+
     /**
-     * replacement for flash.utils.IExternalizable
+     * initial work on replacement for flash.utils.IDataOutput
      */
-    public interface IExternalizable
+       COMPILE::JS
+    public interface IDataOutput extends IBinaryDataOutput
     {
-        function readExternal(input:IDataInput):void;
-        
-        function writeExternal(output:IDataOutput):void;
+
+        function writeObject(object:*):void;
     }
+       
+       
+       COMPILE::SWF
+       public interface IDataOutput extends IBinaryDataOutput, 
flash.utils.IDataOutput
+       {
+               /*function get objectEncoding():uint;
+               function set objectEncoding(value:uint):void;
+               function writeObject(object:*):void;*/
+       }
+
 }
diff --git 
a/frameworks/projects/Network/src/main/royale/org/apache/royale/net/utils/IExternalizable.as
 
b/frameworks/projects/Network/src/main/royale/org/apache/royale/net/utils/IExternalizable.as
index 19364f4..c9ee92d 100644
--- 
a/frameworks/projects/Network/src/main/royale/org/apache/royale/net/utils/IExternalizable.as
+++ 
b/frameworks/projects/Network/src/main/royale/org/apache/royale/net/utils/IExternalizable.as
@@ -18,13 +18,26 @@
 
////////////////////////////////////////////////////////////////////////////////
 package org.apache.royale.net.utils
 {
+    COMPILE::SWF{
+        import flash.utils.IExternalizable;
+    }
+    
     /**
      * replacement for flash.utils.IExternalizable
      */
+    COMPILE::JS
     public interface IExternalizable
     {
         function readExternal(input:IDataInput):void;
         
         function writeExternal(output:IDataOutput):void;
     }
+       
+       COMPILE::SWF
+       public interface IExternalizable extends flash.utils.IExternalizable
+       {
+               /*function readExternal(input:IDataInput):void;
+               
+               function writeExternal(output:IDataOutput):void;*/
+       }
 }
diff --git a/manualtests/UnitTests/src/main/royale/TestClasses.as 
b/manualtests/UnitTests/src/main/royale/TestClasses.as
index 336e258..61462dc 100644
--- a/manualtests/UnitTests/src/main/royale/TestClasses.as
+++ b/manualtests/UnitTests/src/main/royale/TestClasses.as
@@ -22,7 +22,7 @@ package
        import flexUnitTests.*;
 
 
-       public class TestClasses 
+       public class TestClasses
        {
                
                public static function get testClasses():Array {
@@ -30,7 +30,8 @@ package
                                                CoreTester,
                                                ReflectionTester,
                                                ObservedBugsTester,
-                                               JiraIssuesTester
+                                               GithubIssuesTester,
+                                               NetworkTester
                                        ];
                }
        }
diff --git 
a/manualtests/UnitTests/src/main/royale/flexUnitTests/JiraIssuesTester.as 
b/manualtests/UnitTests/src/main/royale/flexUnitTests/GithubIssuesTester.as
similarity index 93%
copy from 
manualtests/UnitTests/src/main/royale/flexUnitTests/JiraIssuesTester.as
copy to 
manualtests/UnitTests/src/main/royale/flexUnitTests/GithubIssuesTester.as
index fc37533..72b5ee1 100644
--- a/manualtests/UnitTests/src/main/royale/flexUnitTests/JiraIssuesTester.as
+++ b/manualtests/UnitTests/src/main/royale/flexUnitTests/GithubIssuesTester.as
@@ -18,12 +18,12 @@
 
////////////////////////////////////////////////////////////////////////////////
 package flexUnitTests
 {
-       import flexUnitTests.jira.*
+       import flexUnitTests.github.*
        
     [Suite]
     [RunWith("org.flexunit.runners.Suite")]
-    public class JiraIssuesTester
+    public class GithubIssuesTester
     {
-        
+    
     }
 }
diff --git 
a/manualtests/UnitTests/src/main/royale/flexUnitTests/JiraIssuesTester.as 
b/manualtests/UnitTests/src/main/royale/flexUnitTests/NetworkTester.as
similarity index 60%
rename from 
manualtests/UnitTests/src/main/royale/flexUnitTests/JiraIssuesTester.as
rename to manualtests/UnitTests/src/main/royale/flexUnitTests/NetworkTester.as
index fc37533..ef8e73b 100644
--- a/manualtests/UnitTests/src/main/royale/flexUnitTests/JiraIssuesTester.as
+++ b/manualtests/UnitTests/src/main/royale/flexUnitTests/NetworkTester.as
@@ -18,12 +18,26 @@
 
////////////////////////////////////////////////////////////////////////////////
 package flexUnitTests
 {
-       import flexUnitTests.jira.*
-       
+       import flexUnitTests.network.*
+
     [Suite]
     [RunWith("org.flexunit.runners.Suite")]
-    public class JiraIssuesTester
+    public class NetworkTester
     {
+        public function NetworkTester()
+        {
+            // for JS, force-link these classes in the output
+            var arr:Array = [AMFBinaryDataTesterTest];
+        }
         
+        // in JS, using a class as a type won't include the class in
+        // the output since types are not chcked in JS.  It is when
+        // the actual class is referenced that it will be included
+        // in the output.
+        // Is there a reason to use reflection to gather the set
+        // of tests?  I would think an array of tests would wokr
+        // better and allow you to define order.
+               public var amfBinaryDataTesterTest:AMFBinaryDataTesterTest;
+
     }
 }
diff --git 
a/manualtests/UnitTests/src/main/royale/flexUnitTests/jira/JiraTesterTest.as 
b/manualtests/UnitTests/src/main/royale/flexUnitTests/github/GithubTesterTest.as
similarity index 95%
rename from 
manualtests/UnitTests/src/main/royale/flexUnitTests/jira/JiraTesterTest.as
rename to 
manualtests/UnitTests/src/main/royale/flexUnitTests/github/GithubTesterTest.as
index c361f39..0cf850d 100644
--- a/manualtests/UnitTests/src/main/royale/flexUnitTests/jira/JiraTesterTest.as
+++ 
b/manualtests/UnitTests/src/main/royale/flexUnitTests/github/GithubTesterTest.as
@@ -16,13 +16,13 @@
 //  limitations under the License.
 //
 
////////////////////////////////////////////////////////////////////////////////
-package flexUnitTests.jira
+package flexUnitTests.github
 {
     import flexunit.framework.Assert;
 
     
-    public class JiraTesterTest
-    {          
+    public class GithubTesterTest
+    {
                public static var isJS:Boolean;
         [BeforeClass]
         public static function setUpBeforeClass():void
@@ -60,14 +60,14 @@ package flexUnitTests.jira
         
        
         /*
-               // TEST METHODS 
+               // TEST METHODS
                */
-        
+  
                //example, postfix the test method with JIRA issue reference:
         /*[Test]
         public function testJIRA_FLEX_9999():void
         {
 
-        }*/    
+        }*/
     }
 }
diff --git 
a/manualtests/UnitTests/src/main/royale/flexUnitTests/network/AMFBinaryDataTesterTest.as
 
b/manualtests/UnitTests/src/main/royale/flexUnitTests/network/AMFBinaryDataTesterTest.as
new file mode 100644
index 0000000..af446a8
--- /dev/null
+++ 
b/manualtests/UnitTests/src/main/royale/flexUnitTests/network/AMFBinaryDataTesterTest.as
@@ -0,0 +1,335 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+//  Licensed to the Apache Software Foundation (ASF) under one or more
+//  contributor license agreements.  See the NOTICE file distributed with
+//  this work for additional information regarding copyright ownership.
+//  The ASF licenses this file to You under the Apache License, Version 2.0
+//  (the "License"); you may not use this file except in compliance with
+//  the License.  You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+package flexUnitTests.network
+{
+       
+       
+       import flexUnitTests.network.support.TestClass1;
+       import flexUnitTests.network.support.TestClass2;
+       import flexUnitTests.network.support.TestClass3;
+       import flexUnitTests.network.support.DynamicTestClass;
+       
+       import flexunit.framework.Assert;
+    import org.apache.royale.net.remoting.amf.AMFBinaryData;
+       
+       import org.apache.royale.reflection.*;
+
+
+    public class AMFBinaryDataTesterTest
+       {
+
+               [Before]
+               public function setUp():void {
+               }
+
+               [After]
+               public function tearDown():void {
+               }
+
+               [BeforeClass]
+               public static function setUpBeforeClass():void {
+               }
+
+               [AfterClass]
+               public static function tearDownAfterClass():void {
+               }
+
+
+               //util check functions
+               private static function 
bytesMatchExpectedData(bd:AMFBinaryData,expected:Array,offset:int=0):Boolean{
+                       var len:uint = expected.length;
+                       var end:uint=offset+len;
+                       for (var i:int=offset;i<end;i++) {
+                               var check:uint = bd.readByteAt(i);
+                               if (expected[i-offset]!=check) {
+                                       // trace('failed at 
',i,expected[i-offset],check);
+                                       return false;
+                               }
+                       }
+                       return true;
+               }
+               
+               private static function 
dynamicKeyCountMatches(forObject:Object, expectedCount:uint):Boolean{
+                       var keyCount:uint=0;
+                       for (var key:String in forObject) {
+                               keyCount++;
+                       }
+                       return keyCount === expectedCount;
+                       
+               }
+
+               [Test]
+               public function testStringObjectEncoding():void{
+                       var ba:AMFBinaryData = new AMFBinaryData();
+                       var testString:String = 'testString';
+                       
+                       ba.writeObject(testString);
+                       
+                       Assert.assertEquals("post-write length was not 
correct", ba.length, 12);
+                       Assert.assertEquals("post-write position was not 
correct", ba.position, 12);
+                       ba.position = 0;
+                       var readString:String = ba.readObject() as String;
+                       Assert.assertEquals("post-write read of written string 
was not correct", readString, testString);
+               }
+               
+               [Test]
+               public function testBooleanObjectEncoding():void{
+                       var ba:AMFBinaryData = new AMFBinaryData();
+                       
+                       ba.writeObject(false);
+                       ba.writeObject(true);
+                       
+                       Assert.assertEquals("post-write length was not 
correct", ba.length, 2);
+                       Assert.assertEquals("post-write position was not 
correct", ba.position, 2);
+                       ba.position = 0;
+
+                       Assert.assertTrue("post-write read of written boolean 
was not correct", ba.readObject() === false);
+                       Assert.assertTrue("post-write read of written boolean 
was not correct", ba.readObject() === true);
+               }
+               
+               [Test]
+               public function testNumberEncoding():void{
+                       var ba:AMFBinaryData = new AMFBinaryData();
+                       
+                       
+                       ba.writeObject(NaN);
+                       ba.writeObject(1.0);
+                       ba.writeObject(-1.0);
+                       ba.writeObject(1.5);
+                       ba.writeObject(-1.5);
+                       ba.writeObject(Infinity);
+                       ba.writeObject(-Infinity);
+                       
+                       Assert.assertEquals("post-write length was not 
correct", ba.length, 52);
+                       Assert.assertEquals("post-write position was not 
correct", ba.position, 52);
+                       ba.position = 0;
+                       
+                       var num:Number = ba.readObject();
+                       Assert.assertTrue("post-write read of written Number 
was not correct", (num is Number));
+                       Assert.assertTrue("post-write read of written Number 
was not correct", isNaN(num));
+                       num = ba.readObject();
+                       Assert.assertTrue("post-write read of written Number 
was not correct", (num is Number));
+                       Assert.assertTrue("post-write read of written Number 
was not correct", num === 1.0);
+                       num = ba.readObject();
+                       Assert.assertTrue("post-write read of written Number 
was not correct", (num is Number));
+                       Assert.assertTrue("post-write read of written Number 
was not correct", num === -1.0);
+                       num = ba.readObject();
+                       Assert.assertTrue("post-write read of written Number 
was not correct", (num is Number));
+                       Assert.assertTrue("post-write read of written Number 
was not correct", num === 1.5);
+                       num = ba.readObject();
+                       Assert.assertTrue("post-write read of written Number 
was not correct", (num is Number));
+                       Assert.assertTrue("post-write read of written Number 
was not correct", num === -1.5);
+                       num = ba.readObject();
+                       Assert.assertTrue("post-write read of written Number 
was not correct", (num is Number));
+                       Assert.assertTrue("post-write read of written Number 
was not correct", !isFinite(num));
+                       Assert.assertTrue("post-write read of written Number 
was not correct", (num > 0));
+                       num = ba.readObject();
+                       Assert.assertTrue("post-write read of written Number 
was not correct", (num is Number));
+                       Assert.assertTrue("post-write read of written Number 
was not correct", !isFinite(num));
+                       Assert.assertTrue("post-write read of written Number 
was not correct", (num < 0));
+               }
+               
+               
+               [Test]
+               public function testArrayInstance():void {
+                       var ba:AMFBinaryData = new AMFBinaryData();
+                       var instance:Array = [];
+                       ba.writeObject(instance);
+
+                       Assert.assertEquals("post-write length was not 
correct", ba.length, 3);
+                       Assert.assertEquals("post-write position was not 
correct", ba.position, 3);
+                       
+                       instance = [99];
+                       ba.length = 0;
+                       ba.writeObject(instance);
+                       ba.position = 0;
+                       Assert.assertTrue("post-write bytes did not match 
expected data", bytesMatchExpectedData(ba,[9, 3, 1, 4, 99]));
+                       instance = ba.readObject() as Array;
+                       Assert.assertTrue("post-write read did not match 
expected result", instance.length == 1 && instance[0] == 99);
+                       //sparse array
+                       instance =[];
+                       instance[100]='100';
+                       ba.length = 0;
+                       ba.writeObject(instance);
+                       Assert.assertEquals("post-write length was not 
correct", ba.length, 9);
+                       Assert.assertEquals("post-write position was not 
correct", ba.position, 9);
+                       Assert.assertTrue("post-write bytes did not match 
expected data", bytesMatchExpectedData(ba,[9, 1, 7, 49, 48, 48, 6, 0, 1]));
+                       //check that read matches
+                       ba.position = 0;
+                       instance = ba.readObject();
+                       
+                       Assert.assertEquals("post-write read was not correct", 
instance.length, 101);
+                       Assert.assertEquals("post-write read was not correct", 
instance[100], '100');
+                       Assert.assertTrue("post-write read was not correct", 
instance[0] === undefined);
+                       //sparse with associative content
+                       instance=[];
+                       instance['test'] = true;
+                       instance[10] = 'I am number 10';
+                       ba.length = 0;
+                       ba.writeObject(instance);
+                       Assert.assertEquals("post-write length was not 
correct", ba.length, 28);
+                       Assert.assertEquals("post-write position was not 
correct", ba.position, 28);
+                       Assert.assertTrue("post-write bytes did not match 
expected data", bytesMatchExpectedData(ba,[9, 1, 5, 49, 48, 6, 29, 73, 32, 97, 
109, 32, 110, 117, 109, 98, 101, 114, 32, 49, 48, 9, 116, 101, 115, 116, 3, 
1]));
+                       
+                       //check that read matches
+                       ba.position = 0;
+                       instance = ba.readObject();
+                       Assert.assertEquals("post-write read was not correct", 
instance.length, 11);
+                       Assert.assertEquals("post-write read was not correct", 
instance[10], 'I am number 10');
+                       Assert.assertEquals("post-write read was not correct", 
instance['test'], true);
+                       Assert.assertTrue("post-write read was not correct", 
instance[0] === undefined);
+                       
+               }
+               
+               
+               [Test]
+               public function testAnonObject():void{
+                       var ba:AMFBinaryData = new AMFBinaryData();
+                       
+                       var instance:Object = {};
+                       ba.writeObject(instance);
+                       
+                       Assert.assertEquals("post-write length was not 
correct", ba.length, 4);
+                       Assert.assertEquals("post-write position was not 
correct", ba.position, 4);
+                       ba.position = 0;
+
+                       Assert.assertTrue("post-write bytes did not match 
expected data", bytesMatchExpectedData(ba,[10, 11, 1, 1]));
+                       instance = ba.readObject();
+                       Assert.assertTrue("post-write read did not match 
expected result", dynamicKeyCountMatches(instance, 0));
+                       
+                       var obj1:Object = {test:true};
+                       var obj2:Object = {test:'maybe'};
+                       var obj3:Object = {test:true};
+                       ba.length = 0;
+                       ba.writeObject([obj1, obj2, obj3]);
+                       ba.position = 0;
+                       Assert.assertTrue("post-write bytes did not match 
expected data", bytesMatchExpectedData(ba,[9, 7, 1, 10, 11, 1, 9, 116, 101, 
115, 116, 3, 1, 10, 1, 0, 6, 11, 109, 97, 121, 98, 101, 1, 10, 1, 0, 3, 1]));
+                       
+               }
+
+
+               [Test]
+               /**
+                * @royaleigrnorecoercion TestClass1
+                */
+               public function testBasicClassInstance():void
+               {
+                       var ba:AMFBinaryData = new AMFBinaryData();
+                       
+                       var instance:TestClass1 = new TestClass1();
+                       ba.writeObject(instance);
+                       
+                       Assert.assertEquals("post-write length was not 
correct", ba.length, 16);
+                       Assert.assertEquals("post-write position was not 
correct", ba.position, 16);
+                       
+                       ba.position = 0;
+                       Assert.assertTrue("post-write bytes did not match 
expected data", bytesMatchExpectedData(ba,[10, 19, 1, 21, 116, 101, 115, 116, 
70, 105, 101, 108, 100, 49, 6, 1]));
+                       ba.position = 0;
+                       
+                       var anonObject:Object = ba.readObject();
+                       
+                       Assert.assertTrue('post-write read did not match 
expected value', anonObject['testField1'] === instance.testField1 );
+                       
+                       var multipleDifferentInstances:Array = [new 
TestClass1(), new TestClass2()];
+                       ba.length = 0;
+                       ba.writeObject(multipleDifferentInstances);
+                       
+                       Assert.assertEquals("post-write length was not 
correct", ba.length, 24);
+                       Assert.assertEquals("post-write position was not 
correct", ba.position, 24);
+                       ba.position = 0;
+                       
+                       Assert.assertTrue("post-write bytes did not match 
expected data", bytesMatchExpectedData(ba,[9, 5, 1, 10, 19, 1, 21, 116, 101, 
115, 116, 70, 105, 101, 108, 100, 49, 6, 1, 10, 19, 1, 0, 3]));
+                       
+               }
+
+               [Test]
+               public function testDynamicClassInstance():void
+               {
+                       var ba:AMFBinaryData = new AMFBinaryData();
+                       var instance:DynamicTestClass = new DynamicTestClass();
+                       ba.writeObject(instance);
+                       
+                       Assert.assertEquals("post-write length was not 
correct", ba.length, 25);
+                       Assert.assertEquals("post-write position was not 
correct", ba.position, 25);
+                       ba.position = 0;
+                       Assert.assertTrue("post-write bytes did not match 
expected data", bytesMatchExpectedData(ba,[10, 27, 1, 39, 115, 101, 97, 108, 
101, 100, 73, 110, 115, 116, 97, 110, 99, 101, 80, 114, 111, 112, 49, 2, 1]));
+                       
+                       instance['someDynamicField'] = 'nonSealedPropValue';
+                       
+                       ba.writeObject(instance);
+                       Assert.assertEquals("post-write length was not 
correct", ba.length, 62);
+                       Assert.assertEquals("post-write position was not 
correct", ba.position, 62);
+                       ba.position = 0;
+                       Assert.assertTrue("post-write bytes did not match 
expected data", bytesMatchExpectedData(ba,[10, 27, 1, 39, 115, 101, 97, 108, 
101, 100, 73, 110, 115, 116, 97, 110, 99, 101, 80, 114, 111, 112, 49, 2, 33, 
115, 111, 109, 101, 68, 121, 110, 97, 109, 105, 99, 70, 105, 101, 108, 100, 6, 
37, 110, 111, 110, 83, 101, 97, 108, 101, 100, 80, 114, 111, 112, 86, 97, 108, 
117, 101, 1]));
+                       
+                       var instanceAnon:Object = ba.readObject();
+                       Assert.assertTrue('post-write read did not match 
expected value', instanceAnon['someDynamicField'] === 'nonSealedPropValue' );
+                       
+                       
+               }
+
+
+               [Test]
+               public function testExternalizable():void
+               {
+                       var ba:AMFBinaryData = new AMFBinaryData();
+                       var test3:TestClass3 = new TestClass3();
+                       //TestClass3 is externalizable and does not have an 
alias, this is an error in flash
+                       
+                       var err:Error;
+                       try {
+                               ba.writeObject(test3);
+                       } catch(e:Error) {
+                               err = e;
+                       }
+
+                       Assert.assertTrue("externalizable writing should fail 
without an alias registered", err != null);
+                       Assert.assertEquals("post-write error length was not 
correct", ba.length, 1);
+                       Assert.assertEquals("post-write error position was not 
correct", ba.position, 1);
+                       ba.position = 0;
+                       Assert.assertTrue("post-write bytes did not match 
expected data", bytesMatchExpectedData(ba,[10]));
+                       
+                       ba.length=0;
+                       //register an alias
+                       registerClassAlias('TestClass3', TestClass3);
+                       ba.writeObject(test3);
+                       Assert.assertEquals("post-write length was not 
correct", ba.length, 18);
+                       Assert.assertEquals("post-write position was not 
correct", ba.position, 18);
+                       
+                       ba.position = 0;
+                       Assert.assertTrue("post-write bytes did not match 
expected data", bytesMatchExpectedData(ba,[10, 7, 21, 84, 101, 115, 116, 67, 
108, 97, 115, 115, 51, 9, 3, 1, 6, 0]));
+                       
+                       test3.content[0] = 
(test3.content[0]).split("").reverse().join("");
+                       ba.writeObject(test3);
+                       Assert.assertEquals("post-write length was not 
correct", ba.length, 28);
+                       Assert.assertEquals("post-write position was not 
correct", ba.position, 28);
+                       Assert.assertTrue("post-write bytes did not match 
expected data", bytesMatchExpectedData(ba,[10, 7, 21, 84, 101, 115, 116, 67, 
108, 97, 115, 115, 51, 9, 3, 1, 6, 21, 51, 115, 115, 97, 108, 67, 116, 115, 
101, 84]));
+                       
+                       ba.position=0;
+                       var test3Read:TestClass3 = ba.readObject() as 
TestClass3;
+
+                       //proof that it created a new instance, and that the 
reversed content string content is present in the new instance
+                       Assert.assertTrue("post-write read did not match 
expected data", test3Read.content[0] == test3.content[0]);
+                       
+               }
+
+       
+               
+       }
+}
diff --git a/manualtests/UnitTests/src/main/royale/TestClasses.as 
b/manualtests/UnitTests/src/main/royale/flexUnitTests/network/support/DynamicTestClass.as
similarity index 65%
copy from manualtests/UnitTests/src/main/royale/TestClasses.as
copy to 
manualtests/UnitTests/src/main/royale/flexUnitTests/network/support/DynamicTestClass.as
index 336e258..2032bc0 100644
--- a/manualtests/UnitTests/src/main/royale/TestClasses.as
+++ 
b/manualtests/UnitTests/src/main/royale/flexUnitTests/network/support/DynamicTestClass.as
@@ -16,22 +16,28 @@
 //  limitations under the License.
 //
 
////////////////////////////////////////////////////////////////////////////////
-package
+package flexUnitTests.network.support
 {
-       //test groups
-       import flexUnitTests.*;
 
 
-       public class TestClasses 
+
+       dynamic public class DynamicTestClass
        {
+               //Note: do not change this test class unless you change the 
related tests to
+               //support any changes that might appear when testing with it
+               
+
+               public var sealedInstanceProp1:Boolean;
                
-               public static function get testClasses():Array {
-                       return [
-                                               CoreTester,
-                                               ReflectionTester,
-                                               ObservedBugsTester,
-                                               JiraIssuesTester
-                                       ];
+               
+               /*private var _sealedInstanceAccessor1:String;
+               public function get sealedInstanceAccessor1():String{
+                       return _sealedInstanceAccessor1;
                }
+               
+               public function set sealedInstanceAccessor1(value:String):void{
+                       _sealedInstanceAccessor1 = value;
+               }*/
+
        }
 }
diff --git a/manualtests/UnitTests/src/main/royale/TestClasses.as 
b/manualtests/UnitTests/src/main/royale/flexUnitTests/network/support/TestClass1.as
similarity index 80%
copy from manualtests/UnitTests/src/main/royale/TestClasses.as
copy to 
manualtests/UnitTests/src/main/royale/flexUnitTests/network/support/TestClass1.as
index 336e258..ce78f96 100644
--- a/manualtests/UnitTests/src/main/royale/TestClasses.as
+++ 
b/manualtests/UnitTests/src/main/royale/flexUnitTests/network/support/TestClass1.as
@@ -16,22 +16,21 @@
 //  limitations under the License.
 //
 
////////////////////////////////////////////////////////////////////////////////
-package
+package flexUnitTests.network.support
 {
-       //test groups
-       import flexUnitTests.*;
-
-
-       public class TestClasses 
+       
+       public class TestClass1
        {
-               
-               public static function get testClasses():Array {
-                       return [
-                                               CoreTester,
-                                               ReflectionTester,
-                                               ObservedBugsTester,
-                                               JiraIssuesTester
-                                       ];
+               public function TestClass1()
+               {
                }
+               
+               public var testField1:String = '';
+               //public var testField2:Boolean;
+               //public var testField3:Number;
+               /*public var testField4:Function;*/
+               
+
+
        }
 }
diff --git a/manualtests/UnitTests/src/main/royale/TestClasses.as 
b/manualtests/UnitTests/src/main/royale/flexUnitTests/network/support/TestClass2.as
similarity index 71%
copy from manualtests/UnitTests/src/main/royale/TestClasses.as
copy to 
manualtests/UnitTests/src/main/royale/flexUnitTests/network/support/TestClass2.as
index 336e258..69154fc 100644
--- a/manualtests/UnitTests/src/main/royale/TestClasses.as
+++ 
b/manualtests/UnitTests/src/main/royale/flexUnitTests/network/support/TestClass2.as
@@ -16,22 +16,23 @@
 //  limitations under the License.
 //
 
////////////////////////////////////////////////////////////////////////////////
-package
+package flexUnitTests.network.support
 {
-       //test groups
-       import flexUnitTests.*;
 
-
-       public class TestClasses 
+       
+       public class TestClass2
        {
+               //Note: do not change this test class unless you change the 
related tests to
+               //support any changes that might appear when testing reflection 
into it
                
-               public static function get testClasses():Array {
-                       return [
-                                               CoreTester,
-                                               ReflectionTester,
-                                               ObservedBugsTester,
-                                               JiraIssuesTester
-                                       ];
+               public function TestClass2(){
+
                }
+               
+               
+               public var testField1:Boolean = true;
+               //public var testField2:Boolean;
+               //public var testField3:Number;
+               /*public var testField4:Function;*/
        }
 }
diff --git a/manualtests/UnitTests/src/main/royale/TestClasses.as 
b/manualtests/UnitTests/src/main/royale/flexUnitTests/network/support/TestClass3.as
similarity index 60%
copy from manualtests/UnitTests/src/main/royale/TestClasses.as
copy to 
manualtests/UnitTests/src/main/royale/flexUnitTests/network/support/TestClass3.as
index 336e258..715ad0c 100644
--- a/manualtests/UnitTests/src/main/royale/TestClasses.as
+++ 
b/manualtests/UnitTests/src/main/royale/flexUnitTests/network/support/TestClass3.as
@@ -16,22 +16,35 @@
 //  limitations under the License.
 //
 
////////////////////////////////////////////////////////////////////////////////
-package
+package flexUnitTests.network.support
 {
-       //test groups
-       import flexUnitTests.*;
-
-
-       public class TestClasses 
+       import org.apache.royale.net.utils.IExternalizable;
+       COMPILE::JS{
+               import org.apache.royale.net.utils.IDataInput;
+               import org.apache.royale.net.utils.IDataOutput;
+       }
+       
+       COMPILE::SWF{
+               import flash.utils.IDataInput;
+               import flash.utils.IDataOutput;
+       }
+       
+       
+       public class TestClass3 implements IExternalizable
        {
                
-               public static function get testClasses():Array {
-                       return [
-                                               CoreTester,
-                                               ReflectionTester,
-                                               ObservedBugsTester,
-                                               JiraIssuesTester
-                                       ];
+               public var content:Array=["TestClass3"];
+               
+               
+               public function readExternal(input:IDataInput):void{
+                       var content:Array = input.readObject() as Array;
+                       this.content = content;
+               }
+               
+               public function writeExternal(output:IDataOutput):void {
+                       output.writeObject(content);
                }
+       
        }
+       
 }
diff --git a/manualtests/UnitTests/testsview/image/apache-royale-main-logo.png 
b/manualtests/UnitTests/testsview/image/apache-royale-main-logo.png
new file mode 100644
index 0000000..fd7a201
Binary files /dev/null and 
b/manualtests/UnitTests/testsview/image/apache-royale-main-logo.png differ
diff --git a/manualtests/UnitTests/testsview/index.html 
b/manualtests/UnitTests/testsview/index.html
index 2806402..9370b27 100644
--- a/manualtests/UnitTests/testsview/index.html
+++ b/manualtests/UnitTests/testsview/index.html
@@ -60,6 +60,7 @@
                        border: 0;
                        margin: 0;
                        padding: 0;
+                       border-radius:0;
                }
                .titleContent {
                        white-space:nowrap;
@@ -124,7 +125,7 @@
 <body class="pageStyles">
        <div>
                <div >
-                       <img class="logo" src="image/Royale.png" alt="Apache 
Royale logo">
+                       <img class="logo" 
src="image/apache-royale-main-logo.png" alt="Apache Royale logo">
                        <div class="titleContent">
                                <h1>Royale Framework Development Unit Tests</h1>
                        </div>

Reply via email to