In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

JSAS

Get Adobe Flash player
by wh0 14 Jan 2011
    Embed
/**
 * Copyright wh0 ( http://wonderfl.net/user/wh0 )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/3lRD
 */

package {
    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.events.UncaughtErrorEvent;
    import flash.external.ExternalInterface;
    import flash.system.ApplicationDomain;
    import flash.system.Security;
    import flash.utils.describeType;
    import flash.utils.Dictionary;
    
    // import com.actionscriptbible.Example;
    // public class JSAS extends Example {
    public class JSAS extends Sprite {
        
        private var index:int = 0;
        private var heap:Array = [];
        private var reverseHeap:Dictionary = new Dictionary();
        
        public function JSAS() {
            // loaderInfo.uncaughtErrorEvents.addEventListener(UncaughtErrorEvent.UNCAUGHT_ERROR, function(e:UncaughtErrorEvent):void { trace(e.error); });
            Security.allowDomain('*');
            stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.align = StageAlign.TOP_LEFT;
            
            ExternalInterface.addCallback('_get', _get);
            ExternalInterface.addCallback('_set', _set);
            ExternalInterface.addCallback('_call', _call);
            ExternalInterface.addCallback('_getStatic', _getStatic);
            ExternalInterface.addCallback('_callStatic', _callStatic);
            ExternalInterface.addCallback('_construct', _construct);
            ExternalInterface.call('JSAS._onready', ExternalInterface.objectID, encode(this));
        }
        
        private function _get(v:*, k:String):* {
            v = decode(v);
            // trace('getting ' + v + '.' + k);
            return encode(v[k]);
        }
        
        private function _set(v:*, k:String, u:*):void {
            v = decode(v);
            u = decode(u);
            // trace('setting ' + v + '.' + k + ' = ' + u);
            v[k] = u;
        }
        
        private function _call(v:*, k:String, a:Array=null):* {
            v = decode(v);
            a = a ? a.map(decode) : [];
            // trace('calling ' + v + '.' + k + '(' + a + ')');
            return encode(v[k].apply(v, a));

        }
        
        private function _getStatic(k:String):* {
            // trace('getting ' + k);
            return encode(ApplicationDomain.currentDomain.getDefinition(k));
        }
        
        private function _callStatic(k:*, a:Array=null):* {
            a = a ? a.map(decode) : [];
            // trace('calling ' + k + '(' + a + ')');
            k = ApplicationDomain.currentDomain.getDefinition(k);
            return encode(k.apply(null, a));
        }
        
        private function _construct(v:*, a:Array=null):* {
            var r:* = null;
            v = decode(v);
            a = a ? a.map(decode) : [];
            // trace('constructing ' + v + '(' + a + ')');
            // lol can't invoke constructors with argument array
            switch (a.length) {
                case 0: r = new v(); break;
                case 1: r = new v(a[0]); break;
                case 2: r = new v(a[0], a[1]); break;
                case 3: r = new v(a[0], a[1], a[2]); break;
                case 4: r = new v(a[0], a[1], a[2], a[3]); break;
                case 5: r = new v(a[0], a[1], a[2], a[3], a[4]); break;
                case 6: r = new v(a[0], a[1], a[2], a[3], a[4], a[5]); break;
                case 7: r = new v(a[0], a[1], a[2], a[3], a[4], a[5], a[6]); break;
                case 8: r = new v(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7]); break;
                case 9: r = new v(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8]); break;
                case 10: r = new v(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9]); break;
                case 11: r = new v(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10]); break;
                case 12: r = new v(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11]); break;
                case 13: r = new v(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12]); break;
                case 14: r = new v(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13]); break;
                // 14 max. c.f. http://code.google.com/p/haxe/source/browse/trunk/std/flash9/_std/Type.hx#129
            }
            return encode(r);
        }
        
        private function encode(v:*, i:int=0, a:Array=null):* {
            if (!v) {
                return v;
            } else if (typeof(v) == 'object') {
                if (v in reverseHeap) return {_jsas: true, _index: reverseHeap[v]};
                var d:XML = describeType(v);
                if (d.@name == 'Object') {
                    var o:Object = {};
                    for (var k:String in v) {
                        o[k] = encode(v[k]);
                    }
                    return o;
                } else if (d.@name == 'Array') {
                    return v.map(encode);
                } else {
                    return makeSpec(v, d);
                }
            } else if (typeof(v) == 'function') {
                return {_jsas: true, _function: true};
            } else {
                return v;
            }
        }
        
        private function decode(v:*, i:int=0, a:Array=null):* {
            if (!v) {
                return v;
            } else if (typeof(v) == 'object') {
                if (v._jsas) {
                    if (v._index < index) return heap[v._index];
                    else return makeWrapper(v);
                } else if (v is Array) {
                    return v.map(decode);
                } else {
                    var o:Object = {};
                    for (var k:String in v) {
                        o[k] = decode(v[k]);
                    }
                    return o;
                }
            } else {
                return v;
            }
        }
        
        private function makeSpec(v:*, d:XML):* {
            reverseHeap[v] = index;
            heap[index] = v;
            // trace('heap[' + index + '] = ' + v);
            var r:Object = {_jsas: true, _index: index, _getters: [], _setters: [], _methods: []};
            index += 1;
            var f:XML;
            for each (f in d.constant) {
                r._getters.push(f.@name.toString());
            }
            for each (f in d.variable) {
                r._getters.push(f.@name.toString());
                r._setters.push(f.@name.toString());
            }
            for each (f in d.accessor) {
                if (f.@access != 'writeonly') r._getters.push(f.@name.toString());
                if (f.@access != 'readonly') r._setters.push(f.@name.toString());
            }
            for each (f in d.method) {
                r._methods.push(f.@name.toString());
            }
            if (d.@base == 'Class') r._class = true;
            return r;
        }
        
        private function makeWrapper(v:*):* {
            var r:* = function():* {
                var s:Object = {_jsas: true, _index: v._index};
                var a:Array = arguments.map(encode);
                // trace('calling callback ' + v._index + '(' + a + ')');
                return decode(ExternalInterface.call('JSAS._callback', ExternalInterface.objectID, s, a));
            };
            reverseHeap[r] = v._index;
            heap[v._index] = r;
            // trace('heap[' + v._index + '] = ' + r);
            index = v._index + 1;
            return r;
        }
        
    }
}