For XML and ObjectProxy - true, and for Proxy - false, according to the new unit tests I just committed. Does that look all right? I've never used the Proxy class, and although in the docs it looks like it's not marked as dynamic (as opposed to ObjectProxy, which is), it does provide some pretty dynamic functionality... And yes, the current implementation of isDynamicObject, as donated by Adobe, seems faster (though I haven't tested it) than describeType, so, if it yields correct results, I'd be in favour of keeping it this way.
On 18 February 2016 at 14:26, Mihai Chira <mihai.ch...@gmail.com> wrote: > hey Alex, just letting you know I'll get back to you on Monday, when > I'm working again. > > On 18 February 2016 at 07:32, Alex Harui <aha...@adobe.com> wrote: >> Looks like some nice new capabilities for ArrayUtil and ObjectUtil. Did >> you rule out using describeType for isDynamicObject? I know it is slow, >> but it should always be right. What should isDynamicObject return for >> XML, Proxy and ObjectProxy? >> >> Thanks, >> -Alex >> >> On 2/17/16, 8:00 AM, "mih...@apache.org" <mih...@apache.org> wrote: >> >>>FLEX-35031 >>>-Since I'm planning to use ObjectUtil.isDynamicObject() in the fix, I >>>wanted to unit test it. >>>-Also, I introduced a new function in ObjectUtil to be used in the >>>solution, getEnumerableProperties(), which returns all the dynamic >>>properties of an object. In order to unit test this new method I needed a >>>function with which to compare Arrays. So I added it to ArrayUtil, >>>including the unit tests needed to validate it. >>>-Also edited an asdoc entry and renamed a function parameter. >>> >>> >>>Project: http://git-wip-us.apache.org/repos/asf/flex-sdk/repo >>>Commit: http://git-wip-us.apache.org/repos/asf/flex-sdk/commit/680b405d >>>Tree: http://git-wip-us.apache.org/repos/asf/flex-sdk/tree/680b405d >>>Diff: http://git-wip-us.apache.org/repos/asf/flex-sdk/diff/680b405d >>> >>>Branch: refs/heads/develop >>>Commit: 680b405dfc4559ecf81239352b5bd9676d00adc8 >>>Parents: e68c148 >>>Author: Mihai Chira <mih...@apache.org> >>>Authored: Wed Feb 17 13:35:31 2016 +0100 >>>Committer: Mihai Chira <mih...@apache.org> >>>Committed: Wed Feb 17 13:35:31 2016 +0100 >>> >>>---------------------------------------------------------------------- >>> .../framework/src/mx/utils/ArrayUtil.as | 92 ++++++ >>> .../framework/src/mx/utils/ObjectUtil.as | 33 ++- >>> .../framework/tests/mx/utils/ArrayUtil_Tests.as | 293 +++++++++++++++++++ >>> .../tests/mx/utils/ObjectUtil_Tests.as | 167 +++++++++++ >>> 4 files changed, 581 insertions(+), 4 deletions(-) >>>---------------------------------------------------------------------- >>> >>> >>>http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/680b405d/frameworks/p >>>rojects/framework/src/mx/utils/ArrayUtil.as >>>---------------------------------------------------------------------- >>>diff --git a/frameworks/projects/framework/src/mx/utils/ArrayUtil.as >>>b/frameworks/projects/framework/src/mx/utils/ArrayUtil.as >>>index c41cccf..85ec79c 100644 >>>--- a/frameworks/projects/framework/src/mx/utils/ArrayUtil.as >>>+++ b/frameworks/projects/framework/src/mx/utils/ArrayUtil.as >>>@@ -107,6 +107,98 @@ public class ArrayUtil >>> >>> return -1; >>> } >>>+ >>>+ /** >>>+ * Checks if the Array instances contain the same values >>>+ * against the same indexes. >>>+ * >>>+ * @param a The first Array instance. >>>+ * @param b The second Array instance. >>>+ * @return true if the two Arrays contain the same values >>>+ * (determined using the strict equality operator) associated >>>+ * with the same indexes. >>>+ * >>>+ * @langversion 3.0 >>>+ * @playerversion Flash 9 >>>+ * @playerversion AIR 1.1 >>>+ * @productversion Flex 3 >>>+ */ >>>+ public static function arraysMatch(a:Array, b:Array):Boolean >>>+ { >>>+ if(!a || !b) >>>+ return false; >>>+ >>>+ if(a.length != b.length) >>>+ return false; >>>+ >>>+ var indexesA:Array = ObjectUtil.getEnumerableProperties(a); >>>+ >>>+ for (var i:int = 0; i < indexesA.length; i++) >>>+ { >>>+ var index:String = indexesA[i]; >>>+ >>>+ if(!b.hasOwnProperty(index) || a[index] !== b[index]) >>>+ return false; >>>+ } >>>+ >>>+ return true; >>>+ } >>>+ >>>+ /** >>>+ * Checks if the Array instances contain the same values, >>>+ * even if in different orders. >>>+ * >>>+ * @param a The first Array instance. >>>+ * @param b The second Array instance. >>>+ * @return true if the two Arrays contain the same values. >>>+ * >>>+ * @langversion 3.0 >>>+ * @playerversion Flash 9 >>>+ * @playerversion AIR 1.1 >>>+ * @productversion Flex 3 >>>+ */ >>>+ public static function arrayValuesMatch(a:Array, b:Array):Boolean >>>+ { >>>+ if(!a || !b) >>>+ return false; >>>+ >>>+ var valuesOfA:Array = getArrayValues(a); >>>+ valuesOfA.sort(); >>>+ >>>+ var valuesOfB:Array = getArrayValues(b); >>>+ valuesOfB.sort(); >>>+ >>>+ return arraysMatch(valuesOfA, valuesOfB); >>>+ } >>>+ >>>+ /** >>>+ * Used to obtain the values in an Array, whether indexed >>>+ * or associative. >>>+ * >>>+ * @param value The Array instance. >>>+ * @return an indexed Array with the values found in >>><code>value</code>. >>>+ * >>>+ * @langversion 3.0 >>>+ * @playerversion Flash 9 >>>+ * @playerversion AIR 1.1 >>>+ * @productversion Flex 3 >>>+ */ >>>+ public static function getArrayValues(value:Array):Array >>>+ { >>>+ var result:Array = []; >>>+ >>>+ if(!value) >>>+ return result; >>>+ >>>+ var indexes:Array = ObjectUtil.getEnumerableProperties(value); >>>+ >>>+ for each(var index:String in indexes) >>>+ { >>>+ result.push(value[index]); >>>+ } >>>+ >>>+ return result; >>>+ } >>> } >>> >>> } >>> >>>http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/680b405d/frameworks/p >>>rojects/framework/src/mx/utils/ObjectUtil.as >>>---------------------------------------------------------------------- >>>diff --git a/frameworks/projects/framework/src/mx/utils/ObjectUtil.as >>>b/frameworks/projects/framework/src/mx/utils/ObjectUtil.as >>>index 6b1e79a..b1f23cc 100644 >>>--- a/frameworks/projects/framework/src/mx/utils/ObjectUtil.as >>>+++ b/frameworks/projects/framework/src/mx/utils/ObjectUtil.as >>>@@ -1173,7 +1173,7 @@ public class ObjectUtil >>> /** >>> * Returns <code>true</code> if the object is an instance of a >>>dynamic class. >>> * >>>- * @param obj The object. >>>+ * @param object The object. >>> * >>> * @return <code>true</code> if the object is an instance of a >>>dynamic class. >>> * >>>@@ -1182,24 +1182,49 @@ public class ObjectUtil >>> * @playerversion AIR 1.1 >>> * @productversion Flex 3 >>> */ >>>- public static function isDynamicObject(obj:Object):Boolean >>>+ public static function isDynamicObject(object:Object):Boolean >>> { >>> try >>> { >>> // this test for checking whether an object is dynamic or >>>not is >>> // pretty hacky, but it assumes that no-one actually has a >>> // property defined called "wootHackwoot" >>>- obj["wootHackwoot"]; >>>+ object["wootHackwoot"]; >>> } >>> catch (e:Error) >>> { >>>- // our object isn't from a dynamic class >>>+ // our object isn't an instance of a dynamic class >>> return false; >>> } >>> return true; >>> } >>> >>> /** >>>+ * Returns all the properties defined dynamically on an object. >>>+ * >>>+ * @param object The object to inspect. >>>+ * >>>+ * @return an <code>Array</code> of the enumerable properties of >>>the object. >>>+ * >>>+ * @langversion 3.0 >>>+ * @playerversion Flash 9 >>>+ * @playerversion AIR 1.1 >>>+ * @productversion Flex 3 >>>+ */ >>>+ public static function getEnumerableProperties(object:Object):Array >>>+ { >>>+ var result:Array = []; >>>+ >>>+ if(!isDynamicObject(object)) >>>+ return result; >>>+ >>>+ for (var property:String in object) >>>+ result.push(property); >>>+ >>>+ return result; >>>+ } >>>+ >>>+ /** >>> * Returns the value at the end of the property chain >>><code>path</code>. >>> * If the value cannot be reached due to null links on the chain, >>> * <code>undefined</code> is returned. >>> >>>http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/680b405d/frameworks/p >>>rojects/framework/tests/mx/utils/ArrayUtil_Tests.as >>>---------------------------------------------------------------------- >>>diff --git >>>a/frameworks/projects/framework/tests/mx/utils/ArrayUtil_Tests.as >>>b/frameworks/projects/framework/tests/mx/utils/ArrayUtil_Tests.as >>>new file mode 100644 >>>index 0000000..d11f468 >>>--- /dev/null >>>+++ b/frameworks/projects/framework/tests/mx/utils/ArrayUtil_Tests.as >>>@@ -0,0 +1,293 @@ >>>+///////////////////////////////////////////////////////////////////////// >>>/////// >>>+// >>>+// 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 mx.utils >>>+{ >>>+ import org.flexunit.asserts.assertEquals; >>>+ import org.flexunit.asserts.assertFalse; >>>+ import org.flexunit.asserts.assertNotNull; >>>+ import org.flexunit.asserts.assertTrue; >>>+ >>>+ public class ArrayUtil_Tests >>>+ { >>>+ >>>//------------------------------------------------------------------------ >>>-- >>>+ // >>>+ // arraysMatch() >>>+ // >>>+ >>>//------------------------------------------------------------------------ >>>-- >>>+ >>>+ [Test] >>>+ public function test_array_matches_with_itself():void >>>+ { >>>+ //given >>>+ var array:Array = [1, 2, 3]; >>>+ >>>+ //then >>>+ assertTrue(ArrayUtil.arraysMatch(array, array)); >>>+ } >>>+ >>>+ [Test] >>>+ public function test_empty_arrays_match():void >>>+ { >>>+ //then >>>+ assertTrue(ArrayUtil.arraysMatch([], [])); >>>+ } >>>+ >>>+ [Test] >>>+ public function >>>test_arrays_with_same_values_in_different_indexes_dont_match():void >>>+ { >>>+ //then >>>+ assertFalse(ArrayUtil.arraysMatch(["name", "age"], ["age", >>>"name"])); >>>+ } >>>+ >>>+ [Test] >>>+ public function >>>test_arrays_match_when_properties_created_in_different_orders():void >>>+ { >>>+ //given >>>+ var arrayA:Array = []; >>>+ var arrayB:Array = []; >>>+ >>>+ //when >>>+ arrayA["name"] = "AName"; >>>+ arrayA["age"] = 22; >>>+ >>>+ arrayB["age"] = 22; >>>+ arrayB["name"] = "AName"; >>>+ >>>+ //then >>>+ assertTrue(ArrayUtil.arraysMatch(arrayA, arrayB)); >>>+ } >>>+ >>>+ [Test] >>>+ public function >>>test_arrays_dont_match_when_indexes_match_but_values_different():void >>>+ { >>>+ //given >>>+ var arrayA:Array = []; >>>+ var arrayB:Array = []; >>>+ >>>+ //when >>>+ arrayA["name"] = "AName"; >>>+ arrayA["age"] = 444; >>>+ >>>+ arrayB["age"] = 22; >>>+ arrayB["name"] = "BName"; >>>+ >>>+ //then >>>+ assertFalse(ArrayUtil.arraysMatch(arrayA, arrayB)); >>>+ } >>>+ >>>+ [Test] >>>+ public function >>>test_arrays_dont_match_when_they_have_same_number_of_different_indexes():v >>>oid >>>+ { >>>+ //given >>>+ var arrayA:Array = []; >>>+ var arrayB:Array = []; >>>+ >>>+ //when >>>+ arrayA["name"] = "AName"; >>>+ arrayA["age"] = 444; >>>+ >>>+ arrayB["radius"] = "AName"; >>>+ arrayB[9] = 444; >>>+ >>>+ //then >>>+ assertFalse(ArrayUtil.arraysMatch(arrayA, arrayB)); >>>+ } >>>+ >>>+ [Test] >>>+ public function >>>test_arrays_match_when_indexes_expressed_in_string_and_int():void >>>+ { >>>+ //given >>>+ var arrayA:Array = []; >>>+ var arrayB:Array = []; >>>+ >>>+ //when >>>+ arrayA[3] = "value"; >>>+ arrayA["4"] = "value"; >>>+ >>>+ arrayB["3"] = "value"; >>>+ arrayB[4] = "value"; >>>+ >>>+ //then >>>+ assertTrue(ArrayUtil.arraysMatch(arrayA, arrayB)); >>>+ } >>>+ >>>+ [Test] >>>+ public function >>>test_arrays_dont_match_when_values_expressed_in_string_and_int():void >>>+ { >>>+ //given >>>+ var arrayA:Array = []; >>>+ var arrayB:Array = []; >>>+ >>>+ //when >>>+ arrayA[3] = 3; >>>+ arrayA[4] = 4; >>>+ >>>+ arrayB[3] = "3"; >>>+ arrayB[4] = "4"; >>>+ >>>+ //then >>>+ assertFalse(ArrayUtil.arraysMatch(arrayA, arrayB)); >>>+ } >>>+ >>>+ [Test] >>>+ public function test_array_and_null_dont_match():void >>>+ { >>>+ //then >>>+ assertFalse(ArrayUtil.arraysMatch([1, 2, 3], null)); >>>+ } >>>+ >>>+ [Test] >>>+ public function test_null_and_null_dont_match():void >>>+ { >>>+ //then >>>+ assertFalse(ArrayUtil.arraysMatch(null, null)); >>>+ } >>>+ >>>+ [Test] >>>+ public function >>>test_arrays_with_null_in_different_positions_dont_match():void >>>+ { >>>+ //then >>>+ assertFalse(ArrayUtil.arraysMatch([null, 0], [0, null])); >>>+ } >>>+ >>>+ >>>//------------------------------------------------------------------------ >>>-- >>>+ // >>>+ // arrayValuesMatch() >>>+ // >>>+ >>>//------------------------------------------------------------------------ >>>-- >>>+ >>>+ [Test] >>>+ public function >>>test_arrays_with_same_values_in_different_indexes_match_in_terms_of_values >>>():void >>>+ { >>>+ //then >>>+ assertTrue(ArrayUtil.arrayValuesMatch(["name", "age"], >>>["age", "name"])); >>>+ } >>>+ >>>+ [Test] >>>+ public function test_array_values_dont_match_with_null():void >>>+ { >>>+ //then >>>+ assertFalse(ArrayUtil.arrayValuesMatch(["name", "age"], >>>null)); >>>+ } >>>+ >>>+ [Test] >>>+ public function test_null_doesnt_match_values_with_array():void >>>+ { >>>+ //then >>>+ assertFalse(ArrayUtil.arrayValuesMatch(null, ["name", >>>"age"])); >>>+ } >>>+ >>>+ [Test] >>>+ public function >>>test_null_and_null_dont_have_matching_values():void >>>+ { >>>+ //then >>>+ assertFalse(ArrayUtil.arrayValuesMatch(null, null)); >>>+ } >>>+ >>>+ [Test] >>>+ public function >>>test_array_values_match_although_they_have_different_indexes():void >>>+ { >>>+ //given >>>+ var arrayA:Array = []; >>>+ var arrayB:Array = []; >>>+ >>>+ //when >>>+ arrayA["name"] = "AName"; >>>+ arrayA["age"] = 444; >>>+ >>>+ arrayB["label"] = "AName"; >>>+ arrayB["spin"] = 444; >>>+ >>>+ //then >>>+ assertTrue(ArrayUtil.arrayValuesMatch(arrayA, arrayB)); >>>+ } >>>+ >>>+ [Test] >>>+ public function >>>test_array_values_dont_match_although_they_have_same_indexes():void >>>+ { >>>+ //given >>>+ var arrayA:Array = []; >>>+ var arrayB:Array = []; >>>+ >>>+ //when >>>+ arrayA["name"] = "AName"; >>>+ arrayA["age"] = 444; >>>+ >>>+ arrayB["name"] = "BName"; >>>+ arrayB["age"] = 21; >>>+ >>>+ //then >>>+ assertFalse(ArrayUtil.arrayValuesMatch(arrayA, arrayB)); >>>+ } >>>+ >>>+ [Test] >>>+ //relevant because the array length is changed when a numeric >>>index is used >>>+ public function >>>test_array_values_match_even_when_one_of_their_indexes_is_numeric():void >>>+ { >>>+ //given >>>+ var arrayA:Array = []; >>>+ var arrayB:Array = []; >>>+ >>>+ //when >>>+ arrayA["name"] = "AName"; >>>+ arrayA["age"] = 444; >>>+ >>>+ arrayB["label"] = "AName"; >>>+ arrayB[9] = 444; >>>+ >>>+ //then >>>+ assertTrue(ArrayUtil.arrayValuesMatch(arrayA, arrayB)); >>>+ } >>>+ >>>+ >>>+ >>>//------------------------------------------------------------------------ >>>-- >>>+ // >>>+ // getArrayValues() >>>+ // >>>+ >>>//------------------------------------------------------------------------ >>>-- >>>+ [Test] >>>+ public function test_values_of_null_is_an_empty_array():void >>>+ { >>>+ //when >>>+ var values:Array = ArrayUtil.getArrayValues(null); >>>+ >>>+ //then >>>+ assertNotNull(values); >>>+ assertEquals(0, values.length); >>>+ } >>>+ >>>+ [Test] >>>+ public function >>>test_values_of_array_whose_index_was_set_manually_to_a_number_include_only >>>_that_value():void >>>+ { >>>+ //given >>>+ var array:Array = []; >>>+ array[2] = "hey"; >>>+ >>>+ //when >>>+ var values:Array = ArrayUtil.getArrayValues(array); >>>+ >>>+ //then >>>+ assertNotNull(values); >>>+ assertEquals(3, array.length); >>>+ assertEquals(1, values.length); >>>+ assertEquals("hey", values[0]); >>>+ } >>>+ } >>>+} >>>\ No newline at end of file >>> >>>http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/680b405d/frameworks/p >>>rojects/framework/tests/mx/utils/ObjectUtil_Tests.as >>>---------------------------------------------------------------------- >>>diff --git >>>a/frameworks/projects/framework/tests/mx/utils/ObjectUtil_Tests.as >>>b/frameworks/projects/framework/tests/mx/utils/ObjectUtil_Tests.as >>>new file mode 100644 >>>index 0000000..a373267 >>>--- /dev/null >>>+++ b/frameworks/projects/framework/tests/mx/utils/ObjectUtil_Tests.as >>>@@ -0,0 +1,167 @@ >>>+///////////////////////////////////////////////////////////////////////// >>>/////// >>>+// >>>+// 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 mx.utils { >>>+ import flash.utils.Dictionary; >>>+ >>>+ import org.flexunit.asserts.assertEquals; >>>+ >>>+ import org.flexunit.asserts.assertFalse; >>>+ import org.flexunit.asserts.assertTrue; >>>+ >>>+ public class ObjectUtil_Tests >>>+ { >>>+ >>>//------------------------------------------------------------------------ >>>-- >>>+ // >>>+ // isDynamicObject() >>>+ // >>>+ >>>//------------------------------------------------------------------------ >>>-- >>>+ >>>+ [Test] >>>+ public function >>>test_dynamic_class_instance_recognized_as_dynamic_object():void >>>+ { >>>+ //then >>>+ assertTrue(ObjectUtil.isDynamicObject(new >>>DynamicVO("John"))); >>>+ } >>>+ >>>+ [Test] >>>+ public function >>>test_anonymous_class_instance_recognized_as_dynamic_object():void >>>+ { >>>+ //then >>>+ assertTrue(ObjectUtil.isDynamicObject({name:"John"})); >>>+ } >>>+ >>>+ [Test] >>>+ public function >>>test_array_instance_recognized_as_dynamic_object():void >>>+ { >>>+ //then >>>+ assertTrue(ObjectUtil.isDynamicObject([])); >>>+ } >>>+ >>>+ [Test] >>>+ public function >>>test_dictionary_instance_recognized_as_dynamic_object():void >>>+ { >>>+ //then >>>+ assertTrue(ObjectUtil.isDynamicObject(new Dictionary())); >>>+ } >>>+ >>>+ [Test] >>>+ public function >>>test_sealed_class_instance_recognized_as_non_dynamic_object():void >>>+ { >>>+ //then >>>+ assertFalse(ObjectUtil.isDynamicObject(new >>>NonDynamicVO("John"))); >>>+ } >>>+ >>>+ [Test] >>>+ public function test_null_does_not_throw_fatal():void >>>+ { >>>+ //then >>>+ assertFalse(ObjectUtil.isDynamicObject(null)); >>>+ } >>>+ >>>+ >>>//------------------------------------------------------------------------ >>>-- >>>+ // >>>+ // getEnumerableProperties() >>>+ // >>>+ >>>//------------------------------------------------------------------------ >>>-- >>>+ >>>+ [Test] >>>+ public function >>>test_enumerable_properties_of_anonymous_object():void >>>+ { >>>+ //given >>>+ var object:Object = {name:"John", age:32}; >>>+ >>>+ //when >>>+ var enumerableProperties:Array = >>>ObjectUtil.getEnumerableProperties(object); >>>+ >>>+ //then >>>+ assertTrue(ArrayUtil.arrayValuesMatch(["age", "name"], >>>enumerableProperties)); >>>+ } >>>+ >>>+ [Test] >>>+ public function test_enumerable_properties_of_null():void >>>+ { >>>+ //when >>>+ var enumerableProperties:Array = >>>ObjectUtil.getEnumerableProperties(null); >>>+ >>>+ //then >>>+ assertEquals(0, enumerableProperties.length); >>>+ } >>>+ >>>+ [Test] >>>+ public function test_enumerable_properties_of_dictionary():void >>>+ { >>>+ //given >>>+ var object:Object = new Dictionary(false); >>>+ object["name"] = "John"; >>>+ object["age"] = 9; >>>+ >>>+ //when >>>+ var enumerableProperties:Array = >>>ObjectUtil.getEnumerableProperties(object); >>>+ >>>+ //then >>>+ assertTrue(ArrayUtil.arrayValuesMatch(["age", "name"], >>>enumerableProperties)); >>>+ } >>>+ >>>+ [Test] >>>+ public function >>>test_enumerable_properties_of_dynamic_object():void >>>+ { >>>+ //given >>>+ var object:Object = new DynamicVO("John"); >>>+ object["age"] = 9; >>>+ >>>+ //when >>>+ var enumerableProperties:Array = >>>ObjectUtil.getEnumerableProperties(object); >>>+ >>>+ //then >>>+ assertTrue(ArrayUtil.arrayValuesMatch(["age", "name"], >>>enumerableProperties)); >>>+ } >>>+ >>>+ [Test] >>>+ public function >>>test_enumerable_properties_of_sealed_class_instance():void >>>+ { >>>+ //given >>>+ var object:Object = new NonDynamicVO("John"); >>>+ >>>+ //when >>>+ var enumerableProperties:Array = >>>ObjectUtil.getEnumerableProperties(object); >>>+ >>>+ //then >>>+ assertEquals(0, enumerableProperties.length); >>>+ } >>>+ } >>>+} >>>+ >>>+dynamic class DynamicVO >>>+{ >>>+ public function DynamicVO(name:String) >>>+ { >>>+ this.name = name; >>>+ } >>>+} >>>+ >>>+class NonDynamicVO >>>+{ >>>+ public var name:String; >>>+ >>>+ public function NonDynamicVO(name:String) >>>+ { >>>+ this.name = name; >>>+ } >>>+} >>>\ No newline at end of file >>> >>