Compilation d'AS3 en AS3

Tags :

J’ai découvert il y a quelques temps deja, un petit framework contenant une partie du code de tamarin, dans ces premiers commits, et qui permet donc de compiler de l’AS3 avec le Flash Player, moyennant quelques adaptations d’écritures, et quelques issues à connaitre.

L’idée, c’est que l’application cliente ne dispose que des interfaces des classes, pour qu’en cas de décompilation, les classes critiques ne puissent être obtenues.

Applications

Imaginons, un serveur socket, binaire ou xml, qui discute avec son application cliente, elle reçoit en AMF3 ou sous forme Hexa, un String compréssé, modifié, et crypté. On reçoit ce String, on le décompresse, on le décrypte, etc, et on en arrive à la compilation proprement dite.

On peut aussi imaginer tout un tas d’autre cas d’utilisations :

Il faut savoir que sur le framework en question, les seuls trucs utiles à garder, c’est :

Le Compileur en AS3 pur, d’une il marche pas, de deux, il est lent, et de trois, il est tellement mal écrit, qu’il y a 3000 warnings et aucun typage, en gardant que les classes et packages nommés plus haut, il ne devrait plus y avoir de soucis.

Utilisation

Donc la création et la compilation d’une classe au runtime est assez facile, au niveau de la syntaxe, la seule chose qui change, c’est les import :

/*
import flash.utils;
devient :
*/
namespace utils = "flash.utils"; 
use namespace utils;

Prenons une classe toute simple :

namespace event = "flash.events"; 
use namespace event;
public class MyClass extends EventDispatcher
{
	private static var ID : int = 0;
	
	private var _label : String;
	private var _id : int;
	
	public function MyClass ()
	{
		_id = ID;
		ID++;
	}
	
	public function get id () : int
	{
		return _id;
	}
	
	public function set label (value:String) : void
	{
		if (_label != value)
		{
			_label = value;
			dispatchEvent(new Event('labelChanged'));
		}
	}
	
	public function get label () : String
	{
		return _label;
	}
}

Imaginons que le code précédent est stocké dans une variable maClass sous forme de String :

var c : CompiledESC = new CompiledESC ();
var classDump : ByteArray = c.eval(maClass);
var swf : ByteArray = ByteLoader.wrapInSWF([classDump]);
/* ici vous pouvez au choix, loader votre classe dans le LoaderContext qui vont convient : */
var l : Loader = new Loader ();
var lc : LoaderContext = new LoaderContext (false,ApplicationDomain.currentDomain,null);
l.contentLoaderInfo.addEventListener(Event.COMPLETE,onLoaderComplete,false,0,true);
l.loadBytes(swf,lc);
/* et plus loin, dans votre */
private function onLoaderComplete (e:Event) : void
{
	if (ApplicationDomain.currentDomain.hasDefinition('MyClass'))
	{
		var c : Class = ApplicationDomain.currentDomain.getDefinition('MyClass') as Class;
		var instance : * = new c ();
		trace (instance.id);
	}
}

Les quelques problèmes rencontrés, en vrac :

Sinon, ça marche plutôt bien, et ça permet de faire des choses assez sympas :), en esperant que Flash 10 ne casse pas tout :)