////////////////////////////////////////////////////////////////////////////////
//
//  Licensed to the Apache Software Foundation (ASF) under one or more
//  contributor license agreements.  See the NOTICE file distributed with
//  this work for additional information regarding copyright ownership.
//  The ASF licenses this file to You under the Apache License, Version 2.0
//  (the "License"); you may not use this file except in compliance with
//  the License.  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////
package org.apache.flex.core
{
    import flash.display.DisplayObject;
    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.events.IOErrorEvent;
    import flash.system.ApplicationDomain;
    import flash.utils.getQualifiedClassName;

    import org.apache.flex.events.Event;
    import org.apache.flex.utils.MXMLDataInterpreter;

    //--------------------------------------
    //  Events
    //--------------------------------------

    /**
     *  Dispatched at startup. Attributes and sub-instances of
     *  the MXML document have been created and assigned.
     *  The component lifecycle is different
     *  than the Flex SDK.  There is no creationComplete event.
     *
     *  @langversion 3.0
     *  @playerversion Flash 10.2
     *  @playerversion AIR 2.6
     *  @productversion FlexJS 0.0
     */
    [Event(name="initialize", type="org.apache.flex.events.Event")]

    /**
     *  Dispatched at startup after the initial view has been
     *  put on the display list.
     *
     *  @langversion 3.0
     *  @playerversion Flash 10.2
     *  @playerversion AIR 2.6
     *  @productversion FlexJS 0.0
     */
    [Event(name="viewChanged", type="org.apache.flex.events.Event")]

    /**
     *  Dispatched at startup after the initial view has been
     *  put on the display list.
     *
     *  @langversion 3.0
     *  @playerversion Flash 10.2
     *  @playerversion AIR 2.6
     *  @productversion FlexJS 0.0
     */
    [Event(name="applicationComplete", type="org.apache.flex.events.Event")]

    /**
     *  The Application class is the main class and entry point for a FlexJS
     *  application.  This Application class is different than the
     *  Flex SDK's mx:Application or spark:Application in that it does not contain
     *  user interface elements.  Those UI elements go in the views.  This
     *  Application class expects there to be a main model, a controller, and
     *  an initial view.
     *
     *  @langversion 3.0
     *  @playerversion Flash 10.2
     *  @playerversion AIR 2.6
     *  @productversion FlexJS 0.0
     */
    public class Application extends Sprite implements IStrand, IFlexInfo, IParent
    {
        /**
         *  Constructor.
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function Application()
        {
            super();
			if (stage)
			{
				stage.align = StageAlign.TOP_LEFT;
				stage.scaleMode = StageScaleMode.NO_SCALE;
			}

            loaderInfo.addEventListener(flash.events.Event.INIT, initHandler);
        }

        /**
         *  The document property is used to provide
         *  a property lookup context for non-display objects.
         *  For Application, it points to itself.
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public var document:Object = this;

        private function initHandler(event:flash.events.Event):void
        {
            ValuesManager.valuesImpl = valuesImpl;
            ValuesManager.valuesImpl.init(this);

            dispatchEvent(new Event("initialize"));

            if (initialView)
            {
                initialView.applicationModel =  model;
        	    this.addElement(initialView);
                dispatchEvent(new Event("viewChanged"));
            }
            dispatchEvent(new Event("applicationComplete"));
        }

        /**
         *  The org.apache.flex.core.IValuesImpl that will
         *  determine the default values and other values
         *  for the application.  The most common choice
         *  is org.apache.flex.core.SimpleCSSValuesImpl.
         *
         *  @see org.apache.flex.core.SimpleCSSValuesImpl
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public var valuesImpl:IValuesImpl;

        /**
         *  The initial view.
         *
         *  @see org.apache.flex.core.ViewBase
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public var initialView:ViewBase;

        /**
         *  The data model (for the initial view).
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public var model:Object;

        /**
         *  The controller.  The controller typically watches
         *  the UI for events and updates the model accordingly.
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public var controller:Object;

        /**
         *  An array of data that describes the MXML attributes
         *  and tags in an MXML document.  This data is usually
         *  decoded by an MXMLDataInterpreter
         *
         *  @see org.apache.flex.utils.MXMLDataInterpreter
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function get MXMLDescriptor():Array
        {
            return null;
        }

        /**
         *  An method called by the compiler's generated
         *  code to kick off the setting of MXML attribute
         *  values and instantiation of child tags.
         *
         *  The call has to be made in the generated code
         *  in order to ensure that the constructors have
         *  completed first.
         *
         *  @param data The encoded data representing the
         *  MXML attributes.
         *
         *  @see org.apache.flex.utils.MXMLDataInterpreter
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
    	public function generateMXMLAttributes(data:Array):void
        {
			MXMLDataInterpreter.generateMXMLProperties(this, data);
        }

        /**
         *  The array property that is used to add additional
         *  beads to an MXML tag.  From ActionScript, just
         *  call addBead directly.
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public var beads:Array;

        private var _beads:Vector.<IBead>;

        /**
         *  @copy org.apache.flex.core.IStrand#addBead()
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function addBead(bead:IBead):void
        {
            if (!_beads)
                _beads = new Vector.<IBead>;
            _beads.push(bead);
            bead.strand = this;
        }

        /**
         *  @copy org.apache.flex.core.IStrand#getBeadByType()
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function getBeadByType(classOrInterface:Class):IBead
        {
            for each (var bead:IBead in _beads)
            {
                if (bead is classOrInterface)
                    return bead;
            }
            return null;
        }

        /**
         *  @copy org.apache.flex.core.IStrand#removeBead()
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function removeBead(value:IBead):IBead
        {
            var n:int = _beads.length;
            for (var i:int = 0; i < n; i++)
            {
                var bead:IBead = _beads[i];
                if (bead == value)
                {
                    _beads.splice(i, 1);
                    return bead;
                }
            }
            return null;
        }

        private var _info:Object;

        /**
         *  An Object containing information generated
         *  by the compiler that is useful at startup time.
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function info():Object
        {
            if (!_info)
            {
                var mainClassName:String = getQualifiedClassName(this);
                var initClassName:String = "_" + mainClassName + "_FlexInit";
                var c:Class = ApplicationDomain.currentDomain.getDefinition(initClassName) as Class;
                _info = c.info();
            }
            return _info;
        }

        /**
         *  @copy org.apache.flex.core.IParent#addElement()
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function addElement(c:Object):void
        {
            if (c is IUIBase)
            {
                addChild(IUIBase(c).element as DisplayObject);
                IUIBase(c).addedToParent();
            }
            else
                addChild(c as DisplayObject);
        }

        /**
         *  @copy org.apache.flex.core.IParent#addElementAt()
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function addElementAt(c:Object, index:int):void
        {
            if (c is IUIBase)
            {
                addChildAt(IUIBase(c).element as DisplayObject, index);
                IUIBase(c).addedToParent();
            }
            else
                addChildAt(c as DisplayObject, index);
        }

        /**
         *  @copy org.apache.flex.core.IParent#getElementIndex()
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function getElementIndex(c:Object):int
        {
            if (c is IUIBase)
                return getChildIndex(IUIBase(c).element as DisplayObject);

            return getChildIndex(c as DisplayObject);
        }

        /**
         *  @copy org.apache.flex.core.IParent#removeElement()
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function removeElement(c:Object):void
        {
            if (c is IUIBase)
            {
                removeChild(IUIBase(c).element as DisplayObject);
            }
            else
                removeChild(c as DisplayObject);
        }

        /**
         *  @copy org.apache.flex.core.IParent#numElements
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function get numElements():int
        {
            return numChildren;
        }
    }
}

////////////////////////////////////////////////////////////////////////////////
//
//  Licensed to the Apache Software Foundation (ASF) under one or more
//  contributor license agreements.  See the NOTICE file distributed with
//  this work for additional information regarding copyright ownership.
//  The ASF licenses this file to You under the Apache License, Version 2.0
//  (the "License"); you may not use this file except in compliance with
//  the License.  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////
package org.apache.flex.core
{
    import flash.display.DisplayObject;
    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageQuality;
    import flash.display.StageScaleMode;
    import flash.events.IOErrorEvent;
    import flash.system.ApplicationDomain;
    import flash.utils.getQualifiedClassName;

    import org.apache.flex.events.Event;
    import org.apache.flex.utils.MXMLDataInterpreter;

    //--------------------------------------
    //  Events
    //--------------------------------------

    /**
     *  Dispatched at startup. Attributes and sub-instances of
     *  the MXML document have been created and assigned.
     *  The component lifecycle is different
     *  than the Flex SDK.  There is no creationComplete event.
     *
     *  @langversion 3.0
     *  @playerversion Flash 10.2
     *  @playerversion AIR 2.6
     *  @productversion FlexJS 0.0
     */
    [Event(name="initialize", type="org.apache.flex.events.Event")]

    /**
     *  Dispatched at startup after the initial view has been
     *  put on the display list.
     *
     *  @langversion 3.0
     *  @playerversion Flash 10.2
     *  @playerversion AIR 2.6
     *  @productversion FlexJS 0.0
     */
    [Event(name="viewChanged", type="org.apache.flex.events.Event")]

    /**
     *  Dispatched at startup after the initial view has been
     *  put on the display list.
     *
     *  @langversion 3.0
     *  @playerversion Flash 10.2
     *  @playerversion AIR 2.6
     *  @productversion FlexJS 0.0
     */
    [Event(name="applicationComplete", type="org.apache.flex.events.Event")]

    /**
     *  The Application class is the main class and entry point for a FlexJS
     *  application.  This Application class is different than the
     *  Flex SDK's mx:Application or spark:Application in that it does not contain
     *  user interface elements.  Those UI elements go in the views.  This
     *  Application class expects there to be a main model, a controller, and
     *  an initial view.
     *
     *  @langversion 3.0
     *  @playerversion Flash 10.2
     *  @playerversion AIR 2.6
     *  @productversion FlexJS 0.0
     */
    public class Application extends Sprite implements IStrand, IFlexInfo, IParent
    {
        /**
         *  Constructor.
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function Application()
        {
            super();
			if (stage)
			{
				stage.align = StageAlign.TOP_LEFT;
				stage.scaleMode = StageScaleMode.NO_SCALE;
				stage.quality = StageQuality.HIGH_16X16_LINEAR;
				trace("working");
			}

            loaderInfo.addEventListener(flash.events.Event.INIT, initHandler);
        }

        /**
         *  The document property is used to provide
         *  a property lookup context for non-display objects.
         *  For Application, it points to itself.
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public var document:Object = this;

        private function initHandler(event:flash.events.Event):void
        {
            ValuesManager.valuesImpl = valuesImpl;
            ValuesManager.valuesImpl.init(this);

            dispatchEvent(new Event("initialize"));

            if (initialView)
            {
                initialView.applicationModel =  model;
        	    this.addElement(initialView);
                dispatchEvent(new Event("viewChanged"));
            }
            dispatchEvent(new Event("applicationComplete"));
        }

        /**
         *  The org.apache.flex.core.IValuesImpl that will
         *  determine the default values and other values
         *  for the application.  The most common choice
         *  is org.apache.flex.core.SimpleCSSValuesImpl.
         *
         *  @see org.apache.flex.core.SimpleCSSValuesImpl
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public var valuesImpl:IValuesImpl;

        /**
         *  The initial view.
         *
         *  @see org.apache.flex.core.ViewBase
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public var initialView:ViewBase;

        /**
         *  The data model (for the initial view).
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public var model:Object;

        /**
         *  The controller.  The controller typically watches
         *  the UI for events and updates the model accordingly.
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public var controller:Object;

        /**
         *  An array of data that describes the MXML attributes
         *  and tags in an MXML document.  This data is usually
         *  decoded by an MXMLDataInterpreter
         *
         *  @see org.apache.flex.utils.MXMLDataInterpreter
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function get MXMLDescriptor():Array
        {
            return null;
        }

        /**
         *  An method called by the compiler's generated
         *  code to kick off the setting of MXML attribute
         *  values and instantiation of child tags.
         *
         *  The call has to be made in the generated code
         *  in order to ensure that the constructors have
         *  completed first.
         *
         *  @param data The encoded data representing the
         *  MXML attributes.
         *
         *  @see org.apache.flex.utils.MXMLDataInterpreter
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
    	public function generateMXMLAttributes(data:Array):void
        {
			MXMLDataInterpreter.generateMXMLProperties(this, data);
        }

        /**
         *  The array property that is used to add additional
         *  beads to an MXML tag.  From ActionScript, just
         *  call addBead directly.
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public var beads:Array;

        private var _beads:Vector.<IBead>;

        /**
         *  @copy org.apache.flex.core.IStrand#addBead()
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function addBead(bead:IBead):void
        {
            if (!_beads)
                _beads = new Vector.<IBead>;
            _beads.push(bead);
            bead.strand = this;
        }

        /**
         *  @copy org.apache.flex.core.IStrand#getBeadByType()
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function getBeadByType(classOrInterface:Class):IBead
        {
            for each (var bead:IBead in _beads)
            {
                if (bead is classOrInterface)
                    return bead;
            }
            return null;
        }

        /**
         *  @copy org.apache.flex.core.IStrand#removeBead()
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function removeBead(value:IBead):IBead
        {
            var n:int = _beads.length;
            for (var i:int = 0; i < n; i++)
            {
                var bead:IBead = _beads[i];
                if (bead == value)
                {
                    _beads.splice(i, 1);
                    return bead;
                }
            }
            return null;
        }

        private var _info:Object;

        /**
         *  An Object containing information generated
         *  by the compiler that is useful at startup time.
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function info():Object
        {
            if (!_info)
            {
                var mainClassName:String = getQualifiedClassName(this);
                var initClassName:String = "_" + mainClassName + "_FlexInit";
                var c:Class = ApplicationDomain.currentDomain.getDefinition(initClassName) as Class;
                _info = c.info();
            }
            return _info;
        }

        /**
         *  @copy org.apache.flex.core.IParent#addElement()
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function addElement(c:Object):void
        {
            if (c is IUIBase)
            {
                addChild(IUIBase(c).element as DisplayObject);
                IUIBase(c).addedToParent();
            }
            else
                addChild(c as DisplayObject);
        }

        /**
         *  @copy org.apache.flex.core.IParent#addElementAt()
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function addElementAt(c:Object, index:int):void
        {
            if (c is IUIBase)
            {
                addChildAt(IUIBase(c).element as DisplayObject, index);
                IUIBase(c).addedToParent();
            }
            else
                addChildAt(c as DisplayObject, index);
        }

        /**
         *  @copy org.apache.flex.core.IParent#getElementIndex()
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function getElementIndex(c:Object):int
        {
            if (c is IUIBase)
                return getChildIndex(IUIBase(c).element as DisplayObject);

            return getChildIndex(c as DisplayObject);
        }

        /**
         *  @copy org.apache.flex.core.IParent#removeElement()
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function removeElement(c:Object):void
        {
            if (c is IUIBase)
            {
                removeChild(IUIBase(c).element as DisplayObject);
            }
            else
                removeChild(c as DisplayObject);
        }

        /**
         *  @copy org.apache.flex.core.IParent#numElements
         *
         *  @langversion 3.0
         *  @playerversion Flash 10.2
         *  @playerversion AIR 2.6
         *  @productversion FlexJS 0.0
         */
        public function get numElements():int
        {
            return numChildren;
        }
    }
}

Set Application.stageQuality to HIGH_16X16_LINEAR


/*
#
# Copyright (c) 2007-2011 rPath, Inc.
#
# All rights reserved
#
*/

package com.rpath.xobj
{
import flash.utils.Dictionary;

import mx.collections.ArrayCollection;

public class XObjArrayCollection extends ArrayCollection implements IXObjCollection
{
    public function XObjArrayCollection(source:Array=null, typeMap:*=null)
    {
        super(source);

        if (!typeMap)
            this.type = {};

        this.type = typeMap;
    }

    // the type of objects we expect in the collection
    // null means unknown type. Can be a single Class
    // or a Dictionary of typeMap entries
    [xobjTransient]
    public function get type():*
    {
        return _type;
    }

    private var _type:*;

    public function set type(t:*):void
    {
        _type = t;
    }

    public function elementType():Class
    {
        return (type as Class);
    }

    public function typeMap():Dictionary
    {
        return (type as Dictionary);
    }

    public function elementTypeForElementName(name:String):Class
    {
        return XObjTypeMap.elementTypeForElementName(type, name);
    }

    public function elementTagForMember(member:*):String
    {
        return XObjTypeMap.elementTagForMember(type, member);
    }

    public function addItemIfAbsent(value:Object):Boolean
    {
        if (getItemIndex(value) == -1)
        {
            addItem(value);
            return true;
        }
        return false;
    }

    public function removeItemIfPresent(object:Object):Boolean
    {
        return XObjUtils.removeItemIfPresent(this, object);
    }

    public function isElementMember(propName:String):Boolean
    {
       return XObjUtils.isElementMember(this, propName);
    }

    [xobjTransient]
    public function get isByReference():Boolean
    {
        return _isByReference;
    }

    private var _isByReference:Boolean;

    public function set isByReference(b:Boolean):void
    {
        _isByReference = b;
    }

}
}

/*
#
# Copyright (c) 2007-2011 rPath, Inc.
#
# All rights reserved
#
*/

package com.rpath.xobj
{
import flash.utils.Dictionary;

import mx.collections.ArrayCollection;

[Bindable]
public class XObjArrayCollection extends ArrayCollection implements IXObjCollection
{
    public function XObjArrayCollection(source:Array=null, typeMap:*=null)
    {
        super(source);

        if (!typeMap)
            this.type = {};

        this.type = typeMap;
    }

    // the type of objects we expect in the collection
    // null means unknown type. Can be a single Class
    // or a Dictionary of typeMap entries
    [xobjTransient]
    public function get type():*
    {
        return _type;
    }

    private var _type:*;

    public function set type(t:*):void
    {
        _type = t;
    }

    public function elementType():Class
    {
        return (type as Class);
    }

    public function typeMap():Dictionary
    {
        return (type as Dictionary);
    }

    public function elementTypeForElementName(name:String):Class
    {
        return XObjTypeMap.elementTypeForElementName(type, name);
    }

    public function elementTagForMember(member:*):String
    {
        return XObjTypeMap.elementTagForMember(type, member);
    }

    public function addItemIfAbsent(value:Object):Boolean
    {
        if (getItemIndex(value) == -1)
        {
            addItem(value);
            return true;
        }
        return false;
    }

    public function removeItemIfPresent(object:Object):Boolean
    {
        return XObjUtils.removeItemIfPresent(this, object);
    }

    public function isElementMember(propName:String):Boolean
    {
       return XObjUtils.isElementMember(this, propName);
    }

    [xobjTransient]
    public function get isByReference():Boolean
    {
        return _isByReference;
    }

    private var _isByReference:Boolean;

    public function set isByReference(b:Boolean):void
    {
        _isByReference = b;
    }

}
}

Make XObjArrayCollection bindable

Make XObjArrayCollection bindable


////////////////////////////////////////////////////////////////////////////////
//
//  Licensed to the Apache Software Foundation (ASF) under one or more
//  contributor license agreements.  See the NOTICE file distributed with
//  this work for additional information regarding copyright ownership.
//  The ASF licenses this file to You under the Apache License, Version 2.0
//  (the "License"); you may not use this file except in compliance with
//  the License.  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////

package mx.binding
{

import mx.collections.errors.ItemPendingError;
import mx.core.mx_internal;
import flash.utils.Dictionary;

use namespace mx_internal;

[ExcludeClass]

/**
 *  @private
 */
public class Binding
{
    include "../core/Version.as";

    // Certain errors are normal during binding execution, so we swallow them.
    // 1507 - invalid null argument
    // 2005 - argument error (null gets converted to 0)
    mx_internal static var allowedErrors:Object = generateAllowedErrors();
    mx_internal static function generateAllowedErrors():Object
    {
        var o:Object = {};
        o[1507] = 1;
        o[2005] = 1;
        return o;
    }

    //--------------------------------------------------------------------------
	//
	//  Constructor
	//
	//--------------------------------------------------------------------------

    /**
     *  Create a Binding object
	 *
     *  @param document The document that is the target of all of this work.
	 *
     *  @param srcFunc The function that returns us the value
	 *  to use in this Binding.
	 *
     *  @param destFunc The function that will take a value
	 *  and assign it to the destination.
	 *
     *  @param destString The destination represented as a String.
	 *  We can then tell the ValidationManager to validate this field.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function Binding(document:Object, srcFunc:Function,
						    destFunc:Function, destString:String,
							srcString:String = null)
    {
		super();

        this.document = document;
        this.srcFunc = srcFunc;
        this.destFunc = destFunc;
        this.destString = destString;
        this.srcString = srcString;
        this.destFuncFailed = false;

        if (this.srcFunc == null)
        {
            this.srcFunc = defaultSrcFunc;
        }

        if (this.destFunc == null)
        {
            this.destFunc = defaultDestFunc;
        }

        _isEnabled = true;
        isExecuting = false;
        isHandlingEvent = false;
        hasHadValue = false;
        uiComponentWatcher = -1;

        BindingManager.addBinding(document, destString, this);
    }

 	//--------------------------------------------------------------------------
	//
	//  Variables
	//
	//--------------------------------------------------------------------------

    /**
     *  @private
     *  Internal storage for isEnabled property.
     */
    mx_internal var _isEnabled:Boolean;

    /**
     *  @private
     *  Indicates that a Binding is enabled.
     *  Used to disable bindings.
     */
    mx_internal function get isEnabled():Boolean
    {
        return _isEnabled;
    }

    /**
     *  @private
     */
    mx_internal function set isEnabled(value:Boolean):void
    {
        _isEnabled = value;

        if (value)
        {
            processDisabledRequests();
        }
    }

	/**
 	 *  @private
     *  Indicates that a Binding is executing.
	 *  Used to prevent circular bindings from causing infinite loops.
     */
    mx_internal var isExecuting:Boolean;

	/**
 	 *  @private
     *  Indicates that the binding is currently handling an event.
     *  Used to prevent us from infinitely causing an event
	 *  that re-executes the the binding.
     */
    mx_internal var isHandlingEvent:Boolean;

    /**
     *  @private
     *  Queue of watchers that fired while we were disabled.
     *  We will resynch with our binding if isEnabled is set to true
     *  and one or more of our watchers fired while we were disabled.
     */
    mx_internal var disabledRequests:Dictionary;

	/**
 	 *  @private
     *  True as soon as a non-null or non-empty-string value has been used.
     *  We don't auto-validate until this is true
     */
    private var hasHadValue:Boolean;

	/**
 	 *  @private
     *  This is no longer used in Flex 3.0, but it is required to load
     *  Flex 2.0.0 and Flex 2.0.1 modules.
     */
    public var uiComponentWatcher:int;

	/**
 	 *  @private
     *  It's possible that there is a two-way binding set up, in which case
     *  we'll do a rudimentary optimization by not executing ourselves
     *  if our counterpart is already executing.
     */
    public var twoWayCounterpart:Binding;

    /**
     *  @private
     *  If there is a twoWayCounterpart, hasHadValue is false, and
     *  isTwoWayPrimary is true, then the twoWayCounterpart will be
     *  executed first.
     */
    public var isTwoWayPrimary:Boolean;

    /**
     *  @private
     *  True if a wrapped function call does not throw an error.  This is used by
     *  innerExecute() to tell if the srcFunc completed successfully.
     */
    private var wrappedFunctionSuccessful:Boolean;

 	//--------------------------------------------------------------------------
	//
	//  Properties
	//
	//--------------------------------------------------------------------------

    /**
     *  All Bindings hang off of a document for now,
	 *  but really it's just the root of where these functions live.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    mx_internal var document:Object;

	/**
     *  The function that will return us the value.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    mx_internal var srcFunc:Function;

	/**
     *  The function that takes the value and assigns it.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    mx_internal var destFunc:Function;

    mx_internal var destFuncFailed:Boolean;

	/**
     *  The destination represented as a String.
	 *  This will be used so we can signal validation on a field.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    mx_internal var destString:String;

	/**
     *  The source represented as a String.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 4
     */
    mx_internal var srcString:String;

	/**
	 * 	@private
	 *  Used to suppress calls to destFunc when incoming value is either
	 *	a) an XML node identical to the previously assigned XML node, or
	 *  b) an XMLList containing the identical node sequence as the previously assigned XMLList
	 */
	private var lastValue:Object;

 	//--------------------------------------------------------------------------
	//
	//  Methods
	//
	//--------------------------------------------------------------------------

    private function defaultDestFunc(value:Object):void
    {
        var chain:Array = destString.split(".");
        var element:Object = document;
        var i:uint = 0;

        if (chain[0] == "this")
        {
            i++;
        }

        while (i < (chain.length - 1))
        {
            element = element[chain[i++]];
            //if the element does not exist : avoid exception as it's heavy on memory allocations
            if (element == null || element == undefined) {
                destFuncFailed = true;
                if (BindingManager.debugDestinationStrings[destString])
                {
                    trace("Binding: destString = " + destString + ", error = 1009");
                }
                return;
            }
        }

        element[chain[i]] = value;
    }

    private function defaultSrcFunc():Object
    {
        return document[srcString];
    }

    /**
     *  Execute the binding.
	 *  Call the source function and get the value we'll use.
	 *  Then call the destination function passing the value as an argument.
	 *  Finally try to validate the destination.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function execute(o:Object = null):void
    {
        if (!isEnabled)
        {
            if (o != null)
            {
                registerDisabledExecute(o);
            }
            return;
        }

        if (twoWayCounterpart && !twoWayCounterpart.hasHadValue && twoWayCounterpart.isTwoWayPrimary)
        {
            twoWayCounterpart.execute();
            hasHadValue = true;
            return;
        }

        if (isExecuting || (twoWayCounterpart && twoWayCounterpart.isExecuting))
        {
            // If there is a twoWayCounterpart already executing, that means that it is
            // assigning something of value so even though we won't execute we should be
            // sure to mark ourselves as having had a value so that future executions will
            // be correct.  If isExecuting is true but we re-entered, that means we
            // clearly had a value so setting hasHadValue is safe.
            hasHadValue = true;
            return;
        }

        try
        {
            isExecuting = true;
            wrapFunctionCall(this, innerExecute, o);
        }
        catch(error:Error)
        {
            if (allowedErrors[error.errorID] == null)
                throw error;
        }
        finally
        {
            isExecuting = false;
        }
    }

    /**
     * @private
     * Take note of any execute request that occur when we are disabled.
     */
    private function registerDisabledExecute(o:Object):void
    {
        if (o != null)
        {
            disabledRequests = (disabledRequests != null) ? disabledRequests :
                new Dictionary(true);

            disabledRequests[o] = true;
        }
    }

    /**
     * @private
     * Resynch with any watchers that may have updated while we were disabled.
     */
    private function processDisabledRequests():void
    {
        if (disabledRequests != null)
        {
            for (var key:Object in disabledRequests)
            {
                execute(key);
            }

            disabledRequests = null;
        }
    }

    /**
	 *  @private
	 *  Note: use of this wrapper needs to be reexamined. Currently there's at least one situation where a
	 *	wrapped function invokes another wrapped function, which is unnecessary (i.e., only the inner function
	 *  will throw), and also risks future errors due to the 'wrappedFunctionSuccessful' member variable
	 *  being stepped on. Leaving alone for now to minimize pre-GMC volatility, but should be revisited for
	 *  an early dot release.
	 *  Also note that the set of suppressed error codes below is repeated verbatim in Watcher.wrapUpdate.
	 *  These need to be consolidated and the motivations for each need to be documented.
     */
    protected function wrapFunctionCall(thisArg:Object, wrappedFunction:Function, object:Object = null, ...args):Object
    {
        wrappedFunctionSuccessful = false;

        try
        {
            var result:Object = wrappedFunction.apply(thisArg, args);
            if (destFuncFailed) {
                return null;
            }
            wrappedFunctionSuccessful = true;
            return result;
        }
        catch(itemPendingError:ItemPendingError)
        {
            itemPendingError.addResponder(new EvalBindingResponder(this, object));
            if (BindingManager.debugDestinationStrings[destString])
            {
                trace("Binding: destString = " + destString + ", error = " + itemPendingError);
            }
        }
        catch(rangeError:RangeError)
        {
            if (BindingManager.debugDestinationStrings[destString])
            {
                trace("Binding: destString = " + destString + ", error = " + rangeError);
            }
        }
        catch(error:Error)
        {
            // Certain errors are normal when executing a srcFunc or destFunc,
            // so we swallow them:
            //   Error #1006: Call attempted on an object that is not a function.
            //   Error #1009: null has no properties.
            //   Error #1010: undefined has no properties.
            //   Error #1055: - has no properties.
            //   Error #1069: Property - not found on - and there is no default value
            // We allow any other errors to be thrown.
            if ((error.errorID != 1006) &&
                (error.errorID != 1009) &&
                (error.errorID != 1010) &&
                (error.errorID != 1055) &&
                (error.errorID != 1069))
            {
                throw error;
            }
            else
            {
                if (BindingManager.debugDestinationStrings[destString])
                {
                    trace("Binding: destString = " + destString + ", error = " + error);
                }
            }
        }

        return null;
    }

	/**
	 *	@private
	 *  true iff XMLLists x and y contain the same node sequence.
	 */
	private function nodeSeqEqual(x:XMLList, y:XMLList):Boolean
	{
		var n:uint = x.length();
		if (n == y.length())
		{
			for (var i:uint = 0; i < n && x[i] === y[i]; i++)
			{
			}
			return i == n;
		}
		else
		{
			return false;
		}
	}

    /**
	 *  @private
     */
    private function innerExecute():void
    {
        var value:Object = wrapFunctionCall(document, srcFunc);

        if (BindingManager.debugDestinationStrings[destString])
        {
            trace("Binding: destString = " + destString + ", srcFunc result = " + value);
        }

        if (hasHadValue || wrappedFunctionSuccessful)
        {
        	//	Suppress binding assignments on non-simple XML: identical single nodes, or
        	//	lists over identical node sequences.
			//	Note: outer tests are inline for efficiency
        	if (!(lastValue is XML && lastValue.hasComplexContent() && lastValue === value) &&
        		!(lastValue is XMLList && lastValue.hasComplexContent() && value is XMLList &&
        			nodeSeqEqual(lastValue as XMLList, value as XMLList)))
        	{
	            destFunc.call(document, value);

                if (!destFuncFailed) {
                    //	Note: state is not updated if destFunc throws
                    lastValue = value;
                    hasHadValue = true;
	            }
	        }
        }
    }

    /**
	 *  This function is called when one of this binding's watchers
	 *  detects a property change.
	 *
	 *  @langversion 3.0
	 *  @playerversion Flash 9
	 *  @playerversion AIR 1.1
	 *  @productversion Flex 3
	 */
    public function watcherFired(commitEvent:Boolean, cloneIndex:int):void
    {
        if (isHandlingEvent)
            return;

        try
        {
	        isHandlingEvent = true;
			execute(cloneIndex);
		}
		finally
		{
        	isHandlingEvent = false;
        }
    }
}

}

////////////////////////////////////////////////////////////////////////////////
//
//  Licensed to the Apache Software Foundation (ASF) under one or more
//  contributor license agreements.  See the NOTICE file distributed with
//  this work for additional information regarding copyright ownership.
//  The ASF licenses this file to You under the Apache License, Version 2.0
//  (the "License"); you may not use this file except in compliance with
//  the License.  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////

package mx.binding
{

import mx.collections.errors.ItemPendingError;
import mx.core.mx_internal;
import flash.utils.Dictionary;

use namespace mx_internal;

[ExcludeClass]

/**
 *  @private
 */
public class Binding
{
    include "../core/Version.as";

    // Certain errors are normal during binding execution, so we swallow them.
    // 1507 - invalid null argument
    // 2005 - argument error (null gets converted to 0)
    mx_internal static var allowedErrors:Object = generateAllowedErrors();
    mx_internal static function generateAllowedErrors():Object
    {
        var o:Object = {};
        o[1507] = 1;
        o[2005] = 1;
        return o;
    }

    //--------------------------------------------------------------------------
	//
	//  Constructor
	//
	//--------------------------------------------------------------------------

    /**
     *  Create a Binding object
	 *
     *  @param document The document that is the target of all of this work.
	 *
     *  @param srcFunc The function that returns us the value
	 *  to use in this Binding.
	 *
     *  @param destFunc The function that will take a value
	 *  and assign it to the destination.
	 *
     *  @param destString The destination represented as a String.
	 *  We can then tell the ValidationManager to validate this field.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function Binding(document:Object, srcFunc:Function,
						    destFunc:Function, destString:String,
							srcString:String = null)
    {
		super();

        this.document = document;
        this.srcFunc = srcFunc;
        this.destFunc = destFunc;
        this.destString = destString;
        this.srcString = srcString;

        if (this.srcFunc == null)
        {
            this.srcFunc = defaultSrcFunc;
        }

        if (this.destFunc == null)
        {
            this.destFunc = defaultDestFunc;
        }

        _isEnabled = true;
        isExecuting = false;
        isHandlingEvent = false;
        hasHadValue = false;
        uiComponentWatcher = -1;

        BindingManager.addBinding(document, destString, this);
    }

 	//--------------------------------------------------------------------------
	//
	//  Variables
	//
	//--------------------------------------------------------------------------

    /**
     *  @private
     *  Internal storage for isEnabled property.
     */
    mx_internal var _isEnabled:Boolean;

    /**
     *  @private
     *  Indicates that a Binding is enabled.
     *  Used to disable bindings.
     */
    mx_internal function get isEnabled():Boolean
    {
        return _isEnabled;
    }

    /**
     *  @private
     */
    mx_internal function set isEnabled(value:Boolean):void
    {
        _isEnabled = value;

        if (value)
        {
            processDisabledRequests();
        }
    }

	/**
 	 *  @private
     *  Indicates that a Binding is executing.
	 *  Used to prevent circular bindings from causing infinite loops.
     */
    mx_internal var isExecuting:Boolean;

	/**
 	 *  @private
     *  Indicates that the binding is currently handling an event.
     *  Used to prevent us from infinitely causing an event
	 *  that re-executes the the binding.
     */
    mx_internal var isHandlingEvent:Boolean;

    /**
     *  @private
     *  Queue of watchers that fired while we were disabled.
     *  We will resynch with our binding if isEnabled is set to true
     *  and one or more of our watchers fired while we were disabled.
     */
    mx_internal var disabledRequests:Dictionary;

	/**
 	 *  @private
     *  True as soon as a non-null or non-empty-string value has been used.
     *  We don't auto-validate until this is true
     */
    private var hasHadValue:Boolean;

	/**
 	 *  @private
     *  This is no longer used in Flex 3.0, but it is required to load
     *  Flex 2.0.0 and Flex 2.0.1 modules.
     */
    public var uiComponentWatcher:int;

	/**
 	 *  @private
     *  It's possible that there is a two-way binding set up, in which case
     *  we'll do a rudimentary optimization by not executing ourselves
     *  if our counterpart is already executing.
     */
    public var twoWayCounterpart:Binding;

    /**
     *  @private
     *  If there is a twoWayCounterpart, hasHadValue is false, and
     *  isTwoWayPrimary is true, then the twoWayCounterpart will be
     *  executed first.
     */
    public var isTwoWayPrimary:Boolean;

    /**
     *  @private
     *  True if a wrapped function call does not throw an error.  This is used by
     *  innerExecute() to tell if the srcFunc completed successfully.
     */
    private var wrappedFunctionSuccessful:Boolean;

 	//--------------------------------------------------------------------------
	//
	//  Properties
	//
	//--------------------------------------------------------------------------

    /**
     *  All Bindings hang off of a document for now,
	 *  but really it's just the root of where these functions live.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    mx_internal var document:Object;

	/**
     *  The function that will return us the value.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    mx_internal var srcFunc:Function;

	/**
     *  The function that takes the value and assigns it.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    mx_internal var destFunc:Function;

	/**
     *  The destination represented as a String.
	 *  This will be used so we can signal validation on a field.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    mx_internal var destString:String;

	/**
     *  The source represented as a String.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 4
     */
    mx_internal var srcString:String;

	/**
	 * 	@private
	 *  Used to suppress calls to destFunc when incoming value is either
	 *	a) an XML node identical to the previously assigned XML node, or
	 *  b) an XMLList containing the identical node sequence as the previously assigned XMLList
	 */
	private var lastValue:Object;

 	//--------------------------------------------------------------------------
	//
	//  Methods
	//
	//--------------------------------------------------------------------------

    private function defaultDestFunc(value:Object):void
    {
        var chain:Array = destString.split(".");
        var element:Object = document;
        var i:uint = 0;

        if (chain[0] == "this")
        {
            i++;
        }

        while (i < (chain.length - 1))
        {
            element = element[chain[i++]];
        }

        element[chain[i]] = value;
    }

    private function defaultSrcFunc():Object
    {
        return document[srcString];
    }

    /**
     *  Execute the binding.
	 *  Call the source function and get the value we'll use.
	 *  Then call the destination function passing the value as an argument.
	 *  Finally try to validate the destination.
     *
     *  @langversion 3.0
     *  @playerversion Flash 9
     *  @playerversion AIR 1.1
     *  @productversion Flex 3
     */
    public function execute(o:Object = null):void
    {
        if (!isEnabled)
        {
            if (o != null)
            {
                registerDisabledExecute(o);
            }
            return;
        }

        if (twoWayCounterpart && !twoWayCounterpart.hasHadValue && twoWayCounterpart.isTwoWayPrimary)
        {
            twoWayCounterpart.execute();
            hasHadValue = true;
            return;
        }

        if (isExecuting || (twoWayCounterpart && twoWayCounterpart.isExecuting))
        {
            // If there is a twoWayCounterpart already executing, that means that it is
            // assigning something of value so even though we won't execute we should be
            // sure to mark ourselves as having had a value so that future executions will
            // be correct.  If isExecuting is true but we re-entered, that means we
            // clearly had a value so setting hasHadValue is safe.
            hasHadValue = true;
            return;
        }

        try
        {
            isExecuting = true;
            wrapFunctionCall(this, innerExecute, o);
        }
        catch(error:Error)
        {
            if (allowedErrors[error.errorID] == null)
                throw error;
        }
        finally
        {
            isExecuting = false;
        }
    }

    /**
     * @private
     * Take note of any execute request that occur when we are disabled.
     */
    private function registerDisabledExecute(o:Object):void
    {
        if (o != null)
        {
            disabledRequests = (disabledRequests != null) ? disabledRequests :
                new Dictionary(true);

            disabledRequests[o] = true;
        }
    }

    /**
     * @private
     * Resynch with any watchers that may have updated while we were disabled.
     */
    private function processDisabledRequests():void
    {
        if (disabledRequests != null)
        {
            for (var key:Object in disabledRequests)
            {
                execute(key);
            }

            disabledRequests = null;
        }
    }

    /**
	 *  @private
	 *  Note: use of this wrapper needs to be reexamined. Currently there's at least one situation where a
	 *	wrapped function invokes another wrapped function, which is unnecessary (i.e., only the inner function
	 *  will throw), and also risks future errors due to the 'wrappedFunctionSuccessful' member variable
	 *  being stepped on. Leaving alone for now to minimize pre-GMC volatility, but should be revisited for
	 *  an early dot release.
	 *  Also note that the set of suppressed error codes below is repeated verbatim in Watcher.wrapUpdate.
	 *  These need to be consolidated and the motivations for each need to be documented.
     */
    protected function wrapFunctionCall(thisArg:Object, wrappedFunction:Function, object:Object = null, ...args):Object
    {
        wrappedFunctionSuccessful = false;

        try
        {
            var result:Object = wrappedFunction.apply(thisArg, args);
            wrappedFunctionSuccessful = true;
            return result;
        }
        catch(itemPendingError:ItemPendingError)
        {
            itemPendingError.addResponder(new EvalBindingResponder(this, object));
            if (BindingManager.debugDestinationStrings[destString])
            {
                trace("Binding: destString = " + destString + ", error = " + itemPendingError);
            }
        }
        catch(rangeError:RangeError)
        {
            if (BindingManager.debugDestinationStrings[destString])
            {
                trace("Binding: destString = " + destString + ", error = " + rangeError);
            }
        }
        catch(error:Error)
        {
            // Certain errors are normal when executing a srcFunc or destFunc,
            // so we swallow them:
            //   Error #1006: Call attempted on an object that is not a function.
            //   Error #1009: null has no properties.
            //   Error #1010: undefined has no properties.
            //   Error #1055: - has no properties.
            //   Error #1069: Property - not found on - and there is no default value
            // We allow any other errors to be thrown.
            if ((error.errorID != 1006) &&
                (error.errorID != 1009) &&
                (error.errorID != 1010) &&
                (error.errorID != 1055) &&
                (error.errorID != 1069))
            {
                throw error;
            }
            else
            {
                if (BindingManager.debugDestinationStrings[destString])
                {
                    trace("Binding: destString = " + destString + ", error = " + error);
                }
            }
        }

        return null;
    }

	/**
	 *	@private
	 *  true iff XMLLists x and y contain the same node sequence.
	 */
	private function nodeSeqEqual(x:XMLList, y:XMLList):Boolean
	{
		var n:uint = x.length();
		if (n == y.length())
		{
			for (var i:uint = 0; i < n && x[i] === y[i]; i++)
			{
			}
			return i == n;
		}
		else
		{
			return false;
		}
	}

    /**
	 *  @private
     */
    private function innerExecute():void
    {
        var value:Object = wrapFunctionCall(document, srcFunc);

        if (BindingManager.debugDestinationStrings[destString])
        {
            trace("Binding: destString = " + destString + ", srcFunc result = " + value);
        }

        if (hasHadValue || wrappedFunctionSuccessful)
        {
        	//	Suppress binding assignments on non-simple XML: identical single nodes, or
        	//	lists over identical node sequences.
			//	Note: outer tests are inline for efficiency
        	if (!(lastValue is XML && lastValue.hasComplexContent() && lastValue === value) &&
        		!(lastValue is XMLList && lastValue.hasComplexContent() && value is XMLList &&
        			nodeSeqEqual(lastValue as XMLList, value as XMLList)))
        	{
	            destFunc.call(document, value);

	            //	Note: state is not updated if destFunc throws
	            lastValue = value;
	            hasHadValue = true;
	        }
        }
    }

    /**
	 *  This function is called when one of this binding's watchers
	 *  detects a property change.
	 *
	 *  @langversion 3.0
	 *  @playerversion Flash 9
	 *  @playerversion AIR 1.1
	 *  @productversion Flex 3
	 */
    public function watcherFired(commitEvent:Boolean, cloneIndex:int):void
    {
        if (isHandlingEvent)
            return;

        try
        {
	        isHandlingEvent = true;
			execute(cloneIndex);
		}
		finally
		{
        	isHandlingEvent = false;
        }
    }
}

}

Revert "FLEX-33874 improve binding performance"

This reverts commit ccdbfebd403b913c67d58b096f570d4c088fd0c1.


/*
 *  WorkshopConstants.as
 *  This file is part of FRESteamWorks.
 *
 *  Created by Ventero <http://github.com/Ventero> on 2013-04-24
 *  Copyright (c) 2013 Level Up Labs, LLC. All rights reserved.
 */

package com.amanitadesign.steam
{
	public class WorkshopConstants
	{
		public static const FILETYPE_Community:int = 0;
		public static const FILETYPE_Microtransaction:int = 1;
		public static const FILETYPE_Collection:int = 2;
		public static const FILETYPE_Art:int = 3;
		public static const FILETYPE_Video:int = 4;
		public static const FILETYPE_Screenshot:int = 5;
		public static const FILETYPE_Game:int = 6;
		public static const FILETYPE_Software:int = 7;
		public static const FILETYPE_Concept:int = 8;
		public static const FILETYPE_WebGuide:int = 9;
		public static const FILETYPE_IntegratedGuide:int = 10;

		public static const ENUMTYPE_RankedByVote:int = 0;
		public static const ENUMTYPE_Recent:int = 1;
		public static const ENUMTYPE_Trending:int = 2;
		public static const ENUMTYPE_FavoritesOfFriends:int = 3;
		public static const ENUMTYPE_VotedByFriends:int = 4;
		public static const ENUMTYPE_ContentByFriends:int = 5;
		public static const ENUMTYPE_RecentFromFollowedUsers:int = 6;

		public static const FILEACTION_Played:int = 0;
		public static const FILEACTION_Completed:int = 1;

		public static const VISIBILITY_Public:int = 0;
		public static const VISIBILITY_FriendsOnly:int = 1;
		public static const VISIBILITY_Private:int = 2;

		public static const OVERLAYSTOREFLAG_None:int = 0;
		public static const OVERLAYSTOREFLAG_AddToCart:int = 1;
		public static const OVERLAYSTOREFLAG_AddToCartAndShow:int = 2;

		public static const WORKSHOPVOTE_Unvoted:int = 0;
		public static const WORKSHOPVOTE_VoteFor:int = 1;
		public static const WORKSHOPVOTE_VoteAgainst:int = 2;

		public static const FILEUPDATEHANDLE_Invalid:String = "18446744073709551615"; // 0xffffffffffffffffull
		public static const UGCHANDLE_Invalid:String = "18446744073709551615"; // 0xffffffffffffffffull
	}
}

/*
 *  WorkshopConstants.as
 *  This file is part of FRESteamWorks.
 *
 *  Created by Ventero <http://github.com/Ventero> on 2013-04-24
 *  Copyright (c) 2013 Level Up Labs, LLC. All rights reserved.
 */

package com.amanitadesign.steam
{
	public class WorkshopConstants
	{
		public static const FILETYPE_Community:int = 0;
		public static const FILETYPE_Microtransaction:int = 1;
		public static const FILETYPE_Collection:int = 2;
		public static const FILETYPE_Art:int = 3;
		public static const FILETYPE_Video:int = 4;
		public static const FILETYPE_Screenshot:int = 5;
		public static const FILETYPE_Game:int = 6;
		public static const FILETYPE_Software:int = 7;
		public static const FILETYPE_Concept:int = 8;
		public static const FILETYPE_WebGuide:int = 9;
		public static const FILETYPE_IntegratedGuide:int = 10;
		public static const FILETYPE_Merch:int = 11;
		public static const FILETYPE_ControllerBinding:int = 11;

		public static const ENUMTYPE_RankedByVote:int = 0;
		public static const ENUMTYPE_Recent:int = 1;
		public static const ENUMTYPE_Trending:int = 2;
		public static const ENUMTYPE_FavoritesOfFriends:int = 3;
		public static const ENUMTYPE_VotedByFriends:int = 4;
		public static const ENUMTYPE_ContentByFriends:int = 5;
		public static const ENUMTYPE_RecentFromFollowedUsers:int = 6;

		public static const FILEACTION_Played:int = 0;
		public static const FILEACTION_Completed:int = 1;

		public static const VISIBILITY_Public:int = 0;
		public static const VISIBILITY_FriendsOnly:int = 1;
		public static const VISIBILITY_Private:int = 2;

		public static const OVERLAYSTOREFLAG_None:int = 0;
		public static const OVERLAYSTOREFLAG_AddToCart:int = 1;
		public static const OVERLAYSTOREFLAG_AddToCartAndShow:int = 2;

		public static const WORKSHOPVOTE_Unvoted:int = 0;
		public static const WORKSHOPVOTE_VoteFor:int = 1;
		public static const WORKSHOPVOTE_VoteAgainst:int = 2;

		public static const FILEUPDATEHANDLE_Invalid:String = "18446744073709551615"; // 0xffffffffffffffffull
		public static const UGCHANDLE_Invalid:String = "18446744073709551615"; // 0xffffffffffffffffull
	}
}

Add new filetypes.

Add new filetypes.


package aerys.minko.render.shader.part
{
	import aerys.minko.render.shader.SFloat;
	import aerys.minko.render.shader.Shader;
	import aerys.minko.render.shader.ShaderSettings;
	import aerys.minko.type.enum.DepthTest;
	import aerys.minko.type.enum.SamplerFiltering;
	import aerys.minko.type.enum.SamplerMipMapping;
	import aerys.minko.type.enum.SamplerWrapping;

	public final class PostProcessingShaderPart extends ShaderPart
	{
		public function get backBufferTexture() : SFloat
		{
			return sceneBindings.getTextureParameter(
				'backBuffer',
				SamplerFiltering.LINEAR,
				SamplerMipMapping.DISABLE,
				SamplerWrapping.CLAMP
			);
		}

		public function get vertexPosition() : SFloat
		{
			return multiply(vertexXYZ, float4(1, 1, 1, .5));
		}

		public function get backBufferPixel() : SFloat
		{
			return sampleBackBuffer(interpolate(vertexUV));
		}

		public function PostProcessingShaderPart(main : Shader)
		{
			super(main);
		}

		public function initializeSettings(settings : ShaderSettings) : void
		{
			settings.depthWriteEnabled = false;
			settings.depthTest = DepthTest.ALWAYS;
		}

		public function sampleBackBuffer(uv : SFloat) : SFloat
		{
			return sampleTexture(backBufferTexture, interpolate(vertexUV));
		}
	}
}

package aerys.minko.render.shader.part
{
	import aerys.minko.render.shader.SFloat;
	import aerys.minko.render.shader.Shader;
	import aerys.minko.render.shader.ShaderSettings;
	import aerys.minko.type.enum.DepthTest;
	import aerys.minko.type.enum.SamplerFiltering;
	import aerys.minko.type.enum.SamplerMipMapping;
	import aerys.minko.type.enum.SamplerWrapping;

	public final class PostProcessingShaderPart extends ShaderPart
	{
		public function get backBufferTexture() : SFloat
		{
			return sceneBindings.getTextureParameter(
				'backBuffer',
				SamplerFiltering.LINEAR,
				SamplerMipMapping.DISABLE,
				SamplerWrapping.CLAMP
			);
		}

		public function get vertexPosition() : SFloat
		{
			return multiply(vertexXYZ, float4(1, 1, 1, .5));
		}

		public function get backBufferPixel() : SFloat
		{
			return sampleBackBuffer(interpolate(vertexUV));
		}

		public function PostProcessingShaderPart(main : Shader)
		{
			super(main);
		}

		public function initializeSettings(settings : ShaderSettings) : void
		{
			settings.depthWriteEnabled = false;
			settings.depthTest = DepthTest.ALWAYS;
		}

		public function sampleBackBuffer(uv : SFloat) : SFloat
		{
			return sampleTexture(backBufferTexture, uv || interpolate(vertexUV));
		}
	}
}

fix PostProcessingShaderPart.sampleBackBuffer() to actually use the uv argument when provided


package laml.display {
	import flash.display.Bitmap;
	import flash.display.Loader;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.SecurityErrorEvent;
	import flash.geom.Rectangle;
	import flash.net.URLRequest;

	import laml.events.PayloadEvent;

	public class Image extends Component {
		private var bitmap:Bitmap;
		private var originalWidth:Number;
		private var originalHeight:Number;

		override protected function initialize():void {
			super.initialize();
			horizontalAlign = Component.ALIGN_CENTER;
			verticalAlign = Component.ALIGN_CENTER;

			model.validate_source = validateSource;
		}

		/**
		 * @source can be a string URL that the Image should load,
		 * a Class definition (by reference) that it Image should
		 * instantiate, or a subclass (or instance) of Bitmap.
		 *
		 * The Image will figure out what type of source it just
		 * received and respond accordingly.
		 *
		 * Of course images that need loaded will not be available
		 * immediately, but attached Bitmaps and classes will update
		 * preferredHeight and preferredWidth right away.
		 */
		public function set source(source:*):void {
			model.source = source;
		}

		public function get source():* {
			return model.source;
		}

		public function set maintainAspectRatio(maintain:Boolean):void {
			model.maintainAspectRatio = maintain;
		}

		public function get maintainAspectRatio():Boolean {
			return model.maintainAspectRatio;
		}

		private function validateSource(newValue:*, oldValue:*):void {
			if(bitmap) {
				view.removeChild(bitmap);
			}
			newValue = createImageFromValue(newValue);
			if(newValue) {
				bitmap = newValue;
				bitmap.smoothing = true;
				view.addChild(bitmap);
				preferredWidth = originalWidth = bitmap.width;
				preferredHeight = originalHeight = bitmap.height;
			}
		}

		private function createImageFromValue(value:*):Bitmap {
			if(value is Bitmap) {
				return value;
			}
			else if(value is Class) {
				return new value();
			}
			else {
				loadImage(value);
			}
			return null;
		}

		private function loadImage(url:String):void {
			//var context:LoaderContext = new LoaderContext(false, ApplicationDomain.currentDomain);
			var loader:Loader = new Loader();
			loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, loadErrorHandler);
			loader.contentLoaderInfo.addEventListener(SecurityErrorEvent.SECURITY_ERROR, loadErrorHandler);
			loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadCompleteHandler);
			loader.load(new URLRequest(url));
		}

		private function loadCompleteHandler(event:Event):void {
			source = event.target.content;
			render();
			dispatchPayloadEvent(PayloadEvent.LOADING_COMPLETED);
		}

		private function loadErrorHandler(event:Event):void {
			dispatchPayloadEvent(PayloadEvent.ERROR, event);
		}

		override protected function updateDisplayList(w:Number, h:Number):void {
			super.updateDisplayList(w, h);
			var availableWidth:Number = w - (paddingLeft + paddingRight);
			var availableHeight:Number = h - (paddingTop + paddingBottom);

			if(maintainAspectRatio) {
				if(bitmap) {
					var rect:Rectangle = constrainSize(originalWidth, originalHeight, availableWidth, availableHeight);
					var bw:Number = Math.floor(rect.width);
					var bh:Number = Math.floor(rect.height);
					bitmap.width = bw;
					bitmap.height = bh;

					switch(horizontalAlign) {
						case Component.ALIGN_LEFT :
							bitmap.x = paddingLeft;
							break;
						case Component.ALIGN_RIGHT :
							bitmap.x = w - (bw + paddingLeft);
							break;
						case Component.ALIGN_CENTER :
							bitmap.x = w/2 - bw/2;
							break;
					}

					switch(verticalAlign) {
						case Component.ALIGN_TOP :
							bitmap.y = paddingTop;
							break;
						case Component.ALIGN_BOTTOM :
							bitmap.y = h - (bh + paddingBottom);
							break;
						case Component.ALIGN_CENTER :
							bitmap.y = h/2 - bh/2;
							break;
					}
				}
			}
			else if(bitmap) {
				bitmap.width = w;
				bitmap.height = h;
			}
		}

		private function constrainSize(ow:int, oh:int, cw:int, ch:int):Rectangle {
			var w:int;
			var h:int;

			if (ow/oh > cw/ch) {
				w = cw;
				h = (w/ow) * oh;
			}
			else if (ow/oh < cw/ch) {
				h = ch;
				w = (h/oh) * ow;
			}
			else {
				if (ow > oh) {
					w = cw;
					h = (w/ow)*oh;
				}
				else {
					h = ch;
					w = (h/oh)*ow;
				}
			}
			return new Rectangle(0, 0, w, h);
		}
	}
}

package laml.display {
	import flash.display.Bitmap;
	import flash.display.DisplayObject;
	import flash.display.Loader;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.SecurityErrorEvent;
	import flash.geom.Rectangle;
	import flash.net.URLRequest;

	import laml.events.PayloadEvent;

	public class Image extends Component {
		private var bitmap:DisplayObject;
		private var originalWidth:Number;
		private var originalHeight:Number;

		override protected function initialize():void {
			super.initialize();
			horizontalAlign = Component.ALIGN_CENTER;
			verticalAlign = Component.ALIGN_CENTER;

			model.validate_source = validateSource;
		}

		/**
		 * @source can be a string URL that the Image should load,
		 * a Class definition (by reference) that it Image should
		 * instantiate, or a subclass (or instance) of Bitmap.
		 *
		 * The Image will figure out what type of source it just
		 * received and respond accordingly.
		 *
		 * Of course images that need loaded will not be available
		 * immediately, but attached Bitmaps and classes will update
		 * preferredHeight and preferredWidth right away.
		 */
		public function set source(source:*):void {
			model.source = source;
		}

		public function get source():* {
			return model.source;
		}

		public function set maintainAspectRatio(maintain:Boolean):void {
			model.maintainAspectRatio = maintain;
		}

		public function get maintainAspectRatio():Boolean {
			return model.maintainAspectRatio;
		}

		private function validateSource(newValue:*, oldValue:*):void {
			if(bitmap) {
				view.removeChild(bitmap);
			}
			newValue = createImageFromValue(newValue);
			if(newValue) {
				bitmap = newValue;
				if (bitmap is Bitmap) Bitmap(bitmap).smoothing = true;
				view.addChild(bitmap);
				preferredWidth = originalWidth = bitmap.width;
				preferredHeight = originalHeight = bitmap.height;
			}
		}

		private function createImageFromValue(value:*):DisplayObject {
			if(value is DisplayObject) {
				return value;
			}
			else if(value is Class) {
				return new value();
			}
			else {
				loadImage(value);
			}
			return null;
		}

		private function loadImage(url:String):void {
			//var context:LoaderContext = new LoaderContext(false, ApplicationDomain.currentDomain);
			var loader:Loader = new Loader();
			loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, loadErrorHandler);
			loader.contentLoaderInfo.addEventListener(SecurityErrorEvent.SECURITY_ERROR, loadErrorHandler);
			loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadCompleteHandler);
			loader.load(new URLRequest(url));
		}

		private function loadCompleteHandler(event:Event):void {
			source = event.target.content;
			render();
			dispatchPayloadEvent(PayloadEvent.LOADING_COMPLETED);
		}

		private function loadErrorHandler(event:Event):void {
			dispatchPayloadEvent(PayloadEvent.ERROR, event);
		}

		override protected function updateDisplayList(w:Number, h:Number):void {
			super.updateDisplayList(w, h);
			var availableWidth:Number = w - (paddingLeft + paddingRight);
			var availableHeight:Number = h - (paddingTop + paddingBottom);

			if(maintainAspectRatio) {
				if(bitmap) {
					var rect:Rectangle = constrainSize(originalWidth, originalHeight, availableWidth, availableHeight);
					var bw:Number = Math.floor(rect.width);
					var bh:Number = Math.floor(rect.height);
					bitmap.width = bw;
					bitmap.height = bh;

					switch(horizontalAlign) {
						case Component.ALIGN_LEFT :
							bitmap.x = paddingLeft;
							break;
						case Component.ALIGN_RIGHT :
							bitmap.x = w - (bw + paddingLeft);
							break;
						case Component.ALIGN_CENTER :
							bitmap.x = w/2 - bw/2;
							break;
					}

					switch(verticalAlign) {
						case Component.ALIGN_TOP :
							bitmap.y = paddingTop;
							break;
						case Component.ALIGN_BOTTOM :
							bitmap.y = h - (bh + paddingBottom);
							break;
						case Component.ALIGN_CENTER :
							bitmap.y = h/2 - bh/2;
							break;
					}
				}
			}
			else if(bitmap) {
				bitmap.width = w;
				bitmap.height = h;
			}
		}

		private function constrainSize(ow:int, oh:int, cw:int, ch:int):Rectangle {
			var w:int;
			var h:int;

			if (ow/oh > cw/ch) {
				w = cw;
				h = (w/ow) * oh;
			}
			else if (ow/oh < cw/ch) {
				h = ch;
				w = (h/oh) * ow;
			}
			else {
				if (ow > oh) {
					w = cw;
					h = (w/ow)*oh;
				}
				else {
					h = ch;
					w = (h/oh)*ow;
				}
			}
			return new Rectangle(0, 0, w, h);
		}
	}
}

Support passing in any kind of display object into image source

git-svn-id: 02605e11d3a461bc7e12f3f3880edf4b0c8dcfd0@4741 3e7533ad-8678-4d30-8e38-00a379d3f0d0


package com.amanitadesign.steam {
	import flash.desktop.NativeProcess;
	import flash.desktop.NativeProcessStartupInfo;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.StatusEvent;
	import flash.filesystem.File;
	import flash.utils.ByteArray;
	import flash.utils.IDataInput;
	import flash.utils.IDataOutput;
	import flash.utils.clearInterval;
	import flash.utils.setInterval;

	public class FRESteamWorks extends EventDispatcher {
		[Event(name="steam_response", type="com.amanitadesign.steam.SteamEvent")]

		private static const PATH:String = "NativeApps/Linux/APIWrapper";

		private var _file:File;
		private var _process:NativeProcess;
		private var _tm:int;

		public var isReady:Boolean = false;

		private static const AIRSteam_Init:int = 0;
		private static const AIRSteam_RunCallbacks:int = 1;
		private static const AIRSteam_RequestStats:int = 2;
		private static const AIRSteam_SetAchievement:int = 3;
		private static const AIRSteam_ClearAchievement:int = 4;
		private static const AIRSteam_IsAchievement:int = 5;
		private static const AIRSteam_GetStatInt:int = 6;
		private static const AIRSteam_GetStatFloat:int = 7;
		private static const AIRSteam_SetStatInt:int = 8;
		private static const AIRSteam_SetStatFloat:int = 9;
		private static const AIRSteam_StoreStats:int = 10;
		private static const AIRSteam_ResetAllStats:int = 11;
		private static const AIRSteam_GetFileCount:int = 12;
		private static const AIRSteam_GetFileSize:int = 13;
		private static const AIRSteam_FileExists:int = 14;
		private static const AIRSteam_FileWrite:int = 15;
		private static const AIRSteam_FileRead:int = 16;
		private static const AIRSteam_FileDelete:int = 17;
		private static const AIRSteam_IsCloudEnabledForApp:int = 18;
		private static const AIRSteam_SetCloudEnabledForApp:int = 19;

		public function FRESteamWorks (target:IEventDispatcher = null) {
			_file = File.applicationDirectory.resolvePath(PATH);
			_process = new NativeProcess();
			super(target);
		}

		public function dispose():void {
			if(_process.running) {
				_process.closeInput();
				_process.exit();
			}
			clearInterval(_tm);
			isReady = false;
		}

		private function startProcess():void {
			var startupInfo:NativeProcessStartupInfo = new NativeProcessStartupInfo();
			startupInfo.executable = _file;

			_process.start(startupInfo);
			_process.addEventListener(ProgressEvent.STANDARD_ERROR_DATA, eventDispatched);
			_process.addEventListener(IOErrorEvent.STANDARD_OUTPUT_IO_ERROR, errorCallback);
		}

		public function init():Boolean {
			if(!_file.exists) return false;
			startProcess();
			if(!_process.running) return false;

			callWrapper(AIRSteam_Init);
			isReady = readBoolResponse();
			if(isReady) _tm = setInterval(runCallbacks, 100);
			return isReady;
		}

		private function callWrapper(funcName:int, params:Array = null):void{
			if(!_process.running) startProcess();

			var stdin:IDataOutput = _process.standardInput;
			stdin.writeUTFBytes(funcName + "\n");

			if(!params) return;

			for(var i:int = 0; i < params.length; ++i) {
				if(params[i] is ByteArray) {
					var length:uint = params[i].length;
					// length + 1 for the added newline
					stdin.writeUTFBytes(String(length + 1) + "\n");
					stdin.writeBytes(params[i]);
					stdin.writeUTFBytes("\n");
				} else {
					stdin.writeUTFBytes(String(params[i]) + "\n");
				}
			}
		}

		private function waitForData(output:IDataInput):uint {
			while(!output.bytesAvailable) {
				// wait
			}

			return output.bytesAvailable;
		}

		private function readBoolResponse():Boolean {
			if(!_process.running) return false;
			var stdout:IDataInput = _process.standardOutput;
			var avail:uint = waitForData(stdout);

			var response:String = stdout.readUTFBytes(1);
			return (response == "t");
		}

		private function readIntResponse():int {
			if(!_process.running) return 0;
			var stdout:IDataInput = _process.standardOutput;
			var avail:uint = waitForData(stdout);

			var response:String = stdout.readUTFBytes(avail);
			return parseInt(response, 10);
		}

		private function readFloatResponse():Number {
			if(!_process.running) return 0.0;
			var stdout:IDataInput = _process.standardOutput;
			var avail:uint = waitForData(stdout);

			var response:String = stdout.readUTFBytes(avail)
			return parseFloat(response);
		}

		private function readStringResponse():String {
			if(!_process.running) return "";
			var stdout:IDataInput = _process.standardOutput;
			var avail:uint = waitForData(stdout);

			var response:String = stdout.readUTFBytes(avail)
			return response;
		}

		private function eventDispatched(e:ProgressEvent):void {
			var stderr:IDataInput = _process.standardError;
			var avail:uint = stderr.bytesAvailable;
			var data:String = stderr.readUTFBytes(avail);

			var pattern:RegExp = /__event__<(\d+),(\d+)>/g;
			var result:Object;
			while((result = pattern.exec(data))) {
				var req_type:int = new int(result[1]);
				var response:int = new int(result[2]);
				var steamEvent:SteamEvent = new SteamEvent(SteamEvent.STEAM_RESPONSE, req_type, response);
				dispatchEvent(steamEvent);
			}
		}

		private function errorCallback(e:IOErrorEvent):void {
			// the process doesn't accept our input anymore, try to restart it
			if(_process.running) {
				_process.closeInput();
				_process.exit();
			}

			startProcess();
		}

		public function requestStats():Boolean {
			callWrapper(AIRSteam_RequestStats);
			return readBoolResponse();
		}

		public function runCallbacks():Boolean {
			callWrapper(AIRSteam_RunCallbacks);
			return true;
		}

		public function setAchievement(id:String):Boolean {
			callWrapper(AIRSteam_SetAchievement, [id]);
			return readBoolResponse();
		}

		public function clearAchievement(id:String):Boolean {
			callWrapper(AIRSteam_ClearAchievement, [id]);
			return readBoolResponse();
		}

		public function isAchievement(id:String):Boolean {
			callWrapper(AIRSteam_IsAchievement, [id]);
			return readBoolResponse();
		}

		public function getStatInt(id:String):int {
			callWrapper(AIRSteam_GetStatInt, [id]);
			return readIntResponse();
		}

		public function getStatFloat(id:String):Number {
			callWrapper(AIRSteam_GetStatFloat, [id]);
			return readFloatResponse();
		}

		public function setStatInt(id:String, value:int):Boolean {
			callWrapper(AIRSteam_SetStatInt, [id, value]);
			return readBoolResponse();
		}

		public function setStatFloat(id:String, value:Number):Boolean {
			callWrapper(AIRSteam_SetStatFloat, [id, value]);
			return readBoolResponse();
		}

		public function storeStats():Boolean {
			callWrapper(AIRSteam_StoreStats);
			return readBoolResponse();
		}

		public function resetAllStats(bAchievementsToo:Boolean):Boolean {
			callWrapper(AIRSteam_ResetAllStats, [bAchievementsToo]);
			return readBoolResponse();
		}

		public function getFileCount():int {
			callWrapper(AIRSteam_GetFileCount);
			return readIntResponse();
		}

		public function getFileSize(fileName:String):int {
			callWrapper(AIRSteam_GetFileSize, [fileName]);
			return readIntResponse();
		}

		public function fileExists(fileName:String):Boolean {
			callWrapper(AIRSteam_FileExists, [fileName]);
			return readBoolResponse();
		}

		public function fileWrite(fileName:String, data:ByteArray):Boolean {
			callWrapper(AIRSteam_FileWrite, [fileName, data]);
			return readBoolResponse();
		}

		public function fileRead(fileName:String, data:ByteArray):Boolean {
			callWrapper(AIRSteam_FileRead, [fileName]);

			var success:Boolean = readBoolResponse();
			if(success) {
				var content:String = readStringResponse();
				data.writeUTFBytes(content);
				data.position = 0;
			}

			return success;
		}

		public function fileDelete(fileName:String):Boolean {
			callWrapper(AIRSteam_FileDelete, [fileName]);
			return readBoolResponse();
		}

		public function isCloudEnabledForApp():Boolean {
			callWrapper(AIRSteam_IsCloudEnabledForApp);
			return readBoolResponse();
		}

		public function setCloudEnabledForApp(enabled:Boolean):Boolean {
			callWrapper(AIRSteam_SetCloudEnabledForApp, [enabled]);
			return readBoolResponse();
		}
	}
}

package com.amanitadesign.steam {
	import flash.desktop.NativeProcess;
	import flash.desktop.NativeProcessStartupInfo;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.StatusEvent;
	import flash.filesystem.File;
	import flash.utils.ByteArray;
	import flash.utils.IDataInput;
	import flash.utils.IDataOutput;
	import flash.utils.clearInterval;
	import flash.utils.setInterval;

	public class FRESteamWorks extends EventDispatcher {
		[Event(name="steam_response", type="com.amanitadesign.steam.SteamEvent")]

		private static const PATH:String = "NativeApps/Linux/APIWrapper";

		private var _file:File;
		private var _process:NativeProcess;
		private var _tm:int;
		private var _error:Boolean = false;

		public var isReady:Boolean = false;

		private static const AIRSteam_Init:int = 0;
		private static const AIRSteam_RunCallbacks:int = 1;
		private static const AIRSteam_RequestStats:int = 2;
		private static const AIRSteam_SetAchievement:int = 3;
		private static const AIRSteam_ClearAchievement:int = 4;
		private static const AIRSteam_IsAchievement:int = 5;
		private static const AIRSteam_GetStatInt:int = 6;
		private static const AIRSteam_GetStatFloat:int = 7;
		private static const AIRSteam_SetStatInt:int = 8;
		private static const AIRSteam_SetStatFloat:int = 9;
		private static const AIRSteam_StoreStats:int = 10;
		private static const AIRSteam_ResetAllStats:int = 11;
		private static const AIRSteam_GetFileCount:int = 12;
		private static const AIRSteam_GetFileSize:int = 13;
		private static const AIRSteam_FileExists:int = 14;
		private static const AIRSteam_FileWrite:int = 15;
		private static const AIRSteam_FileRead:int = 16;
		private static const AIRSteam_FileDelete:int = 17;
		private static const AIRSteam_IsCloudEnabledForApp:int = 18;
		private static const AIRSteam_SetCloudEnabledForApp:int = 19;

		public function FRESteamWorks (target:IEventDispatcher = null) {
			_file = File.applicationDirectory.resolvePath(PATH);
			_process = new NativeProcess();
			_process.addEventListener(ProgressEvent.STANDARD_ERROR_DATA, eventDispatched);
			_process.addEventListener(IOErrorEvent.STANDARD_INPUT_IO_ERROR, errorCallback);
			super(target);
		}

		public function dispose():void {
			if(_process.running) {
				_process.closeInput();
				_process.exit();
			}
			clearInterval(_tm);
			isReady = false;
		}

		private function startProcess():void {
			var startupInfo:NativeProcessStartupInfo = new NativeProcessStartupInfo();
			startupInfo.executable = _file;

			_process.start(startupInfo);
		}

		public function init():Boolean {
			if(!_file.exists) return false;
			startProcess();
			if(!_process.running) return false;

			if(!callWrapper(AIRSteam_Init)) return false;
			isReady = readBoolResponse();
			if(isReady) _tm = setInterval(runCallbacks, 100);
			return isReady;
		}

		private function errorCallback(e:IOErrorEvent):void {
			_error = true;
			// the process doesn't accept our input anymore, so just stop it
			clearInterval(_tm);

			if(_process.running) {
				try {
					_process.closeInput();
				} catch(e:*) {
					// no-op
				}

				_process.exit();
			}
		}

		private function callWrapper(funcName:int, params:Array = null):Boolean {
			_error = false;
			if(!_process.running) return false;

			var stdin:IDataOutput = _process.standardInput;
			stdin.writeUTFBytes(funcName + "\n");

			if (params) {
				for(var i:int = 0; i < params.length; ++i) {
					if(params[i] is ByteArray) {
						var length:uint = params[i].length;
						// length + 1 for the added newline
						stdin.writeUTFBytes(String(length + 1) + "\n");
						stdin.writeBytes(params[i]);
						stdin.writeUTFBytes("\n");
					} else {
						stdin.writeUTFBytes(String(params[i]) + "\n");
					}
				}
			}

			return !_error;
		}

		private function waitForData(output:IDataInput):uint {
			while(!output.bytesAvailable) {
				// wait
				if(!_process.running) return 0;
			}

			return output.bytesAvailable;
		}

		private function readBoolResponse():Boolean {
			if(!_process.running) return false;
			var stdout:IDataInput = _process.standardOutput;
			var avail:uint = waitForData(stdout);

			var response:String = stdout.readUTFBytes(1);
			return (response == "t");
		}

		private function readIntResponse():int {
			if(!_process.running) return 0;
			var stdout:IDataInput = _process.standardOutput;
			var avail:uint = waitForData(stdout);

			var response:String = stdout.readUTFBytes(avail);
			return parseInt(response, 10);
		}

		private function readFloatResponse():Number {
			if(!_process.running) return 0.0;
			var stdout:IDataInput = _process.standardOutput;
			var avail:uint = waitForData(stdout);

			var response:String = stdout.readUTFBytes(avail)
			return parseFloat(response);
		}

		private function readStringResponse():String {
			if(!_process.running) return "";
			var stdout:IDataInput = _process.standardOutput;
			var avail:uint = waitForData(stdout);

			var response:String = stdout.readUTFBytes(avail)
			return response;
		}

		private function eventDispatched(e:ProgressEvent):void {
			var stderr:IDataInput = _process.standardError;
			var avail:uint = stderr.bytesAvailable;
			var data:String = stderr.readUTFBytes(avail);

			var pattern:RegExp = /__event__<(\d+),(\d+)>/g;
			var result:Object;
			while((result = pattern.exec(data))) {
				var req_type:int = new int(result[1]);
				var response:int = new int(result[2]);
				var steamEvent:SteamEvent = new SteamEvent(SteamEvent.STEAM_RESPONSE, req_type, response);
				dispatchEvent(steamEvent);
			}
		}

		public function requestStats():Boolean {
			if(!callWrapper(AIRSteam_RequestStats)) return false;
			return readBoolResponse();
		}

		public function runCallbacks():Boolean {
			if(!callWrapper(AIRSteam_RunCallbacks)) return false;
			return true;
		}

		public function setAchievement(id:String):Boolean {
			if(!callWrapper(AIRSteam_SetAchievement, [id])) return false;
			return readBoolResponse();
		}

		public function clearAchievement(id:String):Boolean {
			if(!callWrapper(AIRSteam_ClearAchievement, [id])) return false;
			return readBoolResponse();
		}

		public function isAchievement(id:String):Boolean {
			if(!callWrapper(AIRSteam_IsAchievement, [id])) return false;
			return readBoolResponse();
		}

		public function getStatInt(id:String):int {
			if(!callWrapper(AIRSteam_GetStatInt, [id])) return 0;
			return readIntResponse();
		}

		public function getStatFloat(id:String):Number {
			if(!callWrapper(AIRSteam_GetStatFloat, [id])) return 0.0;
			return readFloatResponse();
		}

		public function setStatInt(id:String, value:int):Boolean {
			if(!callWrapper(AIRSteam_SetStatInt, [id, value])) return false;
			return readBoolResponse();
		}

		public function setStatFloat(id:String, value:Number):Boolean {
			if(!callWrapper(AIRSteam_SetStatFloat, [id, value])) return false;
			return readBoolResponse();
		}

		public function storeStats():Boolean {
			if(!callWrapper(AIRSteam_StoreStats)) return false;
			return readBoolResponse();
		}

		public function resetAllStats(bAchievementsToo:Boolean):Boolean {
			if(!callWrapper(AIRSteam_ResetAllStats, [bAchievementsToo])) return false;
			return readBoolResponse();
		}

		public function getFileCount():int {
			if(!callWrapper(AIRSteam_GetFileCount)) return 0;
			return readIntResponse();
		}

		public function getFileSize(fileName:String):int {
			if(!callWrapper(AIRSteam_GetFileSize, [fileName])) return 0;
			return readIntResponse();
		}

		public function fileExists(fileName:String):Boolean {
			if(!callWrapper(AIRSteam_FileExists, [fileName])) return false;
			return readBoolResponse();
		}

		public function fileWrite(fileName:String, data:ByteArray):Boolean {
			if(!callWrapper(AIRSteam_FileWrite, [fileName, data])) return false;
			return readBoolResponse();
		}

		public function fileRead(fileName:String, data:ByteArray):Boolean {
			if(!callWrapper(AIRSteam_FileRead, [fileName])) return false;

			var success:Boolean = readBoolResponse();
			if(success) {
				var content:String = readStringResponse();
				data.writeUTFBytes(content);
				data.position = 0;
			}

			return success;
		}

		public function fileDelete(fileName:String):Boolean {
			if(!callWrapper(AIRSteam_FileDelete, [fileName])) return false;
			return readBoolResponse();
		}

		public function isCloudEnabledForApp():Boolean {
			if(!callWrapper(AIRSteam_IsCloudEnabledForApp)) return false;
			return readBoolResponse();
		}

		public function setCloudEnabledForApp(enabled:Boolean):Boolean {
			if(!callWrapper(AIRSteam_SetCloudEnabledForApp, [enabled])) return false;
			return readBoolResponse();
		}
	}
}

Improve error handling

Improve error handling