You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@royale.apache.org by gr...@apache.org on 2020/05/28 11:48:24 UTC
[royale-asjs] 01/05: AMF improvements: Coverage for ignoring custom
namespaces and also cases where Transient fields are still deserialized.
They are only skipped during local serialization.
This is an automated email from the ASF dual-hosted git repository.
gregdove pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/royale-asjs.git
commit db0995ea20121a7e0490627592367473248266f9
Author: greg-dove <gr...@gmail.com>
AuthorDate: Thu May 28 16:36:51 2020 +1200
AMF improvements: Coverage for ignoring custom namespaces and also cases where Transient fields are still deserialized. They are only skipped during local serialization.
---
.../royale/net/remoting/amf/AMFBinaryData.as | 41 +++++---
.../network/AMFBinaryDataTesterTest.as | 109 ++++++++++++++++++++-
.../flexUnitTests/network/support/TestClass6.as | 72 ++++++++++++++
.../flexUnitTests/network/support/TestClass7a.as | 51 ++++++++++
.../flexUnitTests/network/support/TestClass7b.as | 49 +++++++++
.../flexUnitTests/network/support/testnamespace.as | 26 +++++
6 files changed, 334 insertions(+), 14 deletions(-)
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
index 3eb6955..89350f4 100644
--- 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
@@ -499,6 +499,7 @@ class SerializationContext extends BinaryData implements IDataInput, IDataOutpu
var l:uint;
var metas:Array;
var exclude:Boolean;
+ var transient:Boolean;
var fieldName:String;
const into:Array = localTraits.props;
@@ -509,9 +510,11 @@ class SerializationContext extends BinaryData implements IDataInput, IDataOutpu
if (fieldName.indexOf('::') != -1) continue;
var field:Object = fieldSet[fieldName];
exclude = false;
+ transient = false;
+ var alreadyPresent:Boolean = into.indexOf(fieldName) != -1 ;
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
+ if (exclude && !alreadyPresent) { //<-- 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
@@ -524,21 +527,18 @@ class SerializationContext extends BinaryData implements IDataInput, IDataOutpu
}
}
}
- if (!exclude && excludeTransient && field.metadata != null) {
- //exclude anything marked as Transient
+ //if a subclass override does not redeclare the field as transient, then it is already considered explicitly 'non-transient'
+ if (!exclude && !alreadyPresent && excludeTransient && field.metadata != null) {
+ //we need to mark Transient fields as special case
metas = field.metadata();
l = metas.length;
while (l--) {
if (metas[l].name == 'Transient') {
- exclude = true;
+ transient = true;
+ Traits.markTransient(fieldName, localTraits);
+ break;
}
}
- 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)
@@ -554,7 +554,10 @@ class SerializationContext extends BinaryData implements IDataInput, IDataOutpu
} else {
nullValues[fieldName] = null;
}
- into.push(fieldName);
+ if (alreadyPresent) {
+ into.splice(into.indexOf(fieldName), 1);
+ }
+ if (!transient) into.push(fieldName);
if (asAccessors) {
localTraits.getterSetters[fieldName] = Traits.createInstanceAccessorGetterSetter(fieldName);
} else {
@@ -610,6 +613,9 @@ class SerializationContext extends BinaryData implements IDataInput, IDataOutpu
classInfo = c.constructor.superClass_.ROYALE_CLASS_INFO;
c = c.constructor.superClass_;
}
+ //sometimes flash native seriazliation double-counts props and outputs some props data twice.
+ //this can happen with overrides (it was noticed with Transient overrides)
+ //it may mean that js amf output can sometimes be more compact, but should always deserialize to the same result.
localTraits.count = localTraits.props.length;
//not required, but useful when testing:
localTraits.props.sort();
@@ -632,7 +638,6 @@ class SerializationContext extends BinaryData implements IDataInput, IDataOutpu
}
//not required, but useful when testing:
localTraits.props.sort();
-
}
return localTraits;
}
@@ -1102,7 +1107,7 @@ class SerializationContext extends BinaryData implements IDataInput, IDataOutpu
for (var i:uint = 0; i < l; i++) {
var fieldValue:* = readObject();
var prop:String = decodedTraits.props[i];
- hasProp = localTraits && (localTraits.hasProp(prop) || localTraits.isDynamic);
+ hasProp = localTraits && (localTraits.hasProp(prop) || localTraits.isDynamic || localTraits.isTransient(prop));
if (hasProp) {
localTraits.getterSetters[prop].setValue(obj, fieldValue);
} else {
@@ -1319,6 +1324,11 @@ class Traits {
}
};
}
+
+ public static function markTransient(fieldName:String, traits:Traits):void{
+ if (!traits.transients) traits.transients={};
+ traits.transients[fieldName] = true;
+ }
private static var _emtpy_object:Traits;
@@ -1362,10 +1372,15 @@ class Traits {
public var nullValues:Object = {};
public var getterSetters:Object = {};
+ public var transients:Object ;
public function hasProp(prop:String):Boolean {
return props.indexOf(prop) != -1;
}
+
+ public function isTransient(prop:String):Boolean {
+ return transients && prop in transients;
+ }
public function toString():String {
if (goog.DEBUG) {
diff --git a/frameworks/projects/Network/src/test/royale/flexUnitTests/network/AMFBinaryDataTesterTest.as b/frameworks/projects/Network/src/test/royale/flexUnitTests/network/AMFBinaryDataTesterTest.as
index 144d034..1cca14c 100644
--- a/frameworks/projects/Network/src/test/royale/flexUnitTests/network/AMFBinaryDataTesterTest.as
+++ b/frameworks/projects/Network/src/test/royale/flexUnitTests/network/AMFBinaryDataTesterTest.as
@@ -27,7 +27,9 @@ package flexUnitTests.network
import flexUnitTests.network.support.TestClass3;
import flexUnitTests.network.support.TestClass4;
import flexUnitTests.network.support.DynamicTestClass;
-
+ import flexUnitTests.network.support.TestClass6;
+ import flexUnitTests.network.support.TestClass7a;
+ import flexUnitTests.network.support.TestClass7b;
import org.apache.royale.test.asserts.*;
import org.apache.royale.net.remoting.amf.AMFBinaryData;
@@ -532,6 +534,111 @@ package flexUnitTests.network
//javascript toXMLString pretty printing does not match exactly flash...
assertTrue( xml.toXMLString() === xml2.toXMLString(), "XML round-tripping failed");
}
+
+
+ [Test]
+ public function testWithCustomNS():void
+ {
+ var ba:AMFBinaryData = new AMFBinaryData();
+ var test:TestClass6 = new TestClass6();
+ ba.writeObject(test);
+ ba.position = 0;
+ assertEquals(ba.length, 50, 'unexpected serialized content with custom namespaces');
+ //cover variation in order
+ const validOptions:Array = [
+ '0a23010b6d79566172156d794163636573736f7206177075626c69634d79566172061f7075626c6963206163636573736f72',
+ '0a2301156d794163636573736f720b6d79566172061f7075626c6963206163636573736f7206177075626c69634d79566172'
+ ];
+
+ assertTrue(validOptions.indexOf(getBytesOut(ba)) != -1, 'unexpected byte content with custom namespace content');
+
+ /* var restored:Object = ba.readObject();
+
+ var json:String = JSON.stringify(restored)*/
+ //order may be different... need json object check here for: {"myAccessor":"public accessor","myVar":"publicMyVar"}
+ }
+
+ [Test]
+ public function testTransientAndBindable():void{
+ var ba:AMFBinaryData = new AMFBinaryData();
+ registerClassAlias('TestClass7a', TestClass7a);
+ registerClassAlias('TestClass7b', TestClass7b);
+ var test1:TestClass7a = new TestClass7a();
+ test1.something = 'whatever';
+ ba.writeObject(test1);
+
+ ba.position = 0;
+
+ var retrieved:Object = ba.readObject();
+
+ assertTrue(retrieved is TestClass7a, 'unexpected deserialization');
+
+ var test2:TestClass7b = new TestClass7b();
+ test1.something = 'whatever';
+ ba.length = 0;
+ ba.writeObject(test2);
+
+ ba.position = 0;
+ retrieved = ba.readObject();
+
+ assertTrue(retrieved is TestClass7b, 'unexpected deserialization');
+
+ }
+
+
+ [Test]
+ public function testTransientDeserialized():void{
+ //if a transient field is already serialized, then we do deserialize it
+ //this means it can be sent from the server (for example) but is not sent to the server
+
+ //to test this we will use TestClass7b (where 'something' is not Transient) which will serialize the 'something' field with an alias that matches
+ //a subsequent deserialization to a TestClass7a instance (where 'something' is Transient);
+ //the expected result will be that the Transient field is still deserialized
+
+ var ba:AMFBinaryData = new AMFBinaryData();
+ registerClassAlias('TestClass7a', TestClass7b);
+ var test1:TestClass7b = new TestClass7b();
+ test1.something = 'something interesting';
+ ba.length = 0;
+ //non-transient inbound:
+ ba.writeObject(test1);
+
+ //The bytes for the above can differ between swf and js. 54 vs. 57 bytes length
+ //It is possible to correct that. But it is the swf output that is serializing the 'something' field twice
+ // (second time is string ref for both field and value, so quite compact, but still unnecessary)
+ //so not trying to match that exactly, because it is redundant data.
+
+ ba.position = 0;
+
+ //read it back as TestClass7a
+ registerClassAlias('TestClass7a', TestClass7a);
+
+ var retrieved:Object = ba.readObject();
+
+
+ assertTrue(retrieved is TestClass7a, 'unexpected deserialization');
+ assertEquals(retrieved.something , 'something interesting', 'unexpected deserialization');
+ assertEquals(retrieved.test , 'test', 'unexpected deserialization');
+
+ //this time round it won't be read out because it is Transient for serialization/inbound:
+ ba.position = 0;
+ ba.length=0;
+ ba.writeObject(retrieved);
+ ba.position = 0;
+ retrieved = ba.readObject();
+ assertTrue(retrieved is TestClass7a, 'unexpected deserialization');
+ assertEquals(retrieved.something , null, 'unexpected deserialization');
+ assertEquals(retrieved.test , 'test', 'unexpected deserialization');
+ }
+
+
+ private function getBytesOut(bytes:AMFBinaryData):String{
+ var out:Array = [];
+ for each(var byte:uint in bytes) {
+ out.push(('0'+byte.toString(16)).substr(-2));
+ }
+ return out.join('');
+ }
}
}
diff --git a/frameworks/projects/Network/src/test/royale/flexUnitTests/network/support/TestClass6.as b/frameworks/projects/Network/src/test/royale/flexUnitTests/network/support/TestClass6.as
new file mode 100644
index 0000000..42a1e3c
--- /dev/null
+++ b/frameworks/projects/Network/src/test/royale/flexUnitTests/network/support/TestClass6.as
@@ -0,0 +1,72 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.support
+{
+
+ import flexUnitTests.network.support.testnamespace;
+
+ /**
+ * @royalesuppresspublicvarwarning
+ */
+ public class TestClass6
+ {
+ //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 function TestClass6()
+ {
+
+ }
+
+
+ public var myVar:String = 'publicMyVar';
+
+ testnamespace var myVar:String = 'testnamespaceMyVar';
+
+ public function myMethod():String{
+ return 'public myMethod';
+ }
+
+ testnamespace function myMethod():String{
+ return 'testnamespace myMethod';
+ }
+
+ private var _v:String = 'public accessor';
+ public function get myAccessor():String{
+ return _v;
+ }
+
+ public function set myAccessor(value:String):void{
+ _v = value;
+ }
+
+ private var _v2:String = 'testnamespace accessor';
+ testnamespace function get myAccessor():String{
+ return _v2;
+ }
+
+ testnamespace function set myAccessor(value:String):void{
+ _v2 = value;
+ }
+
+
+ }
+
+
+}
diff --git a/frameworks/projects/Network/src/test/royale/flexUnitTests/network/support/TestClass7a.as b/frameworks/projects/Network/src/test/royale/flexUnitTests/network/support/TestClass7a.as
new file mode 100644
index 0000000..db6ec8b
--- /dev/null
+++ b/frameworks/projects/Network/src/test/royale/flexUnitTests/network/support/TestClass7a.as
@@ -0,0 +1,51 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.support
+{
+
+ import flexUnitTests.network.support.testnamespace;
+
+ /**
+ * @royalesuppresspublicvarwarning
+ */
+ public class TestClass7a
+ {
+ //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 function TestClass7a()
+ {
+
+ }
+
+ public var test:String = 'test';
+
+ protected var _something:String;
+ [Transient]
+ public function get something():String{
+ return _something;
+ }
+ public function set something(value:String):void{
+ _something = value;
+ }
+
+ }
+
+
+}
diff --git a/frameworks/projects/Network/src/test/royale/flexUnitTests/network/support/TestClass7b.as b/frameworks/projects/Network/src/test/royale/flexUnitTests/network/support/TestClass7b.as
new file mode 100644
index 0000000..39b5f7d
--- /dev/null
+++ b/frameworks/projects/Network/src/test/royale/flexUnitTests/network/support/TestClass7b.as
@@ -0,0 +1,49 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.support
+{
+
+ import flexUnitTests.network.support.testnamespace;
+
+ /**
+ * @royalesuppresspublicvarwarning
+ */
+ public class TestClass7b extends TestClass7a
+ {
+ //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 function TestClass7b()
+ {
+
+ }
+
+
+ [Bindable]
+ override public function get something():String{
+ return _something;
+ }
+ override public function set something(value:String):void{
+ _something = value;
+ }
+
+ }
+
+
+}
diff --git a/frameworks/projects/Network/src/test/royale/flexUnitTests/network/support/testnamespace.as b/frameworks/projects/Network/src/test/royale/flexUnitTests/network/support/testnamespace.as
new file mode 100644
index 0000000..3a552b8
--- /dev/null
+++ b/frameworks/projects/Network/src/test/royale/flexUnitTests/network/support/testnamespace.as
@@ -0,0 +1,26 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.support
+{
+
+
+
+ public namespace testnamespace = 'http://testnamespace.com/network';
+
+}