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 32555dea1f1b661f95f36c1f2b1beb9d9c2251fb Author: greg-dove <[email protected]> AuthorDate: Wed Apr 6 13:43:57 2022 +1200 Fix for an issue encountered with ObjectUtil.clone for Strings. Related: restored some commented-out code in UIDUtil. Added some initial ObjectUtil cloning tests. --- .../src/main/royale/mx/utils/ObjectUtil.as | 22 +++++++++- .../src/main/royale/mx/utils/UIDUtil.as | 13 +++--- .../flexUnitTests/mxroyale/ObjectUtilTest.as | 47 ++++++++++++++++++---- 3 files changed, 68 insertions(+), 14 deletions(-) diff --git a/frameworks/projects/MXRoyaleBase/src/main/royale/mx/utils/ObjectUtil.as b/frameworks/projects/MXRoyaleBase/src/main/royale/mx/utils/ObjectUtil.as index 48d18c0abc..4392fa0ad2 100644 --- a/frameworks/projects/MXRoyaleBase/src/main/royale/mx/utils/ObjectUtil.as +++ b/frameworks/projects/MXRoyaleBase/src/main/royale/mx/utils/ObjectUtil.as @@ -199,13 +199,31 @@ public class ObjectUtil return result; } + /** + * Helper to abstract some VM-level differences + * @param value + * @return true if the value argument has a 'uid' property + */ + private static function isUIDObject(value:Object):Boolean{ + var ret:Boolean = false; + COMPILE::JS{ + //in JS, the getter/setter for 'uid' is not considered an 'own' property, in SWF, it is, so we check also in the prototype chain if needed + ret = (value && (value.hasOwnProperty("uid") || ("uid" in value.constructor.prototype))) + } + COMPILE::SWF{ + ret = (value && value.hasOwnProperty("uid")); + } + return ret; + } + /** * Recursive helper used by the public clone method. * @private */ private static function cloneInternal(result:Object, value:Object):void { - if (value && /*value.hasOwnProperty*/("uid" in value)) + + if (isUIDObject(value)) result.uid = value.uid; var classInfo:Object = getClassInfo(value); @@ -214,7 +232,7 @@ public class ObjectUtil { //@todo the following 'v = value[p]' will only be emulated safely in js by using reflection library: v = value[p]; - if (v && /*v.hasOwnProperty*/("uid" in v)) + if (isUIDObject(v)) cloneInternal(result[p], v); } } diff --git a/frameworks/projects/MXRoyaleBase/src/main/royale/mx/utils/UIDUtil.as b/frameworks/projects/MXRoyaleBase/src/main/royale/mx/utils/UIDUtil.as index f6f3cc5798..b0fb4465d8 100644 --- a/frameworks/projects/MXRoyaleBase/src/main/royale/mx/utils/UIDUtil.as +++ b/frameworks/projects/MXRoyaleBase/src/main/royale/mx/utils/UIDUtil.as @@ -198,7 +198,11 @@ public class UIDUtil IUID(item).uid = result; } } - else if ((item is IPropertyChangeNotifier) && + //(GD) commented out the following 'else if' clause because I don't expect it should ever execute + // why: IPropertyChangeNotifier extends IUID, so any such item will have already passed the (item is IUID) check and caused previous code block to execute instead) + // therefore the (item is IPropertyChangeNotifier) check should always be false in 'else if' below + //@todo check this against Flex: + /*else if ((item is IPropertyChangeNotifier) && !(item is IUIComponent)) { result = IPropertyChangeNotifier(item).uid; @@ -207,7 +211,7 @@ public class UIDUtil result = createUID(); IPropertyChangeNotifier(item).uid = result; } - } + }*/ else if (item is String) { return item as String; @@ -221,7 +225,7 @@ public class UIDUtil if (item is XMLList && item.length == 1) item = item[0]; - /* LATER + if (item is XML) { // XML nodes carry their UID on the @@ -255,7 +259,6 @@ public class UIDUtil } else { - */ if ("mx_internal_uid" in item) return item['mx_internal_uid'] @@ -283,7 +286,7 @@ public class UIDUtil } } } - //} + } } catch(e:Error) { diff --git a/frameworks/projects/MXRoyaleBase/src/test/royale/flexUnitTests/mxroyale/ObjectUtilTest.as b/frameworks/projects/MXRoyaleBase/src/test/royale/flexUnitTests/mxroyale/ObjectUtilTest.as index 7c2bc51718..4a1797ae14 100644 --- a/frameworks/projects/MXRoyaleBase/src/test/royale/flexUnitTests/mxroyale/ObjectUtilTest.as +++ b/frameworks/projects/MXRoyaleBase/src/test/royale/flexUnitTests/mxroyale/ObjectUtilTest.as @@ -21,8 +21,9 @@ package flexUnitTests.mxroyale import mx.utils.ObjectUtil; - - import org.apache.royale.test.asserts.*; +import mx.utils.UIDUtil; + +import org.apache.royale.test.asserts.*; import flexUnitTests.mxroyale.support.*; //import testshim.RoyaleUnitTestRunner; @@ -357,12 +358,44 @@ package flexUnitTests.mxroyale } - /*[Test] + [Test] public function testCloning():void{ - var item:TestClass6 = new TestClass6(); - - - }*/ + var s:String = "myString"; + + var out:Object = ObjectUtil.clone(s); + + assertStrictlyEquals(s, out, 'unexpected String clone result'); + + var obj:Object = { test:'test'}; + var inJSON:String = JSON.stringify(obj); + out = ObjectUtil.clone(obj); + assertStrictlyEquals(inJSON, JSON.stringify(out), 'unexpected dyn Object clone result'); + + UIDUtil.getUID(obj); + out = ObjectUtil.clone(obj); + //field order variation means JSON is not a valid way to compare: + assertTrue(simpleObjectCheckFields(obj, out), 'unexpected dyn Object clone result'); + + } + + private static function simpleObjectCheckFields(obj1:Object, obj2:Object):Boolean{ + if (obj1) { + if (!obj2) return false; + if (obj1 is String || obj1 is Number || obj1 is Boolean) return obj1 === obj2; + var obj1Count:uint = 0; + for (var field:String in obj1) { + if (obj1[field] !== obj2[field]) return false; + obj1Count++; + } + for (field in obj1) { + obj1Count--; + } + if (obj1Count != 0) return false //mismatched field count + } else { + if (obj2) return false; + } + return true; + } } }
