JSProxy - AS3 から意識せずに JS を操作

AS3 から HTML の特定要素の内容を取得したり JS のメソッドを引数つけて呼び出したり、値をセットしたりがめんどくさくなってきたので作ってみました。
JSProxy.proxy もしくは new JSProxy() で JSProxy のインスタンスを作り、適当にプロパティを呼び出していって(この時点ではスタックにどういう処理を行うかを書いてるだけ)、最後JSを本当に叩いて値を取得やメソッド呼び出しを行いたいときは、プロパティの頭に $ をつけます。

// アラート関数を実行
JSProxy.proxy.$alert('foo'); 
// body の本文を取得
var body:String = JSProxy.proxy.document.body.$innerHTML; 
// body の style を変更
JSProxy.proxy.document.body.style.$backgroundColor = '#FF0000';

proxy チェインの途中のインスタンスから呼び出すことも出来ます。

var location:JSProxy = JSProxy.proxy.location;
// location の情報を取得できる
var browserUrl:String = location.$href;
var hostname:String = location.$hostname;
// 代入も出来る。以下の例では別のURLに移動する。
location.$href = 'http://www.hatena.ne.jp/';

DOM の要素を取得して配列に値を代入、などの操作もそれっぽく書けます。

// 全体から P タグを取得
var pElements:JSProxy = JSProxy.proxy.document.getElementsByTagName('p');
// 一個目の innerHTML に代入して変更
pElements[0].innerHTML = '1st p';
// 一個目の innerHTML に代入して変更
pElements[1].innerHTML = '2nd p';

フォームに適当に値を入力して submit なども可能です。

<form action="/" id="testform">
  <input type="input" value="yuichi" name="username">
  <input type="input" value="foo@example.com" name="email">
  <input type="submit">
</form>

なフォームなら

var form:JSProxy = JSProxy.proxy.document.getElementById('testform');
var inputs:JSProxy = form.getElementsByTagName('input');
inputs[0].value = 'oreore';
inputs[1].value = 'oreore@example.com';
form.forceAsync = true; // 後述
form.$submit();

な感じでできます。

ExternalInterface の呼び出しタイミング

location.href に代入や form.submit() の呼び出しなど、一部のブラウザ組み込みのオブジェクトやプロパティに ExternalInterface から関数呼び出しをしたり、値のセットを行うと、タイミングによって Flash の IOError が発生し、Flash 側からでは回避できません。そのため値を setTimeout をしこんで、セッターのコードは

(function(_0) {setTimeout(function(){try{location.href = _0}catch(e){};}, 0);})

のように呼び出しています。セッターは戻り値を取得する必要が無いためこんな回避方法で問題無いのですが、関数呼び出しはそうも行きません。しかし戻り値が別にあっても無くても問題ない関数もあるため(form.submit() などそうですね)、forceAsync を true に設定すると setTimeout(function() {}, 0) を使った関数呼び出しへと強制的に変更できます。

その他 ExternalInterface の呼び出し周りの BK が JSProxy.as に結構つまってるので、ExternalInterface に興味のある方は参考になるかもしれません。