gnash-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Gnash-commit] /srv/bzr/gnash/trunk r11561: Widespread but relatively un


From: Benjamin Wolsey
Subject: [Gnash-commit] /srv/bzr/gnash/trunk r11561: Widespread but relatively unimportant changes to get rid of annoyances and
Date: Wed, 14 Oct 2009 18:40:32 +0200
User-agent: Bazaar (1.16.1)

------------------------------------------------------------
revno: 11561 [merge]
committer: Benjamin Wolsey <address@hidden>
branch nick: trunk
timestamp: Wed 2009-10-14 18:40:32 +0200
message:
  Widespread but relatively unimportant changes to get rid of annoyances and
  misleading code (intrusive_ptr).
  
  Various changes to the Array implementation so that it's less type-dependant
  and closer to the target implementation.
modified:
  libcore/Button.cpp
  libcore/MovieClip.cpp
  libcore/MovieClip.h
  libcore/PropertyList.cpp
  libcore/PropertyList.h
  libcore/TextField.cpp
  libcore/Video.cpp
  libcore/as_function.cpp
  libcore/as_object.cpp
  libcore/as_object.h
  libcore/as_value.cpp
  libcore/as_value.h
  libcore/asobj/Array_as.cpp
  libcore/asobj/Array_as.h
  libcore/asobj/AsBroadcaster.cpp
  libcore/asobj/Color_as.cpp
  libcore/asobj/Global_as.h
  libcore/asobj/Globals.cpp
  libcore/asobj/Globals.h
  libcore/asobj/LoadableObject.cpp
  libcore/asobj/MovieClipLoader.cpp
  libcore/asobj/Object.cpp
  libcore/asobj/QName_as.cpp
  libcore/asobj/Selection_as.cpp
  libcore/asobj/String_as.cpp
  libcore/asobj/TextFormat_as.cpp
  libcore/asobj/flash/display/BitmapData_as.cpp
  libcore/asobj/flash/display/DisplayObjectContainer_as.cpp
  libcore/asobj/flash/display/MovieClip_as.cpp
  libcore/asobj/flash/geom/ColorTransform_as.cpp
  libcore/asobj/flash/geom/Matrix_as.cpp
  libcore/asobj/flash/geom/Point_as.cpp
  libcore/asobj/flash/geom/Rectangle_as.cpp
  libcore/asobj/flash/geom/Transform_as.cpp
  libcore/asobj/flash/media/Camera_as.cpp
  libcore/asobj/flash/media/Microphone_as.cpp
  libcore/asobj/flash/media/Sound_as.cpp
  libcore/asobj/flash/net/LocalConnection_as.cpp
  libcore/asobj/flash/net/NetStream_as.cpp
  libcore/asobj/flash/net/SharedObject_as.cpp
  libcore/asobj/flash/text/TextSnapshot_as.cpp
  libcore/asobj/flash/text/TextSnapshot_as.h
  libcore/asobj/flash/ui/ContextMenu_as.cpp
  libcore/asobj/flash/xml/XMLDocument_as.cpp
  libcore/asobj/flash/xml/XMLNode_as.cpp
  libcore/movie_root.cpp
  libcore/swf_function.cpp
  libcore/swf_function.h
  libcore/vm/ASHandlers.cpp
  libcore/vm/Machine.cpp
  testsuite/actionscript.all/array.as
  testsuite/swfdec/PASSING
=== modified file 'libcore/Button.cpp'
--- a/libcore/Button.cpp        2009-10-12 12:06:51 +0000
+++ b/libcore/Button.cpp        2009-10-14 08:47:08 +0000
@@ -1024,7 +1024,7 @@
 as_value
 button_blendMode(const fn_call& fn)
 {
-    as_object* obj = ensureType<Button>(fn.this_ptr).get();
+    as_object* obj = ensureType<Button>(fn.this_ptr);
     UNUSED(obj);
     return as_value();
 }
@@ -1032,7 +1032,7 @@
 as_value
 button_cacheAsBitmap(const fn_call& fn)
 {
-    as_object* obj = ensureType<Button>(fn.this_ptr).get();
+    as_object* obj = ensureType<Button>(fn.this_ptr);
     UNUSED(obj);
     return as_value();
 }
@@ -1040,7 +1040,7 @@
 as_value
 button_filters(const fn_call& fn)
 {
-    as_object* obj = ensureType<Button>(fn.this_ptr).get();
+    as_object* obj = ensureType<Button>(fn.this_ptr);
     UNUSED(obj);
     return as_value();
 }
@@ -1048,7 +1048,7 @@
 as_value
 button_scale9Grid(const fn_call& fn)
 {
-    as_object* obj = ensureType<Button>(fn.this_ptr).get();
+    as_object* obj = ensureType<Button>(fn.this_ptr);
     UNUSED(obj);
     return as_value();
 }
@@ -1056,7 +1056,7 @@
 as_value
 button_getTabIndex(const fn_call& fn)
 {
-    as_object* obj = ensureType<Button>(fn.this_ptr).get();
+    as_object* obj = ensureType<Button>(fn.this_ptr);
     UNUSED(obj);
     return as_value();
 }
@@ -1064,7 +1064,7 @@
 as_value
 button_setTabIndex(const fn_call& fn)
 {
-    as_object* obj = ensureType<Button>(fn.this_ptr).get();
+    as_object* obj = ensureType<Button>(fn.this_ptr);
     UNUSED(obj);
     return as_value();
 }
@@ -1072,7 +1072,7 @@
 as_value
 button_getDepth(const fn_call& fn)
 {
-    as_object* obj = ensureType<Button>(fn.this_ptr).get();
+    as_object* obj = ensureType<Button>(fn.this_ptr);
     UNUSED(obj);
     return as_value();
 }

=== modified file 'libcore/MovieClip.cpp'
--- a/libcore/MovieClip.cpp     2009-10-13 07:59:26 +0000
+++ b/libcore/MovieClip.cpp     2009-10-14 08:47:08 +0000
@@ -597,47 +597,15 @@
 }
 
 DisplayObject*
-MovieClip::add_empty_movieclip(const std::string& name, int depth)
+MovieClip::addDisplayListObject(DisplayObject* obj, int depth)
 {
-    MovieClip* movieclip = new MovieClip(0, _swf, this);
-    movieclip->set_name(name);
-    movieclip->setDynamic();
-
     // TODO: only call set_invalidated if this DisplayObject actually overrides
     //             an existing one !
     set_invalidated(); 
-
-    _displayList.placeDisplayObject(movieclip, depth);     
-
-    return movieclip;
-}
-
-boost::intrusive_ptr<DisplayObject>
-MovieClip::add_textfield(const std::string& name, int depth, int x, int y,
-        float width, float height)
-{
-    
-    // Set textfield bounds
-    SWFRect bounds(0, 0, pixelsToTwips(width), pixelsToTwips(height));
-
-    // Create an instance
-    boost::intrusive_ptr<DisplayObject> txt_char = new TextField(this, bounds);
-
-    // Give name and mark as dynamic
-    txt_char->set_name(name);
-    txt_char->setDynamic();
-
-    // Set _x and _y
-    SWFMatrix txt_matrix;
-    txt_matrix.set_translation(pixelsToTwips(x), pixelsToTwips(y));
-    // update caches (although shouldn't be needed as we only set translation)
-    txt_char->setMatrix(txt_matrix, true); 
-
-    // Here we add the DisplayObject to the displayList.    
-    _displayList.placeDisplayObject(txt_char.get(), depth); 
-
-    return txt_char;
-}
+    _displayList.placeDisplayObject(obj, depth);     
+    return obj;
+}
+
 
 boost::intrusive_ptr<MovieClip> 
 MovieClip::duplicateMovieClip(const std::string& newname, int depth,
@@ -847,7 +815,7 @@
         return tmp.to_sprite(true);
     }
 
-    return tmp.to_object(*getGlobal(*this)).get();
+    return tmp.to_object(*getGlobal(*this));
 }
 
 bool

=== modified file 'libcore/MovieClip.h'
--- a/libcore/MovieClip.h       2009-10-13 07:59:26 +0000
+++ b/libcore/MovieClip.h       2009-10-14 06:55:13 +0000
@@ -318,10 +318,8 @@
     ///
     DisplayObject* getDisplayObjectAtDepth(int depth);
 
-    DisplayObject* add_empty_movieclip(const std::string& name, int depth);
-
-    boost::intrusive_ptr<DisplayObject> add_textfield(const std::string& name,
-            int depth, int x, int y, float width, float height);
+    /// Attach a DisplayObject at the specified depth.
+    DisplayObject* addDisplayListObject(DisplayObject* obj, int depth);
 
     /// Place a DisplayObject or mask to the DisplayList.
     //

=== modified file 'libcore/PropertyList.cpp'
--- a/libcore/PropertyList.cpp  2009-07-30 11:20:20 +0000
+++ b/libcore/PropertyList.cpp  2009-10-14 08:47:08 +0000
@@ -65,7 +65,7 @@
 // something in namespace 0.
 static inline
 PropertyList::container::iterator
-iterator_find(PropertyList::container &p, string_table::key name,
+iterator_find(const PropertyList::container &p, string_table::key name,
        string_table::key nsId)
 {
        if (nsId)
@@ -251,13 +251,10 @@
 }
 
 Property*
-PropertyList::getProperty(string_table::key key, string_table::key nsId)
+PropertyList::getProperty(string_table::key key, string_table::key nsId) const
 {
        container::iterator found = iterator_find(_props, key, nsId);
-       if (found == _props.end())
-       {
-               return NULL;
-       }
+       if (found == _props.end()) return 0;
        return const_cast<Property*>(&(*found));
 }
 

=== modified file 'libcore/PropertyList.h'
--- a/libcore/PropertyList.h    2009-07-29 14:33:56 +0000
+++ b/libcore/PropertyList.h    2009-10-14 08:47:08 +0000
@@ -298,7 +298,8 @@
        ///     ownership of returned Propery is kept by the PropertyList,
        ///     so plase *don't* delete it !
        ///
-       Property* getProperty(string_table::key key, string_table::key nsId = 
0);
+       Property* getProperty(string_table::key key, string_table::key nsId = 0)
+        const;
 
        /// Get a property, if existing, by order
        ///

=== modified file 'libcore/TextField.cpp'
--- a/libcore/TextField.cpp     2009-10-12 12:15:41 +0000
+++ b/libcore/TextField.cpp     2009-10-14 14:50:52 +0000
@@ -88,6 +88,8 @@
     void attachPrototypeProperties(as_object& proto);
     void attachTextFieldStaticMembers(as_object& o);
 
+    as_value textfield_createTextField(const fn_call& fn);
+
     as_value textfield_variable(const fn_call& fn);
     as_value textfield_setTextFormat(const fn_call& fn);
     as_value textfield_getTextFormat(const fn_call& fn);
@@ -254,17 +256,12 @@
 {
 
     as_object* proto = getTextFieldInterface(getVM(*this));
+    attachPrototypeProperties(*proto);
  
-    // This is an instantiation, so attach properties to the
-    // prototype.
-    // TODO: is it correct to do it here, or can some TextFields
-    // be constructed without attaching these?
-    attachPrototypeProperties(*proto);
-
     set_prototype(proto);
 
-    Array_as* ar = new Array_as();
-    ar->push(this);
+    as_object* ar = getGlobal(*this)->createArray();
+    ar->callMethod(NSV::PROP_PUSH, this);
     set_member(NSV::PROP_uLISTENERS, ar);
     
     registerTextVariable();
@@ -2362,6 +2359,9 @@
     vm.registerNative(textfield_setNewTextFormat, 104, 105);
     vm.registerNative(textfield_getDepth, 104, 106);
     vm.registerNative(textfield_replaceText, 104, 107);
+
+    vm.registerNative(textfield_createTextField, 104, 200);
+    vm.registerNative(textfield_getFontList, 104, 201);
 }
 
 bool
@@ -2797,12 +2797,8 @@
 void
 attachPrototypeProperties(as_object& o)
 {
-    // Standard flags.
-    const int flags = PropFlags::dontDelete
-        |PropFlags::dontEnum;
-
     // SWF6 or higher
-    const int swf6Flags = flags | PropFlags::onlySWF6Up;
+    const int swf6Flags = as_object::DefaultFlags | PropFlags::onlySWF6Up;
 
     boost::intrusive_ptr<builtin_function> getset;
 
@@ -2866,6 +2862,68 @@
 }
 
 
+/// This is in fact a property of MovieClip, but it is more a TextField
+/// function, as its major number (104) in the native table shows.
+as_value
+textfield_createTextField(const fn_call& fn)
+{
+    boost::intrusive_ptr<MovieClip> ptr = ensureType<MovieClip>(fn.this_ptr);
+    
+    // name, depth, x, y, width, height
+    if (fn.nargs < 6) {
+        IF_VERBOSE_ASCODING_ERRORS(
+        log_aserror(_("createTextField called with %d args, "
+            "expected 6 - returning undefined"), fn.nargs);
+        );
+        return as_value();
+    }
+
+    const std::string& name = fn.arg(0).to_string();
+    int depth = fn.arg(1).to_int();
+    int x = fn.arg(2).to_int();
+    int y = fn.arg(3).to_int();
+    int width = fn.arg(4).to_int();
+
+    if (width < 0) {
+        IF_VERBOSE_ASCODING_ERRORS(
+        log_aserror(_("createTextField: negative width (%d)"
+            " - reverting sign"), width);
+        );
+        width = -width;
+    }
+
+    int height = fn.arg(5).to_int();
+    if ( height < 0 )
+    {
+        IF_VERBOSE_ASCODING_ERRORS(
+        log_aserror(_("createTextField: negative height (%d)"
+            " - reverting sign"), height);
+        );
+        height = -height;
+    }
+    // Set textfield bounds
+    SWFRect bounds(0, 0, pixelsToTwips(width), pixelsToTwips(height));
+
+    // Create an instance
+    DisplayObject* tf = new TextField(ptr.get(), bounds);
+
+    // Give name and mark as dynamic
+    tf->set_name(name);
+    tf->setDynamic();
+
+    // Set _x and _y
+    SWFMatrix matrix;
+    matrix.set_translation(pixelsToTwips(x), pixelsToTwips(y));
+    // update caches (although shouldn't be needed as we only set translation)
+    tf->setMatrix(matrix, true); 
+
+    DisplayObject* txt = ptr->addDisplayListObject(tf, depth);
+
+    // createTextField returns void, it seems
+    if (getSWFVersion(fn) > 7) return as_value(txt);
+    return as_value(); 
+}
+
 as_value
 textfield_background(const fn_call& fn)
 {
@@ -3281,7 +3339,7 @@
     }
 
     TextFormat_as* tf;
-    if (!isNativeType(fn.arg(0).to_object(*getGlobal(fn)).get(), tf)) {
+    if (!isNativeType(fn.arg(0).to_object(*getGlobal(fn)), tf)) {
 
         IF_VERBOSE_ASCODING_ERRORS(
             std::stringstream ss; fn.dump_args(ss);
@@ -3661,17 +3719,10 @@
 void
 attachTextFieldStaticMembers(as_object& o)
 {
-    // Standard flags.
-    const int flags = PropFlags::dontDelete
-        |PropFlags::dontEnum;
-
     // SWF6 or higher
-    const int swf6Flags = flags | PropFlags::onlySWF6Up;
-
-    Global_as* gl = getGlobal(o);
-    o.init_member("getFontList",
-            gl->createFunction(textfield_getFontList), swf6Flags);
-
+    const int swf6Flags = as_object::DefaultFlags | PropFlags::onlySWF6Up;
+    VM& vm = getVM(o);
+    o.init_member("getFontList", vm.getNative(104, 201), swf6Flags);
 }
 
 /// This is called when a prototype should be added

=== modified file 'libcore/Video.cpp'
--- a/libcore/Video.cpp 2009-10-12 09:42:13 +0000
+++ b/libcore/Video.cpp 2009-10-14 08:47:08 +0000
@@ -394,7 +394,7 @@
                return as_value();
        }
 
-    as_object* obj = fn.arg(0).to_object(*getGlobal(fn)).get();
+    as_object* obj = fn.arg(0).to_object(*getGlobal(fn));
        NetStream_as* ns;
 
     if (isNativeType(obj, ns)) {

=== modified file 'libcore/as_function.cpp'
--- a/libcore/as_function.cpp   2009-08-20 12:19:38 +0000
+++ b/libcore/as_function.cpp   2009-10-14 08:47:08 +0000
@@ -195,7 +195,7 @@
     // 'this' pointer. Others return a new object. This is to handle those
     // cases.
     if (isBuiltin() && ret.is_object()) {
-        newobj = ret.to_object(*getGlobal(env)).get();
+        newobj = ret.to_object(*getGlobal(env));
 
         newobj->init_member(NSV::PROP_uuCONSTRUCTORuu, as_value(this),
                 flags);
@@ -294,7 +294,7 @@
        else
        {
                // Get the object to use as 'this' reference
-               as_object* obj = fn.arg(0).to_object(*getGlobal(fn)).get();
+               as_object* obj = fn.arg(0).to_object(*getGlobal(fn));
 
         if (!obj) obj = new as_object; 
 
@@ -377,7 +377,7 @@
        else {
                // Get the object to use as 'this' reference
                as_value this_val = fn.arg(0);
-               as_object* this_ptr = this_val.to_object(*getGlobal(fn)).get();
+               as_object* this_ptr = this_val.to_object(*getGlobal(fn));
 
                if (!this_ptr) {
                        // If the first argument is not an object, we should
@@ -397,7 +397,7 @@
                }
                else {
                        new_fn_call.this_ptr = this_ptr;
-                       as_object* proto = this_ptr->get_prototype().get();
+                       as_object* proto = this_ptr->get_prototype();
             if (proto) {
                 new_fn_call.super = this_ptr->get_super();
             }

=== modified file 'libcore/as_object.cpp'
--- a/libcore/as_object.cpp     2009-10-12 08:56:07 +0000
+++ b/libcore/as_object.cpp     2009-10-14 08:47:08 +0000
@@ -107,7 +107,7 @@
                        throw ActionLimitException("Lookup depth exceeded.");
         }
 
-        _object = _object->get_prototype().get();
+        _object = _object->get_prototype();
 
         // TODO: there is recursion prevention anyway; is this extra 
         // check for circularity really necessary?
@@ -218,7 +218,7 @@
 private:
 
     as_object* prototype() {
-        return _super ? _super->get_prototype().get() : 0;
+        return _super ? _super->get_prototype() : 0;
     }
 
     as_function* constructor() {
@@ -236,7 +236,7 @@
        // Our class superclass prototype is __proto__.__proto__
 
        // Our class prototype is __proto__.
-       as_object* proto = get_prototype().get(); 
+       as_object* proto = get_prototype(); 
        if (!proto) return new as_super(*getGlobal(*this), 0);
 
     if (!fname || getSWFVersion(*this) <= 6) {
@@ -254,7 +254,7 @@
 
     as_object* tmp = proto;
     while (tmp && tmp->get_prototype() != owner) {
-        tmp = tmp->get_prototype().get();
+        tmp = tmp->get_prototype();
     }
     // ok, now 'tmp' should be the object whose __proto__ member
     // contains the actual named method.
@@ -486,7 +486,7 @@
        as_object *obj = this;
        while (depth--)
        {
-               obj = obj->get_prototype().get();
+               obj = obj->get_prototype();
                if (!obj)
                        return NULL;
        }
@@ -502,7 +502,7 @@
        // Our class superclass prototype is __proto__.__proto__
 
        // Our class prototype is __proto__.
-       as_object* proto = get_prototype().get();
+       as_object* proto = get_prototype();
 
        if ( fname && getSWFVersion(*this) > 6)
        {
@@ -542,7 +542,7 @@
        as_object *obj = this;
        while (i--)
        {
-               obj = obj->get_prototype().get();
+               obj = obj->get_prototype();
                if (!obj)
                        return 0;
        }
@@ -550,7 +550,7 @@
        const Property *p = obj->_members.getOrderAfter(index);
        if (!p)
        {
-               obj = obj->get_prototype().get();
+               obj = obj->get_prototype();
                if (!obj)
                        return 0;
                p = obj->_members.getOrderAfter(0);
@@ -940,7 +940,7 @@
 #endif
                return false;
        }
-       as_object* ctorProto = protoVal.to_object(*getGlobal(*this)).get();
+       as_object* ctorProto = protoVal.to_object(*getGlobal(*this));
        if ( ! ctorProto )
        {
 #ifdef GNASH_DEBUG_INSTANCE_OF
@@ -957,7 +957,7 @@
        as_object* obj = this;
        while (obj && visited.insert(obj).second )
        {
-               as_object* thisProto = obj->get_prototype().get();
+               as_object* thisProto = obj->get_prototype();
                if ( ! thisProto )
                {
                        break;
@@ -1186,14 +1186,14 @@
        return getOwnProperty(key, nsname) != NULL;
 }
 
-boost::intrusive_ptr<as_object>
-as_object::get_prototype()
+as_object*
+as_object::get_prototype() const
 {
        int swfVersion = getSWFVersion(*this);
 
        Property* prop = _members.getProperty(NSV::PROP_uuPROTOuu);
-       if ( ! prop ) return 0;
-       if ( ! prop->visible(swfVersion) ) return 0;
+       if (!prop) return 0;
+       if (!prop->visible(swfVersion)) return 0;
 
        as_value tmp = prop->getValue(*this);
 
@@ -1325,7 +1325,7 @@
                return NULL;
        }
 
-       return tmp.to_object(*getGlobal(*this)).get();
+       return tmp.to_object(*getGlobal(*this));
 }
 
 void

=== modified file 'libcore/as_object.h'
--- a/libcore/as_object.h       2009-10-12 08:56:07 +0000
+++ b/libcore/as_object.h       2009-10-14 08:47:08 +0000
@@ -983,12 +983,7 @@
     ///
     /// NOTE: can return NULL (and it is expected to do for Object.prototype)
     ///
-    boost::intrusive_ptr<as_object> get_prototype();
-
-    const boost::intrusive_ptr<as_object> get_prototype() const {
-        // cast away constness
-        return const_cast<as_object*>(this)->get_prototype();
-    }
+    as_object* get_prototype() const;
 
     /// Set this object's '__proto__' member
     //
@@ -1185,14 +1180,14 @@
 /// @param obj the pointer to be cast.
 /// @return If the cast succeeds, the pointer cast to the requested type.
 template <typename T>
-boost::intrusive_ptr<T>
-ensureType(boost::intrusive_ptr<as_object> obj)
+T*
+ensureType(as_object* obj)
 {
-    boost::intrusive_ptr<T> ret = boost::dynamic_pointer_cast<T>(obj);
+    T* ret = dynamic_cast<T*>(obj);
 
     if (!ret) {
-        std::string target = typeName(ret.get());
-        std::string source = typeName(obj.get());
+        std::string target = typeName(ret);
+        std::string source = typeName(obj);
 
         std::string msg = "builtin method or gettersetter for " +
             target + " called from " + source + " instance.";

=== modified file 'libcore/as_value.cpp'
--- a/libcore/as_value.cpp      2009-10-07 09:30:57 +0000
+++ b/libcore/as_value.cpp      2009-10-14 14:26:23 +0000
@@ -315,12 +315,10 @@
     :
     m_type(AS_FUNCTION)
 {
-       if ( func )
-       {
-               _value = boost::intrusive_ptr<as_object>(func);
+       if (func) {
+               _value = func;
        }
-       else
-       {
+       else {
                m_type = NULLTYPE;
                _value = boost::blank();
        }
@@ -379,8 +377,7 @@
                case AS_FUNCTION:
                case OBJECT:
                {
-            as_object* obj = m_type == AS_FUNCTION ? getFun().get() :
-                                                     getObj().get();
+            as_object* obj = m_type == AS_FUNCTION ? getFun() : getObj();
             String_as* s;
             if (isNativeType(obj, s)) return s->value();
 
@@ -469,7 +466,7 @@
 
        if (m_type == OBJECT && swfVersion > 5) {
         Date_as* d;
-        if (isNativeType(getObj().get(), d)) hint = STRING;
+        if (isNativeType(getObj(), d)) hint = STRING;
     }
 
        return to_primitive(hint);
@@ -485,7 +482,7 @@
 
        if (m_type == OBJECT && swfVersion > 5) {
         Date_as* d;
-        if (isNativeType<Date_as>(getObj().get(), d)) hint = STRING;
+        if (isNativeType<Date_as>(getObj(), d)) hint = STRING;
     }
 
     *this = to_primitive(hint);
@@ -515,8 +512,8 @@
                        return as_value(NaN);
                }
 #endif
-               if ( m_type == OBJECT ) obj = getObj().get();
-               else obj = getFun().get();
+               if ( m_type == OBJECT ) obj = getObj();
+               else obj = getFun();
 
                if ((!obj->get_member(NSV::PROP_VALUE_OF, &method)) || 
(!method.is_function())) 
                {
@@ -539,8 +536,8 @@
                        return as_value(getCharacterProxy().getTarget());
                }
 
-               if ( m_type == OBJECT ) obj = getObj().get();
-               else obj = getFun().get();
+               if ( m_type == OBJECT ) obj = getObj();
+               else obj = getFun();
 
                // @@ Moock says, "the value that results from
                // calling toString() on the object".
@@ -902,21 +899,19 @@
 }
        
 // Return value as an object.
-boost::intrusive_ptr<as_object>
+as_object*
 as_value::to_object(Global_as& global) const
 {
-       typedef boost::intrusive_ptr<as_object> ptr;
-
        switch (m_type)
        {
                case OBJECT:
                        return getObj();
 
                case AS_FUNCTION:
-                       return getFun().get();
+                       return getFun();
 
                case MOVIECLIP:
-                       return ptr(toDisplayObject());
+                       return toDisplayObject();
 
                case STRING:
                        return global.createString(getStr());
@@ -952,12 +947,6 @@
 }
 
 void
-as_value::set_sprite(MovieClip& sprite)
-{
-       setDisplayObject(sprite);
-}
-
-void
 as_value::setDisplayObject(DisplayObject& sprite)
 {
        m_type = MOVIECLIP;
@@ -971,7 +960,7 @@
 {
     if (m_type == AS_FUNCTION) {
            // OK.
-           return getFun().get();
+           return getFun();
     }
 
     return NULL;
@@ -999,10 +988,10 @@
                set_null();
                return;
        }
-       DisplayObject* sp = obj->toDisplayObject();
-       if ( sp )
-       {
-               setDisplayObject(*sp);
+    if (obj->displayObject()) {
+        // The static cast is fine as long as the as_object is genuinely
+        // a DisplayObject.
+               setDisplayObject(static_cast<DisplayObject&>(*obj));
                return;
        }
        as_function* func = obj->to_function();
@@ -1014,7 +1003,7 @@
        if (m_type != OBJECT || getObj() != obj)
        {
                m_type = OBJECT;
-               _value = boost::intrusive_ptr<as_object>(obj);
+               _value = obj;
        }
 }
 
@@ -1027,12 +1016,12 @@
 void
 as_value::set_as_function(as_function* func)
 {
-    if (m_type != AS_FUNCTION || getFun().get() != func)
+    if (m_type != AS_FUNCTION || getFun() != func)
     {
        m_type = AS_FUNCTION;
        if (func)
        {
-               _value = boost::intrusive_ptr<as_object>(func);
+               _value = func;
        }
        else
        {
@@ -1043,13 +1032,6 @@
 }
 
 bool
-as_value::conforms_to(string_table::key /*name*/)
-{
-       // TODO: Implement
-       return false;
-}
-
-bool
 as_value::equals(const as_value& v) const
 {
     // Comments starting with numbers refer to the ECMA-262 document
@@ -1087,7 +1069,7 @@
     /// Compare to same type
     if ( obj_or_func && v_obj_or_func )
     {
-        return boost::get<AsObjPtr>(_value) == boost::get<AsObjPtr>(v._value); 
+        return boost::get<as_object*>(_value) == 
boost::get<as_object*>(v._value); 
     }
 
     if ( m_type == v.m_type ) return equalsSameType(v);
@@ -1373,13 +1355,13 @@
             return ret.str();
                case OBJECT:
                {
-                       as_object* obj = getObj().get();
+                       as_object* obj = getObj();
                        ret = boost::format("[object(%s):%p]") % typeName(*obj) 
% static_cast<void*>(obj);
                        return ret.str();
                }
                case AS_FUNCTION:
                {
-                       as_function* obj = getFun().get();
+                       as_function* obj = getFun();
                        ret = boost::format("[function(%s):%p]") % 
typeName(*obj) % static_cast<void*>(obj);
                        return ret.str();
                }
@@ -1566,14 +1548,14 @@
        {
                case OBJECT:
                {
-                       as_value::AsObjPtr op = getObj();
+                       as_object* op = getObj();
                        if (op)
                                op->setReachable();
                        break;
                }
                case AS_FUNCTION:
                {
-                       as_value::AsFunPtr fp = getFun();
+                       as_function* fp = getFun();
                        if (fp)
                                fp->setReachable();
                        break;
@@ -1589,18 +1571,18 @@
 #endif // GNASH_USE_GC
 }
 
-as_value::AsFunPtr
+as_function*
 as_value::getFun() const
 {
        assert(m_type == AS_FUNCTION);
-       return boost::get<AsObjPtr>(_value)->to_function();
+       return boost::get<as_object*>(_value)->to_function();
 }
 
-as_value::AsObjPtr
+as_object*
 as_value::getObj() const
 {
        assert(m_type == OBJECT);
-       return boost::get<AsObjPtr>(_value);
+       return boost::get<as_object*>(_value);
 }
 
 CharacterProxy
@@ -1616,15 +1598,6 @@
        return getCharacterProxy().get(allowUnloaded);
 }
 
-as_value::SpritePtr
-as_value::getSprite(bool allowUnloaded) const
-{
-       assert(m_type == MOVIECLIP);
-       DisplayObject* ch = getCharacter(allowUnloaded);
-       if ( ! ch ) return 0;
-       return ch->to_movie();
-}
-
 void
 as_value::set_string(const std::string& str)
 {
@@ -1704,6 +1677,7 @@
     
     VM& vm = VM::get();
     string_table& st = vm.getStringTable();
+    Global_as* gl = vm.getGlobal();
 
     switch (el.getType()) {
       case amf::Element::NOTYPE:
@@ -1813,7 +1787,9 @@
 #ifdef GNASH_DEBUG_AMF_DESERIALIZE
           log_debug("as_value(Element&) : AMF type ECMA_ARRAY");
 #endif
-          Array_as* obj = new Array_as;
+
+          as_object* obj = gl->createArray();
+
           if (el.propertySize()) {
               for (size_t i=0; i < el.propertySize(); i++) {
                  const boost::shared_ptr<amf::Element> prop = 
el.getProperty(i);
@@ -1834,9 +1810,9 @@
 #ifdef GNASH_DEBUG_AMF_DESERIALIZE
           log_debug("as_value(Element&) : AMF type STRICT_ARRAY");
 #endif
-          Array_as* obj = new Array_as;
+          as_object* obj = gl->createArray();
           size_t len = el.propertySize();
-          obj->resize(len);
+          obj->set_member(NSV::PROP_LENGTH, len);
 
           for (size_t i=0; i < el.propertySize(); i++) {
               const boost::shared_ptr<amf::Element> prop = el.getProperty(i);
@@ -1947,6 +1923,8 @@
                }
        }
 
+    Global_as* gl = vm.getGlobal();
+
        switch (amf_type)
     {
 
@@ -2032,89 +2010,89 @@
 
                case amf::Element::STRICT_ARRAY_AMF0:
         {
-                               boost::intrusive_ptr<Array_as> array(new 
Array_as());
-                objRefs.push_back(array.get());
+            as_object* array = gl->createArray();
+            objRefs.push_back(array);
 
-                boost::uint32_t li = readNetworkLong(b); b += 4;
+            boost::uint32_t li = readNetworkLong(b); b += 4;
 #ifdef GNASH_DEBUG_AMF_DESERIALIZE
-                               log_debug("amf0 starting read of STRICT_ARRAY 
with %i elements", li);
+            log_debug("amf0 starting read of STRICT_ARRAY with %i elements", 
li);
 #endif
-                               as_value arrayElement;
-                               for(size_t i = 0; i < li; ++i)
-                               {
-                                       if ( ! amf0_read_value(b, end, 
arrayElement, -1,
-                                objRefs, vm) )
-                                       {
-                                               return false;
-                                       }
-                                       array->push(arrayElement);
-                               }
+            as_value arrayElement;
+            for (size_t i = 0; i < li; ++i)
+            {
+                if ( ! amf0_read_value(b, end, arrayElement, -1,
+                            objRefs, vm) )
+                {
+                    return false;
+                }
+                array->callMethod(NSV::PROP_PUSH, arrayElement);
+            }
 
-                               ret.set_as_object(array);
-                               return true;
+            ret.set_as_object(array);
+            return true;
         }
 
                case amf::Element::ECMA_ARRAY_AMF0:
         {
-                               Array_as* obj = new Array_as(); // GC-managed...
-                objRefs.push_back(obj);
-
-                // set the value immediately, so if there's any problem parsing
-                // (like premature end of buffer) we still get something.
-                               ret.set_as_object(obj);
-
-                boost::uint32_t li = readNetworkLong(b); b += 4;
-                
-                log_debug("array size: %d", li);
-                
-                // the count specifies array size, so to have that even if 
none of the members are indexed
-                // if short, will be incremented everytime an indexed member 
is found
-                obj->resize(li);
-
-                // TODO: do boundary checking (if b >= end...)
-
-#ifdef GNASH_DEBUG_AMF_DESERIALIZE
-                               log_debug("amf0 starting read of ECMA_ARRAY 
with %i elements", li);
-#endif
-                               as_value objectElement;
-                               string_table& st = vm.getStringTable();
-                               for (;;)
-                               {
-                    if ( b+2 >= end )
-                    {
-                        log_error("MALFORMED SOL: premature end of ECMA_ARRAY "
-                                "block");
-                        break;
-                    }
-                                       boost::uint16_t strlen = 
readNetworkShort(b); b+=2; 
-
-                    // end of ECMA_ARRAY is signalled by an empty string
-                    // followed by an OBJECT_END_AMF0 (0x09) byte
-                    if ( ! strlen )
-                    {
-                        // expect an object terminator here
-                        if ( *b++ != amf::Element::OBJECT_END_AMF0 )
-                        {
-                            log_error("MALFORMED SOL: empty member name not "
-                                    "followed by OBJECT_END_AMF0 byte");
-                        }
-                        break;
-                    }
-
-                                       std::string name(reinterpret_cast<const 
char*>(b), strlen);
-
-#ifdef GNASH_DEBUG_AMF_DESERIALIZE
-                                       log_debug("amf0 ECMA_ARRAY prop name is 
%s", name);
-#endif
-                                       b += strlen;
-                                       if ( ! amf0_read_value(b, end, 
objectElement, -1, objRefs, vm) )
-                                       {
-                                               return false;
-                                       }
-                                       obj->set_member(st.find(name), 
objectElement);
-                               }
-
-                               return true;
+            as_object* obj = gl->createArray();
+            objRefs.push_back(obj);
+
+            // set the value immediately, so if there's any problem parsing
+            // (like premature end of buffer) we still get something.
+            ret.set_as_object(obj);
+
+            boost::uint32_t li = readNetworkLong(b); b += 4;
+            
+            log_debug("array size: %d", li);
+            
+            // the count specifies array size, so to have that even if none of 
the members are indexed
+            // if short, will be incremented everytime an indexed member is 
found
+            obj->set_member(NSV::PROP_LENGTH, li);
+
+            // TODO: do boundary checking (if b >= end...)
+
+#ifdef GNASH_DEBUG_AMF_DESERIALIZE
+            log_debug("amf0 starting read of ECMA_ARRAY with %i elements", li);
+#endif
+            as_value objectElement;
+            string_table& st = vm.getStringTable();
+            for (;;)
+            {
+                if ( b+2 >= end )
+                {
+                    log_error("MALFORMED SOL: premature end of ECMA_ARRAY "
+                            "block");
+                    break;
+                }
+                boost::uint16_t strlen = readNetworkShort(b); b+=2; 
+
+                // end of ECMA_ARRAY is signalled by an empty string
+                // followed by an OBJECT_END_AMF0 (0x09) byte
+                if ( ! strlen )
+                {
+                    // expect an object terminator here
+                    if ( *b++ != amf::Element::OBJECT_END_AMF0 )
+                    {
+                        log_error("MALFORMED SOL: empty member name not "
+                                "followed by OBJECT_END_AMF0 byte");
+                    }
+                    break;
+                }
+
+                std::string name(reinterpret_cast<const char*>(b), strlen);
+
+#ifdef GNASH_DEBUG_AMF_DESERIALIZE
+                log_debug("amf0 ECMA_ARRAY prop name is %s", name);
+#endif
+                b += strlen;
+                if ( ! amf0_read_value(b, end, objectElement, -1, objRefs, vm) 
)
+                {
+                    return false;
+                }
+                obj->set_member(st.find(name), objectElement);
+            }
+
+            return true;
         }
 
                case amf::Element::OBJECT_AMF0:
@@ -2211,7 +2189,6 @@
                        log_debug("amf0 read date: %e", dub);
 #endif
 
-            Global_as* gl = vm.getGlobal();
             as_function* ctor = 
gl->getMember(NSV::CLASS_DATE).to_as_function();
             if (ctor) {
                 fn_call::Args args;
@@ -2272,7 +2249,7 @@
 
         case OBJECT:
         {
-            as_object* obj = to_object(*vm.getGlobal()).get();
+            as_object* obj = to_object(*vm.getGlobal());
             assert(obj);
             OffsetTable::iterator it = offsetTable.find(obj);
             if (it == offsetTable.end()) {

=== modified file 'libcore/as_value.h'
--- a/libcore/as_value.h        2009-10-07 07:46:44 +0000
+++ b/libcore/as_value.h        2009-10-14 09:29:00 +0000
@@ -286,7 +286,7 @@
     static bool parseNonDecimalInt(const std::string& s, double& d,
             bool whole = true);
 
-       /// Return the primitive type of this value, as a string.
+       /// Return the primitive type of this value as a string.
        const char* typeOf() const;
 
        /// Get the primitive type of this value
@@ -294,14 +294,10 @@
     /// Only used in AVM2
        primitive_types ptype() const;
 
-       // Chad: Document
-       bool conforms_to(string_table::key name);
-
        /// \brief
        /// Return true if this value is callable
        /// (AS_FUNCTION).
-       bool is_function() const
-       {
+       bool is_function() const {
                return m_type == AS_FUNCTION;
        }
 
@@ -435,7 +431,7 @@
     /// @param global   The global object object for the conversion. This
     ///                 contains the prototypes or constructors necessary for
     ///                 conversion.
-       boost::intrusive_ptr<as_object> to_object(Global_as& global) const;
+       as_object* to_object(Global_as& global) const;
 
        /// Return value as a sprite or NULL if this is not possible.
        //
@@ -510,8 +506,11 @@
 
        void set_bool(bool val);
 
-       void set_sprite(MovieClip& sp);
-
+    /// Set this as_value to a DisplayObject
+    //
+    /// as_value itself does not distinguish between MovieClips and other
+    /// types of DisplayObject; TextFields initially appear as type
+    /// "movieclip".
        void setDisplayObject(DisplayObject& sp);
 
        void set_int(int val) { set_double(val); }
@@ -545,19 +544,26 @@
 
        bool is_bool() const { return (m_type == BOOLEAN); }
 
-        bool is_exception() const
-       { return (m_type == UNDEFINED_EXCEPT || m_type == NULLTYPE_EXCEPT
-               || m_type == BOOLEAN_EXCEPT || m_type == NUMBER_EXCEPT
-               || m_type == OBJECT_EXCEPT || m_type == AS_FUNCTION_EXCEPT
-               || m_type == MOVIECLIP_EXCEPT || m_type == STRING_EXCEPT);
+    bool is_exception() const {
+        return (m_type == UNDEFINED_EXCEPT || m_type == NULLTYPE_EXCEPT
+                || m_type == BOOLEAN_EXCEPT || m_type == NUMBER_EXCEPT
+                || m_type == OBJECT_EXCEPT || m_type == AS_FUNCTION_EXCEPT
+                || m_type == MOVIECLIP_EXCEPT || m_type == STRING_EXCEPT);
        }
 
        // Flag or unflag an as_value as an exception -- this gets flagged
        // when an as_value is 'thrown'.
-       void flag_exception() 
-       { if (!is_exception()) m_type = 
static_cast<AsType>(static_cast<int>(m_type) + 1); }
-       void unflag_exception()
-       { if (is_exception()) m_type = 
static_cast<AsType>(static_cast<int>(m_type) - 1); }
+       void flag_exception() {
+        if (!is_exception()) {
+            m_type = static_cast<AsType>(static_cast<int>(m_type) + 1);
+        }
+    }
+
+       void unflag_exception() {
+        if (is_exception()) {
+            m_type = static_cast<AsType>(static_cast<int>(m_type) - 1);
+        }
+    }
 
        /// Return true if this value is strictly equal to the given one
        //
@@ -606,10 +612,7 @@
 
        AsType m_type;
 
-       typedef MovieClip* SpritePtr;
        typedef DisplayObject* CharacterPtr;
-       typedef boost::intrusive_ptr<as_function> AsFunPtr;
-       typedef boost::intrusive_ptr<as_object> AsObjPtr;
        
        /// AsValueType handles the following AS types:
        //
@@ -620,24 +623,17 @@
        /// 5. MovieClip
        /// 6. String
     typedef boost::variant<boost::blank, double,
-            bool, AsObjPtr, CharacterProxy,    std::string> AsValueType;
+            bool, as_object*, CharacterProxy, std::string> AsValueType;
     
     AsValueType _value;
 
-
        /// Get the function pointer variant member (we assume m_type == 
FUNCTION)
-       AsFunPtr getFun() const;
+       as_function* getFun() const;
 
        /// Get the object pointer variant member (we assume m_type == OBJECT)
-       AsObjPtr getObj() const;
-
-       /// Get the sprite pointer variant member (we assume m_type == 
MOVIECLIP)
-       //
-       /// NOTE: this is possibly NULL !
-       ///
-       SpritePtr getSprite(bool skipRebinding=false) const;
-
-       /// Get the DisplayObject pointer variant member (we assume m_type == 
MOVIECLIP)
+       as_object* getObj() const;
+
+       /// Get the DisplayObject variant member (we assume m_type == MOVIECLIP)
        //
        /// NOTE: this is possibly NULL !
        ///
@@ -648,22 +644,19 @@
        CharacterProxy getCharacterProxy() const;
 
        /// Get the number variant member (we assume m_type == NUMBER)
-       double getNum() const
-       {
+       double getNum() const {
                assert(m_type == NUMBER);
                return boost::get<double>(_value);
        }
 
        /// Get the boolean variant member (we assume m_type == BOOLEAN)
-       bool getBool() const
-       {
+       bool getBool() const {
                assert(m_type == BOOLEAN);
                return boost::get<bool>(_value);
        }
 
        /// Get the boolean variant member (we assume m_type == STRING)
-       const std::string& getStr() const
-       {
+       const std::string& getStr() const {
                assert(m_type == STRING);
                return boost::get<std::string>(_value);
        }

=== modified file 'libcore/asobj/Array_as.cpp'
--- a/libcore/asobj/Array_as.cpp        2009-10-04 15:55:41 +0000
+++ b/libcore/asobj/Array_as.cpp        2009-10-14 15:45:27 +0000
@@ -47,6 +47,23 @@
 
 typedef boost::function2<bool, const as_value&, const as_value&> as_cmp_fn;
 
+inline string_table::key
+arrayKey(string_table& st, size_t i)
+{
+    std::ostringstream os;
+    os << i;
+    return st.find(os.str());
+}
+
+namespace {
+
+string_table::key getKey(const fn_call& fn, size_t i) {
+    string_table& st = getStringTable(fn);
+    return arrayKey(st, i);
+}
+
+}
+
 static as_object* getArrayInterface();
 static void attachArrayProperties(as_object& proto);
 static void attachArrayInterface(as_object& proto);
@@ -607,61 +624,6 @@
 }
 
 void
-Array_as::push(const as_value& val)
-{
-        const ArrayContainer::size_type s = elements.size();
-        elements.resize(s+1);
-        elements[s] = val;
-}
-
-void
-Array_as::unshift(const as_value& val)
-{
-        shiftElementsRight(1);
-        elements[0] = val;
-}
-
-as_value
-Array_as::pop()
-{
-    // If the array is empty, report an error and return undefined!
-    const ArrayContainer::size_type s = elements.size();
-
-    if ( ! s )
-    {
-        IF_VERBOSE_ASCODING_ERRORS(
-        log_aserror(_("tried to pop element from back of empty array, 
returning undef"));
-        );
-        return as_value(); // undefined
-    }
-
-    as_value ret = elements[s - 1];
-    elements.resize(s - 1);
-
-    return ret;
-}
-
-as_value
-Array_as::shift()
-{
-    const ArrayContainer::size_type s = elements.size();
-
-    // If the array is empty, report an error and return undefined!
-    if ( ! s )
-    {
-        IF_VERBOSE_ASCODING_ERRORS(
-        log_aserror(_("tried to shift element from front of empty array, 
returning undef"));
-        );
-        return as_value(); // undefined
-    }
-
-    as_value ret = elements[0];
-    shiftElementsLeft(1);
-
-    return ret;
-}
-
-void
 Array_as::reverse()
 {
     const ArrayContainer::size_type s = elements.size();
@@ -709,21 +671,6 @@
 
 }
 
-void
-Array_as::concat(const Array_as& other)
-{
-    for (ArrayContainer::size_type i = 0, e = other.size(); i < e; i++)
-    {
-        push(other.at(i));
-    }
-}
-
-std::string
-Array_as::toString() const
-{
-    return join(",");
-}
-
 unsigned int
 Array_as::size() const
 {
@@ -763,20 +710,6 @@
 
 }
 
-bool
-Array_as::removeFirst(const as_value& v)
-{
-    for (iterator it = elements.begin(), e = elements.end(); it != e; ++it)
-    {
-        if ( v.equals(*it) )
-        {
-            splice(it.index(), 1);
-            return true;
-        }
-    }
-    return false;
-}
-
 /* virtual public, overriding as_object::get_member */
 bool
 Array_as::get_member(string_table::key name, as_value *val,
@@ -844,20 +777,6 @@
     elements.resize(newsize);
 }
 
-void
-Array_as::set_indexed(unsigned int index,
-    const as_value& val)
-{
-    if (index >= elements.size())
-    {
-        // make sure the vector is large enough.
-        elements.resize(index + 1);
-    }
-
-    elements[index] = val;
-    return;
-}
-
 /* virtual public, overriding as_object::set_member */
 bool
 Array_as::set_member(string_table::key name,
@@ -892,7 +811,7 @@
     for (std::deque<indexed_as_value>::const_iterator it = elems.begin();
         it != elems.end(); ++it)
     {
-        intIndexes->push(as_value(it->vec_index));
+        intIndexes->callMethod(NSV::PROP_PUSH, it->vec_index);
     }
     return intIndexes;
 }
@@ -1176,67 +1095,119 @@
 }
 
 // Callback to push values to the back of an array
-static as_value
+as_value
 array_push(const fn_call& fn)
 {
-    boost::intrusive_ptr<Array_as> array = ensureType<Array_as>(fn.this_ptr);
-
-        IF_VERBOSE_ACTION (
-    log_action(_("calling array push, pushing %d values onto back of 
array"),fn.nargs);
-        );
-
-    for (unsigned int i=0;i<fn.nargs;i++)
-        array->push(fn.arg(i));
-
-    return as_value(array->size());
+    as_object* array = ensureType<as_object>(fn.this_ptr);
+ 
+    if (!fn.nargs) return as_value();
+
+    const size_t shift = fn.nargs;
+
+    as_value length;
+    if (!array->get_member(NSV::PROP_LENGTH, &length)) return as_value();
+    
+    const int size = length.to_int();
+    if (size < 0) return as_value();
+
+    for (size_t i = 0; i < fn.nargs; ++i) {
+        array->set_member(getKey(fn, size + i), fn.arg(i));
+    }
+    
+    // TODO: this is wrong, but Gnash relies on it.
+    array->set_member(NSV::PROP_LENGTH, size + shift);
+
+    return as_value(size + shift);
 }
 
 // Callback to push values to the front of an array
 static as_value
 array_unshift(const fn_call& fn)
 {
-    boost::intrusive_ptr<Array_as> array = ensureType<Array_as>(fn.this_ptr);
-
-        IF_VERBOSE_ACTION (
-    log_action(_("calling array unshift, pushing %d values onto front of 
array"), fn.nargs);
-        );
-
-    for (int i=fn.nargs-1; i>=0; i--)
-        array->unshift(fn.arg(i));
-
-    return as_value(array->size());
+
+    as_object* array = ensureType<as_object>(fn.this_ptr);
+ 
+    if (!fn.nargs) return as_value();
+
+    const size_t shift = fn.nargs;
+
+    as_value length;
+    if (!array->get_member(NSV::PROP_LENGTH, &length)) return as_value();
+    
+    const int size = length.to_int();
+    if (size < 0) return as_value();
+
+    string_table& st = getStringTable(fn);
+    as_value ret = array->getMember(st.find("0"));
+    
+    for (size_t i = size + shift - 1; i >= shift ; --i) {
+        const string_table::key nextkey = getKey(fn, i - shift);
+        const string_table::key currentkey = getKey(fn, i);
+        array->delProperty(currentkey);
+        array->set_member(currentkey, array->getMember(nextkey));
+    }
+
+    for (size_t i = shift; i > 0; --i) {
+        const size_t index = i - 1;
+        array->set_member(getKey(fn, index), fn.arg(index));
+    }
+ 
+    // TODO: this is wrong, but Gnash relies on it.
+    array->set_member(NSV::PROP_LENGTH, size + shift);
+
+    return as_value(size + shift);
 }
 
 // Callback to pop a value from the back of an array
 static as_value
 array_pop(const fn_call& fn)
 {
-    boost::intrusive_ptr<Array_as> array = ensureType<Array_as>(fn.this_ptr);
-
-    // Get our index, log, then return result
-    as_value rv = array->pop();
-
-    IF_VERBOSE_ACTION (
-    log_action(_("calling array pop, result:%s, new array size:%d"),
-        rv, array->size());
-    );
-        return rv;
+
+    as_object* array = ensureType<as_object>(fn.this_ptr);
+
+    as_value length;
+    if (!array->get_member(NSV::PROP_LENGTH, &length)) return as_value();
+    
+    const int size = length.to_int();
+    if (size < 1) return as_value();
+
+    const string_table::key ind = getKey(fn, size - 1);
+    as_value ret = array->getMember(ind);
+    array->delProperty(ind);
+    
+    // TODO: this is wrong, but Gnash relies on it.
+    array->set_member(NSV::PROP_LENGTH, size - 1);
+
+    return ret;
 }
 
 // Callback to pop a value from the front of an array
 static as_value
 array_shift(const fn_call& fn)
 {
-    boost::intrusive_ptr<Array_as> array = ensureType<Array_as>(fn.this_ptr);
-
-    // Get our index, log, then return result
-    as_value rv = array->shift();
-
-    IF_VERBOSE_ACTION (
-    log_action(_("calling array shift, result:%s, new array size:%d"),
-        rv, array->size());
-    );
-    return rv;
+    as_object* array = ensureType<as_object>(fn.this_ptr);
+
+    as_value length;
+    if (!array->get_member(NSV::PROP_LENGTH, &length)) return as_value();
+    
+    const int size = length.to_int();
+
+    // An array with no elements has nothing to return.
+    if (size < 1) return as_value();
+
+    as_value ret = array->getMember(getKey(fn, 0));
+
+    for (size_t i = 0; i < static_cast<size_t>(size - 1); ++i) {
+        const string_table::key nextkey = getKey(fn, i + 1);
+        const string_table::key currentkey = getKey(fn, i);
+        array->delProperty(currentkey);
+        array->set_member(currentkey, array->getMember(nextkey));
+    }
+    
+    // TODO: this is wrong, but Gnash relies on it.
+    array->set_member(NSV::PROP_LENGTH, size - 1);
+
+    return ret;
 }
 
 // Callback to reverse the position of the elements in an array
@@ -1256,51 +1227,68 @@
     return rv;
 }
 
-// Callback to convert array to a string with optional custom separator 
(default ',')
-static as_value
+as_value
+join(as_object* array, const std::string& separator)
+{
+    as_value length;
+    if (!array->get_member(NSV::PROP_LENGTH, &length)) return as_value("");
+
+    const double size = length.to_int();
+    if (size < 0) return as_value("");
+
+    std::string s;
+
+    string_table& st = getStringTable(*array);
+    const int version = getSWFVersion(*array);
+
+    for (size_t i = 0; i < size; ++i) {
+        std::ostringstream os;
+        os << i;
+        if (i) s += separator;
+        as_value el;
+        array->get_member(st.find(os.str()), &el);
+        s += el.to_string_versioned(version);
+    }
+    return as_value(s);
+}
+
+as_value
 array_join(const fn_call& fn)
 {
-    boost::intrusive_ptr<Array_as> array = ensureType<Array_as>(fn.this_ptr);
-
-    std::string separator = ",";
-    int version = getSWFVersion(fn);
-
-    if (fn.nargs > 0)
-    {
-        separator = fn.arg(0).to_string_versioned(version);
-    }
-
-    std::string ret = array->join(separator);
-
-    return as_value(ret);
+    as_object* array = ensureType<as_object>(fn.this_ptr);
+
+    const int version = getSWFVersion(fn);
+    const std::string separator =
+        fn.nargs ? fn.arg(0).to_string_versioned(version) : ",";
+
+    return join(array, separator);
 }
 
 // Callback to convert array to a string
-// TODO CHECKME: rely on Object.toString  ? (
-static as_value
-array_to_string(const fn_call& fn)
+as_value
+array_toString(const fn_call& fn)
 {
-    boost::intrusive_ptr<Array_as> array = ensureType<Array_as>(fn.this_ptr);
-
-    std::string ret = array->toString();
-
-        IF_VERBOSE_ACTION
-        (
-    log_action(_("array_to_string called, nargs = %d, "
-            "this_ptr = %p"),
-            fn.nargs, (void*)fn.this_ptr);
-    log_action(_("to_string result is: %s"), ret);
-        );
-
-    return as_value(ret);
+    as_object* array = ensureType<as_object>(fn.this_ptr);
+    return join(array, ",");
 }
 
+class PushToArray
+{
+public:
+    PushToArray(as_object& obj) : _obj(obj) {}
+    void operator()(const as_value& val) {
+        _obj.callMethod(NSV::PROP_PUSH, val);
+    }
+private:
+    as_object& _obj;
+};
+
 /// concatenates the elements specified in the parameters with
 /// the elements in my_array, and creates a new array. If the
 /// value parameters specify an array, the elements of that
 /// array are concatenated, rather than the array itself. The
 /// array my_array is left unchanged.
-static as_value
+as_value
 array_concat(const fn_call& fn)
 {
     boost::intrusive_ptr<Array_as> array = ensureType<Array_as>(fn.this_ptr);
@@ -1308,23 +1296,29 @@
     // use copy ctor
     Array_as* newarray = new Array_as();
 
-    for (size_t i=0, e=array->size(); i<e; i++)
-        newarray->push(array->at(i));
-
-    for (unsigned int i=0; i<fn.nargs; i++)
-    {
+    PushToArray push(*newarray);
+    if (!foreachArray(*array, push)) return as_value();
+
+    for (size_t i = 0; i < fn.nargs; ++i) {
+
         // Array args get concatenated by elements
-        boost::intrusive_ptr<Array_as> other =
-            boost::dynamic_pointer_cast<Array_as>(
-                    fn.arg(i).to_object(*getGlobal(fn)));
-        if ( other )
-        {
-            newarray->concat(*other);
-        }
-        else
-        {
-            newarray->push(fn.arg(i));
-        }
+        // The type is checked using instanceOf.
+        const as_value& arg = fn.arg(i);
+
+        Global_as* gl = getGlobal(fn);
+        as_object* other = arg.to_object(*gl);
+
+        if (other) {
+            
+            // If it's not an array, we want to carry on and add it as an
+            // object.
+            if (other->instanceOf(getClassConstructor(fn, "Array"))) {
+                // Do we care if it has no length property?
+                foreachArray(*other, push);
+                continue;
+            }
+        }
+        newarray->callMethod(NSV::PROP_PUSH, fn.arg(i));
     }
 
     return as_value(newarray);        
@@ -1444,7 +1438,7 @@
         as_value    index_number;
         for (unsigned int i = 0; i < fn.nargs; i++)
         {
-            ao->push(fn.arg(i));
+            ao->callMethod(NSV::PROP_PUSH, fn.arg(i));
         }
     }
 
@@ -1478,54 +1472,18 @@
 {
     VM& vm = getVM(proto);
 
-    // Array.push
-    vm.registerNative(array_push, 252, 1);
     proto.init_member("push", vm.getNative(252, 1));
-
-    // Array.pop
-    vm.registerNative(array_pop, 252, 2);
     proto.init_member("pop", vm.getNative(252, 2));
-
-    // Array.concat
-    vm.registerNative(array_concat, 252, 3);
     proto.init_member("concat", vm.getNative(252, 3));
-
-    // Array.shift
-    vm.registerNative(array_shift, 252, 4);
     proto.init_member("shift", vm.getNative(252, 4));
-
-    // Array.unshift
-    vm.registerNative(array_unshift, 252, 5);
     proto.init_member("unshift", vm.getNative(252, 5));
-
-    // Array.slice
-    vm.registerNative(array_slice, 252, 6);
     proto.init_member("slice", vm.getNative(252, 6));
-
-    // Array.join
-    vm.registerNative(array_join, 252, 7);
     proto.init_member("join", vm.getNative(252, 7));
-
-    // Array.splice
-    vm.registerNative(array_splice, 252, 8);
     proto.init_member("splice", vm.getNative(252, 8));
-
-    // Array.toString
-    vm.registerNative(array_to_string, 252, 9);
     proto.init_member("toString", vm.getNative(252, 9));
-
-    // Array.sort
-    vm.registerNative(array_sort, 252, 10);
     proto.init_member("sort", vm.getNative(252, 10));
-
-    // Array.reverse
-    vm.registerNative(array_reverse, 252, 11);
     proto.init_member("reverse", vm.getNative(252, 11));
-
-    // Array.sortOn
-    vm.registerNative(array_sortOn, 252, 12);
     proto.init_member("sortOn", vm.getNative(252, 12));
-
 }
 
 static as_object*
@@ -1547,6 +1505,18 @@
 {
     VM& vm = getVM(global);
     vm.registerNative(array_new, 252, 0);
+    vm.registerNative(array_push, 252, 1);
+    vm.registerNative(array_pop, 252, 2);
+    vm.registerNative(array_concat, 252, 3);
+    vm.registerNative(array_shift, 252, 4);
+    vm.registerNative(array_unshift, 252, 5);
+    vm.registerNative(array_slice, 252, 6);
+    vm.registerNative(array_join, 252, 7);
+    vm.registerNative(array_splice, 252, 8);
+    vm.registerNative(array_toString, 252, 9);
+    vm.registerNative(array_sort, 252, 10);
+    vm.registerNative(array_reverse, 252, 11);
+    vm.registerNative(array_sortOn, 252, 12);
 }
 
 // this registers the "Array" member on a "Global"
@@ -1589,44 +1559,6 @@
 }
 
 void
-Array_as::shiftElementsLeft(unsigned int count)
-{
-    ArrayContainer& v = elements;
-
-    if ( count >= v.size() )
-    {
-       // NOTE: v.clear() would NOT set size to 0 !!
-        v.resize(0);
-        return;
-    }
-
-    for (unsigned int i=0; i<count; ++i) v.erase_element(i);
-
-    for (iterator i=v.begin(), e=v.end(); i!=e; ++i)
-    {
-        int currentIndex = i.index();
-        int newIndex = currentIndex-count;
-        v[newIndex] = *i;
-    }
-    v.resize(v.size()-count);
-}
-
-void
-Array_as::shiftElementsRight(unsigned int count)
-{
-    ArrayContainer& v = elements;
-
-    v.resize(v.size()+count);
-        for (ArrayContainer::reverse_iterator i=v.rbegin(), e=v.rend(); i!=e; 
++i)
-    {
-        int currentIndex = i.index();
-        int newIndex = currentIndex+count;
-        v[newIndex] = *i;
-    }
-    while (count--) v.erase_element(count);
-}
-
-void
 Array_as::splice(unsigned int start, unsigned int count, const 
std::vector<as_value>* replace, Array_as* receive)
 {
     size_t sz = elements.size();
@@ -1661,7 +1593,7 @@
     if ( receive )
     {
         for (size_t i=start; i<start+count; ++i )
-            receive->push(elements[i]);
+            receive->callMethod(NSV::PROP_PUSH, elements[i]);
     }
 
     elements = newelements;

=== modified file 'libcore/asobj/Array_as.h'
--- a/libcore/asobj/Array_as.h  2009-08-19 08:48:14 +0000
+++ b/libcore/asobj/Array_as.h  2009-10-14 16:12:54 +0000
@@ -20,6 +20,7 @@
 
 #include "as_object.h" // for inheritance
 #include "smart_ptr.h" // GNASH_USE_GC
+#include "namedStrings.h"
 
 #include <deque>
 #include <vector>
@@ -54,8 +55,6 @@
        void visit(as_value& v) { cont.push_back(v); }
 };
 
-struct blank {};
-
 /// The Array ActionScript object
 class Array_as : public as_object
 {
@@ -137,40 +136,20 @@
 
        Array_as::const_iterator end();
 
-       /// Push an element to the end of the array
-       //
-       /// @param val
-       ///     The element to add 
-       ///
-       void push(const as_value& val);
-
-       void unshift(const as_value& val);
-
-       as_value shift();
-
-       as_value pop();
-
        as_value at(unsigned int index) const;
 
        Array_as* get_indices(std::deque<indexed_as_value> origElems);
 
        void reverse();
 
-       void set_indexed(unsigned int index, const as_value &v);
-
        /// @param separator
     ///     String to use as separator between elements
        std::string join(const std::string& separator) const;
 
-    /// Convert array to string.
-       std::string toString() const;
-
        unsigned int size() const;
 
        void resize(unsigned int);
 
-       void concat(const Array_as& other);
-
        /// \brief
        /// Return a newly created array containing elements
        /// from 'start' up to but not including 'end'.
@@ -193,21 +172,6 @@
        boost::intrusive_ptr<Array_as> slice(
                unsigned int start, unsigned int one_past_end);
 
-       /// Remove first element matching the given value
-       //
-       /// Return true if any element was removed, false otherwise
-       ///
-       /// NOTE: if an element is removed, holes in the array will be
-       ///       filled.
-       ///
-       /// @param v
-       ///     The value to compare elements against
-       ///
-       /// @param env
-       ///     The environment to use when comparing (needed by 
as_value::equals)
-       ///
-       bool removeFirst(const as_value& v);
-
        /// \brief
        /// Replace count elements from start with given values, optionally
        /// returning the erased ones.
@@ -404,21 +368,26 @@
        // if the string does not refer to an index, or an appropriate int if 
the string does refer to an index
        int index_requested(string_table::key name);
 
-       /// Shift all elements to the left by count positions
-       //
-       /// Pre-condition: size of the array must be >= count
-       /// Post-condition: size of the array will reduce by 'count'
-       ///
-       void shiftElementsLeft(unsigned int count);
-
-       /// Shift all elements to the right by count positions
-       //
-       /// Pre-condition: none
-       /// Post-condition: size of the array will incremented by 'count'
-       ///
-       void shiftElementsRight(unsigned int count);
 };
 
+string_table::key arrayKey(string_table& st, size_t i);
+
+template<typename T>
+bool foreachArray(as_object& array, T& pred)
+{
+    as_value length;
+    if (!array.get_member(NSV::PROP_LENGTH, &length)) return false;
+    
+    const int size = length.to_int();
+    if (size < 0) return false;
+
+    string_table& st = getStringTable(array);
+
+    for (size_t i = 0; i < static_cast<size_t>(size); ++i) {
+        pred(array.getMember(arrayKey(st, i)));
+    }
+    return true;
+}
 
 /// Initialize the global.Array object
 // needed by SWFHandlers::ActionInitArray
@@ -426,10 +395,6 @@
 
 void registerArrayNative(as_object& global);
 
-/// Constructor for ActionScript class Array.
-// needed by SWFHandlers::ActionInitArray
-as_value array_new(const fn_call& fn);
-
 }
 
 #endif

=== modified file 'libcore/asobj/AsBroadcaster.cpp'
--- a/libcore/asobj/AsBroadcaster.cpp   2009-08-20 09:36:50 +0000
+++ b/libcore/asobj/AsBroadcaster.cpp   2009-10-14 14:31:24 +0000
@@ -120,7 +120,7 @@
 
     // Find _global.AsBroadcaster.
     as_object* asb =
-        gl->getMember(NSV::CLASS_AS_BROADCASTER).to_object(*gl).get();
+        gl->getMember(NSV::CLASS_AS_BROADCASTER).to_object(*gl);
 
     // If it's not an object, these are left undefined, but they are
     // always attached to the initialized object.
@@ -139,7 +139,7 @@
     const as_value& asn = gl->callMethod(NSV::PROP_AS_NATIVE, 101, 12);
     o.set_member(NSV::PROP_BROADCAST_MESSAGE, asn);
 
-    o.set_member(NSV::PROP_uLISTENERS, new Array_as());
+    o.set_member(NSV::PROP_uLISTENERS, gl->createArray());
 
 }
 
@@ -256,30 +256,16 @@
                 "an object: %s"), (void*)fn.this_ptr, fn.dump_args(),
                 listenersValue);
         );
-        return as_value(false); // TODO: check this
-    }
-
-    boost::intrusive_ptr<as_object> listenersObj =
-        listenersValue.to_object(*getGlobal(fn));
-    assert(listenersObj);
-
-    boost::intrusive_ptr<Array_as> listeners = 
boost::dynamic_pointer_cast<Array_as>(listenersObj);
-    if ( ! listeners )
-    {
-        IF_VERBOSE_ASCODING_ERRORS(
-        log_aserror(_("%p.addListener(%s): this object's _listener isn't "
-                "an array: %s -- will call 'push' on it anyway"),
-                (void*)fn.this_ptr,
-                fn.dump_args(), listenersValue);
-        );
-
-        listenersObj->callMethod(NSV::PROP_PUSH, newListener);
-
-    }
-    else
-    {
-        listeners->push(newListener);
-    }
+        // TODO: check this
+        return as_value(false); 
+    }
+
+    as_object* listeners = listenersValue.to_object(*getGlobal(fn));
+
+    // We checked is_object() above.
+    assert(listeners); 
+
+    listeners->callMethod(NSV::PROP_PUSH, newListener);
 
     return as_value(true);
 
@@ -359,10 +345,24 @@
         // Remove the first listener matching the new value
         // See http://www.senocular.com/flash/tutorials/
         // listenersasbroadcaster/?page=2
-        // TODO: make this call as a normal (don't want to
-        // rely on _listeners type at all)
-        bool removed = listeners->removeFirst(listenerToRemove);
-        return as_value(removed);
+        
+        // This is an ActionScript-like implementation, which is why it looks
+        // like poor C++.
+        int length = listenersObj->getMember(NSV::PROP_LENGTH).to_int();
+        int i = 0;
+        string_table& st = getStringTable(fn);
+        while (i < length) {
+            std::ostringstream s;
+            s << i;
+            as_value el =
+                listenersObj->getMember(st.find(s.str()));
+            if (el.equals(listenerToRemove)) {
+                listeners->callMethod(NSV::PROP_SPLICE, s.str(), 1);
+                return as_value(true);
+            }
+            ++i;
+        }
+        return as_value(false);
     }
 
 }
@@ -401,8 +401,7 @@
     }
 
     boost::intrusive_ptr<Array_as> listeners =
-        boost::dynamic_pointer_cast<Array_as>(
-                listenersValue.to_object(*getGlobal(fn)));
+        dynamic_cast<Array_as*>(listenersValue.to_object(*getGlobal(fn)));
 
     if ( ! listeners )
     {

=== modified file 'libcore/asobj/Color_as.cpp'
--- a/libcore/asobj/Color_as.cpp        2009-08-27 06:40:41 +0000
+++ b/libcore/asobj/Color_as.cpp        2009-10-14 08:47:08 +0000
@@ -72,7 +72,7 @@
             attachColorInterface, 0, uri);
 
     as_object* proto =
-        cl->getMember(NSV::PROP_PROTOTYPE).to_object(*getGlobal(where)).get();
+        cl->getMember(NSV::PROP_PROTOTYPE).to_object(*getGlobal(where));
 
     if (!proto) return;
 

=== modified file 'libcore/asobj/Global_as.h'
--- a/libcore/asobj/Global_as.h 2009-09-29 09:56:55 +0000
+++ b/libcore/asobj/Global_as.h 2009-10-14 14:20:47 +0000
@@ -83,6 +83,13 @@
     /// expected behaviour.
     virtual as_object* createBoolean(bool b) = 0;
 
+    /// Create an Array object
+    //
+    /// This calls the Array constructor. If that has been changed, this
+    /// function may not produce an Array object. This is generally
+    /// expected behaviour.
+    virtual as_object* createArray() = 0;
+
     /// Create an Object
     //
     /// This function returns an Object with Object.prototype as its

=== modified file 'libcore/asobj/Globals.cpp'
--- a/libcore/asobj/Globals.cpp 2009-10-12 11:37:04 +0000
+++ b/libcore/asobj/Globals.cpp 2009-10-14 14:20:47 +0000
@@ -240,6 +240,16 @@
 
 }
 
+/// This serves the purpose of hiding the Array_as type from the
+/// implementation, which at least enforces good behaviour from users.
+//
+/// TODO: it could well already call the Array constructor.
+as_object*
+AVM1Global::createArray()
+{
+    return new Array_as();
+}
+
 as_object*
 AVM1Global::createBoolean(bool b)
 {
@@ -292,6 +302,14 @@
     return constructObject(*this, b, NSV::CLASS_BOOLEAN);
 }
 
+/// This serves the purpose of hiding the Array_as type from the
+/// implementation, which at least enforces good behaviour from users.
+as_object*
+AVM2Global::createArray()
+{
+    return new Array_as();
+}
+
 void 
 AVM1Global::markReachableResources() const
 {
@@ -1025,7 +1043,7 @@
 
     Global_as* gl = getGlobal(fn);
 
-    as_object* targetObject = fn.arg(0).to_object(*gl).get();
+    as_object* targetObject = fn.arg(0).to_object(*gl);
     if (!targetObject) {
         return as_value();
     }
@@ -1096,7 +1114,7 @@
 
     Global_as* gl = getGlobal(fn);
 
-    as_object* targetObject = fn.arg(0).to_object(*gl).get();
+    as_object* targetObject = fn.arg(0).to_object(*gl);
     if (!targetObject) {
         return as_value();
     }
@@ -1171,7 +1189,7 @@
 as_value
 local_errorConstructor(const fn_call& fn)
 {
-    as_object* obj = ensureType<as_object>(fn.this_ptr).get();
+    as_object* obj = ensureType<as_object>(fn.this_ptr);
     const as_value& arg = fn.nargs ? fn.arg(0) : as_value();
     string_table& st = getStringTable(fn);
     obj->set_member(st.find("message"), arg);

=== modified file 'libcore/asobj/Globals.h'
--- a/libcore/asobj/Globals.h   2009-09-07 17:34:36 +0000
+++ b/libcore/asobj/Globals.h   2009-10-14 14:20:47 +0000
@@ -74,6 +74,8 @@
     
     virtual as_object* createObject();
     
+    virtual as_object* createArray();
+
     virtual const ClassHierarchy& classHierarchy() const {
         return _classes;
     }
@@ -140,6 +142,8 @@
 
     virtual as_object* createObject();
 
+    virtual as_object* createArray();
+
     virtual const ClassHierarchy& classHierarchy() const {
         return _classes;
     }

=== modified file 'libcore/asobj/LoadableObject.cpp'
--- a/libcore/asobj/LoadableObject.cpp  2009-10-12 12:52:36 +0000
+++ b/libcore/asobj/LoadableObject.cpp  2009-10-14 16:10:50 +0000
@@ -46,6 +46,71 @@
     as_value loadableobject_sendAndLoad(const fn_call& fn);
 }
 
+/// Functors for use with foreachArray
+namespace {
+
+class WriteHeaders
+{
+public:
+
+    WriteHeaders(NetworkAdapter::RequestHeaders& headers)
+        :
+        _headers(headers),
+        _i(0)
+    {}
+
+    void operator()(const as_value& val)
+    {
+        // Store even elements and continue
+        if (!(_i++ % 2)) {
+            _key = val;
+            return;
+        }
+
+        // Both elements apparently must be strings, or we move onto the 
+        // next pair.
+        if (!val.is_string() || !_key.is_string()) return;
+        _headers[_key.to_string()] = val.to_string();
+    }
+
+private:
+    as_value _key;
+    NetworkAdapter::RequestHeaders _headers;
+    size_t _i;
+};
+
+class GetHeaders
+{
+public:
+
+    GetHeaders(as_object& target)
+        :
+        _target(target),
+        _i(0)
+    {}
+
+    void operator()(const as_value& val)
+    {
+        // Store even elements and continue
+        if (!(_i++ % 2)) {
+            _key = val;
+            return;
+        }
+
+        // Both elements apparently must be strings, or we move onto the 
+        // next pair.
+        if (!val.is_string() || !_key.is_string()) return;
+        _target.callMethod(NSV::PROP_PUSH, _key, val);
+    }
+
+private:
+    as_value _key;
+    as_object& _target;
+    size_t _i;
+};
+
+}
+
 LoadableObject::LoadableObject(as_object* owner)
     :
     ActiveRelay(owner),
@@ -95,8 +160,7 @@
     URL url(urlstr, ri.baseURL());
 
     std::auto_ptr<IOChannel> str;
-    if (post)
-    {
+    if (post) {
         as_value customHeaders;
 
         NetworkAdapter::RequestHeaders headers;
@@ -106,33 +170,10 @@
 
             /// Read in our custom headers if they exist and are an
             /// array.
-            Array_as* array = dynamic_cast<Array_as*>(
-                            customHeaders.to_object(*getGlobal(target)).get());
-                            
-            if (array)
-            {
-                Array_as::const_iterator e = array->end();
-                --e;
-
-                for (Array_as::const_iterator i = array->begin(); i != e; ++i)
-                {
-                    // Only even indices can be a header.
-                    if (i.index() % 2) continue;
-                    if (! (*i).is_string()) continue;
-                    
-                    // Only the immediately following odd number can be 
-                    // a value.
-                    if (array->at(i.index() + 1).is_string())
-                    {
-                        const std::string& name = (*i).to_string();
-                        const std::string& val =
-                                    array->at(i.index() + 1).to_string();
-                                    
-                        // Values should overwrite existing ones.
-                        headers[name] = val;
-                    }
-                    
-                }
+            as_object* array = customHeaders.to_object(*getGlobal(target));
+            if (array) {
+                WriteHeaders wh(headers);
+                foreachArray(*array, wh);
             }
         }
 
@@ -331,6 +372,7 @@
     return bytesTotal;
 }
 
+
 /// Can take either a two strings as arguments or an array of strings,
 /// alternately header and value.
 as_value
@@ -340,9 +382,11 @@
     as_value customHeaders;
     as_object* array;
 
+    Global_as* gl = getGlobal(fn);
+
     if (fn.this_ptr->get_member(NSV::PROP_uCUSTOM_HEADERS, &customHeaders))
     {
-        array = customHeaders.to_object(*getGlobal(fn)).get();
+        array = customHeaders.to_object(*gl);
         if (!array)
         {
             IF_VERBOSE_ASCODING_ERRORS(
@@ -352,15 +396,11 @@
             return as_value();
         }
     }
-    else
-    {
-        array = new Array_as;
+    else {
+        array = gl->createArray();
         // This property is always initialized on the first call to
-        // addRequestHeaders.
-        const int flags = PropFlags::dontEnum |
-                          PropFlags::dontDelete;
-
-        fn.this_ptr->init_member(NSV::PROP_uCUSTOM_HEADERS, array, flags);
+        // addRequestHeaders. It has default properties.
+        fn.this_ptr->init_member(NSV::PROP_uCUSTOM_HEADERS, array);
     }
 
     if (fn.nargs == 0)
@@ -375,14 +415,11 @@
     
     if (fn.nargs == 1)
     {
-        // This must be an array. Keys / values are pushed in valid
-        // pairs to the _customHeaders array.    
-        boost::intrusive_ptr<as_object> obj =
-            fn.arg(0).to_object(*getGlobal(fn));
-        Array_as* headerArray = dynamic_cast<Array_as*>(obj.get());
+        // This must be an array (or something like it). Keys / values are
+        // pushed in valid pairs to the _customHeaders array.    
+        boost::intrusive_ptr<as_object> headerArray = fn.arg(0).to_object(*gl);
 
-        if (!headerArray)
-        {
+        if (!headerArray) {
             IF_VERBOSE_ASCODING_ERRORS(
                 log_aserror(_("XML.addRequestHeader: single argument "
                                 "is not an array"));
@@ -390,23 +427,8 @@
             return as_value();
         }
 
-        Array_as::const_iterator e = headerArray->end();
-        --e;
-
-        for (Array_as::const_iterator i = headerArray->begin(); i != e; ++i)
-        {
-            // Only even indices can be a key, and they must be a string.
-            if (i.index() % 2) continue;
-            if (!(*i).is_string()) continue;
-            
-            // Only the immediately following odd number can be 
-            // a value, and it must also be a string.
-            const as_value& val = headerArray->at(i.index() + 1);
-            if (val.is_string())
-            {
-                array->callMethod(NSV::PROP_PUSH, *i, val);
-            }
-        }
+        GetHeaders gh(*array);
+        foreachArray(*headerArray, gh);
         return as_value();
     }
         

=== modified file 'libcore/asobj/MovieClipLoader.cpp'
--- a/libcore/asobj/MovieClipLoader.cpp 2009-08-18 10:32:14 +0000
+++ b/libcore/asobj/MovieClipLoader.cpp 2009-10-14 14:41:39 +0000
@@ -144,8 +144,8 @@
        as_object(getMovieClipLoaderInterface())
 {
 
-       Array_as* ar = new Array_as();
-       ar->push(this);
+       as_object* ar = getGlobal(*this)->createArray();
+       ar->callMethod(NSV::PROP_PUSH, this);
        set_member(NSV::PROP_uLISTENERS, ar);
 }
 

=== modified file 'libcore/asobj/Object.cpp'
--- a/libcore/asobj/Object.cpp  2009-08-27 06:41:27 +0000
+++ b/libcore/asobj/Object.cpp  2009-10-14 08:47:08 +0000
@@ -169,7 +169,7 @@
     Global_as* gl = getGlobal(fn);
 
        if (fn.nargs == 1) {
-        as_object* obj = fn.arg(0).to_object(*gl).get();
+        as_object* obj = fn.arg(0).to_object(*gl);
         if (obj) return as_value(obj);
        }
 

=== modified file 'libcore/asobj/QName_as.cpp'
--- a/libcore/asobj/QName_as.cpp        2009-10-07 06:18:09 +0000
+++ b/libcore/asobj/QName_as.cpp        2009-10-14 08:47:08 +0000
@@ -98,7 +98,7 @@
 as_value
 qname_ctor(const fn_call& fn)
 {
-    as_object* obj = ensureType<as_object>(fn.this_ptr).get();
+    as_object* obj = ensureType<as_object>(fn.this_ptr);
     attachQNameInterface(*obj);
     return as_value(); 
 }

=== modified file 'libcore/asobj/Selection_as.cpp'
--- a/libcore/asobj/Selection_as.cpp    2009-08-20 10:16:35 +0000
+++ b/libcore/asobj/Selection_as.cpp    2009-10-14 08:47:08 +0000
@@ -221,7 +221,7 @@
     else {
         /// Try converting directly to DisplayObject.
         ch = dynamic_cast<DisplayObject*>(
-                focus.to_object(*getGlobal(fn)).get());
+                focus.to_object(*getGlobal(fn)));
     }
 
     // If the argument does not resolve to a DisplayObject, do nothing.

=== modified file 'libcore/asobj/String_as.cpp'
--- a/libcore/asobj/String_as.cpp       2009-10-02 08:18:58 +0000
+++ b/libcore/asobj/String_as.cpp       2009-10-14 14:31:24 +0000
@@ -28,7 +28,6 @@
 #include "builtin_function.h" // need builtin_function
 #include "NativeFunction.h" 
 #include "log.h"
-#include "Array_as.h"
 #include "as_value.h"
 #include "GnashException.h"
 #include "movie_definition.h" 
@@ -240,13 +239,14 @@
     
     std::wstring wstr = utf8::decodeCanonicalString(str, version);
 
-    boost::intrusive_ptr<Array_as> array(new Array_as());
+    Global_as* gl = getGlobal(fn);
+    as_object* array = gl->createArray();
 
     if (fn.nargs == 0)
     {
         // Condition 1:
-        array->push(str);
-        return as_value(array.get());
+        array->callMethod(NSV::PROP_PUSH, str);
+        return as_value(array);
     }
 
     const std::wstring& delim = utf8::decodeCanonicalString(
@@ -257,8 +257,8 @@
         (version >= 6 && fn.arg(0).is_undefined()))
     {
         // Condition 2:
-        array->push(str);
-        return as_value(array.get());
+        array->callMethod(NSV::PROP_PUSH, str);
+        return as_value(array);
     }
 
     size_t max = wstr.size() + 1;
@@ -272,7 +272,7 @@
             if (limit < 1)
             {
                 // Return empty array.
-                return as_value(array.get());
+                return as_value(array);
             }
             max = clamp<size_t>(limit, 0, max);
         }
@@ -281,8 +281,8 @@
         {
             // Condition 3 (plus a shortcut if the string itself
             // is empty).
-            array->push(str);
-            return as_value(array.get());            
+            array->callMethod(NSV::PROP_PUSH, str);
+            return as_value(array);            
         }
     }
     else
@@ -293,8 +293,8 @@
             // If the string itself is empty, SWF6 returns a 0-sized
             // array only if the delimiter is also empty. Otherwise
             // it returns an array with 1 empty element.
-            if (delimiterSize) array->push(str);
-            return as_value(array.get());
+            if (delimiterSize) array->callMethod(NSV::PROP_PUSH, str);
+            return as_value(array);
         }
 
         // If we reach this point, the string is not empty and
@@ -304,7 +304,7 @@
             int limit = fn.arg(1).to_int();
             if (limit < 1) {
                 // Return empty array if 
-                return as_value(array.get());
+                return as_value(array);
             }
             max = clamp<size_t>(limit, 0, max);
         }
@@ -314,9 +314,10 @@
         if (delim.empty()) {
             for (size_t i = 0, e = std::min<size_t>(wstr.size(), max);
                     i < e; ++i) {
-                array->push(utf8::encodeCanonicalString(wstr.substr(i, 1), 
version));
+                array->callMethod(NSV::PROP_PUSH,
+                       utf8::encodeCanonicalString(wstr.substr(i, 1), 
version));
             }
-            return as_value(array.get());
+            return as_value(array);
         }
 
     }
@@ -327,16 +328,16 @@
     while (num < max) {
         pos = wstr.find(delim, pos);
 
-        array->push(utf8::encodeCanonicalString(
-                       wstr.substr(prevpos, pos - prevpos),
-                       version));
+        array->callMethod(NSV::PROP_PUSH, utf8::encodeCanonicalString(
+                       wstr.substr(prevpos, pos - prevpos), version));
+
         if (pos == std::wstring::npos) break;
         num++;
         prevpos = pos + delimiterSize;
         pos++;
     }
 
-    return as_value(array.get());
+    return as_value(array);
 }
 
 /// String.lastIndexOf[string[, pos]]

=== modified file 'libcore/asobj/TextFormat_as.cpp'
--- a/libcore/asobj/TextFormat_as.cpp   2009-08-27 10:18:44 +0000
+++ b/libcore/asobj/TextFormat_as.cpp   2009-10-14 08:47:08 +0000
@@ -176,7 +176,7 @@
 textformat_new(const fn_call& fn)
 {
 
-    as_object* obj = ensureType<as_object>(fn.this_ptr).get();
+    as_object* obj = ensureType<as_object>(fn.this_ptr);
 
     std::auto_ptr<TextFormat_as> tf(new TextFormat_as);
 
@@ -223,7 +223,7 @@
        }
        
     obj->setRelay(tf.release());
-    as_object* proto = obj->get_prototype().get();
+    as_object* proto = obj->get_prototype();
     if (proto) attachTextFormatInterface(*proto);
 
     const int flags = 0;
@@ -293,7 +293,7 @@
                return ret;
        }
        
-    as_object* arg = fn.arg(0).to_object(*getGlobal(fn)).get();
+    as_object* arg = fn.arg(0).to_object(*getGlobal(fn));
     Array_as* tStops = dynamic_cast<Array_as*>(arg);
 
     if (!tStops) return as_value();

=== modified file 'libcore/asobj/flash/display/BitmapData_as.cpp'
--- a/libcore/asobj/flash/display/BitmapData_as.cpp     2009-09-29 11:09:52 
+0000
+++ b/libcore/asobj/flash/display/BitmapData_as.cpp     2009-10-14 08:47:08 
+0000
@@ -356,7 +356,7 @@
     }
 
     // This can be any object with the right properties.   
-    as_object* obj = arg.to_object(*getGlobal(fn)).get();
+    as_object* obj = arg.to_object(*getGlobal(fn));
     assert(obj);
     
     as_value x, y, w, h;
@@ -653,7 +653,7 @@
 as_value
 bitmapdata_ctor(const fn_call& fn)
 {
-    as_object* ptr = ensureType<as_object>(fn.this_ptr).get();
+    as_object* ptr = ensureType<as_object>(fn.this_ptr);
        if (fn.nargs < 2) {
         IF_VERBOSE_ASCODING_ERRORS(
              log_aserror("BitmapData constructor requires at least two "

=== modified file 'libcore/asobj/flash/display/DisplayObjectContainer_as.cpp'
--- a/libcore/asobj/flash/display/DisplayObjectContainer_as.cpp 2009-07-29 
05:59:24 +0000
+++ b/libcore/asobj/flash/display/DisplayObjectContainer_as.cpp 2009-10-14 
08:47:08 +0000
@@ -145,7 +145,7 @@
         );
     }
 
-    as_object* objArg = fn.arg(0).to_object(*getGlobal(fn)).get();
+    as_object* objArg = fn.arg(0).to_object(*getGlobal(fn));
     if (!objArg) {
         IF_VERBOSE_ASCODING_ERRORS(
         std::stringstream ss; fn.dump_args(ss);
@@ -191,7 +191,7 @@
         );
     }
 
-    as_object* objArg = fn.arg(0).to_object(*getGlobal(fn)).get();
+    as_object* objArg = fn.arg(0).to_object(*getGlobal(fn));
     if (!objArg) {
         IF_VERBOSE_ASCODING_ERRORS(
         std::stringstream ss; fn.dump_args(ss);

=== modified file 'libcore/asobj/flash/display/MovieClip_as.cpp'
--- a/libcore/asobj/flash/display/MovieClip_as.cpp      2009-10-13 09:07:45 
+0000
+++ b/libcore/asobj/flash/display/MovieClip_as.cpp      2009-10-14 08:47:08 
+0000
@@ -60,7 +60,6 @@
     as_value movieclip_beginBitmapFill(const fn_call& fn);
     as_value movieclip_createEmptyMovieClip(const fn_call& fn);
     as_value movieclip_removeMovieClip(const fn_call& fn);
-    as_value movieclip_createTextField(const fn_call& fn);
     as_value movieclip_curveTo(const fn_call& fn);
     as_value movieclip_beginFill(const fn_call& fn);
     as_value movieclip_prevFrame(const fn_call& fn);
@@ -221,8 +220,6 @@
     vm.registerNative(movieclip_beginBitmapFill, 901, 11);
     vm.registerNative(movieclip_scale9Grid, 901, 12);
 
-    vm.registerNative(movieclip_createTextField, 104, 200);
-
 }
 
 /// Properties (and/or methods) attached to every *instance* of a MovieClip 
@@ -352,6 +349,44 @@
 
 }
 
+//createEmptyMovieClip(name:String, depth:Number) : MovieClip
+as_value
+movieclip_createEmptyMovieClip(const fn_call& fn)
+{
+    boost::intrusive_ptr<MovieClip> ptr = ensureType<MovieClip>(fn.this_ptr);
+
+    if (fn.nargs != 2) {
+        if (fn.nargs < 2) {
+            IF_VERBOSE_ASCODING_ERRORS(
+                log_aserror(_("createEmptyMovieClip needs "
+                    "2 args, but %d given,"
+                    " returning undefined"),
+                    fn.nargs);
+            );
+            return as_value();
+        }
+        IF_VERBOSE_ASCODING_ERRORS(
+            log_aserror(_("createEmptyMovieClip takes "
+                "2 args, but %d given, discarding"
+                " the excess"),
+                fn.nargs);
+        )
+    }
+
+    // TODO: improve MovieClip ctor (and don't use it here anyway).
+    Movie* m = getRoot(fn).topLevelMovie();
+    MovieClip* mc = new MovieClip(0, m, ptr.get());
+
+    mc->set_name(fn.arg(0).to_string());
+    mc->setDynamic();
+
+    // Unlike other MovieClip methods, the depth argument of an empty movie 
clip
+    // can be any number. All numbers are converted to an int32_t, and are 
valid
+    // depths even when outside the usual bounds.
+    DisplayObject* ch = ptr->addDisplayListObject(mc, fn.arg(1).to_int());
+    return as_value(ch);
+}
+
 
 as_value
 movieclip_play(const fn_call& fn)
@@ -585,7 +620,7 @@
     }
 
     NetStream_as* ns;
-    if (!isNativeType(fn.arg(0).to_object(*getGlobal(fn)).get(), ns))
+    if (!isNativeType(fn.arg(0).to_object(*getGlobal(fn)), ns))
     { 
         std::stringstream ss; fn.dump_args(ss);
         // TODO: find out what to do here
@@ -614,39 +649,6 @@
 }
 
 
-//createEmptyMovieClip(name:String, depth:Number) : MovieClip
-as_value
-movieclip_createEmptyMovieClip(const fn_call& fn)
-{
-    boost::intrusive_ptr<MovieClip> movieclip = 
-        ensureType<MovieClip>(fn.this_ptr);
-
-    if (fn.nargs != 2) {
-        if (fn.nargs < 2) {
-            IF_VERBOSE_ASCODING_ERRORS(
-                log_aserror(_("createEmptyMovieClip needs "
-                    "2 args, but %d given,"
-                    " returning undefined"),
-                    fn.nargs);
-            );
-            return as_value();
-        }
-        IF_VERBOSE_ASCODING_ERRORS(
-            log_aserror(_("createEmptyMovieClip takes "
-                "2 args, but %d given, discarding"
-                " the excess"),
-                fn.nargs);
-        )
-    }
-
-    // Unlike other MovieClip methods, the depth argument of an empty movie 
clip
-    // can be any number. All numbers are converted to an int32_t, and are 
valid
-    // depths even when outside the usual bounds.
-    DisplayObject* ch = movieclip->add_empty_movieclip(fn.arg(0).to_string(),
-            fn.arg(1).to_int());
-    return as_value(ch);
-}
-
 as_value
 movieclip_getDepth(const fn_call& fn)
 {
@@ -1146,57 +1148,6 @@
 
 }
 
-as_value
-movieclip_createTextField(const fn_call& fn)
-{
-    boost::intrusive_ptr<MovieClip> movieclip = 
-        ensureType<MovieClip>(fn.this_ptr);
-
-    if (fn.nargs < 6) // name, depth, x, y, width, height
-    {
-        IF_VERBOSE_ASCODING_ERRORS(
-        log_aserror(_("createTextField called with %d args, "
-            "expected 6 - returning undefined"), fn.nargs);
-        );
-        return as_value();
-    }
-
-    std::string txt_name = fn.arg(0).to_string();
-
-    int txt_depth = fn.arg(1).to_int();
-
-    int txt_x = fn.arg(2).to_int();
-
-    int txt_y = fn.arg(3).to_int();
-
-    int txt_width = fn.arg(4).to_int();
-    if ( txt_width < 0 )
-    {
-        IF_VERBOSE_ASCODING_ERRORS(
-        log_aserror(_("createTextField: negative width (%d)"
-            " - reverting sign"), txt_width);
-        );
-        txt_width = -txt_width;
-    }
-
-    int txt_height = fn.arg(5).to_int();
-    if ( txt_height < 0 )
-    {
-        IF_VERBOSE_ASCODING_ERRORS(
-        log_aserror(_("createTextField: negative height (%d)"
-            " - reverting sign"), txt_height);
-        );
-        txt_height = -txt_height;
-    }
-
-    boost::intrusive_ptr<DisplayObject> txt = 
movieclip->add_textfield(txt_name,
-            txt_depth, txt_x, txt_y, txt_width, txt_height);
-
-    // createTextField returns void, it seems
-    if (getSWFVersion(fn) > 7) return as_value(txt.get());
-    else return as_value(); 
-}
-
 //getNextHighestDepth() : Number
 as_value
 movieclip_getNextHighestDepth(const fn_call& fn)
@@ -2421,7 +2372,7 @@
         return as_value();
     }
 
-    as_object* obj = fn.arg(0).to_object(*getGlobal(fn)).get();
+    as_object* obj = fn.arg(0).to_object(*getGlobal(fn));
     BitmapData_as* bd;
 
     if (!isNativeType(obj, bd)) {
@@ -2443,13 +2394,8 @@
 as_value
 movieclip_as2_ctor(const fn_call& fn)
 {
-
     assert(!isAS3(fn));
-
-    boost::intrusive_ptr<as_object> clip = 
-        new as_object(getMovieClipAS2Interface());
-
-    return as_value(clip.get());
+    return as_value();
 }
 
 

=== modified file 'libcore/asobj/flash/geom/ColorTransform_as.cpp'
--- a/libcore/asobj/flash/geom/ColorTransform_as.cpp    2009-10-07 05:52:30 
+0000
+++ b/libcore/asobj/flash/geom/ColorTransform_as.cpp    2009-10-14 08:47:08 
+0000
@@ -255,7 +255,7 @@
 colortransform_toString(const fn_call& fn)
 {
 
-    as_object* ptr = ensureType<as_object>(fn.this_ptr).get();
+    as_object* ptr = ensureType<as_object>(fn.this_ptr);
 
     string_table& st = getStringTable(fn);
 
@@ -330,7 +330,7 @@
 colortransform_ctor(const fn_call& fn)
 {
 
-    as_object* obj = ensureType<as_object>(fn.this_ptr).get();
+    as_object* obj = ensureType<as_object>(fn.this_ptr);
 
     // Default arguments.
     if (fn.nargs < 8)

=== modified file 'libcore/asobj/flash/geom/Matrix_as.cpp'
--- a/libcore/asobj/flash/geom/Matrix_as.cpp    2009-10-07 05:52:30 +0000
+++ b/libcore/asobj/flash/geom/Matrix_as.cpp    2009-10-14 08:47:08 +0000
@@ -201,7 +201,7 @@
     }
 
     // The object to concatenate doesn't have to be a matrix.    
-    as_object* obj = arg.to_object(*getGlobal(fn)).get();
+    as_object* obj = arg.to_object(*getGlobal(fn));
     assert(obj);
 
     MatrixType concatMatrix;
@@ -404,7 +404,7 @@
 
     // It doesn't have to be a point. If it has x and y
     // properties, they will be used.    
-    as_object* obj = arg.to_object(*getGlobal(fn)).get();
+    as_object* obj = arg.to_object(*getGlobal(fn));
     assert(obj);
 
     const PointType& point = transformPoint(obj, ptr.get());
@@ -706,7 +706,7 @@
         return as_value();
     }
     
-    as_object* obj = arg.to_object(*getGlobal(fn)).get();
+    as_object* obj = arg.to_object(*getGlobal(fn));
     assert(obj);
     if (!obj->instanceOf(getClassConstructor(fn, "flash.geom.Point"))) {
         /// Isn't a point.

=== modified file 'libcore/asobj/flash/geom/Point_as.cpp'
--- a/libcore/asobj/flash/geom/Point_as.cpp     2009-10-07 08:06:57 +0000
+++ b/libcore/asobj/flash/geom/Point_as.cpp     2009-10-14 08:47:08 +0000
@@ -128,7 +128,7 @@
         }
         );
         const as_value& arg1 = fn.arg(0);
-        as_object* o = arg1.to_object(*getGlobal(fn)).get();
+        as_object* o = arg1.to_object(*getGlobal(fn));
         if ( ! o )
         {
             IF_VERBOSE_ASCODING_ERRORS(
@@ -199,7 +199,7 @@
         );
         return as_value(false);
     }
-    as_object* o = arg1.to_object(*getGlobal(fn)).get();
+    as_object* o = arg1.to_object(*getGlobal(fn));
     assert(o);
     if (!o->instanceOf(getClassConstructor(fn, "flash.geom.Point")))
     {
@@ -305,7 +305,7 @@
 as_value
 point_subtract(const fn_call& fn)
 {
-    as_object* ptr = ensureType<as_object>(fn.this_ptr).get();
+    as_object* ptr = ensureType<as_object>(fn.this_ptr);
 
     as_value x, y;
     ptr->get_member(NSV::PROP_X, &x);
@@ -329,7 +329,7 @@
         }
         );
         const as_value& arg1 = fn.arg(0);
-        as_object* o = arg1.to_object(*getGlobal(fn)).get();
+        as_object* o = arg1.to_object(*getGlobal(fn));
         if ( ! o )
         {
             IF_VERBOSE_ASCODING_ERRORS(
@@ -367,7 +367,7 @@
 as_value
 point_toString(const fn_call& fn)
 {
-    as_object* ptr = ensureType<as_object>(fn.this_ptr).get();
+    as_object* ptr = ensureType<as_object>(fn.this_ptr);
 
     as_value x, y;
     ptr->get_member(NSV::PROP_X, &x);
@@ -386,7 +386,7 @@
 as_value
 point_length(const fn_call& fn)
 {
-    as_object* ptr = ensureType<as_object>(fn.this_ptr).get();
+    as_object* ptr = ensureType<as_object>(fn.this_ptr);
 
     if ( ! fn.nargs ) // getter
     {
@@ -438,7 +438,7 @@
         );
         return as_value();
     }
-    as_object* o1 = arg1.to_object(*getGlobal(fn)).get();
+    as_object* o1 = arg1.to_object(*getGlobal(fn));
     assert(o1);
     if (!o1->instanceOf(getClassConstructor(fn, "flash.geom.Point")))
     {
@@ -450,7 +450,7 @@
     }
 
     const as_value& arg2 = fn.arg(1);
-    as_object* o2 = arg2.to_object(*getGlobal(fn)).get();
+    as_object* o2 = arg2.to_object(*getGlobal(fn));
     assert(o2);
     // it seems there's no need to check arg2 (see actionscript.all/Point.as)
 
@@ -510,7 +510,7 @@
         );
 
         const as_value& p0val = fn.arg(0);
-        as_object* p0 = p0val.to_object(*getGlobal(fn)).get();
+        as_object* p0 = p0val.to_object(*getGlobal(fn));
         if ( ! p0 )
         {
             IF_VERBOSE_ASCODING_ERRORS(
@@ -525,7 +525,7 @@
         }
 
         const as_value& p1val = fn.arg(1);
-        as_object* p1 = p1val.to_object(*getGlobal(fn)).get();
+        as_object* p1 = p1val.to_object(*getGlobal(fn));
         if ( ! p1 )
         {
             IF_VERBOSE_ASCODING_ERRORS(
@@ -605,7 +605,7 @@
 point_ctor(const fn_call& fn)
 {
 
-    as_object* obj = ensureType<as_object>(fn.this_ptr).get();
+    as_object* obj = ensureType<as_object>(fn.this_ptr);
 
     as_value x;
     as_value y;

=== modified file 'libcore/asobj/flash/geom/Rectangle_as.cpp'
--- a/libcore/asobj/flash/geom/Rectangle_as.cpp 2009-10-07 07:46:44 +0000
+++ b/libcore/asobj/flash/geom/Rectangle_as.cpp 2009-10-14 08:47:08 +0000
@@ -609,7 +609,7 @@
 Rectangle_ctor(const fn_call& fn)
 {
 
-    as_object* obj = ensureType<as_object>(fn.this_ptr).get();
+    as_object* obj = ensureType<as_object>(fn.this_ptr);
 
     as_value x;
     as_value y;

=== modified file 'libcore/asobj/flash/geom/Transform_as.cpp'
--- a/libcore/asobj/flash/geom/Transform_as.cpp 2009-10-07 05:52:30 +0000
+++ b/libcore/asobj/flash/geom/Transform_as.cpp 2009-10-14 08:47:08 +0000
@@ -345,7 +345,7 @@
     boost::intrusive_ptr<MovieClip> mc =
         ensureType<MovieClip>(fn.arg(0).to_object(*getGlobal(fn)));
 
-    as_object* obj = ensureType<as_object>(fn.this_ptr).get();
+    as_object* obj = ensureType<as_object>(fn.this_ptr);
     obj->setRelay(new Transform_as(*mc));
 
     return as_value(); 

=== modified file 'libcore/asobj/flash/media/Camera_as.cpp'
--- a/libcore/asobj/flash/media/Camera_as.cpp   2009-08-28 11:03:35 +0000
+++ b/libcore/asobj/flash/media/Camera_as.cpp   2009-10-14 14:50:52 +0000
@@ -30,7 +30,6 @@
 #include "builtin_function.h" 
 #include "NativeFunction.h" 
 #include "Object.h" 
-#include "Array_as.h"
 #include "MediaHandler.h"
 #include "VideoInput.h"
 
@@ -534,13 +533,14 @@
     
     const size_t size = names.size();
     
-    boost::intrusive_ptr<Array_as> data = new Array_as;
+    Global_as* gl = getGlobal(fn);
+    as_object* data = gl->createArray();
 
     for (size_t i = 0; i < size; ++i) {
-        data->push(names[i]);
+        data->callMethod(NSV::PROP_PUSH, names[i]);
     }
     
-    return as_value(data.get());
+    return as_value(data);
 } 
 
 

=== modified file 'libcore/asobj/flash/media/Microphone_as.cpp'
--- a/libcore/asobj/flash/media/Microphone_as.cpp       2009-09-13 22:29:48 
+0000
+++ b/libcore/asobj/flash/media/Microphone_as.cpp       2009-10-14 14:50:52 
+0000
@@ -30,7 +30,6 @@
 #include "builtin_function.h"
 #include "NativeFunction.h"
 #include "Object.h" // for getObjectInterface
-#include "Array_as.h"
 #include <cmath>
 
 #ifdef USE_GST
@@ -426,15 +425,16 @@
     
     size_t size = vect.size();
     
-    boost::intrusive_ptr<Array_as> data = new Array_as;
+    Global_as* gl = getGlobal(fn);
+    as_object* data = gl->createArray();
     
     for (size_t i=0; i < size; ++i) {
-        data->push(vect[i]);
+        data->callMethod(NSV::PROP_PUSH, vect[i]);
     }
         
     if ( fn.nargs == 0 ) // getter
     {
-        return as_value(data.get());
+        return as_value(data);
     }
     else // setter
     {

=== modified file 'libcore/asobj/flash/media/Sound_as.cpp'
--- a/libcore/asobj/flash/media/Sound_as.cpp    2009-08-26 14:29:24 +0000
+++ b/libcore/asobj/flash/media/Sound_as.cpp    2009-10-14 08:47:08 +0000
@@ -810,7 +810,7 @@
         const as_value& arg0 = fn.arg(0);
         if ( ! arg0.is_null() && ! arg0.is_undefined() )
         {
-            as_object* obj = arg0.to_object(*getGlobal(fn)).get();
+            as_object* obj = arg0.to_object(*getGlobal(fn));
             DisplayObject* ch = obj ? obj->toDisplayObject() : 0;
             IF_VERBOSE_ASCODING_ERRORS(
             if (!ch) {

=== modified file 'libcore/asobj/flash/net/LocalConnection_as.cpp'
--- a/libcore/asobj/flash/net/LocalConnection_as.cpp    2009-08-26 14:29:24 
+0000
+++ b/libcore/asobj/flash/net/LocalConnection_as.cpp    2009-10-14 08:47:08 
+0000
@@ -265,7 +265,7 @@
 localconnection_new(const fn_call& fn)
 {
     // TODO: this doesn't happen on construction.
-    as_object* obj = ensureType<as_object>(fn.this_ptr).get();
+    as_object* obj = ensureType<as_object>(fn.this_ptr);
     obj->setRelay(new LocalConnection_as(obj));
     return as_value();
 }

=== modified file 'libcore/asobj/flash/net/NetStream_as.cpp'
--- a/libcore/asobj/flash/net/NetStream_as.cpp  2009-08-27 10:35:23 +0000
+++ b/libcore/asobj/flash/net/NetStream_as.cpp  2009-10-14 08:47:08 +0000
@@ -1580,7 +1580,7 @@
     if (fn.nargs) {
 
         NetConnection_as* nc;
-        if (isNativeType(fn.arg(0).to_object(*getGlobal(fn)).get(), nc)) {
+        if (isNativeType(fn.arg(0).to_object(*getGlobal(fn)), nc)) {
             ns->setNetCon(nc);
         }
         else {

=== modified file 'libcore/asobj/flash/net/SharedObject_as.cpp'
--- a/libcore/asobj/flash/net/SharedObject_as.cpp       2009-09-07 17:34:36 
+0000
+++ b/libcore/asobj/flash/net/SharedObject_as.cpp       2009-10-14 08:47:08 
+0000
@@ -880,7 +880,7 @@
     }
     
     NetConnection_as* nc;
-    if (!isNativeType(fn.arg(0).to_object(*getGlobal(fn)).get(), nc)) {
+    if (!isNativeType(fn.arg(0).to_object(*getGlobal(fn)), nc)) {
         return as_value();
     }
 

=== modified file 'libcore/asobj/flash/text/TextSnapshot_as.cpp'
--- a/libcore/asobj/flash/text/TextSnapshot_as.cpp      2009-08-26 14:29:24 
+0000
+++ b/libcore/asobj/flash/text/TextSnapshot_as.cpp      2009-10-14 14:50:52 
+0000
@@ -37,7 +37,6 @@
 #include "MovieClip.h"
 #include "Font.h"
 #include "swf/TextRecord.h"
-#include "Array_as.h"
 #include "RGBA.h"
 #include "GnashNumeric.h"
 
@@ -171,7 +170,7 @@
 }
 
 void
-TextSnapshot_as::getTextRunInfo(size_t start, size_t end, Array_as& ri) const
+TextSnapshot_as::getTextRunInfo(size_t start, size_t end, as_object& ri) const
 {
     std::string::size_type pos = 0;
 
@@ -233,7 +232,7 @@
                 el->init_member("matrix_tx", xpos);
                 el->init_member("matrix_ty", ypos);
 
-                ri.push(el);
+                ri.callMethod(NSV::PROP_PUSH, el);
 
                 ++pos;
                 x += k->advance;
@@ -455,7 +454,8 @@
     size_t start = std::max<boost::int32_t>(0, fn.arg(0).to_int());
     size_t end = std::max<boost::int32_t>(start + 1, fn.arg(1).to_int());
 
-    Array_as* ri = new Array_as;
+    Global_as* gl = getGlobal(fn);
+    as_object* ri = gl->createArray();;
 
     ts->getTextRunInfo(start, end, *ri);
     

=== modified file 'libcore/asobj/flash/text/TextSnapshot_as.h'
--- a/libcore/asobj/flash/text/TextSnapshot_as.h        2009-08-26 14:29:24 
+0000
+++ b/libcore/asobj/flash/text/TextSnapshot_as.h        2009-10-14 14:50:52 
+0000
@@ -30,7 +30,6 @@
 namespace gnash {
 
        class StaticText;
-    class Array_as;
     namespace SWF {
         class TextRecord;
     }
@@ -73,7 +72,7 @@
 
     std::string getSelectedText(bool newlines) const;
 
-    void getTextRunInfo(size_t start, size_t end, Array_as& ri) const;
+    void getTextRunInfo(size_t start, size_t end, as_object& ri) const;
 
 protected:
 

=== modified file 'libcore/asobj/flash/ui/ContextMenu_as.cpp'
--- a/libcore/asobj/flash/ui/ContextMenu_as.cpp 2009-08-27 11:29:16 +0000
+++ b/libcore/asobj/flash/ui/ContextMenu_as.cpp 2009-10-14 14:50:52 +0000
@@ -31,7 +31,6 @@
 #include "GnashException.h" // for ActionException
 #include "Object.h" // for getObjectInterface
 #include "namedStrings.h"
-#include "Array_as.h"
 
 namespace gnash {
 
@@ -118,7 +117,7 @@
     
     string_table& st = getStringTable(fn);
     as_value onSelect, builtInItems;
-    as_value customItems = new Array_as;;
+    as_value customItems = gl->createArray();
 
     ptr->get_member(NSV::PROP_ON_SELECT, &onSelect);
     ptr->get_member(st.find("builtInItems"), &builtInItems);
@@ -131,11 +130,11 @@
 
     // The customItems object is a deep copy, but only of elements that are
     // instances of ContextMenuItem (have its prototype as a __proto__ member).
-    as_object* nc = new Array_as;
+    as_object* nc = gl->createArray();
     as_object* customs;
 
     if (customItems.is_object() &&
-            (customs = customItems.to_object(*getGlobal(fn)).get())) {
+            (customs = customItems.to_object(*getGlobal(fn)))) {
         // TODO: only copy properties that are ContextMenuItems.
         nc->copyProperties(*customs);
         customItems = nc;
@@ -163,7 +162,7 @@
     obj->set_member(st.find("builtInItems"), builtInItems);
 
     // There is an empty customItems array.
-    Array_as* customItems = new Array_as();
+    as_object* customItems = gl->createArray();
     obj->set_member(st.find("customItems"), customItems);
 
     return as_value();

=== modified file 'libcore/asobj/flash/xml/XMLDocument_as.cpp'
--- a/libcore/asobj/flash/xml/XMLDocument_as.cpp        2009-09-07 17:34:36 
+0000
+++ b/libcore/asobj/flash/xml/XMLDocument_as.cpp        2009-10-14 08:47:08 
+0000
@@ -585,7 +585,7 @@
     o.init_property("xmlDecl", &xml_xmlDecl, &xml_xmlDecl, flags);
     o.init_property("docTypeDecl", &xml_docTypeDecl, &xml_docTypeDecl, flags);
 
-    as_object* proto = o.get_prototype().get();
+    as_object* proto = o.get_prototype();
     if (!proto) return;
     proto->init_property("loaded", xml_loaded, xml_loaded);
     proto->init_property("status", xml_status, xml_status);
@@ -651,7 +651,7 @@
 
         // Copy constructor clones nodes.
         if (fn.arg(0).is_object()) {
-            as_object* obj = fn.arg(0).to_object(*getGlobal(fn)).get();
+            as_object* obj = fn.arg(0).to_object(*getGlobal(fn));
             xml_obj = dynamic_cast<XMLDocument_as*>(obj);
 
             if (xml_obj) {

=== modified file 'libcore/asobj/flash/xml/XMLNode_as.cpp'
--- a/libcore/asobj/flash/xml/XMLNode_as.cpp    2009-08-27 06:01:23 +0000
+++ b/libcore/asobj/flash/xml/XMLNode_as.cpp    2009-10-14 14:50:52 +0000
@@ -23,7 +23,6 @@
 
 #include "xml/XMLNode_as.h"
 #include "xml/XMLDocument_as.h"
-#include "Array_as.h"
 #include "Object.h"
 #include "VM.h"
 #include "log.h"
@@ -538,7 +537,8 @@
        }
 
        boost::intrusive_ptr<XMLNode_as> xml_obj = 
-        
boost::dynamic_pointer_cast<XMLNode_as>(fn.arg(0).to_object(*getGlobal(fn)));  
+        dynamic_cast<XMLNode_as*>(fn.arg(0).to_object(*getGlobal(fn)));
+
        if ( ! xml_obj )
        {
                IF_VERBOSE_ASCODING_ERRORS(
@@ -582,7 +582,7 @@
        }
 
        boost::intrusive_ptr<XMLNode_as> newnode = 
-        
boost::dynamic_pointer_cast<XMLNode_as>(fn.arg(0).to_object(*getGlobal(fn)));
+        dynamic_cast<XMLNode_as*>(fn.arg(0).to_object(*getGlobal(fn)));
 
        if (!newnode) {
                IF_VERBOSE_ASCODING_ERRORS(
@@ -594,7 +594,7 @@
        }
 
        boost::intrusive_ptr<XMLNode_as> pos = 
-        
boost::dynamic_pointer_cast<XMLNode_as>(fn.arg(1).to_object(*getGlobal(fn)));
+        dynamic_cast<XMLNode_as*>(fn.arg(1).to_object(*getGlobal(fn)));
 
        if (!pos) {
                IF_VERBOSE_ASCODING_ERRORS(
@@ -921,7 +921,9 @@
 xmlnode_childNodes(const fn_call& fn)
 {
     boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
-    boost::intrusive_ptr<Array_as> ary = new Array_as();
+ 
+    Global_as* gl = getGlobal(fn);
+    as_object* ary = gl->createArray();
 
     typedef XMLNode_as::Children Children;
 
@@ -930,10 +932,10 @@
                     it != itEnd; ++it )
     {
         boost::intrusive_ptr<XMLNode_as> node = *it;
-        ary->push(as_value(node.get()));
+        ary->callMethod(NSV::PROP_PUSH, node.get());
     }
 
-    return as_value(ary.get());
+    return as_value(ary);
 }
 
 

=== modified file 'libcore/movie_root.cpp'
--- a/libcore/movie_root.cpp    2009-10-07 11:54:54 +0000
+++ b/libcore/movie_root.cpp    2009-10-14 08:47:08 +0000
@@ -525,7 +525,7 @@
     as_value s;
     if (!global->get_member(NSV::CLASS_SELECTION, &s)) return 0;
     
-    as_object* sel = s.to_object(*global).get();
+    as_object* sel = s.to_object(*global);
    
     return sel;
 }
@@ -538,7 +538,7 @@
        Global_as* global = _vm.getGlobal();
        if (!global) return 0;
        if (!global->get_member(NSV::PROP_iSTAGE, &v) ) return 0;
-       return v.to_object(*global).get();
+       return v.to_object(*global);
 }
                
 void

=== modified file 'libcore/swf_function.cpp'
--- a/libcore/swf_function.cpp  2009-10-13 10:32:52 +0000
+++ b/libcore/swf_function.cpp  2009-10-14 14:41:58 +0000
@@ -34,6 +34,22 @@
 
 namespace gnash {
 
+namespace {
+
+       /// Return an 'arguments' object.
+       //
+       /// The 'arguments' variable is an array with an additional
+       /// 'callee' member, set to the function being called.
+       ///
+       /// NOTE: the callee as_object will be stored in an as_value, thus
+       ///       getting wrapped into an intrusive_ptr. Make sure you have
+       ///       a reference on it!
+       ///       
+       ///
+       as_object* getArguments(swf_function& callee, const fn_call& fn,
+            as_object* caller);
+}
+
 swf_function::~swf_function()
 {
 #ifndef GNASH_USE_GC
@@ -59,31 +75,6 @@
        init_member(NSV::PROP_CONSTRUCTOR, 
as_function::getFunctionConstructor());
 }
 
-/*private static*/
-Array_as* 
-swf_function::getArguments(swf_function& callee, const fn_call& fn,
-        as_object* caller)
-{ 
-#ifndef GNASH_USE_GC
-       // We'll be storing the callee as_object into an as_value
-       // so you must make sure you have a reference on it before
-       // callign this function.
-       assert(callee.get_ref_count() > 0);
-#endif // ndef GNASH_USE_GC
-
-       // Super class prototype is : obj.__proto__.constructor.prototype 
-       Array_as* arguments = new Array_as();
-       for (unsigned int i=0; i<fn.nargs; ++i)
-       {
-               arguments->push(fn.arg(i));
-       }
-       arguments->init_member(NSV::PROP_CALLEE, &callee);
-
-       arguments->init_member(NSV::PROP_CALLER, as_value(caller));
-
-       return arguments;
-
-}
 
 /// Exception safe (scoped) as_environment's target changer
 //
@@ -219,7 +210,8 @@
                }
 
                // Init arguments array, if it's going to be needed.
-               boost::intrusive_ptr<Array_as> arg_array;
+        as_object* arg_array = 0;
+
                if ((m_function2_flags & PRELOAD_ARGUMENTS) || 
                 !(m_function2_flags & SUPPRESS_ARGUMENTS)) {
                        arg_array = getArguments(*this, fn, caller);
@@ -227,13 +219,13 @@
 
                if (m_function2_flags & PRELOAD_ARGUMENTS) {
                        // preload 'arguments' into a register.
-                       m_env.setRegister(current_reg, 
as_value(arg_array.get()));
+                       m_env.setRegister(current_reg, as_value(arg_array));
                        current_reg++;
                }
 
                if (!(m_function2_flags & SUPPRESS_ARGUMENTS)) {
                        // Put 'arguments' in a local var.
-                       m_env.add_local("arguments", as_value(arg_array.get()));
+                       m_env.add_local("arguments", as_value(arg_array));
                }
 
                if ((m_function2_flags & PRELOAD_SUPER) && swfversion > 5) {
@@ -366,5 +358,33 @@
 }
 #endif // GNASH_USE_GC
 
+namespace {
+
+as_object* 
+getArguments(swf_function& callee, const fn_call& fn,
+        as_object* caller)
+{ 
+#ifndef GNASH_USE_GC
+       // We'll be storing the callee as_object into an as_value
+       // so you must make sure you have a reference on it before
+       // callign this function.
+       assert(callee.get_ref_count() > 0);
+#endif // ndef GNASH_USE_GC
+
+       // Super class prototype is : obj.__proto__.constructor.prototype 
+       as_object* arguments = getGlobal(fn)->createArray();
+       for (unsigned int i=0; i<fn.nargs; ++i) {
+               arguments->callMethod(NSV::PROP_PUSH, fn.arg(i));
+       }
+
+       arguments->init_member(NSV::PROP_CALLEE, &callee);
+
+       arguments->init_member(NSV::PROP_CALLER, as_value(caller));
+
+       return arguments;
+
+}
+
+}
 } // end of gnash namespace
 

=== modified file 'libcore/swf_function.h'
--- a/libcore/swf_function.h    2009-07-15 07:37:56 +0000
+++ b/libcore/swf_function.h    2009-10-14 14:41:58 +0000
@@ -82,19 +82,6 @@
        /// See 
http://sswf.sourceforge.net/SWFalexref.html#action_declare_function2
        boost::uint16_t m_function2_flags;
 
-       /// Return an 'arguments' object.
-       //
-       /// The 'arguments' variable is an array with an additional
-       /// 'callee' member, set to the function being called.
-       ///
-       /// NOTE: the callee as_object will be stored in an as_value, thus
-       ///       getting wrapped into an intrusive_ptr. Make sure you have
-       ///       a reference on it!
-       ///       
-       ///
-       static Array_as* getArguments(swf_function& callee, const fn_call& fn,
-            as_object* caller);
-
 public:
 
        enum SWFDefineFunction2Flags

=== modified file 'libcore/vm/ASHandlers.cpp'
--- a/libcore/vm/ASHandlers.cpp 2009-10-13 07:32:05 +0000
+++ b/libcore/vm/ASHandlers.cpp 2009-10-14 15:44:50 +0000
@@ -28,7 +28,6 @@
 #include "rc.h"
 #include "ASHandlers.h"
 #include "movie_definition.h"
-#include "Array_as.h"
 #include "swf_function.h"
 #include "as_function.h"
 #include "fn_call.h"
@@ -2810,7 +2809,7 @@
     assert(array_size >= 0); // TODO: trigger this !!
 
     // Call the array constructor, to create an empty array.
-    as_value result = array_new(fn_call(NULL, env));
+    as_value result = getGlobal(env)->createArray();
 
     boost::intrusive_ptr<as_object> ao = 
convertToObject(*getGlobal(thread.env), result);
     assert(ao);
@@ -3961,7 +3960,7 @@
 {
 
     try {
-        return val.to_object(gl).get();
+        return val.to_object(gl);
     }
     catch (const GnashException& gl) {
         return 0;

=== modified file 'libcore/vm/Machine.cpp'
--- a/libcore/vm/Machine.cpp    2009-10-07 07:46:44 +0000
+++ b/libcore/vm/Machine.cpp    2009-10-14 14:41:51 +0000
@@ -21,7 +21,6 @@
 #include "as_object.h"
 #include "ClassHierarchy.h"
 #include "namedStrings.h"
-#include "Array_as.h"
 #include "AbcBlock.h"
 #include "fn_call.h"
 #include "abc_function.h"
@@ -177,7 +176,7 @@
                if (b)                                                          
                                                                \
                {                                                               
                                                                        \
                        mStream->seekTo(opStart);                               
                                                \
-                       pushGet(e->to_object(*_global).get(), *e, b);           
                                        \
+                       pushGet(e->to_object(*_global), *e, b);                 
                                \
                        break;                                                  
                                                                \
                }                                                               
                                                                        \
        }                                                                       
                                                                        \
@@ -208,7 +207,7 @@
                if (d)                                                          
                                                                \
                {                                                               
                                                                        \
                        mStream->seekTo(opStart);                               
                                                \
-                       pushGet(c->to_object(*_global).get(), *c, d);           
                                        \
+                       pushGet(c->to_object(*_global), *c, d);                 
                                \
                        break;                                                  
                                                                \
                }                                                               
                                                                        \
        }                                                                       
                                                                        \
@@ -255,22 +254,24 @@
     else return a.equals(b);
 }                                                              
 
+/// NB: the stubbed but unimplemented as_value::conforms_to no longer exists,
+/// but the code is left here for later reference.
 #define ABSTRACT_TYPELATE(st, checkval, matchval)                              
                        \
 {                                                                              
                                                                        \
        bool *store = &st;                                                      
                                                        \
-       as_value &a = checkval; /* Don't call checkval multiple times */        
        \
+       /*as_value &a = checkval;  Don't call checkval multiple times */        
        \
        as_value &b = matchval; /* Don't call matchval multiple times */        
        \
        *store = true;                                                          
                                                        \
        if (b.is_object())                                                      
                                                        \
        {                                                                       
                                                                        \
                as_value v;                                                     
                                                                \
                b.to_object(*_global)->get_member(NSV::INTERNAL_TYPE, &v);      
                                \
-               if (!a.conforms_to(mST.find(v.to_string())))                    
                        \
+               if (true) /*(!a.conforms_to(mST.find(v.to_string()))) */        
\
                        *store = false;                                         
                                                        \
        }                                                                       
                                                                        \
        else if (b.is_string())                                                 
                                                \
        {                                                                       
                                                                        \
-               if (!a.conforms_to(mST.find(b.to_string())))                    
                        \
+               if (true) /*(!a.conforms_to(mST.find(b.to_string())))   */      
    \
                        *store = false;                                         
                                                        \
        }                                                                       
                                                                        \
        else                                                                    
                                                                \
@@ -438,7 +439,7 @@
                     
                     // Use get_super?
                     as_object *super = _stack.top(0).to_object(*_global)->
-                        get_prototype().get();
+                        get_prototype();
                     
                     // If we don't have a super, throw.
                     if (!super) throw ASReferenceError();
@@ -470,7 +471,7 @@
                     
                     // Use get_super?
                     as_object* super = _stack.pop().to_object(*_global)->
-                        get_prototype().get();
+                        get_prototype();
                     if (!super) throw ASReferenceError();
                     Property* b = super->findProperty(a.getABCName(), 
                         a.getNamespace()->getURI());
@@ -869,7 +870,7 @@
                 case SWF::ABC_ACTION_PUSHSCOPE:
                 {
                     as_value scope_value = pop_stack();
-                    if (!scope_value.to_object(*_global).get()) {
+                    if (!scope_value.to_object(*_global)) {
                         // Should throw an exception.
                         IF_VERBOSE_ASCODING_ERRORS(
                         log_aserror(_("Can't push a null value onto the "
@@ -893,7 +894,7 @@
                     log_unimpl("ABC_ACTION_PUSHWITH");
                     // A scope object is just a regular object.
             //                 ENSURE_OBJECT(_stack.top(0));
-            //                 as_object *a = 
_stack.top(0).to_object(*_global).get();
+            //                 as_object *a = 
_stack.top(0).to_object(*_global);
             // 
             //                 if (!_scopeStack.empty())
             //                         
a->set_prototype(_scopeStack.top(0).mScope);
@@ -933,7 +934,7 @@
                 {
                     ENSURE_NUMBER(_stack.top(0));
                     ENSURE_OBJECT(_stack.top(1));
-                    as_object *obj = _stack.top(1).to_object(*_global).get();
+                    as_object *obj = _stack.top(1).to_object(*_global);
                     const boost::uint32_t index =
                         _stack.top(0).to_number<boost::uint32_t>();
                     
@@ -965,7 +966,7 @@
                 {
                     ENSURE_NUMBER(_stack.top(0));
                     ENSURE_OBJECT(_stack.top(1));
-                    as_object *obj = _stack.top(1).to_object(*_global).get();
+                    as_object *obj = _stack.top(1).to_object(*_global);
                     boost::uint32_t index =
                         _stack.top(0).to_number<boost::uint32_t>();
                     _stack.drop(1);
@@ -1005,7 +1006,7 @@
                 {
                     ENSURE_NUMBER(_stack.top(0));
                     ENSURE_OBJECT(_stack.top(1));
-                    as_object *obj = _stack.top(1).to_object(*_global).get();
+                    as_object *obj = _stack.top(1).to_object(*_global);
                     const boost::uint32_t index =
                         _stack.top(0).to_number<boost::uint32_t>();
                     const Property *b = obj->getByIndex(index);
@@ -1172,7 +1173,7 @@
                     log_abc("HASNEXT2: Object is %s, index is %d",
                             objv, indexv);
 
-                    as_object *obj = objv.to_object(*_global).get();
+                    as_object *obj = objv.to_object(*_global);
                     if (!obj) {
                         // TODO: Check what to do here.
                         log_error("ABC_ACTION_HASNEXT2: expecting object in "
@@ -1239,7 +1240,7 @@
                     ENSURE_OBJECT(_stack.top(argc + 1)); // The func
                     ENSURE_OBJECT(_stack.top(argc)); // The 'this'
                     as_function *f = _stack.top(argc + 1).to_as_function();
-                    as_object *obj = 
_stack.top(argc).to_object(*_global).get();
+                    as_object *obj = _stack.top(argc).to_object(*_global);
                     // We start with argc + 2 values related to this call
                     // on the stack. We want to end with 1 value. We pass
                     // argc values (the parameters), so we need to drop
@@ -1286,7 +1287,7 @@
                     boost::uint32_t dispatch_id = mStream->read_V32() - 1;
                     boost::uint32_t argc = mStream->read_V32();
                     ENSURE_OBJECT(_stack.top(argc));
-                    as_object *obj = 
_stack.top(argc).to_object(*_global).get();
+                    as_object *obj = _stack.top(argc).to_object(*_global);
                     const Property *f = obj->getByIndex(dispatch_id);
                     as_function* func;
 #if 0
@@ -1322,7 +1323,7 @@
                     boost::uint32_t argc = mStream->read_V32();
                     as_function *func = m->getPrototype();
                     ENSURE_OBJECT(_stack.top(argc));
-                    as_object *obj = 
_stack.top(argc).to_object(*_global).get();
+                    as_object *obj = _stack.top(argc).to_object(*_global);
                     pushCall(func, obj, _stack.top(argc), argc, 0);
                     break;
                 }
@@ -1405,7 +1406,7 @@
 
                     as_value object_val = pop_stack();
 
-                    as_object *object = object_val.to_object(*_global).get();
+                    as_object *object = object_val.to_object(*_global);
                     if (!object) {
                         log_abc(_("CALLPROP: Can't call a method of a value "
                                 "that doesn't cast to an object (%s)."),
@@ -1438,7 +1439,7 @@
 
             /*         int shift = completeName(a, argc);
                     ENSURE_OBJECT(_stack.top(shift + argc));
-                    as_object *obj = _stack.top(argc + 
shift).to_object(*_global).get();
+                    as_object *obj = _stack.top(argc + 
shift).to_object(*_global);
                     Property *b = obj->findProperty(a.getABCName(), 
                         a.getNamespace()->getURI());
                     if (!b)
@@ -1513,11 +1514,11 @@
                     fn_call::Args args;
                     get_args(argc, args);
                     
-                    as_object* obj = 
_stack.top(argc).to_object(*_global).get();
+                    as_object* obj = _stack.top(argc).to_object(*_global);
 
                     // Using get_super() here fails; is it broken, or is
                     // prototype what we want?
-                    as_object* super = obj ? obj->get_prototype().get() : 0;
+                    as_object* super = obj ? obj->get_prototype() : 0;
                     log_abc("CONSTRUCTSUPER: object %s, super %s, args %s",
                             _stack.top(argc), super, argc);
 
@@ -1556,7 +1557,7 @@
                             "%s on object %s", mST.value(a.getGlobalName()),
                             _stack.top(0));
 
-                    as_object* object = pop_stack().to_object(*_global).get();
+                    as_object* object = pop_stack().to_object(*_global);
 
                     if (!object) {
                         //TODO: Should this result in an exeception or an 
@@ -1598,7 +1599,7 @@
                             as_value val = c.to_object(*_global)->getMember(
                                     NSV::PROP_CONSTRUCTOR, 0);
 
-                            call_method(val, env, c.to_object(*_global).get(), 
args);
+                            call_method(val, env, c.to_object(*_global), args);
 
                             // Push the constructed property
                             push_stack(c);
@@ -1647,12 +1648,11 @@
                 case SWF::ABC_ACTION_NEWARRAY:
                 {
                     boost::uint32_t asize = mStream->read_V32();
-                    log_abc("Creating array of size %u",asize);
-                    Array_as *arr = new Array_as;
-                    arr->resize(asize);
                     boost::uint32_t i = asize;
+
+                    as_object* arr = _global->createArray();
                     while (i--) {
-                        arr->set_indexed(i, pop_stack());
+                        arr->callMethod(NSV::PROP_PUSH, pop_stack());
                     }
                     push_stack(as_value(arr));
                     break;
@@ -1697,7 +1697,7 @@
                             mST.value(c->getName()));
                     
                     // This may be 0, and that's fine.
-                    as_object* base_class = 
pop_stack().to_object(*_global).get();
+                    as_object* base_class = pop_stack().to_object(*_global);
                     as_object* new_class = c->getPrototype();
                     
                     new_class->set_prototype(base_class);
@@ -1868,7 +1868,7 @@
                     else name = a.getGlobalName();
 
                     as_value val = pop_stack();
-                    as_object *object = val.to_object(*_global).get();
+                    as_object *object = val.to_object(*_global);
 
                     if (!object) {
                         log_error("ABC_ACTION_SETPROPERTY: expecting object "
@@ -1956,7 +1956,7 @@
                     else name = a.getGlobalName();
 
                     as_value object_val = pop_stack();
-                    as_object* object = object_val.to_object(*_global).get();
+                    as_object* object = object_val.to_object(*_global);
                     
                     log_abc(_("GETPROPERTY: Looking for property "
                             "%s of object %s"), mST.value(name), object_val);
@@ -2004,7 +2004,7 @@
                     // pop name and namespace values.
                     as_value object_val = pop_stack();
 
-                    as_object* object = object_val.to_object(*_global).get();
+                    as_object* object = object_val.to_object(*_global);
                     if (!object) {
                         log_abc("INITPROPERTY: expecting object on stack, "
                                 "got %s", object_val);
@@ -2027,7 +2027,7 @@
                 {
                     asName a = pool_name(mStream->read_V32(), mPoolObject);
                     _stack.drop(completeName(a));
-                    as_object* obj = _stack.top(0).to_object(*_global).get();
+                    as_object* obj = _stack.top(0).to_object(*_global);
 
                     if (!obj) {
                         // TODO: what here?
@@ -2056,7 +2056,7 @@
                 {
                     as_value val;
                     boost::uint32_t sindex = mStream->read_V32();
-                    as_object* object = pop_stack().to_object(*_global).get();
+                    as_object* object = pop_stack().to_object(*_global);
                     if (!object) {
                         log_abc("GETSLOT: Did not find expected object on "
                                 "stack");
@@ -2088,7 +2088,7 @@
                     log_abc("SETSLOT object: %s, value: %s, index: %s",
                             object, value, sindex);
 
-                    as_object* obj = object.to_object(*_global).get();
+                    as_object* obj = object.to_object(*_global);
                     if ( ! obj )
                     {
                         IF_VERBOSE_ASCODING_ERRORS(
@@ -2234,7 +2234,7 @@
                 /// Do: If obj is Undefined or Null, throw TypeError
                 case SWF::ABC_ACTION_CONVERT_O:
                 {
-                    _stack.top(0) = _stack.top(0).to_object(*_global).get();
+                    _stack.top(0) = _stack.top(0).to_object(*_global);
                     if (_stack.top(0).is_undefined() || 
_stack.top(0).is_null())
                         throw ASTypeError();
                     break;
@@ -2352,7 +2352,7 @@
                 case SWF::ABC_ACTION_COERCE_O:
                 {
                     if (_stack.top(0).is_undefined())
-                        _stack.top(0) = 
_stack.top(0).to_object(*_global).get();
+                        _stack.top(0) = _stack.top(0).to_object(*_global);
                     else
                         _stack.top(0).set_undefined();
                     break;
@@ -2687,8 +2687,8 @@
                 {
                     asName a = pool_name(mStream->read_V32(), mPoolObject);
                     _stack.drop(completeName(a));
-                    // TODO: Namespace stuff?
-                    
_stack.top(0).set_bool(_stack.top(0).conforms_to(a.getABCName()));
+                    // TODO: Implement it.
+                    
//_stack.top(0).set_bool(_stack.top(0).conforms_to(a.getABCName()));
                 }
 
                 /// 0xB3 ABC_ACTION_ISTYPELATE
@@ -2701,8 +2701,8 @@
                 {
                     as_value type = pop_stack();
                     as_value value = pop_stack();
-                    as_object* const valueObject = 
value.to_object(*_global).get();
-                    as_object* const typeObject = 
type.to_object(*_global).get();
+                    as_object* const valueObject = value.to_object(*_global);
+                    as_object* const typeObject = type.to_object(*_global);
 
                     if (!valueObject || !typeObject) {
                         // TODO: what here!?

=== modified file 'testsuite/actionscript.all/array.as'
--- a/testsuite/actionscript.all/array.as       2009-02-25 22:33:03 +0000
+++ b/testsuite/actionscript.all/array.as       2009-10-14 11:56:50 +0000
@@ -1459,6 +1459,65 @@
  check(!a.hasOwnProperty(2)); 
 #endif
 
+/// Test array functions on normal objects for a better idea of what goes
+/// on.
+
+fakeArray = function() {
+    o = {};
+    o[1] = "one";
+    o[2] = "two";
+    o[3] = "three";
+    o[4] = "four";
+    o[5] = "five";
+    o[6] = "six";
+    o[7] = "seven";
+
+    // This is deliberately less than the actual length!
+    o.length = 6;
+    return o;
+};
+
+traceProps = function(obj) {
+        s = "";
+        for (i in obj) { s += i + ","; };
+        return s;
+};
+
+o = fakeArray();
+o.shift = Array.prototype.shift;
+
+// Order of property creation.
+check_equals(traceProps(o), "shift,length,7,6,5,4,3,2,1,");
+
+o.shift();
+// Properties are readded from 0 to 5.
+check_equals(traceProps(o), "4,3,2,1,0,shift,length,7,6,5,");
+xcheck_equals(o.length, 6);
+
+o = fakeArray();
+o.unshift = Array.prototype.unshift;
+
+// Order of property creation.
+check_equals(traceProps(o), "unshift,length,7,6,5,4,3,2,1,");
+
+o.unshift("new");
+// Properties are readded in reverse order.
+check_equals(traceProps(o), "0,1,2,3,4,5,6,unshift,length,7,")
+xcheck_equals(o.length, 6);
+
+
+o = fakeArray();
+o.pop = Array.prototype.pop;
+
+// Order of property creation.
+check_equals(traceProps(o), "pop,length,7,6,5,4,3,2,1,");
+
+val = o.pop();
+check_equals(val, "five");
+// Length is not decremented, property 5 is deleted.
+check_equals(traceProps(o), "pop,length,7,6,4,3,2,1,");
+xcheck_equals(o.length, 6);
+
 
 // TODO: test ASnative-returned functions:
 //
@@ -1478,11 +1537,11 @@
 
 
 #if OUTPUT_VERSION < 6
- check_totals(501);
+ check_totals(511);
 #else
 # if OUTPUT_VERSION < 7
-  check_totals(562);
+  check_totals(572);
 # else
-  check_totals(572);
+  check_totals(582);
 # endif
 #endif

=== modified file 'testsuite/swfdec/PASSING'
--- a/testsuite/swfdec/PASSING  2009-10-13 10:23:35 +0000
+++ b/testsuite/swfdec/PASSING  2009-10-14 14:52:58 +0000
@@ -232,6 +232,7 @@
 constructor-madness-8.swf:5357273baf6b66f6af0223cb1d13b144
 constructor-prototype.swf:22505f0f8dd8440972a298110d697e3b
 constructor-relay-5.swf:2d1a814c37f55485d66624cb97c58e03
+construct-properties-5.swf:2683d3e400600e0288470ca5b6fbe94c
 context-menu-5.swf:867624e2cb2c3d47dc07270d756152db
 context-menu-6.swf:9124c06f1cc4725684717eb3641837bd
 context-menu-7.swf:fc22bea201998188714399c2de1ac1f5


reply via email to

[Prev in Thread] Current Thread [Next in Thread]