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 2019/03/01 07:28:38 UTC
[royale-asjs] 02/05: Fixes to reflection,
restoring functonality to UnitTests App Addition of support for
release build access to public vars via reflection Addition of reflection
utility methods: isDynamicObject getDynamicFields Addition of
CompilationData inspector for runtime awareness of compiletime settings
used on the inspection target.
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 a56de5b2b9a76833a26a63ce5ceacd25309a34e9
Author: greg-dove <gr...@gmail.com>
AuthorDate: Tue Feb 26 22:59:45 2019 +1300
Fixes to reflection, restoring functonality to UnitTests App
Addition of support for release build access to public vars via reflection
Addition of reflection utility methods:
isDynamicObject
getDynamicFields
Addition of CompilationData inspector for runtime awareness of compiletime settings used on the inspection target.
---
.../apache/royale/reflection/AccessorDefinition.as | 55 +++++-
.../apache/royale/reflection/CompilationData.as | 179 ++++++++++++++++++
.../royale/reflection/MemberDefinitionBase.as | 44 +++--
.../apache/royale/reflection/MethodDefinition.as | 12 +-
.../royale/reflection/ParameterDefinition.as | 6 +-
.../org/apache/royale/reflection/TypeDefinition.as | 44 +++--
.../apache/royale/reflection/VariableDefinition.as | 106 ++++++++++-
.../apache/royale/reflection/getDynamicFields.as | 197 ++++++++++++++++++++
.../apache/royale/reflection/isDynamicObject.as | 80 ++++++++
manualtests/UnitTests/build.xml | 12 +-
manualtests/UnitTests/pom.xml | 18 +-
.../src/main/config/compile-app-config.xml | 1 +
.../UnitTests/src/main/royale/MyInitialView.mxml | 16 +-
.../main/royale/flexUnitTests/ReflectionTester.as | 5 +-
.../flexUnitTests/core/BinaryDataTesterTest.as | 34 ++--
.../reflection/ReflectionTesterTest.as | 20 +-
.../reflection/ReflectionTesterTestDynamic.as | 203 +++++++++++++++++++++
.../reflection/support/DynamicTestClass.as | 89 +++++++++
.../support/DynamicTestClass2.as} | 57 ++++--
.../support/DynamicTestClass3.as} | 34 ++--
.../flexUnitTests/reflection/support/TestClass1.as | 3 +-
manualtests/UnitTests/testsview/index.html | 45 +++--
22 files changed, 1109 insertions(+), 151 deletions(-)
diff --git a/frameworks/projects/Reflection/src/main/royale/org/apache/royale/reflection/AccessorDefinition.as b/frameworks/projects/Reflection/src/main/royale/org/apache/royale/reflection/AccessorDefinition.as
index d18f855..4a93d8b 100644
--- a/frameworks/projects/Reflection/src/main/royale/org/apache/royale/reflection/AccessorDefinition.as
+++ b/frameworks/projects/Reflection/src/main/royale/org/apache/royale/reflection/AccessorDefinition.as
@@ -17,6 +17,15 @@
//
////////////////////////////////////////////////////////////////////////////////
package org.apache.royale.reflection {
+
+ COMPILE::JS{
+ import goog.DEBUG;
+ }
+
+ COMPILE::SWF{
+ import flash.utils.getDefinitionByName;
+ }
+
/**
* The description of a Class or Interface accessor (get and/or set)
*
@@ -27,8 +36,9 @@ package org.apache.royale.reflection {
*/
public class AccessorDefinition extends VariableDefinition
{
- public function AccessorDefinition(name:String, rawData:Object) {
- super(name, rawData);
+ public function AccessorDefinition(name:String, isStatic:Boolean, owner:TypeDefinition, rawData:Object = null)
+ {
+ super(name,isStatic, owner, rawData);
}
/**
* The type that defined this accessor
@@ -42,7 +52,7 @@ package org.apache.royale.reflection {
COMPILE::JS{
var declareBy:String = _rawData.declaredBy;
}
- return TypeDefinition.getDefinition(declareBy);
+ return TypeDefinition.internalGetDefinition(declareBy);
}
@@ -65,6 +75,45 @@ package org.apache.royale.reflection {
return _access;
}
+
+ COMPILE::JS
+ override public function get getValue():Function{
+ if (_getter != null) return _getter;
+ var cl:Class = getDefinitionByName(owner.qualifiedName) as Class;
+ var fieldName:String = name;
+ if (isStatic) {
+ _getter = function():* {return cl[fieldName]}
+ } else {
+ _getter = function(instance:Object):* {
+ if (goog.DEBUG) {
+ if (arguments.length != 1 || (!(instance is cl))) throw 'invalid getValue parameters';
+ }
+ return instance[fieldName];
+ }
+ }
+ return _getter;
+ }
+
+ COMPILE::JS
+ override public function get setValue():Function{
+ if (_setter != null) return _setter;
+ var cl:Class = getDefinitionByName(owner.qualifiedName) as Class;
+ var fieldName:String = name;
+ if (isStatic) {
+ _setter = function(value:*):* {
+ cl[fieldName] = value
+ }
+ } else {
+ _setter = function(instance:Object, value:*):* {
+ if (goog.DEBUG) {
+ if (arguments.length != 2 || (!(instance is cl))) throw 'invalidsetValue parameters';
+ }
+ instance[fieldName] = value;
+ }
+ }
+ return _getter;
+ }
+
/**
* A string representation of this accessor definition
diff --git a/frameworks/projects/Reflection/src/main/royale/org/apache/royale/reflection/CompilationData.as b/frameworks/projects/Reflection/src/main/royale/org/apache/royale/reflection/CompilationData.as
new file mode 100644
index 0000000..9d7ba42
--- /dev/null
+++ b/frameworks/projects/Reflection/src/main/royale/org/apache/royale/reflection/CompilationData.as
@@ -0,0 +1,179 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 org.apache.royale.reflection {
+
+ COMPILE::JS{
+ import goog.DEBUG;
+ }
+
+ COMPILE::SWF{
+ import flash.utils.getDefinitionByName;
+ }
+
+ /**
+ * Information about compiletime settings used when compiling the target class or instance
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.0
+ */
+ public class CompilationData {
+ COMPILE::JS{
+ //mirror of JSGoogConfiguration getReflectionFlags
+
+ public static const WITH_DEFAULT_INITIALIZERS:uint = 1;
+ public static const HAS_KEEP_AS3_METADATA:uint = 2;
+ public static const HAS_KEEP_CODE_WITH_METADATA:uint = 4;
+ public static const HAS_EXPORT_PUBLIC_SYMBOLS:uint = 8;
+ public static const EXPORT_PROTECTED_SYMBOLS:uint = 16;
+
+ private static const _ALL:Array = [
+ WITH_DEFAULT_INITIALIZERS,
+ HAS_KEEP_AS3_METADATA,
+ HAS_KEEP_CODE_WITH_METADATA,
+ HAS_EXPORT_PUBLIC_SYMBOLS,
+ EXPORT_PROTECTED_SYMBOLS
+ ];
+
+ private static const _DESCRIPTIONS:Object = {
+ '1': 'Compiled with default initializers enabled',
+ '2': 'Compiled with request to keep specific as3 metadata, if present',
+ '4': 'Compiled to avoid deadcode elimination if code has metadata',
+ '8': 'Compiled with public symbols export enabled',
+ '16': 'Compiled with protected symbols export enabled'
+ }
+ }
+
+
+ public static function hasCompilationOption(flags:uint, optionBits:uint):Boolean {
+ COMPILE::SWF{
+ return false;
+ }
+ COMPILE::JS{
+ return Boolean((flags & optionBits) === optionBits);
+ }
+ }
+
+ public static function asStrings(flags:uint):Array {
+ var ret:Array = [];
+ COMPILE::JS{
+ var source:Array = _ALL;
+ const l:uint = source.length;
+ for (var i:uint = 0; i < l; i++) {
+ var itemFlag:uint = source[i];
+ if (Boolean(flags & itemFlag)) {
+ ret.push(_DESCRIPTIONS[itemFlag]);
+ }
+ }
+ }
+ return ret;
+ }
+
+ COMPILE::SWF
+ public function CompilationData(inspect:Object) {
+ throw new Error('CompilationData not implemented for swf');
+ }
+
+ COMPILE::JS
+ /**
+ * @royaleignorecoercion Class
+ */
+ public function CompilationData(inspect:Object) {
+ if (!inspect) throw new Error('CompilationData constructor parameter cannot be null');
+ var constructor:Object = inspect.constructor;
+
+ if (constructor === Object['constructor']) {
+ //class or interface
+ if (inspect.prototype && inspect.prototype.ROYALE_REFLECTION_INFO) {
+ _qName = inspect.prototype.ROYALE_CLASS_INFO.names[0].qName;
+ _flags = inspect.prototype.ROYALE_REFLECTION_INFO.compileFlags;
+ _class = inspect as Class;
+ }
+ } else {
+ //instance
+ if (inspect.ROYALE_REFLECTION_INFO) {
+ _flags = inspect.ROYALE_REFLECTION_INFO.compileFlags;
+ _qName = inspect.ROYALE_CLASS_INFO.names[0].qName;
+ _class = constructor as Class;
+ }
+ }
+ if (!_qName) {
+ throw new Error('This is not a Royale Class, cannot get compilation data');
+ }
+ }
+
+ private var _class:Class;
+
+ /**
+ * Check the ancestry for consistent compilation settings.
+ * @param specificFlags a flag or flag combination to check for on ancestor classes.
+ * If not specified or less than zero, then it is the full set of flags on this
+ * CompilationData.
+ * @return true if the ancestors have the same flags set, false otherwise
+ */
+ public function hasSameAncestry(specificFlags:int = -1):Boolean{
+
+ var checkFlags:uint = specificFlags > -1 ? specificFlags : _flags;
+ COMPILE::JS{
+ //check that the prototype chain has the same compile flags
+ var proto:Object = _class.prototype;
+ while (proto && proto.ROYALE_REFLECTION_INFO) {
+ if (!hasCompilationOption(proto.ROYALE_REFLECTION_INFO.compileFlags, checkFlags)) {
+ return false;
+ }
+ proto = proto.constructor.superClass_;
+ }
+ }
+ return true;
+ }
+
+ private var _qName:String;
+
+ /**
+ *
+ */
+ public function get qualifiedName():String{
+ return _qName;
+ }
+
+ private var _flags:uint;
+ /**
+ * the compilation flags applicable to the inspected item
+ */
+ public function get flags():uint{
+ return flags;
+ }
+
+
+ /**
+ * A string representation of this CompilationData definition
+ */
+ public function toString():String {
+ var s:String = "CompilationData for: '" + _qName + "\n";
+ var contents:Array = asStrings(_flags);
+ if (!contents.length) {
+ s += '[no compilation flags recognized]\n';
+ } else {
+ s +=('[' + contents.join(',\n ') + ']\n');
+ }
+ return s;
+ }
+ }
+}
diff --git a/manualtests/UnitTests/src/main/royale/flexUnitTests/ReflectionTester.as b/frameworks/projects/Reflection/src/main/royale/org/apache/royale/reflection/MemberDefinitionBase.as
similarity index 54%
copy from manualtests/UnitTests/src/main/royale/flexUnitTests/ReflectionTester.as
copy to frameworks/projects/Reflection/src/main/royale/org/apache/royale/reflection/MemberDefinitionBase.as
index 74c5b4d..2878e26 100644
--- a/manualtests/UnitTests/src/main/royale/flexUnitTests/ReflectionTester.as
+++ b/frameworks/projects/Reflection/src/main/royale/org/apache/royale/reflection/MemberDefinitionBase.as
@@ -16,23 +16,37 @@
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////
-package flexUnitTests
+package org.apache.royale.reflection
{
- import flexUnitTests.reflection.*;
-
- [Suite]
- [RunWith("org.flexunit.runners.Suite")]
- public class ReflectionTester
- {
- public function ReflectionTester()
+
+ /**
+ * The base class for definition types that can be decorated with metadata in actionscript
+ * source code
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.0
+ */
+ public class MemberDefinitionBase extends DefinitionWithMetaData
+ {
+ public function MemberDefinitionBase(name:String, isStatic:Boolean, owner:TypeDefinition, rawData:Object = null)
{
- // see notes in CoreTester
- var arr:Array = [ReflectionTesterTest, ReflectionTesterTestUseCache, ReflectionTesterTestAlias];
+ super(name, rawData);
+ _isStatic = isStatic;
+ _owner = owner;
}
-
- public var reflectionTesterCacheTest:ReflectionTesterTestUseCache;
- public var reflectionTesterTest:ReflectionTesterTest;
-
- public var reflectionTesterAliasTest:ReflectionTesterTestAlias;
+
+ private var _isStatic:Boolean;
+ public function get isStatic():Boolean{
+ return _isStatic;
+ }
+
+ private var _owner:TypeDefinition;
+ public function get owner():TypeDefinition{
+ return _owner;
+ }
+
+
}
}
diff --git a/frameworks/projects/Reflection/src/main/royale/org/apache/royale/reflection/MethodDefinition.as b/frameworks/projects/Reflection/src/main/royale/org/apache/royale/reflection/MethodDefinition.as
index 0f5eafc..1cf7259 100755
--- a/frameworks/projects/Reflection/src/main/royale/org/apache/royale/reflection/MethodDefinition.as
+++ b/frameworks/projects/Reflection/src/main/royale/org/apache/royale/reflection/MethodDefinition.as
@@ -21,17 +21,17 @@ package org.apache.royale.reflection
/**
* The description of a method inside a class or interface
- *
+ *
* @langversion 3.0
* @playerversion Flash 10.2
* @playerversion AIR 2.6
* @productversion Royale 0.0
*/
- public class MethodDefinition extends DefinitionWithMetaData
+ public class MethodDefinition extends MemberDefinitionBase
{
- public function MethodDefinition(name:String, rawData:Object)
+ public function MethodDefinition(name:String, isStatic:Boolean, owner:TypeDefinition, rawData:Object = null)
{
- super(name, rawData);
+ super(name,isStatic, owner, rawData);
}
/**
@@ -46,7 +46,7 @@ package org.apache.royale.reflection
COMPILE::JS{
var declareBy:String = _rawData.declaredBy;
}
- return TypeDefinition.getDefinition(declareBy);
+ return TypeDefinition.internalGetDefinition(declareBy);
}
private var _parameters:Array;
@@ -100,7 +100,7 @@ package org.apache.royale.reflection
var returnType:String = _rawData.type;
}
- return TypeDefinition.getDefinition(returnType);
+ return TypeDefinition.internalGetDefinition(returnType);
}
/**
diff --git a/frameworks/projects/Reflection/src/main/royale/org/apache/royale/reflection/ParameterDefinition.as b/frameworks/projects/Reflection/src/main/royale/org/apache/royale/reflection/ParameterDefinition.as
index c9893f7..1a88e1c 100644
--- a/frameworks/projects/Reflection/src/main/royale/org/apache/royale/reflection/ParameterDefinition.as
+++ b/frameworks/projects/Reflection/src/main/royale/org/apache/royale/reflection/ParameterDefinition.as
@@ -21,7 +21,7 @@ package org.apache.royale.reflection
/**
* The description of a Function parameter
- *
+ *
* @langversion 3.0
* @playerversion Flash 10.2S
* @playerversion AIR 2.6
@@ -40,11 +40,11 @@ package org.apache.royale.reflection
*/
public function get type():TypeDefinition{
COMPILE::SWF {
- return TypeDefinition.getDefinition(_rawData.@type);
+ return TypeDefinition.internalGetDefinition(_rawData.@type);
}
COMPILE::JS {
- return TypeDefinition.getDefinition(_rawData.type);
+ return TypeDefinition.internalGetDefinition(_rawData.type);
}
}
diff --git a/frameworks/projects/Reflection/src/main/royale/org/apache/royale/reflection/TypeDefinition.as b/frameworks/projects/Reflection/src/main/royale/org/apache/royale/reflection/TypeDefinition.as
index dd64e86..44bab7c 100755
--- a/frameworks/projects/Reflection/src/main/royale/org/apache/royale/reflection/TypeDefinition.as
+++ b/frameworks/projects/Reflection/src/main/royale/org/apache/royale/reflection/TypeDefinition.as
@@ -19,12 +19,12 @@
package org.apache.royale.reflection
{
COMPILE::SWF {
- import flash.utils.describeType;
+ import flash.utils.describeType;
}
/**
* The description of a Class or Interface
- *
+ *
* @langversion 3.0
* @playerversion Flash 10.2
* @playerversion AIR 2.6
@@ -110,7 +110,11 @@ COMPILE::SWF {
*/
public static function getDefinition(name:String, rawData:Object = null):TypeDefinition {
if (rawData == null) return null;
- return _cache ? (_cache[name] || new TypeDefinition(name, rawData)) : new TypeDefinition(name, rawData);
+ return internalGetDefinition(name, rawData);
+ }
+
+ internal static function internalGetDefinition(name:String, rawData:Object = null):TypeDefinition{
+ return _cache ? (_cache[name] || new TypeDefinition(name, rawData)) : new TypeDefinition(name, rawData);
}
/**
@@ -224,7 +228,7 @@ COMPILE::SWF {
if (_rawData == null)
{
if (_packageName.length)
- def = getDefinitionByName(_packageName + "::" + _name);
+ def = getDefinitionByName(_packageName + "." + _name);
else def = getDefinitionByName(_name);
_rawData = flash.utils.describeType(def);
@@ -259,10 +263,10 @@ COMPILE::SWF {
if (source ==null) {
//constructor with no params
_constructorMethod =
- new MethodDefinition(_name, XML('<method name="'+_name+'" declaredBy="'+declaredBy+'" returnType="" />'));
+ new MethodDefinition(_name, false, this, XML('<method name="'+_name+'" declaredBy="'+declaredBy+'" returnType="" />'));
} else {
var params:XMLList = source.parameter;
- _constructorMethod=new MethodDefinition(_name, XML('<method name="'+_name+'" declaredBy="'+declaredBy+'" returnType="">'+params.toXMLString()+'</method>'))
+ _constructorMethod=new MethodDefinition(_name, false, this, XML('<method name="'+_name+'" declaredBy="'+declaredBy+'" returnType="">'+params.toXMLString()+'</method>'))
}
}
}
@@ -290,7 +294,7 @@ COMPILE::SWF {
* For a "class" kind TypeDefinition, this returns the TypeDefinitions
* of the base classes (inheritance chain). This may differ between
* javascript and flash platform targets for some classes.
- * @royaleignorecoercion XML
+ * @royaleignorecoercion XML
*/
public function get baseClasses():Array
{
@@ -322,7 +326,7 @@ COMPILE::SWF {
{
var item:XML = data[i] as XML;
var qname:String = item.@type;
- results.push(TypeDefinition.getDefinition(qname));
+ results.push(TypeDefinition.internalGetDefinition(qname));
}
}
COMPILE::JS
@@ -337,7 +341,7 @@ COMPILE::SWF {
{
if (superClass.ROYALE_CLASS_INFO !== undefined) {
qname = superClass.ROYALE_CLASS_INFO.names[0].qName;
- results.push(TypeDefinition.getDefinition(qname));
+ results.push(TypeDefinition.internalGetDefinition(qname));
def = getDefinitionByName(qname);
superClass = def.superClass_;
//todo: support for when superClass is not a royale 'class'
@@ -388,7 +392,7 @@ COMPILE::SWF {
{
var item:XML = data[i] as XML;
var qname:String = item.@type;
- results.push(TypeDefinition.getDefinition(qname));
+ results.push(TypeDefinition.internalGetDefinition(qname));
}
}
COMPILE::JS
@@ -433,7 +437,7 @@ COMPILE::SWF {
_interfaces = results;
results = results.slice();
}
- return results;
+ return results;
}
@@ -566,7 +570,7 @@ COMPILE::SWF {
_variables = results;
results = results.slice();
}
- return results;
+ return results;
}
private var _accessors:Array;
@@ -606,7 +610,7 @@ COMPILE::SWF {
_accessors = results;
results = results.slice();
}
- return results;
+ return results;
}
@@ -644,7 +648,7 @@ COMPILE::SWF {
{
results = getCollection("methods");
//special case, remove constructor method:
- var i:int=0, l:int=results.length;
+ var i:uint=0, l:uint=results.length;
for (;i<l;i++) {
if (results[i].name==this.name) {
//trace('found constructor '+results[i].toString());
@@ -658,7 +662,7 @@ COMPILE::SWF {
_methods = results;
results = results.slice();
}
- return results;
+ return results;
}
@@ -680,7 +684,7 @@ COMPILE::SWF {
{
var item:XML = data[i] as XML;
var qname:String = item.@name;
- results[i]= new itemClass(qname, item);
+ results[i]= new itemClass(qname,isStatic, this, item);
}
return results;
}
@@ -714,7 +718,7 @@ COMPILE::SWF {
else data = null;
if (data) {
- results = TypeDefinition.getDefinition(data.names[0].qName,data)[collection];
+ results = TypeDefinition.getDefinition(data.names[0].qName, data)[collection];
l=results.length;
for (i=0;i<l;i++) oldNames[i]=results[i].name;
} else results=[];
@@ -730,7 +734,7 @@ COMPILE::SWF {
var itemDef:Object = items[item];
if (isStatic) {
//we are looking for static members only
- if (item.charAt(0)=="|") results[i++] = new itemClass(item.substr(1), itemDef);
+ if (item.charAt(0)=="|") results[i++] = new itemClass(item.substr(1), true, this, itemDef);
// if ( itemDef.isStatic) results[i++] = new itemClass(item, itemDef);
} else {
@@ -738,10 +742,10 @@ COMPILE::SWF {
if (item.charAt(0)=="|") continue;
//if (itemDef.isStatic) continue;
//instance member:
- var itemClassDef:DefinitionWithMetaData = new itemClass(item, itemDef);
+ var itemClassDef:MemberDefinitionBase = new itemClass(item, false, this, itemDef);
if (resolve) {
//resolve against older versions ("overrides")
- var oldIdx:uint = oldNames.indexOf(itemClassDef.name);
+ var oldIdx:int = oldNames.indexOf(itemClassDef.name);
if (oldIdx != -1) {
//we have an override of an ancestor's definition, replace it
results[oldIdx] = itemClassDef;
diff --git a/frameworks/projects/Reflection/src/main/royale/org/apache/royale/reflection/VariableDefinition.as b/frameworks/projects/Reflection/src/main/royale/org/apache/royale/reflection/VariableDefinition.as
index 36cf9e4..b6b89bb 100755
--- a/frameworks/projects/Reflection/src/main/royale/org/apache/royale/reflection/VariableDefinition.as
+++ b/frameworks/projects/Reflection/src/main/royale/org/apache/royale/reflection/VariableDefinition.as
@@ -18,20 +18,26 @@
////////////////////////////////////////////////////////////////////////////////
package org.apache.royale.reflection
{
-
+ COMPILE::JS{
+ import goog.DEBUG;
+ }
+
+ COMPILE::SWF{
+ import flash.utils.getDefinitionByName;
+ }
/**
* The description of a Class or Interface variable
- *
+ *
* @langversion 3.0
* @playerversion Flash 10.2
* @playerversion AIR 2.6
* @productversion Royale 0.0
*/
- public class VariableDefinition extends DefinitionWithMetaData
+ public class VariableDefinition extends MemberDefinitionBase
{
- public function VariableDefinition(name:String, rawData:Object)
+ public function VariableDefinition(name:String, isStatic:Boolean, owner:TypeDefinition, rawData:Object = null)
{
- super(name, rawData);
+ super(name,isStatic, owner, rawData);
}
/**
@@ -40,13 +46,99 @@ package org.apache.royale.reflection
*/
public function get type():TypeDefinition {
COMPILE::SWF {
- return TypeDefinition.getDefinition(_rawData.@type);
+ return TypeDefinition.internalGetDefinition(_rawData.@type);
}
COMPILE::JS {
- return TypeDefinition.getDefinition(_rawData.type);
+ return TypeDefinition.internalGetDefinition(_rawData.type);
}
}
+
+ protected var _getter:Function;
+ /**
+ * provides a function that supports reading the value described by this definition
+ * For instance member definitions it requires the instance to be passed as a single argument
+ * For static member definitions it requires no arguments
+ */
+ public function get getValue():Function{
+ if (_getter != null) return _getter;
+ COMPILE::SWF{
+ var fieldName:String = this.name;
+ var cl:Class = flash.utils.getDefinitionByName(owner.qualifiedName) as Class;
+ if (isStatic) {
+ _getter = function():* {return cl[fieldName]}
+ } else {
+ _getter = function(instance:Object):* {
+ if (arguments.length != 1 || (!(instance is cl))) throw 'invalid getValue parameters';
+ return instance[fieldName];
+ }
+ }
+ }
+ COMPILE::JS {
+ var f:Function = _rawData.get_set;
+ var canBeUndefined:Boolean = type.qualifiedName == '*';
+ if (isStatic) {
+ _getter = function():* {return canBeUndefined ? f(f) : f()}
+ } else {
+ _getter = function(instance:Object):* {
+ if (goog.DEBUG) {
+ if (arguments.length != 1 || !instance) throw 'invalid getValue parameters';
+ }
+ return canBeUndefined ? f(instance, f) : f(instance)
+ }
+ }
+ }
+ return _getter;
+ }
+
+
+ protected var _setter:Function;
+ /**
+ * provides a function that supports setting the value described by this definition
+ * For static member definitions it requires only the value argument
+ * For instance member definitions it requires the instance to be passed as a first argument, followed by the value
+ */
+ public function get setValue():Function{
+ if (_setter != null) return _setter;
+ COMPILE::SWF{
+ var fieldName:String = this.name;
+ var cl:Class = flash.utils.getDefinitionByName(owner.qualifiedName) as Class;
+ if (isStatic) {
+ _setter = function(value:*):* {
+ cl[fieldName] = value
+ }
+ } else {
+ _setter = function(instance:Object, value:*):* {
+ if (!(instance is cl)) throw 'invalid setValue parameters';
+ instance[fieldName] = value;
+ }
+ }
+ }
+
+ COMPILE::JS {
+ var f:Function = _rawData.get_set;
+ if (isStatic) {
+ _setter = function(value:*):* {
+ if (goog.DEBUG) {
+ if (arguments.length != 1) throw 'invalid setValue parameters';
+ //todo: more robust runtime checking of value here for debug mode
+ }
+ f(value);
+ }
+ } else {
+ _setter = function(instance:Object, value:*):* {
+ if (goog.DEBUG) {
+ if (arguments.length != 2 || !instance) throw 'invalid setValue parameters';
+ //todo: more robust runtime checking of value here for debug mode
+ }
+ f(instance, value);
+ }
+ }
+ }
+ return _setter;
+ }
+
+
/**
* A string representation of this variable definition
*/
diff --git a/frameworks/projects/Reflection/src/main/royale/org/apache/royale/reflection/getDynamicFields.as b/frameworks/projects/Reflection/src/main/royale/org/apache/royale/reflection/getDynamicFields.as
new file mode 100644
index 0000000..3479ca9
--- /dev/null
+++ b/frameworks/projects/Reflection/src/main/royale/org/apache/royale/reflection/getDynamicFields.as
@@ -0,0 +1,197 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 org.apache.royale.reflection {
+ COMPILE::JS{
+ import goog.DEBUG;
+ }
+
+ import org.apache.royale.events.EventDispatcher;
+
+ /**
+ * A utility method to check if an object is dynamic (i.e. can have non-sealed members added or deleted)
+ * Note that static class objects are always dynamic, as are (static) Interface Objects
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.0
+ *
+ * @param inspect the class or instance to check for dynamic fields
+ * @param includePredicate an optional function for which takes a single String argument
+ * and returns true to include that specific field in the results. If it returns false,
+ * that property is excluded. Defaults to null, which applies no filtering and returns all
+ * detected properties.
+ * @param checkFirst an optional check to verify that the inspect parameter is dynamic
+ * before inspecting it for dynamic properties. This should normally be left at its default value of true.
+ * If it is know that the object is dynamic before calling this method, setting this to false
+ * could improve performance in performance-sensitive code.
+ * The results of calling this method on non-dynamic objects may be less reliable or less consistent
+ * across target platforms if checkFirst is false
+ *
+ * @return the dynamic fields as Strings in an Array
+ */
+ COMPILE::JS
+ public function getDynamicFields(inspect:Object, includePredicate:Function = null, checkFirst:Boolean = true):Array {
+ var arr:Array;
+ var i:uint = 0;
+ var assumeDynamic:Boolean = checkFirst ? isDynamicObject(inspect) : true;
+ var checkIncludes:Boolean = includePredicate != null;
+ var prop:String;
+ if (assumeDynamic) {
+ var constructor:Object = inspect.constructor;
+ if (constructor === Object['constructor']) {
+ //class or interface
+ //this relies on compiler-added support to prevent enumeration of some fields
+ //that are not protected from enumeration by default
+ //this is only added to classes that have static fields in the definition
+ arr = Object.keys(inspect);
+ if (inspect.prototype && inspect.prototype.ROYALE_REFLECTION_INFO) {
+ if (goog.DEBUG) {
+ if (!CompilationData.hasCompilationOption(inspect.prototype.ROYALE_REFLECTION_INFO.compileFlags, CompilationData.WITH_DEFAULT_INITIALIZERS)) {
+ trace('[WARN] getDynamicFields can be unreliable for static inspection of ' + inspect.prototype.ROYALE_CLASS_INFO.names[0].qName + ' because it was not compiled with \'js-default-initializers=true\'');
+ }
+ }
+ var avoidNames:Array = inspect.prototype.ROYALE_REFLECTION_INFO.statics;
+ if (avoidNames) {
+ var temp:Array = [];
+ var l:uint = arr.length;
+ for (i = 0; i < l; i++) {
+ prop = arr[i];
+ if (avoidNames.indexOf(prop) == -1) {
+ temp.push(prop);
+ }
+ }
+ arr = temp;
+ }
+ }
+ } else {
+ var excludeFields:Array;
+ arr = Object.keys(inspect);
+ var warned:Boolean;
+ //the following is complicated, but appears to work in release mode
+ //if everything (including framework if it needs to be reflected into) is compiled with
+ //js-default-initializers=true
+ if (inspect.ROYALE_REFLECTION_INFO) {
+ const inspectReflect:Object = inspect.ROYALE_REFLECTION_INFO;
+ if (goog.DEBUG) {
+ if (!CompilationData.hasCompilationOption(inspectReflect.compileFlags, CompilationData.WITH_DEFAULT_INITIALIZERS)) {
+ trace('[WARN] getDynamicFields can be unreliable for ' + inspect.ROYALE_CLASS_INFO.names[0].qName + ' and any ancestor classes that were not compiled with \'js-default-initializers=true\'');
+ warned = true;
+ }
+ }
+
+ var instanceExcludes:Array = inspectReflect.instanceExcludes;
+ if (!instanceExcludes) {
+ //special cases:
+ //this is not ideal, but seems necessary unless the properties were made not enumerable
+ //EventDispatcher
+ var eventDispatcherClassInfo:Object;
+ //todo - consider using reflection code instead of hard dependency on EventDispatcher
+ if (inspect is EventDispatcher) {
+ instanceExcludes = getDynamicFields['EventDispatcherFields'];
+ if (!instanceExcludes) {
+ var test:Object = new EventDispatcher();
+ //
+ instanceExcludes = getDynamicFields['EventDispatcherFields'] = Object.keys(test);
+ }
+ const edc:Class = EventDispatcher;
+ eventDispatcherClassInfo = edc.prototype.ROYALE_CLASS_INFO;
+ }
+
+ if (!instanceExcludes) instanceExcludes = [];
+
+ var proto:Object = inspect.constructor.prototype;
+ while (proto) {
+ var protoReflect:Object = proto.ROYALE_REFLECTION_INFO;
+ if (goog.DEBUG && !warned) {
+ if (protoReflect && !CompilationData.hasCompilationOption(protoReflect.compileFlags, CompilationData.WITH_DEFAULT_INITIALIZERS)) {
+ //skip EventDispatcher because we already special-cased it
+ if (proto.ROYALE_CLASS_INFO.names[0].qName != eventDispatcherClassInfo.names[0].qName) {
+ trace('[WARN] getDynamicFields can be unreliable for '
+ + inspect.ROYALE_CLASS_INFO.names[0].qName
+ + '\'s ancestor class '
+ + proto.ROYALE_CLASS_INFO.names[0].qName
+ + ' and any of its ancestors that were not compiled with \'js-default-initializers=true\'');
+ warned = true;
+ }
+ }
+ }
+ var inherited:Array = proto.ROYALE_REFLECTION_INFO ? proto.ROYALE_REFLECTION_INFO.instanceExcludes : null;
+ var protoKeys:Array = inherited || Object.keys(proto);
+ l = protoKeys.length;
+ while (l--) {
+ var key:String = protoKeys[l];
+ if (instanceExcludes.indexOf(key) == -1) instanceExcludes.push(key);
+ }
+ if (inherited) break;
+ proto = proto.constructor.superClass_;
+ }
+
+ inspectReflect.instanceExcludes = instanceExcludes;
+ }
+ l = instanceExcludes.length;
+ if (l && !excludeFields) excludeFields = [];
+ while (l--) {
+ excludeFields.push(instanceExcludes[l]);
+ }
+ }
+
+ if (excludeFields) {
+ l = excludeFields.length;
+ while (l--) {
+ var idx:int = arr.indexOf(excludeFields[l]);
+ if (idx != -1) {
+ arr.splice(idx, 1);
+ }
+ }
+ }
+ }
+
+ if (checkIncludes) {
+ arr = arr.filter(includePredicate);
+ }
+ } else {
+ //it's not considered dynamic...
+ //so assume zero dynamic fields (even if technically in js
+ //there could actually be some at runtime)
+ arr = [];
+ }
+
+ return arr;
+ }
+
+ COMPILE::SWF
+ public function getDynamicFields(inspect:Object, includePredicate:Function = null, checkFirst:Boolean = true):Array {
+
+ var i:uint = 0;
+ var assumeDynamic:Boolean = checkFirst ? isDynamicObject(inspect) : true;
+ var checkIncludes:Boolean = includePredicate != null;
+ var prop:String;
+ var arr:Array = [];
+ if (assumeDynamic) {
+ for (prop in inspect) {
+ if (!checkIncludes || includePredicate(prop))
+ arr[i++] = prop;
+ }
+ }
+
+ return arr;
+ }
+
+}
diff --git a/frameworks/projects/Reflection/src/main/royale/org/apache/royale/reflection/isDynamicObject.as b/frameworks/projects/Reflection/src/main/royale/org/apache/royale/reflection/isDynamicObject.as
new file mode 100644
index 0000000..20aa884
--- /dev/null
+++ b/frameworks/projects/Reflection/src/main/royale/org/apache/royale/reflection/isDynamicObject.as
@@ -0,0 +1,80 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 org.apache.royale.reflection
+{
+COMPILE::SWF
+{
+ import flash.utils.describeType;
+}
+
+ /**
+ * A utility method to check if an object is dynamic (can have non-sealed members added or deleted)
+ * Note that static class objects are always dynamic, as are Interface Objects
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10.2
+ * @playerversion AIR 2.6
+ * @productversion Royale 0.0
+ */
+ public function isDynamicObject(inspect:Object):Boolean
+ {
+ COMPILE::SWF
+ {
+ 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"
+ var o:* = inspect["wootHackwoot"];
+ }
+ catch (e:Error)
+ {
+ // our object isn't an instance of a dynamic class
+ return false;
+ }
+ return true;
+ }
+ COMPILE::JS
+ {
+ if (!inspect) return false;
+ var constructor:Object = inspect.constructor;
+ if (constructor === Object['constructor']) {
+ //class or interface
+ return true;
+ }
+ if (constructor) {
+ //instance
+ if (constructor === Object || constructor === Array) return true;
+ var prototype:Object = constructor.prototype;
+ if (prototype && prototype.ROYALE_CLASS_INFO) {
+ return Boolean(prototype.ROYALE_CLASS_INFO.names[0].isDynamic);
+ }
+ var dyncheck:Boolean = false;
+ try {
+
+ inspect["wootHackwoot"] = "wootHackwoot";
+ if (inspect["wootHackwoot"] == "wootHackwoot") dyncheck=true;
+ delete inspect["wootHackwoot"];
+
+ } catch(e:Error) {};
+ return dyncheck;
+ } else return true
+ }
+ }
+}
diff --git a/manualtests/UnitTests/build.xml b/manualtests/UnitTests/build.xml
index 5712905..55b9a7d 100644
--- a/manualtests/UnitTests/build.xml
+++ b/manualtests/UnitTests/build.xml
@@ -19,7 +19,7 @@
-->
-<project name="GenericTests" default="main" basedir=".">
+<project name="UnitTests" default="main" basedir=".">
<property name="ROYALE_HOME" location="../.."/>
<property name="example" value="UnitTests" />
@@ -27,27 +27,27 @@
<property name="theme_arg" value="-keep-as3-metadata+=Test,BeforeClass,AfterClass,Before,After,TestVariance,Event,Bindable,TestMeta" />
<!-- adding flexuint style meta collection, and additional testing meta tags (Event,Bindable,TestMeta)-->
<property name="extlib_arg" value="-keep-code-with-metadata=Test,BeforeClass,AfterClass,Before,After,TestVariance,TestMeta" />
-
+
<property file="${ROYALE_HOME}/env.properties"/>
<property environment="env"/>
<property file="${ROYALE_HOME}/build.properties"/>
<property name="ROYALE_HOME" value="${ROYALE_HOME}"/>
-
+
<!-- make ant src and output consistent with maven -->
<property name="maven_compat" value="true"/>
-
+
<include file="${basedir}/../build_example.xml" />
<target name="main" depends="clean,build_example.compile" description="Clean build of ${example}">
</target>
-
+
<target name="clean">
<delete dir="${basedir}/bin" failonerror="false" />
<delete dir="${basedir}/bin-debug" failonerror="false" />
<delete dir="${basedir}/bin-release" failonerror="false" />
<delete dir="${basedir}/target" failonerror="false" />
</target>
-
+
<target name="examine" depends="build_example.get.browser">
<echo message="View the swf and js unit tests side-by-side"/>
<exec executable="${browser}" dir="${basedir}" failonerror="true">
diff --git a/manualtests/UnitTests/pom.xml b/manualtests/UnitTests/pom.xml
index c887af5..b4e8f97 100644
--- a/manualtests/UnitTests/pom.xml
+++ b/manualtests/UnitTests/pom.xml
@@ -29,10 +29,10 @@
<version>0.9.6-SNAPSHOT</version>
<packaging>swf</packaging>
<name>Apache Royale: ManualTests: UnitTests</name>
-
- <properties>
+
+ <properties>
<title>${project.artifactId}</title>
- <bgcolor>#ffffff</bgcolor>
+ <bgcolor>#ffffff</bgcolor>
<useBrowserHistory>--</useBrowserHistory>
<version_major>11</version_major>
<version_minor>1</version_minor>
@@ -56,7 +56,7 @@
<mainClass>${project.artifactId}.mxml</mainClass>
<removeCirculars>true</removeCirculars>
<debug>true</debug>
- <additionalCompilerOptions>-keep-as3-metadata+=Test,BeforeClass,AfterClass,Before,After,TestVariance,Event,Bindable,TestMeta -keep-code-with-metadata=Test,BeforeClass,AfterClass,Before,After,TestVariance,TestMeta</additionalCompilerOptions>
+ <additionalCompilerOptions>-js-default-initializers;-keep-as3-metadata+=Test,BeforeClass,AfterClass,Before,After,TestVariance,Event,Bindable,TestMeta;-keep-code-with-metadata=Test,BeforeClass,AfterClass,Before,After,TestVariance,TestMeta</additionalCompilerOptions>
<outputDirectory>${basedir}/target/bin-debug</outputDirectory>
<flashOutputFileName>${project.artifactId}.swf</flashOutputFileName>
</configuration>
@@ -71,11 +71,11 @@
<targets>JSRoyale</targets>
<mainClass>${project.artifactId}.mxml</mainClass>
<debug>false</debug>
- <additionalCompilerOptions>-keep-as3-metadata+=Test,BeforeClass,AfterClass,Before,After,TestVariance,Event,Bindable,TestMeta -keep-code-with-metadata=Test,BeforeClass,AfterClass,Before,After,TestVariance,TestMeta</additionalCompilerOptions>
+ <additionalCompilerOptions>-js-default-initializers;-keep-as3-metadata+=Test,BeforeClass,AfterClass,Before,After,TestVariance,Event,Bindable,TestMeta;-keep-code-with-metadata=Test,BeforeClass,AfterClass,Before,After,TestVariance,TestMeta</additionalCompilerOptions>
<outputDirectory>${basedir}/target</outputDirectory>
</configuration>
</execution>
- </executions>
+ </executions>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
@@ -92,8 +92,8 @@
<includeEmptyDirs>true</includeEmptyDirs>
<resources>
<resource>
- <directory>${basedir}/../../templates/swfobject</directory>
- <filtering>true</filtering>
+ <directory>${basedir}/src/main/resources/swfobject</directory>
+ <filtering>true</filtering>
</resource>
</resources>
</configuration>
@@ -135,7 +135,7 @@
<file>${basedir}/bin-debug/index.template.html</file>
<regex>false</regex>
<replacements>
-
+
</replacements>
</configuration>
</execution>
diff --git a/manualtests/UnitTests/src/main/config/compile-app-config.xml b/manualtests/UnitTests/src/main/config/compile-app-config.xml
index 645a852..8774ac7 100644
--- a/manualtests/UnitTests/src/main/config/compile-app-config.xml
+++ b/manualtests/UnitTests/src/main/config/compile-app-config.xml
@@ -20,6 +20,7 @@
<js-output-optimization>
<optimization>skipFunctionCoercions</optimization>
</js-output-optimization>
+ <js-default-initializers>true</js-default-initializers>
<compiler>
</compiler>
</royale-config>
diff --git a/manualtests/UnitTests/src/main/royale/MyInitialView.mxml b/manualtests/UnitTests/src/main/royale/MyInitialView.mxml
index 375981d..8f72540 100644
--- a/manualtests/UnitTests/src/main/royale/MyInitialView.mxml
+++ b/manualtests/UnitTests/src/main/royale/MyInitialView.mxml
@@ -159,18 +159,14 @@ limitations under the License.
private static function getPlatform():String {
- try {
- var check:* = getDefinitionByName("flash.system.Capabilities");
- } catch (e:Error) {
- return "JS";
+ var platform:String;
+ COMPILE::JS{
+ platform = "JS";
}
- //if this next reference to 'check' is not included, then the above try/catch code
- // appears to be optimized away in js-release mode
- //[this issue was added to ObservedBugs Tests]
- if (check == null) {
- return "JS";
+ COMPILE::SWF{
+ platform = "SWF";
}
- return "SWF";
+ return platform;
}
public static const PLATFORM:String = getPlatform();
diff --git a/manualtests/UnitTests/src/main/royale/flexUnitTests/ReflectionTester.as b/manualtests/UnitTests/src/main/royale/flexUnitTests/ReflectionTester.as
index 74c5b4d..369e763 100644
--- a/manualtests/UnitTests/src/main/royale/flexUnitTests/ReflectionTester.as
+++ b/manualtests/UnitTests/src/main/royale/flexUnitTests/ReflectionTester.as
@@ -27,12 +27,15 @@ package flexUnitTests
public function ReflectionTester()
{
// see notes in CoreTester
- var arr:Array = [ReflectionTesterTest, ReflectionTesterTestUseCache, ReflectionTesterTestAlias];
+ var arr:Array = [ReflectionTesterTest, ReflectionTesterTestUseCache, ReflectionTesterTestAlias, ReflectionTesterTestDynamic];
}
public var reflectionTesterCacheTest:ReflectionTesterTestUseCache;
public var reflectionTesterTest:ReflectionTesterTest;
public var reflectionTesterAliasTest:ReflectionTesterTestAlias;
+
+
+ public var reflectionTesterDynamicTest:ReflectionTesterTestDynamic;
}
}
diff --git a/manualtests/UnitTests/src/main/royale/flexUnitTests/core/BinaryDataTesterTest.as b/manualtests/UnitTests/src/main/royale/flexUnitTests/core/BinaryDataTesterTest.as
index a2473f8..b6613b7 100644
--- a/manualtests/UnitTests/src/main/royale/flexUnitTests/core/BinaryDataTesterTest.as
+++ b/manualtests/UnitTests/src/main/royale/flexUnitTests/core/BinaryDataTesterTest.as
@@ -25,7 +25,7 @@ package flexUnitTests.core
import org.apache.royale.utils.BinaryData
- public class BinaryDataTesterTest
+ public class BinaryDataTesterTest
{
[Before]
@@ -524,20 +524,20 @@ package flexUnitTests.core
[Test]
- public function testWriteBytes():void
+ public function testWriteBinaryData():void
{
var ba:BinaryData = new BinaryData();
for (var i:int=0;i<50;i++) ba.writeByte(i);
var newBa:BinaryData = new BinaryData();
- newBa.writeBytes(ba);
+ newBa.writeBinaryData(ba);
- Assert.assertEquals("BinaryData writeBytes: length", 50, newBa.length);
- Assert.assertEquals("BinaryData writeBytes: position", 50, newBa.position);
+ Assert.assertEquals("BinaryData writeBinaryData: length", 50, newBa.length);
+ Assert.assertEquals("BinaryData writeBinaryData: position", 50, newBa.position);
for (i=0;i<50;i++) {
- Assert.assertEquals("BinaryData writeBytes: content check", i, newBa.array[i]);
+ Assert.assertEquals("BinaryData writeBinaryData: content check", i, newBa.array[i]);
}
@@ -545,21 +545,29 @@ package flexUnitTests.core
}
[Test]
- public function testReadBytes():void
+ public function testReadBinaryData():void
{
var ba:BinaryData = new BinaryData();
for (var i:int=0;i<50;i++) ba.writeByte(i);
ba.position=0;
var newBa:BinaryData = new BinaryData();
- ba.readBytes(newBa,5,10);
- Assert.assertEquals("BinaryData readBytes: position", 10, ba.position);
- Assert.assertEquals("BinaryData readBytes: length", 15, newBa.length);
- Assert.assertEquals("BinaryData readBytes: position", 0, newBa.position);
+ ba.readBinaryData(newBa,5,10);
+ Assert.assertEquals("BinaryData readBinaryData: position", 10, ba.position);
+ Assert.assertEquals("BinaryData readBinaryData: length", 15, newBa.length);
+ Assert.assertEquals("BinaryData readBinaryData: position", 0, newBa.position);
var expected:Array = [0,0,0,0,0,0,1,2,3,4,5,6,7,8,9];
- for (i=5;i<15;i++) {
- Assert.assertEquals("BinaryData readBytes: content check", expected[i], newBa.array[i]);
+ for (i=0;i<15;i++) {
+ Assert.assertEquals("BinaryData readBinaryData: content check", expected[i], newBa.array[i]);
}
+ newBa.position = 15;
+ ba.readBinaryData(newBa,5,10);
+ expected = [0,0,0,0,0,10,11,12,13,14,15,16,17,18,19];
+ for (i=0;i<15;i++) {
+ Assert.assertEquals("BinaryData readBinaryData: content check", expected[i], newBa.array[i]);
+ }
+ Assert.assertEquals("BinaryData readBinaryData: length", 15, newBa.length);
+ Assert.assertEquals("BinaryData readBinaryData: position", 15, newBa.position);
}
[Test]
diff --git a/manualtests/UnitTests/src/main/royale/flexUnitTests/reflection/ReflectionTesterTest.as b/manualtests/UnitTests/src/main/royale/flexUnitTests/reflection/ReflectionTesterTest.as
index f4f0a01..7bd9bee 100644
--- a/manualtests/UnitTests/src/main/royale/flexUnitTests/reflection/ReflectionTesterTest.as
+++ b/manualtests/UnitTests/src/main/royale/flexUnitTests/reflection/ReflectionTesterTest.as
@@ -23,7 +23,7 @@ package flexUnitTests.reflection
import org.apache.royale.reflection.*;
public class ReflectionTesterTest
- {
+ {
public static var isJS:Boolean;
[BeforeClass]
@@ -233,8 +233,12 @@ package flexUnitTests.reflection
Assert.assertEquals("unexpected meta arg name","foo",metaArg.name);
Assert.assertEquals("unexpected meta arg value","instanceVariable",metaArg.value);
- Assert.assertEquals("unexpected reflection initial variable value","testVar_val",inst[variable.name]);
-
+ // Assert.assertEquals("unexpected reflection initial variable value","testVar_val",inst[variable.name]);
+ Assert.assertEquals("unexpected reflection initial variable value","testVar_val",variable.getValue(inst));
+ variable.setValue(inst, "testVar_val_reflection_set");
+ Assert.assertEquals("unexpected reflection initial variable value","testVar_val_reflection_set",variable.getValue(inst));
+ inst.testVar = "testVar_val";
+
var accessors:Array = def.accessors;
var testReadOnly:AccessorDefinition = retrieveItemWithName(accessors,"testReadOnly") as AccessorDefinition;
meta = testReadOnly.retrieveMetaDataByName("TestMeta")[0];
@@ -296,8 +300,14 @@ package flexUnitTests.reflection
Assert.assertEquals("unexpected meta arg name","foo",metaArg.name);
Assert.assertEquals("unexpected meta arg value","staticVariable",metaArg.value);
- Assert.assertEquals("unexpected reflection initial variable value","testStaticVar_val",TestClass2[variable.name]);
-
+ // Assert.assertEquals("unexpected reflection initial variable value","testStaticVar_val",TestClass2[variable.name]);
+ Assert.assertEquals("unexpected reflection initial variable value","testStaticVar_val",variable.getValue());
+ variable.setValue("testStaticVar_val_reflection_set");
+ Assert.assertEquals("unexpected reflection initial variable value","testStaticVar_val_reflection_set",variable.getValue());
+ TestClass2.testStaticVar = "testStaticVar_val";
+
+
+
/** static accessors **/
accessors = def.staticAccessors;
diff --git a/manualtests/UnitTests/src/main/royale/flexUnitTests/reflection/ReflectionTesterTestDynamic.as b/manualtests/UnitTests/src/main/royale/flexUnitTests/reflection/ReflectionTesterTestDynamic.as
new file mode 100644
index 0000000..4aa2155
--- /dev/null
+++ b/manualtests/UnitTests/src/main/royale/flexUnitTests/reflection/ReflectionTesterTestDynamic.as
@@ -0,0 +1,203 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.reflection
+{
+ import flexunit.framework.Assert;
+ import flexUnitTests.reflection.support.*;
+ import org.apache.royale.reflection.*;
+
+ public class ReflectionTesterTestDynamic
+ {
+
+ public static var isJS:Boolean;
+ [BeforeClass]
+ public static function setUpBeforeClass():void
+ {
+ var js:Boolean;
+ COMPILE::JS{
+ js = true;
+ }
+ isJS = js;
+ }
+
+ [AfterClass]
+ public static function tearDownAfterClass():void
+ {
+ }
+
+ [Before]
+ public function setUp():void
+ {
+
+ }
+
+ [After]
+ public function tearDown():void
+ {
+
+ }
+
+ private static function contentStringsMatch(arr1:Array, arr2:Array):Boolean{
+ if (arr1 == arr2) return true;
+ if (!arr1 || !arr2) return false;
+ if (arr1.length != arr2.length) return false;
+ const arr1Copy:Array = arr1.concat();
+ var l:uint = arr1Copy.length;
+ while (l--) {
+ var s:String = arr1Copy.shift();
+ if (arr2.indexOf(s) == -1) return false
+ }
+ return true;
+ }
+
+
+ [Test]
+ public function testisDynamic():void {
+ //class
+
+ Assert.assertTrue("class should be dynamic",isDynamicObject(Object));
+
+ Assert.assertTrue("class should be dynamic",isDynamicObject(TestClass1));
+ //interface is dynamic (even if it doesn't make much sense)
+ Assert.assertTrue("interface should be dynamic",true,isDynamicObject(ITestInterface));
+ //instance
+ Assert.assertTrue("generic object should be dynamic",isDynamicObject({}));
+
+ Assert.assertFalse("sealed class instance should not be dynamic",isDynamicObject(new TestClass1()));
+
+ Assert.assertTrue("dynamic class instance should be dynamic",isDynamicObject(new DynamicTestClass()));
+
+
+ Assert.assertFalse("String instance should not be dynamic",isDynamicObject("String"));
+ Assert.assertFalse("int instance should not be dynamic",isDynamicObject(99));
+ Assert.assertFalse("Number instance should not be dynamic",isDynamicObject(99.99));
+ Assert.assertFalse("Boolean instance should not be dynamic",isDynamicObject(true));
+
+
+ Assert.assertTrue("function instance should be dynamic",isDynamicObject(function():void{}));
+ Assert.assertTrue("Array instance should be dynamic",isDynamicObject([]));
+ }
+
+
+
+ [TestVariance(variance="JS",description="Variance in test due to reliance on 'js-default-initializers=true' throughout entire inheritance chain for 'getDynamicFields' function")]
+ [Test]
+ public function testGetDynamicFields():void {
+
+ const emptyArray:Array = [];
+ const singleDynField:Array = ['test'];
+ Assert.assertTrue("dynamic fields should match reference list",contentStringsMatch(getDynamicFields(Object),emptyArray));
+ Object['test'] = true;
+ Assert.assertTrue("dynamic fields should match reference list",contentStringsMatch(getDynamicFields(Object),singleDynField));
+ delete Object['test'];
+
+ Assert.assertTrue("dynamic fields should match reference list",contentStringsMatch(getDynamicFields(TestClass1),emptyArray));
+ TestClass1['test'] = true;
+ Assert.assertTrue("dynamic fields should match reference list",contentStringsMatch(getDynamicFields(TestClass1),singleDynField));
+ delete TestClass1['test'];
+
+ //interface is dynamic (even if it doesn't make much sense)
+ Assert.assertTrue("dynamic fields should match reference list",contentStringsMatch(getDynamicFields(ITestInterface),emptyArray));
+ ITestInterface['test'] = true;
+ Assert.assertTrue("dynamic fields should match reference list",contentStringsMatch(getDynamicFields(ITestInterface),singleDynField));
+ delete ITestInterface['test'];
+
+ //instance
+ Assert.assertTrue("dynamic fields should match reference list",contentStringsMatch(getDynamicFields({}),emptyArray));
+ Assert.assertTrue("dynamic fields should match reference list",contentStringsMatch(getDynamicFields({test:true}),singleDynField));
+
+ Assert.assertTrue("dynamic fields should match reference list",contentStringsMatch(getDynamicFields(new TestClass1()),emptyArray));
+
+ const dynInstance:DynamicTestClass = new DynamicTestClass();
+ dynInstance.test = true;
+ Assert.assertTrue("dynamic fields should match reference list",contentStringsMatch(getDynamicFields(dynInstance),singleDynField));
+
+
+ Assert.assertTrue("dynamic fields should match reference list",contentStringsMatch(getDynamicFields("String"),emptyArray));
+ Assert.assertTrue("dynamic fields should match reference list",contentStringsMatch(getDynamicFields(99),emptyArray));
+ Assert.assertTrue("dynamic fields should match reference list",contentStringsMatch(getDynamicFields(99.99),emptyArray));
+ Assert.assertTrue("dynamic fields should match reference list",contentStringsMatch(getDynamicFields(true),emptyArray));
+
+ Assert.assertTrue("dynamic fields should match reference list",contentStringsMatch(getDynamicFields(function():void{}),emptyArray));
+
+ const numericFields:Array=["0","1","2","3"];
+ var arr:Array = [1,2,3,4];
+ Assert.assertTrue("dynamic fields should match reference list",contentStringsMatch(getDynamicFields(arr),numericFields));
+ numericFields.push('test');
+ arr['test'] = true;
+ Assert.assertTrue("dynamic fields should match reference list",contentStringsMatch(getDynamicFields(arr),numericFields));
+
+
+ var testclass2:DynamicTestClass2 = new DynamicTestClass2();
+ testclass2.test = true;
+ testclass2.something = '*something*';
+ Assert.assertTrue("dynamic fields should match reference list",contentStringsMatch(getDynamicFields(testclass2),singleDynField));
+
+
+ testclass2.test = 'test';
+ testclass2.something = '*something else*';
+
+ Assert.assertTrue("dynamic fields should match reference list",contentStringsMatch(getDynamicFields(testclass2),singleDynField));
+ var testClass3:DynamicTestClass3 = new DynamicTestClass3();
+ var swapAssertion:Boolean;
+ COMPILE::JS{
+ var check:Boolean = new CompilationData(testClass3).hasSameAncestry(CompilationData.WITH_DEFAULT_INITIALIZERS);
+ if (!check) {
+ //variance... due framework ancestry having different compilation settings
+ swapAssertion = true;
+ }
+ }
+
+ if (!swapAssertion) {
+ Assert.assertTrue("dynamic fields should match reference list", contentStringsMatch(getDynamicFields(testClass3), emptyArray));
+ } else {
+ Assert.assertFalse("dynamic fields should match reference list", contentStringsMatch(getDynamicFields(testClass3), emptyArray));
+ trace('[WARN] Variance: a test is technically wrong in javascript, but is expected to be wrong, because the compilation settings do not support it throughout the inheritance chain');
+ }
+ testClass3.test='true';
+ testClass3.x = 10;
+ testClass3.className = 'hello';
+
+
+ if (!swapAssertion) {
+ Assert.assertTrue("dynamic fields should match reference list",contentStringsMatch(getDynamicFields(testClass3),singleDynField));
+ } else {
+ Assert.assertFalse("dynamic fields should not match reference list",contentStringsMatch(getDynamicFields(testClass3),singleDynField));
+ trace('[WARN] Variance: a test is technically wrong in javascript, but is expected to be wrong, because the compilation settings do not support it throughout the inheritance chain');
+ }
+
+ }
+
+ [Test]
+ public function testGetDynamicFieldsWithPredicate():void {
+ const test:Object = {
+ 'test1':true,
+ 'test2':true,
+ '_underscore':true
+ };
+ const withoutUnderscores:Array = ['test1', 'test2'];
+ var excludeUnderscores:Function = function(prop:String):Boolean {
+ return prop && prop.charAt(0) != '_';
+ };
+ Assert.assertTrue("dynamic fields should match reference list",contentStringsMatch(getDynamicFields(test, excludeUnderscores), withoutUnderscores));
+
+ }
+
+ }
+}
diff --git a/manualtests/UnitTests/src/main/royale/flexUnitTests/reflection/support/DynamicTestClass.as b/manualtests/UnitTests/src/main/royale/flexUnitTests/reflection/support/DynamicTestClass.as
new file mode 100644
index 0000000..c1062a5
--- /dev/null
+++ b/manualtests/UnitTests/src/main/royale/flexUnitTests/reflection/support/DynamicTestClass.as
@@ -0,0 +1,89 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.reflection.support
+{
+
+
+
+ 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 reflection into it
+
+ /*public function DynamicTestClass(){
+
+ }*/
+
+
+ [TestMeta(foo="instanceMethod")]
+ public function method():void{
+
+ }
+
+ [TestMeta(foo="instanceMethod")]
+ public function methodWithArgs(mandatory:String,optional:Boolean=true):void{
+ _test = mandatory;
+ }
+
+ [TestMeta(foo="instanceVariable")]
+ public var testVar:String;
+
+ [TestMeta(foo="instanceAccessor")]
+ public function get testGetter():String{
+ return null
+ }
+
+ [TestMeta(foo="instanceAccessor")]
+ public function set testSetter(value:String):void{
+
+ }
+
+ private var _test:String;
+
+ [TestMeta(foo="staticMethod")]
+ public static function method():void{
+ }
+
+ [TestMeta(foo="staticMethod")]
+ public static function methodWithArgs(mandatory:String,optional:Boolean=true):void{
+ }
+
+ [TestMeta(foo="staticVariable")]
+ public static var testVar:String;
+
+ [TestMeta(foo="staticAccessor")]
+ public static function get testGetter():String{
+ return null
+ }
+
+ [TestMeta(foo="staticAccessor")]
+ public static function set testSetter(value:String):void{
+
+ }
+
+ private var private_var:Boolean;
+
+ protected var protected_var:Boolean;
+
+ private static var private_var:Boolean;
+
+ protected static var protected_var:Boolean;
+
+ }
+}
diff --git a/manualtests/UnitTests/src/main/royale/flexUnitTests/ReflectionTester.as b/manualtests/UnitTests/src/main/royale/flexUnitTests/reflection/support/DynamicTestClass2.as
similarity index 52%
copy from manualtests/UnitTests/src/main/royale/flexUnitTests/ReflectionTester.as
copy to manualtests/UnitTests/src/main/royale/flexUnitTests/reflection/support/DynamicTestClass2.as
index 74c5b4d..2be6a15 100644
--- a/manualtests/UnitTests/src/main/royale/flexUnitTests/ReflectionTester.as
+++ b/manualtests/UnitTests/src/main/royale/flexUnitTests/reflection/support/DynamicTestClass2.as
@@ -16,23 +16,44 @@
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////
-package flexUnitTests
+package flexUnitTests.reflection.support
{
- import flexUnitTests.reflection.*;
-
- [Suite]
- [RunWith("org.flexunit.runners.Suite")]
- public class ReflectionTester
- {
- public function ReflectionTester()
- {
- // see notes in CoreTester
- var arr:Array = [ReflectionTesterTest, ReflectionTesterTestUseCache, ReflectionTesterTestAlias];
- }
-
- public var reflectionTesterCacheTest:ReflectionTesterTestUseCache;
- public var reflectionTesterTest:ReflectionTesterTest;
-
- public var reflectionTesterAliasTest:ReflectionTesterTestAlias;
- }
+
+
+
+ dynamic public class DynamicTestClass2 extends TestClass1
+ {
+ //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 DynamicTestClass2(){
+ //his.constructorDynTest = 'constructorDynTest';
+ }
+
+ public var something:String;
+
+ [TestMeta(foo="staticMethod")]
+ public static function method():void{
+ }
+
+ [TestMeta(foo="staticMethod")]
+ public static function methodWithArgs(mandatory:String,optional:Boolean=true):void{
+ }
+
+ [TestMeta(foo="staticVariable")]
+ public static var testVar:String;
+
+ [TestMeta(foo="staticAccessor")]
+ public static function get testGetter():String{
+ return null
+ }
+
+ [TestMeta(foo="staticAccessor")]
+ public static function set testSetter(value:String):void{
+
+ }
+
+
+
+ }
}
diff --git a/manualtests/UnitTests/src/main/royale/flexUnitTests/ReflectionTester.as b/manualtests/UnitTests/src/main/royale/flexUnitTests/reflection/support/DynamicTestClass3.as
similarity index 62%
copy from manualtests/UnitTests/src/main/royale/flexUnitTests/ReflectionTester.as
copy to manualtests/UnitTests/src/main/royale/flexUnitTests/reflection/support/DynamicTestClass3.as
index 74c5b4d..ce73e9d 100644
--- a/manualtests/UnitTests/src/main/royale/flexUnitTests/ReflectionTester.as
+++ b/manualtests/UnitTests/src/main/royale/flexUnitTests/reflection/support/DynamicTestClass3.as
@@ -16,23 +16,21 @@
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////
-package flexUnitTests
+package flexUnitTests.reflection.support
{
- import flexUnitTests.reflection.*;
-
- [Suite]
- [RunWith("org.flexunit.runners.Suite")]
- public class ReflectionTester
- {
- public function ReflectionTester()
- {
- // see notes in CoreTester
- var arr:Array = [ReflectionTesterTest, ReflectionTesterTestUseCache, ReflectionTesterTestAlias];
- }
-
- public var reflectionTesterCacheTest:ReflectionTesterTestUseCache;
- public var reflectionTesterTest:ReflectionTesterTest;
-
- public var reflectionTesterAliasTest:ReflectionTesterTestAlias;
- }
+
+ import org.apache.royale.core.UIBase;
+
+ dynamic public class DynamicTestClass3 extends UIBase
+ {
+ //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 DynamicTestClass3(){
+
+
+ }
+
+
+ }
}
diff --git a/manualtests/UnitTests/src/main/royale/flexUnitTests/reflection/support/TestClass1.as b/manualtests/UnitTests/src/main/royale/flexUnitTests/reflection/support/TestClass1.as
index 829d14f..8132890 100644
--- a/manualtests/UnitTests/src/main/royale/flexUnitTests/reflection/support/TestClass1.as
+++ b/manualtests/UnitTests/src/main/royale/flexUnitTests/reflection/support/TestClass1.as
@@ -26,12 +26,13 @@ package flexUnitTests.reflection.support
{
public function TestClass1()
{
- var something:ITestInterface2;
+ // var something:ITestInterface2;
}
[Bindable]
[Event(name="foo", type="org.apache.royale.events.Event")]
public var bindableVar:String;
+
[Event(name="foo", type="org.apache.royale.events.Event")]
public var temp:Boolean;
diff --git a/manualtests/UnitTests/testsview/index.html b/manualtests/UnitTests/testsview/index.html
index 6d41e89..2806402 100644
--- a/manualtests/UnitTests/testsview/index.html
+++ b/manualtests/UnitTests/testsview/index.html
@@ -20,20 +20,20 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<style>
- .boxLeft {
- display:inline-block;
+ .boxLeft {
+ display:inline-block;
width:50% ;
- position:absolute;
- top:100px;
- bottom:15px;
+ position:absolute;
+ top:100px;
+ bottom:15px;
left:0px
}
- .boxRight {
- display:inline-block;
+ .boxRight {
+ display:inline-block;
width:50% ;
- position:absolute;
- top:100px;
- bottom:15px;
+ position:absolute;
+ top:100px;
+ bottom:15px;
right:0px
}
.pageStyles {
@@ -66,7 +66,7 @@
}
</style>
<script type="text/javascript">
-
+
console.API;
if (typeof console._commandLineAPI !== 'undefined') {
@@ -94,18 +94,31 @@
case SWAP_TO_RELEASE:
console.API.clear();
button.innerHTML = SWAP_TO_DEBUG;
- jsIframe.src = release;
- status.innerHTML = "Currently showing <em>"+JS_RELEASE+"</em>";;
+ jsIframe.src = release;
+ status.innerHTML = "Currently showing <em>"+JS_RELEASE+"</em>";;
break;
case SWAP_TO_DEBUG:
console.API.clear();
button.innerHTML = SWAP_TO_RELEASE;
- jsIframe.src = debug;
- status.innerHTML = "Currently showing <em>"+JS_DEBUG+"</em>";
+ jsIframe.src = debug;
+ status.innerHTML = "Currently showing <em>"+JS_DEBUG+"</em>";
break;
}
}
}
+
+
+ function onSwfFrameReady(){
+ //this supports intellij's 'launch in browser'
+ var swfFrameSource = "/target/bin-debug/UnitTests.html";
+ if (window.location.search) {
+ var append = window.location.search;
+ if (append) swfFrameSource += append;
+ if ( document.getElementById('swfIframe').src.indexOf(swfFrameSource) == -1) {
+ document.getElementById('swfIframe').src =".."+swfFrameSource;
+ }
+ }
+ }
</script>
</head>
<body class="pageStyles">
@@ -122,7 +135,7 @@
<iframe id="jsIframe" src="../target/javascript/bin/js-debug/index.html" frameborder="1" scrolling="no" height="100%" width="100%" align="left" ></iframe>
</div>
<div class="boxRight">
- <iframe id="swfIframe" src="../target/bin-debug/UnitTests.html" frameborder="1" scrolling="no" height="100%" width="100%" align="left" ></iframe>
+ <iframe id="swfIframe" onload="onSwfFrameReady()" frameborder="1" scrolling="no" height="100%" width="100%" align="left" ></iframe>
</div>
</div>
</body>