Created
April 7, 2012 13:03
-
-
Save bastman/2328725 to your computer and use it in GitHub Desktop.
JsEvalProxy for as3: pimp flash.external.ExternalInterface
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package de.basilicom.utils | |
{ | |
/** | |
* @requires: JSON on javascript-side, e.g: JSON2.js | |
* @description pimp flash.external.ExternalInterface | |
* @author seb | |
*/ | |
import com.adobe.serialization.json.JSON; | |
import flash.external.ExternalInterface; | |
public class JsEvalProxy | |
{ | |
private static var _instance:JsEvalProxy; | |
protected var _proxyName:String; | |
protected var _jsAvailable:Boolean; | |
protected var _isCreated:Boolean; | |
protected var _isDebugLogEnabled:Boolean = true; | |
protected var _debugConsoleName:String = "console"; | |
protected var _autoCreateEnabled:Boolean = true; | |
// debugging | |
protected var _proxyCreateResult: *; | |
protected var _proxyScript:String; | |
protected var _proxyCreateResultType:String; | |
// ++++++++++++++++++++++++++++++++++++++++++++++++++ | |
public function JsEvalProxy() | |
{ | |
_instance = this; | |
if(_autoCreateEnabled) { | |
autoCreate(); | |
} | |
} | |
// ++++++++++++++++++++++++++++++++++++++++++++++++++ | |
public static function getInstance():JsEvalProxy | |
{ | |
if (!JsEvalProxy._instance) { | |
JsEvalProxy._instance = new JsEvalProxy(); | |
} | |
return JsEvalProxy._instance; | |
} | |
// ++++++++++++++++++++ samples ++++++++++++ | |
public function jsInvokeFunction(method:String, params:Array, mashallExceptions:Boolean):* | |
{ | |
if (!method) { | |
throw new Error("Invalid method"); | |
} | |
var result:* = _jsInvokeFunction(method, params, mashallExceptions); | |
return result; | |
} | |
public function jsAlert(...args):* | |
{ | |
var mashallExceptions:Boolean = false; | |
var script:String = "alert.apply(null, arguments)" | |
var params:Array = args; | |
var result:* = run(script, params, mashallExceptions); | |
return result; | |
} | |
public function jsConsoleLog(...args):* | |
{ | |
var mashallExceptions:Boolean = false; | |
var script:String = 'if ((typeof(console)==="object") && (typeof(console.log)==="function")) {console.log.apply(null, arguments);}'; | |
var params:Array = args; | |
var result:* = run(script, params, mashallExceptions); | |
return result; | |
} | |
public function jsTypeOf(variableName:String):* | |
{ | |
if (!variableName) { | |
return "null"; | |
} | |
var script:String = "return typeof("+variableName+");"; | |
return run(script, [], false); | |
} | |
public function jsCreateEchoTestFunction():* | |
{ | |
var methodName:String = "window.JSEvalEchoTest"; | |
var script:String = ""+methodName+"=function(arg) {return arg;};"; | |
return run(script, [], false); | |
} | |
public function jsEchoTest(value:*):* | |
{ | |
var methodName:String = "window.JSEvalEchoTest"; | |
if (jsTypeOf(methodName) !== "function") { | |
jsCreateEchoTestFunction(); | |
} | |
var result:* = jsInvokeFunction(methodName, [value], false); | |
return result; | |
} | |
protected function _jsInvokeFunction(method:String, params:Array, mashallExceptions:Boolean):* | |
{ | |
if (!method) { | |
throw new Error("Invalid method"); | |
} | |
var script:String = "return " + method + ".apply(null, arguments);"; | |
if (!params) { | |
params = []; | |
} | |
var result:* = run(script, params, mashallExceptions); | |
return result; | |
} | |
// ++++++++++++++++++++++++++++++++++++++++++++++++++ | |
public function autoCreate():Boolean | |
{ | |
var name:String = "flashjsevalproxy"; | |
var uid:String = new Date().valueOf() | |
+ "_" + Math.round(Math.random() * 100000) | |
+ "_" + Math.round(Math.random() * 100000) | |
+ "_" + Math.round(Math.random() * 100000) | |
var proxyName:String = "window." + name + "_" + uid; | |
_proxyName = proxyName; | |
var isCreated:Boolean = createByName(proxyName); | |
if (isCreated) { | |
_isCreated = true; | |
} | |
return isCreated; | |
} | |
public function isDebugLogEnabled():Boolean | |
{ | |
return _isDebugLogEnabled; | |
} | |
public function setDebugLogEnabled(enabled:Boolean):void | |
{ | |
_isDebugLogEnabled = enabled; | |
} | |
public function getProxyCreateResult():* | |
{ | |
return _proxyCreateResult; | |
} | |
public function getProxyCreateResultType():* | |
{ | |
return _proxyCreateResultType; | |
} | |
public function getProxyScript():* | |
{ | |
return _proxyScript; | |
} | |
public function getProxyName():String | |
{ | |
return _proxyName; | |
} | |
public function isCreated():Boolean | |
{ | |
return _isCreated; | |
} | |
public function isLocal():Boolean | |
{ | |
return (!isJavascriptAvailable()); | |
} | |
public function isJavascriptAvailable():Boolean | |
{ | |
if (_jsAvailable === true) { | |
return true; | |
} | |
var result:Boolean = false; | |
if (!ExternalInterface.available) { | |
return result; | |
} | |
var r = _invoke("eval", [true], false); | |
var jsAvailable:Boolean = (r === true); | |
if (jsAvailable) { | |
_jsAvailable = true; | |
} | |
return (jsAvailable); | |
} | |
public function run(script: String, params:Array, marshallExceptions:Boolean):* | |
{ | |
var result:* = null; | |
var proxyMethod:String = getProxyName(); | |
if (!proxyMethod) { | |
throw new Error("Invalid proxy method"); | |
} | |
result = runByName(proxyMethod, script, params, marshallExceptions); | |
return result; | |
} | |
public function runByName(name:String, script: String, params:Array, marshallExceptions:Boolean):* | |
{ | |
var result:* = null; | |
var proxyMethod:String = name; | |
if (!proxyMethod) { | |
throw new Error("Inalid proxy method"); | |
} | |
try { | |
var scriptEncoded:String = "" + script; | |
scriptEncoded = JSON.encode(scriptEncoded); | |
scriptEncoded = encodeURIComponent(scriptEncoded); | |
}catch (e:Error) { | |
throw new Error("Encode script failed! " +e.message); | |
} | |
var finalParams:Array = [ | |
"" + scriptEncoded | |
]; | |
if (!params) { | |
params = []; | |
} | |
var i:int; | |
for (i = 0; i < params.length; i++) { | |
var param:* = params[i]; | |
try { | |
param = JSON.encode(param); | |
param = encodeURIComponent(param); | |
}catch (e:Error) { | |
throw new Error("Encode script param at "+i+" failed! " +e.message); | |
} | |
finalParams.push(param); | |
} | |
if (!isJavascriptAvailable()) { | |
return result; | |
} | |
result = _invoke(proxyMethod, finalParams, marshallExceptions); | |
if (result === "undefined") { | |
result = undefined; | |
} | |
if ( typeof(result) === "string" ) { | |
try { | |
result = decodeURIComponent(result); | |
result = JSON.decode(result); | |
}catch (e:Error) { | |
throw new Error("Decode result failed! " +e.message); | |
} | |
} | |
return result; | |
} | |
public function createByName(name:String) | |
{ | |
var result:Boolean = false; | |
if (!name) { | |
throw new Error("Invalid parameter 'name'"); | |
} | |
var consoleName = (_debugConsoleName || "console"); | |
var script:String =''+ | |
'' + name + ' = function () {' + | |
'var logEnabled =' + JSON.encode(isDebugLogEnabled()) + ';' + | |
'var debugConsole ='+consoleName + ';' + | |
'var doLog = ( (logEnabled) && (typeof(debugConsole)==="object") && (debugConsole) );' + | |
'if (doLog) {debugConsole.log("--------------------- JsEvalProxy ----------------------------"); };' + | |
'if (doLog) {debugConsole.log("JsEvalProxy: args=",arguments); };' + | |
'var source=null;'+ | |
'var params=[];' + | |
'for (var i=0; i<arguments.length; i++) {' + | |
' if (i===0) {' + | |
' var source = arguments[i];' + | |
' } else {' + | |
' params.push(arguments[i]);' + | |
' };' + | |
'};' + | |
'if (doLog) {debugConsole.log("JsEvalProxy: source=",source); };'+ | |
'if (doLog) {debugConsole.log("JsEvalProxy: params=",params); };'+ | |
'var $source;'+ | |
'var $params;'+ | |
'if(typeof(source==="string")) {'+ | |
' try {' + | |
' var $source = source;' + | |
' if (doLog) {debugConsole.log("JsEvalProxy: source=",$source);};' + | |
' $source = decodeURIComponent($source);' + | |
' if (doLog) {debugConsole.log("JsEvalProxy: source=",$source);};' + | |
' $source = JSON.parse($source);' + | |
' if (doLog) {debugConsole.log("JsEvalProxy: source=",$source);};' + | |
' }catch (e) {' + | |
' if (doLog) {debugConsole.log("JsEvalProxy: source=",source);};' + | |
' throw new Error("JsEvalProxy: failed to decode source. reason:"+e.message);'+ | |
' };'+ | |
'} else {'+ | |
' $source = source;'+ | |
'};'+ | |
'if(!params) {'+ | |
' var params = [];'+ | |
'};'+ | |
'$params = [];'+ | |
'for(var i=0; i<params.length; i++) {'+ | |
' var p = params[i];' + | |
' if (doLog) {debugConsole.log("JsEvalProxy: prepare param at "+i+" of type="+typeof(p)+" value=",p); };' + | |
' if(typeof(p)==="string") {'+ | |
' try {'+ | |
' var $p = p;'+ | |
' $p = decodeURIComponent($p);'+ | |
' if (doLog) {debugConsole.log("JsEvalProxy: --> decoded param at "+i+" of type="+typeof($p)+" value=",$p); };' + | |
' $p = JSON.parse($p);'+ | |
' if (doLog) {debugConsole.log("JsEvalProxy: --> decoded param at "+i+" of type="+typeof($p)+" value=",$p); };' + | |
' }catch (e) {' + | |
' if (doLog) {debugConsole.log("JsEvalProxy: invalid param=",p); };' + | |
' throw new Error("JsEvalProxy:failed to decode param at "+i+". reason:"+e.message+" param="+p);'+ | |
' };'+ | |
' } else {'+ | |
' var $p = p;'+ | |
' };' + | |
' if (doLog) {debugConsole.log("JsEvalProxy: add param of at "+i+" of type="+typeof($p)+" value=",$p); };' + | |
' $params.push($p);'+ | |
'};'+ | |
'var fnText = "(function() " +'+ | |
' "{" +'+ | |
' ""+$source+";" +'+ | |
' "}" +'+ | |
' ");";' + | |
'if (doLog) {debugConsole.log("JsEvalProxy: eval funcText=",fnText);};' + | |
'if (doLog) {debugConsole.log("JsEvalProxy: $params=",$params);};' + | |
'var func = eval(fnText);'+ | |
'if (doLog) {debugConsole.log("JsEvalProxy: func=",func);};' + | |
'var result = func.apply(null, $params);' + | |
'if (doLog) {debugConsole.log("JsEvalProxy: func result=",result);};' + | |
'if (typeof(result)==="undefined") { result=null; };'+ | |
'if (typeof(result)==="function") { result=null; };' + | |
'try {'+ | |
' var result = JSON.stringify(result);'+ | |
' var result = encodeURIComponent(result);' + | |
'} catch(e) { '+ | |
' throw new Error("JsEvalProxy: Encode result failed! " + e);' + | |
'};' + | |
'return result;'+ | |
'};'+ | |
''; | |
var s:String; | |
s = script; | |
_proxyScript = s; | |
if (!isJavascriptAvailable()) { | |
return result; | |
} | |
_proxyCreateResult = _invoke("eval", [s], false); // supposed to be null, since "fucntion" can't be serialized | |
_proxyCreateResultType = _invoke("eval", ["typeof("+name+")"], false); | |
var isCreated:Boolean = (_proxyCreateResultType === "function"); | |
return (isCreated===true) | |
} | |
// ++++++++++++++++++++++++++++++++++++++++++++++++++ | |
protected function _invoke(method:String, params:Array, marshallExceptions:Boolean):* | |
{ | |
var result:* = null; | |
var error:* = null; | |
var args:Array=[ | |
method | |
]; | |
for(var i:int=0;i<params.length;i++) { | |
args.push(params[i]); | |
} | |
var marshallExceptionsOld:Boolean = (flash.external.ExternalInterface.marshallExceptions === true); | |
flash.external.ExternalInterface.marshallExceptions = (marshallExceptions === true); | |
try { | |
result = flash.external.ExternalInterface.call.apply(null, args); | |
}catch (e:Error) { | |
error = e; | |
} | |
flash.external.ExternalInterface.marshallExceptions = marshallExceptionsOld; | |
if (error is Error) { | |
if (marshallExceptions) { | |
throw error; | |
} | |
} | |
return result; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// +++++++++ NOTE: JSON required on javascript side, e.g. JSON2.js ++++++++++++++++++++++ | |
import com.adobe.serialization.json.JSON; | |
import de.basilicom.utils.JsEvalProxy; | |
var r; | |
// ++++++++++ simple examples +++++++++++++++++++++ | |
JsEvalProxy.getInstance().jsAlert("Hello World from Flash!"); | |
JsEvalProxy.getInstance().jsConsoleLog("Hello World from Flash!", "foo", "bar", "baz"); | |
JsEvalProxy.getInstance().run("console.log('args=',arguments)", ["foo", "bar"], false); | |
r=JsEvalProxy.getInstance().jsInvokeFunction('Math.round', [4.345], false) | |
JsEvalProxy.getInstance().jsConsoleLog( | |
"the result of last function... : ", | |
r | |
); | |
// ++++++++++ complex examples +++++++++++++++++++++ | |
//JsEvalProxy.getInstance().jsCreateEchoTestFunction(); | |
r=JsEvalProxy.getInstance().jsTypeOf("window.JSEvalEchoTest"); | |
r=JsEvalProxy.getInstance().jsEchoTest("foo"); | |
JsEvalProxy.getInstance().jsConsoleLog( | |
"the result of last function... : ", | |
r | |
); | |
var o= { | |
"foo":"bar", | |
"x":1, | |
"r":1.234, | |
"b":true, | |
"a":["foo","bar","baz"], | |
"text":"Hello World. Watch this: äöüÄÖÜ߀$!", | |
"baz": JSON.encode( | |
{ | |
"foo":"bar", | |
"x":1, | |
"r":1.234, | |
"b":true, | |
"a":["foo","bar","baz"], | |
"text":"Hello World. Watch this: äöüÄÖÜ߀$!", | |
"baz": JSON.encode( { | |
"foo":"bar", | |
"x":1, | |
"r":1.234, | |
"b":true, | |
"a":["foo","bar","baz"], | |
"text":"Hello World. Watch this: äöüÄÖÜ߀$!" | |
} | |
) | |
}) | |
}; | |
r = JsEvalProxy.getInstance().jsInvokeFunction('JSON.stringify', [o], false); | |
JsEvalProxy.getInstance().jsConsoleLog( | |
"the result of last function... : ", | |
r | |
); | |
r = JsEvalProxy.getInstance().jsEchoTest(o); | |
JsEvalProxy.getInstance().jsConsoleLog( | |
"the result of last function... : ", | |
r | |
); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment