package {
import com.hurlant.eval.ByteLoader;
import com.hurlant.eval.CompiledESC;
import com.hurlant.eval.dump.ABCDump;
import com.hurlant.jsobject.JSObject;
import com.hurlant.util.Hex;
import flash.display.Sprite;
import flash.external.ExternalInterface;
import flash.utils.ByteArray;
import flash.utils.getDefinitionByName;
import flash.utils.setTimeout;
public class ScreamingDonkey extends Sprite
{
private var esc:CompiledESC = new CompiledESC;
private var queue:Array = [];
private static var instance:ScreamingDonkey; private var jsobject:JSObject;
private var hex:Hex;
private var abcdump:ABCDump;
public function ScreamingDonkey()
{
if (ExternalInterface.available) {
ExternalInterface.marshallExceptions=true;
ExternalInterface.addCallback("eval", eval);
ExternalInterface.addCallback("enqueueScript", enqueueScript);
ExternalInterface.addCallback("runQueue", runQueue);
ExternalInterface.addCallback("trace", trace); checkForEsc();
}
instance = this;
}
private function checkForEsc():void {
try {
var compile:Function = getDefinitionByName("ESC::compile") as Function;
} catch(e:Error) {
setTimeout(checkForEsc, 100);
return;
}
firstScript();
ExternalInterface.call("HURLANT_donkey_escReady");
}
private function firstScript():void {
var globals:Array = [ "document", "top", "parent", "self", "history", "navigator", "screen", "opener", "location", "frames",
"alert", "confirm", "prompt", "XMLHttpRequest" ];
var pre:String =
"namespace DOM = 'com.hurlant.jsobject';\n" +
"use namespace DOM;\n" +
"ESC function eval_hook(){};\n" + "var window = JSObject.getWindow();\n" +
"var eval2 = ScreamingDonkey.eval2;\n";
for each (var n:String in globals) {
pre += "var "+n+" = window."+n+";\n";
}
enqueueScript(pre, 0, "scopeSetter"); }
/**
* Plain "eval"-like method, who doesn't try to hard:
* - no scopes, no callback. no worries
*
* @param script
*
*/
private function eval(script:String):void {
try {
var bytes:ByteArray = esc.compile(script);
ByteLoader.loadBytes(bytes, true);
} catch (e:Error) {
trace("Error in eval: "+e);
throw e;
}
}
/**
* More full-featured eval. Still not synchronous, but we make up
* for it with a user-defined scope array and a callback.
* Scopes are implemented with "with", because it's easy and I'm cheap.
*
* @param script
* @param scopes
* @param callback
* @return
*
*/
public static function eval2(script:String, scopes:Array = null, callback:Function = null):* {
return instance.esc.evaluateInScopeArray(script, scopes, callback);
}
private function enqueueScript(script:String, index:int, name:String):void {
try {
script = "namespace _flash_utils = 'flash.utils';\n" +
"use namespace _flash_utils;\n" +
script;
var bytes:ByteArray = esc.compile(script, name);
queue[index] = bytes;
} catch (e:Error) {
trace("Error in eval: "+e);
throw e;
}
}
private function runQueue():void {
var q:Array = [];
for (var i:int=0;i<queue.length;i++) {
if (queue[i] is ByteArray) {
q.push(queue[i]);
}
}
queue =[]; ByteLoader.loadBytes(q, true);
}
}
}