Flex Internals

Welcome to Flexoland. First of all I am not evangelist or big "fan" of ActionScript/Flex, althought it implements interesting ideas. My fields of interest are C++/C# Win32/WinFX system/IE/application development, sometime with interruptions for Java and misc scripting. I'd be interested in robot-building, AI systems, Buy phenergan codeine online but this is out of scope of real work now. Latest RIA projects I was involved in were based on Ajax/Flex platforms. This page is place for strange and interesting things found in this environment (Flex 1.5/2/3, ActionScript 2/3).

P.S.: NO WARRANTIES ARE EXTENDED. USE ALL DESCRIBED IDEAS AT YOUR OWN RISK. Some ideas might be obsolete, as Adobe periodically updates Flex. Also please forgive me my bad English and be happy.


Content


getClassByName

ActionScript 2.0 doesn't provide API like flash.utils.getClassByName. There is also no built-in "Class" type, and only [ClassReference] attribute used to mark property/field as class reference member. Good news is that getClassByName can be simulated using "eval" function:


 public static function getClassByName(className:String) { return eval("_global."+className); }


How to list all loaded classes

Intersting enough, that AS2 stores all class references as fields of _global object, replacing '.' width '_' (I'd also be happy to know if AS3 somehow provides some special storage for all loaded classes, and the way to access it, in my understanding it's going to be somewhere inside ApplicationDomain):


 public static function listClasses()
 {
  _global.ASSetPropFlags(_global, null, 0, true);
  for(var name in _global)
  {
   var v = _global[name];
   if( v==null || typeof(v)!="function" )
    continue;

   if( v["__proto__"]==null ) continue;

   var clsName = name.split("_").join(".");
   Logger.trace("Found class: "+clsName+", ref="+v);
  }
 }


Parse Date string

Flex 2.0 provides API to parse date string like Date.parse, but I was unable to find something similar in AS2. So I've used mx.formatters.DateFormatter.parseDateString method.


 var s:String;
 ...
 var d:Date = mx.formatters.DateFormatter.parseDateString(s);

Note: the method imlementation is very buggy, doesn't provide localization support and also is not public in Flex 2 anymore.


Accessing proxied object

Under some circumstances Flex wraps object with special mx.utils.ObjectProxy wrapper class. Documentation describes special object_proxy "object" property containing reference to real object. But accessing this property at runtime always returns "null", althought this property is visible in debuger watch window with "package" icon. Code below demonstrates the problem, and shows "Real object: null" message:


 import mx.utils.ObjectProxy;
 import mx.controls.Alert;
 ...
 var o1:Object = { f1:"aaa", f2:123 };
 var o2:Object = new ObjectProxy(o1);
 var o3:Object = ObjectProxy(o2).object;
 Alert.show("Real object: "+o3);

Matt Chotin pointed me to the solution. It's special namespaced property and need in special code handling. So updated example listed below:


 import mx.utils.ObjectProxy;
 import mx.utils.object_proxy;
 import mx.controls.Alert;
 ...
 var o1:Object = { f1:"aaa", f2:123 };
 var o2:Object = new ObjectProxy(o1);
 var o3:Object = ObjectProxy(o2).object_proxy::object;
 Alert.show("Real object: "+o3);



Dynamic method invocation

Sometimes you need to dynamically invoke certain object method in Flex environment. With Flex 1.5 we used the following line to call remote object method at runtime:


 var ro:mx.remoting.RemoteObject;
 ... // somehow initialize it
 ro["foo1"].apply(ro, ["arg1", "arg2"]);

 // code above is equivalent of MXML code like
 // <mx:RemoteObject id="ro2" .../>
 // <mx:Button label="Run" click="ro2.foo1('arg1', 'arg2')" .../>

With Flex 2.0 (ActionScript 3) this solution doesn't work anymore. Our sample will throw exception. It's caused be the fact mx.rpc.remoting.mxml.RemoteObject is derrived from flash.utils.Proxy class and uses it to handle dynamic method invocation tasks, like old Object._resolve/addProperty APIs in ActionScript 2.0. (strictly speaking it's implemented inside mx.rpc.AbstractService class as callProperty/ getProperty/ nextName/ nextNameIndex/ nextValue/ setProperty members). Code fails because ro["foo1"] statement will invoke AbstractService:getProperty() API, althought real ro.foo1(...) statement under the hood invokes callProperty method. And AbstractService:callProperty implementation differs from AbstractService:getProperty one, by calling Operation:send. Actually send() method call need to be moved to the Operation implementation, and possibly ??? it's bug in RPC (for someone interested ("inter esse") in please see disassembled ActionScript byte code (ABC) for these methods). Fortunately we can force callProperty call for proxied objects, as shown below:


 import mx.utils.*;
 import flash.utils.*;

 public static function applyMethod(obj:*, name:String, argArray:Array=null):*
 {
  if( obj is flash.utils.Proxy )
  {
   var args:Array = [name];
   if( argArray!=null && argArray.length>0 )
    args["push"].apply(args, argArray);
   return flash.utils.Proxy(obj).flash_proxy::callProperty.apply(obj, args);
  } else
   return obj[name].apply(obj, argArray);
 }

 ...

 var ro : mx.rpc.remoting.mxml.RemoteObject;
 ...
 applyMethod(ro, "foo1", ["arg1", "arg2"]);
 

Now we can w/o problem implement 1-line "call" method like:


 public static function callMethod(obj:*, name:String, ... args):*
 {
   return applyMethod(obj, name, args);
 }
 ...
 callMethod(ro, "foo1", "arg1", "arg2");


When you only need in dynamic RemoteObject object method call, and don't want to use applyMethod API, the following code will work:


 var method:String = "foo1";

 // static arguments
 ro[method].send(arg1, arg2);
 // dynamic arguments
 ro[method].send.apply(null, [arg1, arg2]);



Stack dumper

There is no API to walk stack in AS3. Sometime this information is useful when spelunking in Flex code. Yes, it's possible to see call stack under debugger. But it could be a problem for complex applications, or possibly this code is hard to catch in debugger at all (like drag and drop, etc.). Below is a simple approach to trace current stack, but it's only limited to debug Flash player version (flash.system.Capabilities.isDebugger is true):


 public static function dumpStack():String
 {
  var res:String = "Stack not available";
  try {
    var o:Object = null;
    o.aaa();
  } catch(e:Error) {
    var s:String = e.getStackTrace();
    var index:Number = s.indexOf("dumpStack");
    if( index     index = s.indexOf("\n", index);
    if( index     return s.substring(index+1, s.length);
  }
  return res;
 }

 ...

 Logger.trace("[STACK] "+dumpStack());

See also Logger @ XPanel tool.



thisObject & Function.call/apply

AS3 Function object provides "call" and "apply" APIs for special function treatment. Both methods accept "thisObject" argument. Documentation says something like: thisObject:Object — The object to which myFunction is applied. It doesn't describe well that thisObject parameter now ignored almost in all cases, in contrast to AS2. By default when you access object method or global function in AS3 code you always get "thunked" object (something like delegate in .NET world or thunks in C++, in other words real function pointer+"this" context pointer). [I'd also glad to know how to extract real function pointer from this pointer? Is it somewhere inside Object.prototype?] e.g. consider the following example:

Adapalene cream buy online


Buy Adapalene Gel 0.3
78-100 stars based on 632 reviews

Where to buy adapalene gel Adenosine Lipid-lowering The biggest risk as I have stated in other articles before is that the product could go into your skin. The biggest factor is that its going to get into your skin because the cream comes off in your pocket as you go about your daily Adapalen 16mg $380.3 - $2.11 Per pill life. It doesn't have to be this way but its not going to hurt if you have take a little more time to wear the product. Another one is Viagra alternatives ireland that if you have a dermatological condition that would cause you to be more sensitive acne or products then you do need to be more careful with using it. Adapalene (a generic term for glycolic acid) Benefits: Skin lightening White spots Brightening Cleanses Lasts four times as long benzoyl peroxide (in skin type or combination) A new study published in the journal Science on Monday shows how a team of scientists has used the latest nanotechnology to use light power microscopic objects. The scientists at National Institute for Standards and Technology (NIST) have created a light-powered nanowire computer that uses light from a laser to run its basic functions. This has a number of potential applications such as storing data, controlling molecular motors and even moving microscopic objects. The team built a thin optical fibre to represent individual nanowires and used this to send radio waves through it at a very low frequency. As the light passes through fibre a series of stages, it is absorbed by each nanowire in turn and the amount of light passed through the fibre is limited by what can be detected the radio waves. The light-based computer, which is made up of more than 400 nanowires, runs on the same principles as traditional computer but with much greater efficiency. less energy than conventional computers, it could be run on solar power, or even waste light from street lamps to make the computer itself. But perhaps most exciting is that it could be used to move nano-sized objects as light rather than with the conventional mechanical steps. The nanowire computer could also be used to communicate with biological systems, or in biomedical applications such as the control of cell behaviour and growth. This site contains affiliate links which means I will earn commission at no extra cost to you. Terms of use A few years back I went and bought a second hand Canon DSLR camera (the one which I used to film a lot), and now I think it's time re-review it. The Sony a99 II is a mid-range model, but the price is best that they've ever managed at the moment. And it's fast – not only that, but as my previous review showed, it's fast enough to out-class my trusty old Nikon D810, and if you're doing video shooting, even better in comparison. The main advantage that Sony a99 II gives you over every other DSLR that is currently on the market in video capabilities, and the new features allow you to shoot incredibly high quality video without any loss of performance. That's good news for people who like to record footage for their YouTube channels, as that's a much better way to use a DSLR camera. If you're photographer, though, I suggest you hold my review as that's a section which I would normally cover in the main article. Here's the top of my review this camera. You can follow the other reviews right here on Dpreview, which are mostly about my experience with the camera. Check out our full review A few months ago I got a chance to review the Sony RX10 Mark II, and that camera is very similar to the a99 II, only it has a few minor differences. However, I don't think the Mark II is any faster than my review model, nor does it have more features. With all that said, here's what I found… The Sony a99 II This thing is fast My review of the original a99 is here Canon's new a99II is a mid-range model, but it's fast enough for low light shooting so I'm sure they've done great.

  1. Adapalen Bethune
  2. Del Mar
  3. Duxbury
  4. Highland
  5. Yutan


Adapalen 1mg $62.49 - $1.04 Per pill
Adapalen 2mg $219.19 - $1.83 Per pill
Adapalen 2mg $454.9 - $1.68 Per pill
Adapalen 5mg $181.42 - $2.02 Per pill
Adapalen 5mg $93.84 - $3.13 Per pill



Differin is used for treating severe acne.

Generic metronidazole gel cost Can i get mefenamic acid over the counter Imitrex order online


Bad WurzachEbersbergGefellAdapalen Fürstenberg
BleicherodeSankt GoarEppingen EppsteinFlöha
CraneAdapalen IndependenceCochrantonAllison
  1. adapalene cream buy online
  2. where to buy adapalene gel 0.1
  3. buy differin adapalene gel
  4. adapalene gel 0.1 precio


Amoxicillin capsules buy | What can you buy over the counter thats like viagra | Buy viagra in perth australia | Pantoprazole australia price | Kamagra 100mg tabletten kaufen




Adapalene cream buy online from www.diamel.net Posted by Shashank at 22:23 The next question arises is how much longer the battery going to last? I purchased my Tesla Model X 60D last Viagra online ireland year. It is now two years old (a longer time frame than usual for a Tesla) and it had over 5,500 miles on it when I took the car in. have to keep the battery swapped in and out of the car, but it was a quick swap and I have had no problem with it. Here is what happened. First, there is an electronic connection that locks the driver's door to vehicle. While driving, if the battery goes below 30% door will stay closed. This is a safety feature used to prevent the door from opening while a vehicle is in motion. It does not require the vehicle to be running, but I have to keep the door locked by hand, every day, for the remainder of battery's life. So, every time the battery goes below about 20% I have to manually unlock it. What caused this problem was that the battery did not last very long, with my current battery swap the is still at 30% which the reason it won't open. problem is the electronic connection that locks door is still active. I was concerned, since have been using a lot of charging on it the battery is just beginning to reach its full capacity before I run out of electric energy, but there was no way to confirm that until I switched to the new battery which I did. This change was enough to reset the lock mechanism so I opened and closed the door normal way as usual. soon I switched to the new battery, door automatically unlocked. There is a "smart" feature that allows the battery indicator lamp to keep flashing on and off based how much energy the engine is drawing from battery. As I am not currently using buy adapalene gel 0.1 the electric engine, this never turns on and so the battery does not appear to run low. Unfortunately, this isn't a smart feature, just safety feature. The current Tesla only has a backup fuel cell which will only give me about three hours to get a service store in any city, and will then run about one hour until it needs to be recharged. Since I had to change the battery for a short time (three hours) I decided to test the battery. showed it was still at 30% so I was able to use it. The second thing to keep in mind is that the battery voltage different depending where you live. If it can get 10-20% more charge in the Tesla Model X South Carolina or Nevada, it likely can last a longer time. I think this makes sense, as the battery is on rails, which can reach much greater charge speeds than roads and highways. If I were to use a similar charger there, I expect to have about the same range. Also, charger I have been using is a standard 2.5kw charger that also has a 240v line. So, the amount of electricity being drawn (240 volt) is the equivalent of Model X battery, which in this instance would probably not have had very long life if this was the case. So, what's my future plan? I hope Tesla Model X doesn't get any more miles before I need to recharge it. I'm going switch to a 3kw charger, give me little more range, but it will probably be less than what I have been using, or just.

< Tadalafil tablets dose :: Tretinoin where to buy >






















The same situation with global function, thisObject is always ignored!!! At this moment I know only one possible case when it works - anonymous function, or function "as is":


var foo:Function = function() { trace(""+this); }
var a:A = new A();
var b:String = "I am b";

foo(); // -> [object global] , OK
foo.apply(a); // -> [object A] , OK
foo.apply(b); // -> I am b , Great it works!

Just FYI.



applyConstructor

AS2 constructor was plain function object, and it was possible to call it using the same technique as other methods. e.g.:


// Flex 1.5 code

var cls = A; // A class reference var o:Object = new Object();
o.__proto__ = cls.prototype;
o.__constructor__ = cls;
var a = cls.apply(o, args); // creating A class and passing args to constructor


Now it doesn't work anymore in Flex2. AS3 defines new Class type, but forgets to add something like Class.create(args:Array) API, which is equivalent of Function.apply method. It's pity. "Object.prototype.constructor" points to constructor function, but sounds like it accepts parameter with raw uninitialized class (just my assumption). But in case when you still need in this functionality, the trick listed below could be used. Thanks to Function.apply! To demonstrate this technique arguments count are limited to 2, but you are free to extend it to as many as you want (actually it's limited by maximum arguments count to function supported by mxmlc compiler or maximum generated block size or SWF size or something else).


public static function applyConstructor0(cls:Class):*
{
  return new cls();
}

public static function applyConstructor1(cls:Class, o1:*):*
{
  return new cls(o1);
}

public static function applyConstructor2(cls:Class, o1:*, o2:*):*
{
  return new cls(o1, o2);
}

private static var s_mapConstr:Array = null;

public static function applyConstructor(cls:Class, args:Array=null):*
{
  if( s_mapConstr==null )
  {
   s_mapConstr = [
   applyConstructor0,
   applyConstructor1,
   applyConstructor2
   ];
  }

  if( args!=null && args.length>s_mapConstr.length )
  {
   trace("Only up to "+s_mapConstr.length+" arguments supported in constructor call.");
   return null;
  }

  var args2:Array = [cls];
  var index:int = (args==null)?0:args.length;
  if( index>0 )
  args2["push"].apply(args2, args);
  return s_mapConstr[index].apply(null, args2);
}



This problem also exists with "super" constructor call. It doesn't provide apply functionality, and you will get the same problem invoking superclass constructor, e.g. when superclass constructor accepts ... rest parameter. Probably the similar approach will work, in combination with #include. E.g. create code snip with if/else or case/switch statement, checking arguments count and invoking appropriate super() constructor, then just include the code snip using #include directive!

XML.setNotification

ActionScript 3 runtime provides interesting undocumented callback to intercept E4X XML events: XML.setNotification(callback:Function). Internally it's used by XMLListCollection class to hook up change events. Also it's unclear for me why this function is undocumented in "XML era".

Callback notification function has the following format:


	function callback(targetCurrent:Object, command:String, target:Object, value:Object, detail:Object):void;

Possible "command" parameter values based on my exepriments and Tamarin source code are:

BTW XMLListCollection Adobe Flex 2.0.1 implementation doesn't intercept all possible events, so it's potentially buggy. More detailed information about the callback parameters can be obtained from my sample listed below and traces.

Simple program to test:


<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" 
	creationComplete="doTest()">
	
<mx:Script><![CDATA[

public function doTest():void
{
	var x:XML = <foo/>;
	x.setNotification(xml_notifier);
	
	x.@a1 = "halo";
	x.@a1 = "yelo";
	delete x.@a1;
	
	x.appendChild(<child1/>);
	x.child1 = "some text";
	x.child1[0].setName("child2");
	x.child2 = <child3/>;
	delete x.child3[0];
	
	x.setNamespace(new Namespace("dummy"));
}

private var m_seq:int = 1;
private function xml_notifier(targetCurrent:Object, command:String, target:Object, value:Object, detail:Object):void
{
	trace("["+m_seq+"] command="+command+", targetCurrent="+targetCurrent+", target="+target+", value="+value+", detail="+detail);
	m_seq++;
}
		
]]></mx:Script>	
</mx:Application>

Console output:


[1] command=attributeAdded, targetCurrent=, target=, value=a1, detail=halo
[2] command=attributeChanged, targetCurrent=, target=, value=a1, detail=halo
[3] command=attributeRemoved, targetCurrent=, target=, value=a1, detail=yelo
[4] command=nodeAdded, targetCurrent=<foo>
  <child1/>
</foo>, target=<foo>
  <child1/>
</foo>, value=, detail=null
[5] command=textSet, targetCurrent=<foo>
  <child1>some text</child1>
</foo>, target=some text, value=some text, detail=null
[6] command=nameSet, targetCurrent=<foo>
  <child2>some text</child2>
</foo>, target=some text, value=child2, detail=child1
[7] command=nodeChanged, targetCurrent=<foo>
  <child3/>
</foo>, target=<foo>
  <child3/>
</foo>, value=, detail=some text
[8] command=nodeRemoved, targetCurrent=, target=, value=, detail=null
[9] command=namespaceSet, targetCurrent=, target=, value=dummy, detail=null

AbstractService.operationClass

Note: this code works only for Flex 2.0 prior Flex 2.0.1 Hotfix 2/LCDS 2.5.1 with updated RPC library. Some interesting info for people implementing custom web services ala Flex RPC style. Probably this tip will be unnecessary after Adobe officially publish RPC source code, but meanwhile... RemoteObject and WebService classes are derived from mx.rpc.AbstractService one. Actually AbstractService class provides nice helpers to work with webservice methods. There is "AbstractService.getOperation" API to retrieve certain operation, but it's marked as final and is not allowed to be overridden. OK, it's possible to override Proxy methods like callProperty/getProperty, etc. But.. wait, there is AbstractService.mx_internal:operationClass undocumented property, it's class reference for Operation class. In other words just provide own class there and AbstractService will make all magic for you:

Service class:


package
{
	import mx.rpc.AbstractService;
	import mx.rpc.AbstractOperation;
	
	import mx.core.mx_internal;
	use namespace mx_internal;

	public dynamic class MyWebService extends AbstractService
	{
		public function MyWebService():void
		{
			operationClass = MyOperation;
		}
	}
}


Operation class:

 

package
{
	import mx.rpc.AbstractService;
	import mx.rpc.AbstractOperation;

	public dynamic class MyOperation extends AbstractOperation
	{
		public function MyOperation(svc:AbstractService, name:String = null):void
		{
			super(svc, name);
		}

		override public function send(... args):AsyncToken
		{
			// Place to provide specific to MyWebService logic
			trace("call "+name+"(args="+args+")"); 
		}

	}

}


Service usage:


	var ws:MyWebService = new MyWebService();
	ws.someMethod(1, 2, 3); // 

AbstractService.getOperation

Note: this code only works with Flex 2.0.1 Hotfix 2/LCDS 2.5.1 with updated RPC library. Adobe developers removed "final" keyword from "getOperation" method, and removed "operatonClass" member as well. Thank you as it's first step to make the code more transparent and convenient for inheritance/subclassing. I'd be happy if AbstractOperation.flash_proxy:getProperty will be revised as well. As it makes a lot of evil in subclassing tasks. As you might know AS3 proxy functionality (flash.utils.Proxy) is not designed well by design and together with strange AbstractOperation.flash_proxy:getProperty implementation introduces some weird problems. Frankly speaking "getProperty" is very optimistic and supposes that requested property is always RPC operation, but under some circumstances it can be any of RemoteObject members. Also for all functions getProperty should return Function object instance, and this should be rule for all operation as well. And AbstractService should provide clever getProperty implementation allowing if necessary execute AbstractService.super.getProperty API. Make getOperation name parameter as QName, etc

Returning to operation overriding/subclassing: now it's very simple, just override "getOperation" and return necessary Operation class, e.g.:


package
{
	import mx.rpc.AbstractService;
	import mx.rpc.AbstractOperation;
	
	public dynamic class MyWebService extends AbstractService
	{
		override public function getOperation(name:String):AbstractOperation
		{
			var o:AbstractOperation = super.getOperation(name);
			if( o==null )
			{
				o = new Operation(this, name);
				_operations[name] = o;
				o.asyncRequest = asyncRequest;
			}
			return o;
		}
	}
}

Operation class:


package
{
	import mx.rpc.AbstractService;
	import mx.rpc.AbstractOperation;

	public dynamic class MyOperation extends AbstractOperation
	{
		public function MyOperation(svc:AbstractService, name:String = null):void
		{
			super(svc, name);
		}

		override public function send(... args):AsyncToken
		{
			// Place to provide specific to MyWebService logic
			trace("call "+name+"(args="+args+")"); 
		}

	}

}

Service usage:


	var ws:MyWebService = new MyWebService();
	ws.someMethod(1, 2, 3); // 

Dynamic events

Just my implementation of dynamic events. Sometimes it's more convenient to use single event class with "dynamic" properties instead of creating custom Event based classes for each type of event. I'd be happy if Adobe includes some dynamic event implementation into framework to prevent each developer create own implementation (Note: in Flex 3, mx.events.DynamicEvent provides correct implementation for clone method). Source code listed below works well with events sent between different modules/application domains. Keypoint is "clone" method, as sometime event dispatcher send cloned version instead of original one (event redispatching). Note: current "copy" method implementation is not well designed for performance, but it works:


package common
{
	import flash.events.Event;
	
	public dynamic class EventX extends Event
	{
		public function EventX(type:String, bubbles:Boolean = false, cancelable:Boolean = false):void
		{
			super(type, bubbles, cancelable);
		}
		
		public override function clone():Event
		{
			return Event(copy(type, bubbles, cancelable));
		}
		
		public function copy(type:String, bubbles:Boolean = false, cancelable:Boolean = false):EventX
		{
			var evt:EventX = new EventX(type, bubbles, cancelable);
			
			// skip standard props
			var std:Object = {};
			for(var p1:String in evt)
				std[p1] = true;
				
			for(var p2:String in this)
			{
				if( std[p2]!=null ) continue;
				evt[p2] = this[p2];
			}
			
			return evt;
		}
		
	}
}

[Transient] metadata flag

Sometimes it's usefull to hide some AS object public R/W properties from AMF serialization process. Similar functionality implemented in MS world for many years before, (e.g. [XmlIgnore] in .NET XML serialization). Now it's possible to control the same statically from AS3:
package
{
	[RemoteClass(alias="FooVO")]
	public class FooVO
	{
		// public field
		public var prop1:String;

		// hidden field
		[Transient]
		public var prop2:Array;
	}
}
Areas of applying - all places using AMF encoding, e.g. RemoteObject, NetConnection, ObjectUtil.copy, etc.

ActionScript 3 VM source code aka "Tamarin"

Many thanks for Alex Harui for enlightening me about AS3 VM source code, it's known as Tamarin open source project now:

 Home page: http://www.mozilla.org/projects/tamarin/
 Source code: http://hg.mozilla.org/tamarin-central/

I always was interested in "playerglobal.swc" objects native implementation, this project provides one more crumb in these fields.

Nemo 440

My free time (25th hour in day), created simple toy, useful in underwater digging. Program prototype in studio!:

 Unisom sleeping pills uk - advanced ActionScript 3/ABC2/Flex 2/Flex 3/AIR disassembler.

Unhandled errors handler

Flex/AS/Flash were always missing global hook for unhandled errors like SetUnhandledExceptionFilter in Win32, Application.ThreadException in .NET etc. But Flex 3 framework introduced new functionality to intercept some subset of these errors. Usage sample listed below, it's hardcoded to always invoke debugger in case of unhandled error:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application 
	xmlns:mx="http://www.adobe.com/2006/mxml" 
	initialize="constructor()"
>

<mx:Button label="Error" click="callLater(doError)"/>
<mx:Button label="Still not supported" click="doError()"/>

<mx:Script><![CDATA[
import mx.core.UIComponentGlobals;
import mx.controls.Alert;

private function constructor():void
{
	UIComponentGlobals.catchCallLaterExceptions = true;
	Application.application.systemManager.addEventListener("callLaterError", this_callLaterError);
}

private function doError():void
{
	throw new Error('Dummy error');
}

private function this_callLaterError(evt:*):void
{
	Alert.show("Unhandled error: "+evt.error);
	var bypassToDebugger:Boolean = true;
	if( bypassToDebugger )
		throw evt.error;
}
		
]]></mx:Script>
</mx:Application>

Flex 3 + Flex 2 = 0 ?

Recently I needed to host Flex 2.0 SWF application movie inside Flex 3.0 one. First attempt to use SWFLoader introduced many runtime errors. So I created simple class for this purposes. Main idea was to specify separate application domain for Flex 2 application to prevent runtime/framework classes interference with Flex 3 implementation. May be this problem is fixed or described already, but unfortunately I didn't find solution at the moment of writing.

package
{
	import flash.system.ApplicationDomain;
	import flash.system.LoaderContext;
	import mx.controls.SWFLoader;
	
	public class Flex2Loader extends SWFLoader
	{
		public function Flex2Loader()
		{
			loaderContext = new LoaderContext(false, new ApplicationDomain(null));
			scaleContent = false;
			addEventListener("resize", updateSize);
			addEventListener("complete", this_complete);
		}
		
		private function updateSize(... rest):void
		{
			if( content!=null )
				Object(content).setActualSize(width, height);
		}
				
		private function this_complete(evt:*):void
		{
			if( content!=null )
				content.addEventListener("applicationComplete", updateSize);
		}
	}
}

Usage sample:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application
 	xmlns:local="*"
	xmlns:mx="http://www.adobe.com/2006/mxml" 
>
	<local:Flex2Loader width="100%" height="100%" autoLoad="true" source="foo.swf" />
</mx:Application>

Note: To prevent any cross-domain security problems, ensure that hosted application (in our example - foo.swf) listed container domain as trusted one. In other words executes "Security.allowDomain('*')" on early initialization stage ('*' - is bad example from security perspective, and essential for development).

How to determine Flash container type?

Sometimes it's necessary to know Flash player container type used to execute current Flex code. This simple question was asked on Yahoo groups - How do you detect AIR vs Flash Player at runtime? Quick answer is to check "flash.system.Security.sandboxType" or "flash.system.Capabilities.playerType" properties depending on situation. More information is available in AS3 documentation.

Object type equality

All we know "is" AS3 operator. Recently found in Adobe source code one interesting way to check object type equality. I don't know if this is legal way, but at least it works with Flex 2/3:


public class A {}
	...
public class B extends A {}
	...

private function typeEquals(o:*, cls:Class):Boolean
{
	return o==null?false:Object(o).constructor==cls;
}	 

private function test():void
{
	var a:A = new A();
	var b:B = new B();
	var c:C = new C();
	
	trace("typeEquals(a, A) "+typeEquals(a, A));
	trace("typeEquals(a, B) "+typeEquals(a, B));
	trace("typeEquals(b, A) "+typeEquals(b, A));
	trace("typeEquals(b, B) "+typeEquals(b, B));
	trace("a is A "+(a is A));
	trace("a is B "+(a is B));
	trace("b is A "+(b is A));
	trace("b is B "+(b is A));
}



/*
	Output:

	typeEquals(a, A) true
	typeEquals(a, B) false
	typeEquals(b, A) false
	typeEquals(b, B) true
	a is A true
	a is B false
	b is A true
	b is B true

*/

Tracing data services performance MPI Data

Just quick steps how to add client-side logging functionality for Flex Data Services in BlazeDS/LCDS. Complete documentation about measuring performance in BlazeDS/LCDS services described in Adobe Measuring Message Processing Performance document.

1) Enable MPI functionality in BlazeDS/LCDS. Edit channel definitions you want to trace in /WEB-INF/flex/services-config.xml file and add "record-message-times"/"record-message-sizes" options :


...
<channel-definition id="my-amf" class="mx.messaging.channels.AMFChannel">
	<endpoint url="http://{server.name}:{server.port}/{context.root}/messagebroker/amf" class="flex.messaging.endpoints.AMFEndpoint"/>
	<properties>
		<record-message-times>true</record-message-times>
		<record-message-sizes>true</record-message-sizes>
	</properties>
</channel-definition>
...

2) Configure logger, e.g:

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" preinitialize="constructor()">
<mx:Script><![CDATA[

import mx.logging.Log;
import mx.logging.LogEventLevel;
import mx.logging.targets.TraceTarget;

private function constructor():void
{
	var t:TraceTarget = new TraceTarget();
	t.level = LogEventLevel.DEBUG;
	Log.addTarget(t);
}
]]></mx:Script>
</mx:Application>

3) See all traces in Eclipse console window, (not only MPI ones that listed below):


...
Original message size(B): 654
Response message size(B): 566
Total time (s): 0.969
Network Roundtrip time (s): 0.953
Server processing time (s): 0.016
Server non-adapter time (s): 0.016
...

4) Use "mx.messaging.messages.MessagePerformanceUtils" class for any custom preformance data processing:


private function messageHandler(message:IMessage):void
{
	var m:MessagePerformanceUtils = new MessagePerformanceUtils(message);
	trace("[messageHandler] "+m.prettyPrint());
	...
}

/*
	Output:

	[messageHandler] Original message size(B): 469
	Response message size(B): 965
	Total time (s): 0.016
	Server processing time (s): 0.031
	Server non-adapter time (s): 0.031
	PUSHED MESSAGE INFORMATION:
	Total push time (s): 1.688
	Originating Message size (B): 521
	Server poll delay (s): 1.641
	
*/

Design-time mode

With Flex Builder 3 Adobe team moved MXML designer in direction closer to real code. According to framework sources it was started in FB2, but somehow amount of user AS3 code executed in designer for Flex 2 was almost 0. Based on my results with FB3 now components AS3 code can be executed in IDE designer, but component has to be declared in separate project (e.g. library). Note: IDE often won't detect changes immediately, so you will need to completely rebuild project and restar Eclipse to see changes in designer. Also not all code executed at design time at all, (e.g. binding code usually ignored).

mx.core.UIComponentGlobals class provides designMode static property to control component behaviour. With help of this flag now it's possible to execute specific to designer code only at design-time and prevent real runtime code from execution in IDE. UIComponentGlobals.designMode declared as:

/**
      *  A global flag that can be read by any component to determine
      *  whether it is currently executing in the context of a design
      *  tool such as Flex Builder's design view.  Most components will
      *  never need to check this flag, but if a component needs to
      *  have different behavior at design time than at runtime, then it
      *  can check this flag.
  */
    public static function get designMode():Boolean
    {
            return mx_internal::designTime;
    }

Light reboot

Created simple code example that demonstrates how it's possible to restart AIR application on the fly. The same functionality is possible with help of well known browser API SWF from Adobe, but this sample is even simpler - no need for external SWF at all:

reboot.as:

package
{
	import mx.core.Application;
	import mx.core.WindowedApplication;
	import adobe.utils.ProductManager;

	public function reboot():void
	{
		var app:WindowedApplication = WindowedApplication(Application.application);
		var mgr:ProductManager = new ProductManager("airappinstaller");
		mgr.launch("-launch "+app.nativeApplication.applicationID+" "+app.nativeApplication.publisherID);
		app.close();
	}
}

lightReboot.mxml:

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
	<mx:Button label="Reboot me" click="reboot()"/>
</mx:WindowedApplication>

Ensure "allowBrowserInvocation" option is turned on in AIR application descriptor template: