--- layout: old_post title: JavaScript → ActionScript なオブジェクトブリッジを作ってみた permalink: /tatsuya/show/359-javascript-actionscript ---

最近、絶賛ActionScript勉強中なのですが、どうもたまにJavaScriptを叩きたいときがある。というかActionScriptからJavaScriptのオブジェクトを触れると色々便利そうなので、オブジェクトブリッジ的な物を作ってみた。ネタ元は

ActionScript JavaScript オブジェクトブリッジを作ってみた : IT戦記

これ。AS→JSがあるなら、JS→ASも必要だろうということで逆方向を作ってみた。

動作

こんな感じでJavaScriptのオブジェクトをActionScriptから触れる。alert("Hoge")なんかのグローバル関数は window.alert("Hoge") でOK。

以下ActionScript

var window:AS2JS = AS2JS.register("window");
window.alert("Alert from ActionScript!!");
//アラート表示を普通に

Picture 1

var document:AS2JS = AS2JS.register("document");
document.getElementById("title1").innerHTML="Hello World from ActionScript with normal";
//DOM操作も普通に

var element:AS2JS = AS2JS.register("Element");
var title2:AS2JS = window.$("title2");
element.update(title2, "Hello World from ActionScript with prototype.js");
//prototype.jsを使ってのDOM操作も普通に

var Comic:AS2JS = AS2JS.register("Comic = new Base('Comic')");
var comicDiv:AS2JS = window.$("comic");
comicDiv.innerHTML = String(Comic.find(3).title);
//最近マイブームのJesterを使ってサーバからデータを取ってくる

Picture 4

デモページは今日夜作る、かも。

 >追記:デモページ作った。FireFoxで動作確認中

コードも貼っておきます、まだ色々改良の余地ありですが。

ActionScript

ActionScript 1.0時代しかやったことなかったので、3.0は違和感ありあり。コード変な書き方あるかも。

package tkmr{
   import flash.utils.*;
   import flash.external.ExternalInterface;

   public dynamic class AS2JS extends Proxy {
      private var _attributes:Array;
      private var _item:Array;

      public function AS2JS(id:String){
        _attributes = new Array();
        _attributes["_JSObjectID"] = id;
      }
      public static function register(generateScript:String):*{
        var id:String = ExternalInterface.call("AS2JS.Register", String(generateScript));
        return (new AS2JS(id));
      }

      //private method....
      public static function callJS(args:*):*{
        var result:Array = ExternalInterface.call("AS2JS.Call", args);
        if(result[0]=="JSObject"){
          var new_js:AS2JS = new AS2JS(result[1]);
          return new_js;
        }else{
          return result[1];
        }
      }
      override flash_proxy function getProperty(name:*):* {
        trace(String(name));
        if(String(name)=="_JSObjectID"){ return _attributes["_JSObjectID"]; }
        return AS2JS.callJS([_attributes["_JSObjectID"], String(name)]);
      }
      override flash_proxy function setProperty(name:*, value:*):void {
        ExternalInterface.call("AS2JS.Set", _attributes["_JSObjectID"], String(name), value);
      }
      override flash_proxy function callProperty(name:*, ... args):* {
        args.unshift(_attributes["_JSObjectID"], String(name));
        return AS2JS.callJS(args);
      }

      //Tekitou....
      override flash_proxy function nextNameIndex(index:int):int {
         if (index == 0){
           _item = new Array();
           _item[0]="_JSObjectID";
         }
         if(index < _item.length){
           return index + 1;
         }else{
           return 0;
         }
      }
      override flash_proxy function nextName(index:int):String {
        return _item[index - 1];
      }
      override flash_proxy function nextValue(index:int):*{
        return _attributes[String(_item[index - 1])];
      }
   }
}

JavaScript

オブジェクトをAS2JS.storeへためておき、ActionScriptへIDを返す

var AS2JS = {
    store: [],
    Set: function(){
        var id = arguments[0];
        var func = arguments[1];
        AS2JS.store[id][func]=arguments[2];
    },
    Call: function (){
        var id = arguments[0].shift();
        var func = arguments[0].shift();
        var obj = AS2JS.store[id];
        for(var i=0; i<arguments[0].length; i++){
            arguments[0][i] = arguments[0][i]["_JSObjectID"] ?
                AS2JS.store[arguments[0][i]["_JSObjectID"]] :
                arguments[0][i];
        }
        var result = typeof(obj[func])=="function" ? obj[func].apply(obj, arguments[0]) : obj[func];
        if(typeof(result)=="string" || typeof(result)=="number" || typeof(result)=="undefined"){
            return [typeof(result), result];
        }else{
            var new_id = AS2JS.store.push(result);
            return ["JSObject", (new_id - 1)];
        }
    },
    Register: function (generateScript){
        var id = AS2JS.store.push(eval(generateScript));
        return (id - 1);
    }
}

あとはActionScriptのガベージコレクトのイベントをキャッチして、ActionScript → JavaScript と不要なオブジェクト削除の処理を加えたいな。ActionScriptでガベージコレクトのイベントをキャッチてどうやるんだろ。。