gnash-commit
[Top][All Lists]
Advanced

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

[Gnash-commit] /srv/bzr/gnash/trunk r11567: Make more as_object function


From: Benjamin Wolsey
Subject: [Gnash-commit] /srv/bzr/gnash/trunk r11567: Make more as_object functions non-virtual. Generally clean up and reduce the
Date: Fri, 16 Oct 2009 16:46:54 +0200
User-agent: Bazaar (1.16.1)

------------------------------------------------------------
revno: 11567 [merge]
committer: Benjamin Wolsey <address@hidden>
branch nick: trunk
timestamp: Fri 2009-10-16 16:46:54 +0200
message:
  Make more as_object functions non-virtual. Generally clean up and reduce the
  as_object class interface, which is still much too large.
  
  Make arrays almost entirely independent of type. Properties are now genuine
  properties.
modified:
  libcore/MovieClip.cpp
  libcore/MovieClip.h
  libcore/PropertyList.h
  libcore/as_object.cpp
  libcore/as_object.h
  libcore/as_value.cpp
  libcore/asobj/Array_as.cpp
  libcore/asobj/Array_as.h
  libcore/asobj/Color_as.cpp
  libcore/asobj/flash/display/MovieClip_as.cpp
  libcore/asobj/flash/net/SharedObject_as.cpp
  libcore/vm/ASHandlers.cpp
  testsuite/actionscript.all/array.as
=== modified file 'libcore/MovieClip.cpp'
--- a/libcore/MovieClip.cpp     2009-10-14 08:47:08 +0000
+++ b/libcore/MovieClip.cpp     2009-10-16 06:56:48 +0000
@@ -812,15 +812,15 @@
     }
     if ( tmp.is_sprite() )
     {
-        return tmp.to_sprite(true);
+        return tmp.toDisplayObject(true);
     }
 
     return tmp.to_object(*getGlobal(*this));
 }
 
 bool
-MovieClip::set_member(string_table::key name,
-        const as_value& val, string_table::key nsname, bool ifFound)
+MovieClip::setTextFieldVariables(string_table::key name, const as_value& val,
+        string_table::key /*nsname*/)
 {
 
     bool found = false;
@@ -853,9 +853,6 @@
     }
 #endif
 
-    // If that didn't work call the default set_member
-    if (as_object::set_member(name, val, nsname, ifFound)) found=true;
-
     return found;
 }
 
@@ -2181,7 +2178,7 @@
     std::string postdata;
     
     // Encode our vars for sending.
-    if (sendVarsMethod != METHOD_NONE) getURLEncodedVars(postdata);
+    if (sendVarsMethod != METHOD_NONE) getURLEncodedVars(*this, postdata);
 
     try 
     {

=== modified file 'libcore/MovieClip.h'
--- a/libcore/MovieClip.h       2009-10-14 06:55:13 +0000
+++ b/libcore/MovieClip.h       2009-10-16 05:29:23 +0000
@@ -526,6 +526,12 @@
     /// simplify things if this function could be dropped.
     bool getTextFieldVariables(string_table::key name, as_value& val);
 
+    // Set TextField variables
+    //
+    /// TODO: this is also unlikely to be the best way to do it.
+    bool setTextFieldVariables(string_table::key name, const as_value& val,
+        string_table::key nsname = 0);
+
     /// Search for a named object on the DisplayList
     //
     /// These are properties, but not attached as genuine members to the
@@ -537,10 +543,6 @@
     /// @return         The object if found, otherwise 0.
     DisplayObject* getDisplayListObject(string_table::key name);
 
-    // See dox in as_object.h
-    virtual bool set_member(string_table::key name, const as_value& val,
-        string_table::key nsname = 0, bool ifFound=false);
-
     /// Overridden to look in DisplayList for a match
     as_object* get_path_element(string_table::key key);
 

=== modified file 'libcore/PropertyList.h'
--- a/libcore/PropertyList.h    2009-10-14 08:47:08 +0000
+++ b/libcore/PropertyList.h    2009-10-16 14:17:00 +0000
@@ -111,20 +111,25 @@
        /// The method will invoke the given visitor method
        /// passing it two arguments: name of the property and
        /// value of it.
-       ///
-       /// @param visitor
-       ///     The visitor function. Must take a string_table::key 
-       ///     reference as first argument and a const as_value reference
-       ///     as second argument. Scan by enumeration order.
+       //
+    /// @tparam V   The type of the visitor.
+    /// @tparam U   An object that may check property values. The object's
+    ///             operator() should return false if the property is not
+    ///             acceptable.
+    //
+       /// @param visitor  The visitor function. It must have the function:
+    ///                     bool accept(string_table::key, const as_value&);
+       ///                     Scan is by enumeration order and stops if 
accept()
+    ///                 returns false.
        ///
        /// @param this_ptr
        ///     The object reference used to extract values from properties.
        ///
-       template <class V>
-       void visitValues(V& visitor, const as_object& this_ptr) const
+       template <class U, class V>
+       void visitValues(V& visitor, const as_object& this_ptr, U cmp = U()) 
const
        {
         typedef container::nth_index<1>::type ContainerByOrder;
-        
+
         // The template keyword is not required by the Standard here, but the
         // OpenBSD compiler needs it. Use of the template keyword where it is
         // not necessary is not an error.
@@ -132,56 +137,11 @@
                 it = _props.template get<1>().rbegin(),
                 ie = _props.template get<1>().rend(); it != ie; ++it)
                {
-                       as_value val = it->getValue(this_ptr);
-                       visitor.accept(it->mName, val);
-               }
-       }
-
-       /// Visit non hidden properties 
-       //
-       /// The method will invoke the given visitor method
-       /// passing it two arguments: name of the property and
-       /// value of it. Scan by enumeration order.
-       ///
-       /// @param visitor
-       ///     The visitor function. Must take a string_table::key 
-       ///     reference as first argument and a const as_value reference
-       ///     as second argument.
-       ///
-       /// @param this_ptr
-       ///     The object reference used to extract values from properties.
-       ///
-       template <class V>
-       void visitNonHiddenValues(V& visitor, const as_object& this_ptr) const
-       {
-        typedef container::nth_index<1>::type ContainerByOrder;
-        
-        // The template keyword is not required by the Standard here, but the
-        // OpenBSD compiler needs it. Use of the template keyword where it is
-        // not necessary is not an error.
-        for (ContainerByOrder::const_reverse_iterator it =
-                _props.template get<1>().rbegin(),
-                ie = _props.template get<1>().rend(); it != ie; ++it)
-               {
-               if (it->getFlags().get_dont_enum()) continue;
-                       as_value val = it->getValue(this_ptr);
-                       visitor.accept(it->mName, val);
-               }
-       }
-
-    /// Is any non-hidden property in this list ?
-    bool hasNonHiddenProperties() const
-    {
-        typedef container::nth_index<1>::type ContainerByOrder;
-        for (ContainerByOrder::const_reverse_iterator it = 
-                _props.get<1>().rbegin(), ie=_props.get<1>().rend();
-                it != ie; ++it)
-               {
-               if (! it->getFlags().get_dont_enum()) return true;
-        }
-        return false;
-    }
-
+            if (!cmp(*it)) continue;
+                       as_value val = it->getValue(this_ptr);
+                       if (!visitor.accept(it->mName, val)) return;
+               }
+       }
 
        /// Get the as_value value of a named property
        //

=== modified file 'libcore/as_object.cpp'
--- a/libcore/as_object.cpp     2009-10-15 05:59:43 +0000
+++ b/libcore/as_object.cpp     2009-10-16 14:17:00 +0000
@@ -50,43 +50,18 @@
 
 
 namespace gnash {
-
-namespace {
-
-    class IsVisible
-    {
-    public:
-        IsVisible(as_object* obj) : _version(getSWFVersion(*obj)) {}
-        bool operator()(const Property* const prop) const {
-            return prop->visible(_version);
-        }
-    private:
-        const int _version;
-
-    };
-
-    class Exists
-    {
-    public:
-        Exists(as_object*) {}
-        bool operator()(const Property* const) const {
-            return true;
-        }
-    };
-}
-
 template<typename T>
 class
 as_object::PrototypeRecursor
 {
 public:
-    PrototypeRecursor(as_object* top, const ObjectURI& property)
+    PrototypeRecursor(as_object* top, const ObjectURI& property, T cmp = T())
         :
         _object(top),
         _name(getName(property)),
         _ns(getNamespace(property)),
         _iterations(0),
-        _condition(top)
+        _condition(cmp)
     {
         _visited.insert(top);
     }
@@ -112,7 +87,7 @@
         // TODO: there is recursion prevention anyway; is this extra 
         // check for circularity really necessary?
         if (!_visited.insert(_object).second) return 0;
-        return _object && !_object->_displayObject;
+        return _object && !_object->displayObject();
     }
 
     /// Return the wanted property if it exists and satisfies the predicate.
@@ -123,7 +98,7 @@
         assert(_object);
         Property* prop = _object->_members.getProperty(_name, _ns);
         
-        if (prop && _condition(prop)) {
+        if (prop && _condition(*prop)) {
             if (owner) *owner = _object;
             return prop;
         }
@@ -178,17 +153,6 @@
                return false;
        }
 
-       // Setting members on 'super' is a no-op
-       virtual void set_member(string_table::key /*key*/, const as_value& 
/*val*/,
-               string_table::key /*nsname*/ = 0)
-       {
-               log_debug("set_member.");
-               // can't assign to super
-               IF_VERBOSE_ASCODING_ERRORS(
-               log_aserror("Can't set members on the 'super' object");
-               );
-       }
-
        /// Dispatch.
        virtual as_value operator()(const fn_call& fn)
        {
@@ -291,11 +255,12 @@
        /// Use the set_member function to properly set *inherited* properties
        /// of the given target object
        ///
-       void accept(string_table::key name, const as_value& val)
+       bool accept(string_table::key name, const as_value& val)
        {
-               if (name == NSV::PROP_uuPROTOuu) return;
+               if (name == NSV::PROP_uuPROTOuu) return true;
                //log_debug(_("Setting member '%s' to value '%s'"), name, val);
                _tgt.set_member(name, val);
+        return true;
        }
 };
 
@@ -343,15 +308,6 @@
        init_member(NSV::PROP_uuPROTOuu, as_value(proto));
 }
 
-as_object::as_object(const as_object& other)
-       :
-    _displayObject(other._displayObject),
-    _relay(0),
-       _vm(VM::get()),
-       _members(other._members)
-{
-}
-
 std::pair<bool,bool>
 as_object::delProperty(string_table::key name, string_table::key nsname)
 {
@@ -430,11 +386,14 @@
 {
        assert(val);
 
-    PrototypeRecursor<IsVisible> pr(this, ObjectURI(name, nsname));
+    const int version = getSWFVersion(*this);
+
+    PrototypeRecursor<IsVisible> pr(this, ObjectURI(name, nsname),
+        IsVisible(version));
        
        Property* prop = pr.getProperty();
     if (!prop) {
-        if (_displayObject) {
+        if (displayObject()) {
             if (getDisplayObjectProperty(*this, name, *val)) return true;
         }
         while (pr()) {
@@ -576,7 +535,10 @@
        as_object **owner)
 {
 
-    PrototypeRecursor<IsVisible> pr(this, ObjectURI(key, nsname));
+    const int version = getSWFVersion(*this);
+
+    PrototypeRecursor<IsVisible> pr(this, ObjectURI(key, nsname),
+        IsVisible(version));
 
     do {
         Property* prop = pr.getProperty(owner);
@@ -591,8 +553,6 @@
 as_object::findUpdatableProperty(const ObjectURI& uri)
 {
 
-       const int swfVersion = getSWFVersion(*this);
-
     PrototypeRecursor<Exists> pr(this, uri);
 
        Property* prop = pr.getProperty();
@@ -600,6 +560,8 @@
        // We won't scan the inheritance chain if we find a member,
        // even if invisible.
        if (prop) return prop; 
+       
+    const int swfVersion = getSWFVersion(*this);
 
     while (pr()) {
         if ((prop = pr.getProperty())) {
@@ -613,12 +575,13 @@
 }
 
 void
-as_object::set_prototype(const as_value& proto, int flags)
+as_object::set_prototype(const as_value& proto)
 {
        // TODO: check what happens if __proto__ is set as a user-defined 
     // getter/setter
        // TODO: check triggers !!
-       _members.setValue(NSV::PROP_uuPROTOuu, proto, *this, 0, flags);
+       _members.setValue(NSV::PROP_uuPROTOuu, proto, *this, 0,
+            as_object::DefaultFlags);
 }
 
 void
@@ -705,6 +668,8 @@
 
 /// Order of property lookup:
 //
+/// 0. MovieClip textfield variables. TODO: this is a hack and should be
+///    eradicated.
 /// 1. Own properties even if invisible or not getter-setters. 
 /// 2. If DisplayObject, magic properties
 /// 3. Visible own getter-setter properties of all __proto__ objects
@@ -714,6 +679,13 @@
        string_table::key nsname, bool ifFound)
 {
 
+    bool tfVarFound = false;
+    if (displayObject()) {
+        MovieClip* mc = dynamic_cast<MovieClip*>(this);
+        if (mc) tfVarFound = mc->setTextFieldVariables(key, val, nsname);
+        // We still need to set the member.
+    }
+
     const ObjectURI uri(key, nsname);
     
     PrototypeRecursor<Exists> pr(this, uri);
@@ -724,7 +696,7 @@
        // even if invisible.
        if (!prop) { 
 
-        if (_displayObject) {
+        if (displayObject()) {
             if (setDisplayObjectProperty(*this, key, val)) return true;
             // TODO: should we execute triggers?
         }
@@ -762,6 +734,10 @@
                return true;
        }
 
+    // Return true if we found a textfield variable, even if it was not
+    // an own property.
+    if (tfVarFound) return true;
+
        // Else, add new property...
        if (ifFound) return false;
 
@@ -1004,7 +980,8 @@
 
        // See actionscript.all/Inheritance.as for a way to trigger this
        IF_VERBOSE_ASCODING_ERRORS(
-       if ( obj ) log_aserror(_("Circular inheritance chain detected during 
isPrototypeOf call"));
+        if (obj) log_aserror(_("Circular inheritance chain detected "
+                "during isPrototypeOf call"));
        );
 
        return false;
@@ -1072,7 +1049,7 @@
        PropsCopier copier(*this);
 
        // TODO: check if non-visible properties should be also copied !
-       o.visitPropertyValues(copier);
+       o.visitProperties<Exists>(copier);
 }
 
 void
@@ -1273,28 +1250,25 @@
 }
 
 void
-as_object::getURLEncodedVars(std::string& data)
+getURLEncodedVars(as_object& o, std::string& data)
 {
-    SortedPropertyList props;
-    enumerateProperties(props);
+    PropertyList::SortedPropertyList props;
+    o.enumerateProperties(props);
 
     std::string del;
     data.clear();
     
-    for (SortedPropertyList::const_iterator i=props.begin(),
-            e=props.end(); i!=e; ++i)
-    {
-      std::string name = i->first;
-      std::string value = i->second;
-      if ( ! name.empty() && name[0] == '$' ) continue; // see bug #22006
-      URL::encode(value);
-      
-      data += del + name + "=" + value;
-      
-      del = "&";
-        
+    for (PropertyList::SortedPropertyList::const_iterator i=props.begin(),
+            e=props.end(); i!=e; ++i) {
+        std::string name = i->first;
+        std::string value = i->second;
+        if (!name.empty() && name[0] == '$') continue; // see bug #22006
+        URL::encode(value);
+
+        data += del + name + "=" + value;
+
+        del = "&";
     }
-    
 }
 
 bool
@@ -1392,24 +1366,11 @@
        }
 }
 
-void
-as_object::visitPropertyValues(AbstractPropertyVisitor& visitor) const
-{
-    _members.visitValues(visitor, *this);
-}
-
-void
-as_object::visitNonHiddenPropertyValues(AbstractPropertyVisitor& visitor) const
-{
-    _members.visitNonHiddenValues(visitor, *this);
-}
-
-bool
-isNativeType(as_object* obj, DisplayObject*& relay)
-{
-    if (!obj || !obj->displayObject()) return false;
-    relay = static_cast<DisplayObject*>(obj);
-    return true;
+DisplayObject*
+getDisplayObject(as_object* obj)
+{
+    if (!obj || !obj->displayObject()) return 0;
+    return &static_cast<DisplayObject&>(*obj);
 }
 
 /// Get the VM from an as_object

=== modified file 'libcore/as_object.h'
--- a/libcore/as_object.h       2009-10-14 08:47:08 +0000
+++ b/libcore/as_object.h       2009-10-16 14:17:00 +0000
@@ -62,7 +62,9 @@
 /// An abstract property visitor
 class AbstractPropertyVisitor {
 public:
-    virtual void accept(string_table::key key, const as_value& val)=0;
+
+    /// This function should return false if no further visits are needed.
+    virtual bool accept(string_table::key key, const as_value& val) = 0;
     virtual ~AbstractPropertyVisitor() {}
 };
 
@@ -160,12 +162,7 @@
 /// Base-class for ActionScript script-defined objects.
 /// This would likely be ActionScript's 'Object' class.
 ///
-class as_object :
-#ifdef GNASH_USE_GC
-    public GcResource
-#else
-    public ref_counted
-#endif
+class as_object : public GcResource
 {
     friend class asClass;
     friend class Machine;
@@ -195,23 +192,12 @@
     /// Construct an ActionScript object based on the given prototype.
     explicit as_object(boost::intrusive_ptr<as_object> proto);
     
-    /// Copy an as_object.
-    //
-    /// This is used by Array_as, but almost certainly shouldn't be. Please
-    /// don't use this function.
-    explicit as_object(const as_object& other);
-
     /// The most common flags for built-in properties.
     //
     /// Most API properties, including classes and objects, have these flags.
     static const int DefaultFlags = PropFlags::dontDelete |
                                     PropFlags::dontEnum;
 
-    /// Is any non-hidden property in this object ?
-    bool hasNonHiddenProperties() const {
-        return _members.hasNonHiddenProperties();
-    }
-
     /// Find a property scanning the inheritance chain
     ///
     /// @param name
@@ -223,7 +209,7 @@
     /// @param owner
     /// If not null, this is set to the object which contained the property.
     ///
-    /// @returns a Propery if found, NULL if not found
+    /// @returns a Property if found, NULL if not found
     ///          or not visible in current VM version
     ///
     Property* findProperty(string_table::key name, string_table::key nsname,
@@ -732,7 +718,7 @@
     ///    - (true, false) : property protected from deletion
     ///    - (true, true) : property successfully deleted
     ///
-    virtual std::pair<bool,bool> delProperty(string_table::key name,
+    std::pair<bool,bool> delProperty(string_table::key name,
             string_table::key nsname = 0);
 
     /// Get this object's own named property, if existing.
@@ -770,7 +756,7 @@
     /// @return
     ///    true if the object has the property, false otherwise.
     ///
-    virtual bool hasOwnProperty(string_table::key name,
+    bool hasOwnProperty(string_table::key name,
             string_table::key nsname = 0);
 
     /// Get a property from this object (or a prototype) by ordering index.
@@ -914,19 +900,6 @@
     ///
     void enumerateProperties(SortedPropertyList& to) const;
 
-    /// Get url-encoded variables
-    //
-    /// This method will be used for loadVariables and loadMovie
-    /// calls, to encode variables for sending over a network.
-    /// Variables starting with a dollar sign will be skipped,
-    /// as non-enumerable ones.
-    ///
-    /// @param data
-    ///    Output parameter, will be set to the url-encoded
-    ///     variables string, w/out any leading delimiter.
-    ///
-    void getURLEncodedVars(std::string& data);
-
     /// Visit the properties of this object by key/as_value pairs
     //
     /// The method will invoke the given visitor method
@@ -939,22 +912,10 @@
     ///    reference as first argument and a const as_value reference
     ///    as second argument.
     ///
-    virtual void visitPropertyValues(AbstractPropertyVisitor& visitor) const;
-
-    /// Visit non-hidden properties of this object by key/as_value pairs
-    //
-    /// The method will invoke the given visitor method
-    /// passing it two arguments: key of the property and
-    /// value of it.
-    ///
-    /// @param visitor
-    ///    The visitor function. Will be invoked for each property
-    ///    of this object with a string_table::key
-    ///    reference as first argument and a const as_value reference
-    ///    as second argument.
-    ///
-    virtual void visitNonHiddenPropertyValues(AbstractPropertyVisitor& visitor)
-        const;
+    template<typename T>
+    void visitProperties(AbstractPropertyVisitor& visitor) const {
+        _members.visitValues<T>(visitor, *this);
+    }
 
     /// \brief
     /// Add a getter/setter property, if no member already has
@@ -982,17 +943,13 @@
     /// of the class this object is an instance of.
     ///
     /// NOTE: can return NULL (and it is expected to do for Object.prototype)
-    ///
     as_object* get_prototype() const;
 
     /// Set this object's '__proto__' member
     //
-    /// There is no point to make this function
-    /// protected or private, as a call to the
-    /// public: set_member("__proto__", anyting)
-    /// will do just the same
-    ///
-    void set_prototype(const as_value& proto, int flags = DefaultFlags);
+    /// This does more or less what set_member("__proto__") does, but without
+    /// the lookup process.
+    void set_prototype(const as_value& proto);
 
     /// Set the as_object's Relay object.
     //
@@ -1099,10 +1056,18 @@
 
     /// Mark properties and triggers list as reachable (for the GC)
     void markAsObjectReachable() const;
+
 #endif // GNASH_USE_GC
 
 private:
 
+    /// Do not allow copies.
+    as_object(const as_object& other);
+
+    /// Don't allow implicit assignment.
+    as_object& operator=(const as_object&);
+
+    /// A utility class for processing this as_object's inheritance chain
     template<typename T> class PrototypeRecursor;
 
     /// DisplayObjects have properties not in the AS inheritance chain
@@ -1120,12 +1085,9 @@
     /// The VM containing this object.
     VM& _vm;   
 
-    /// Properties of this objects 
+    /// Properties of this as_object
     PropertyList _members;
 
-    /// Don't allow implicit copy.
-    as_object& operator=(const as_object&);
-
     /// \brief
     /// Find an existing property for update, only scanning the
     /// inheritance chain for getter/setters or statics.
@@ -1150,6 +1112,50 @@
     TriggerContainer _trigs;
 };
 
+/// Function objects for visiting properties.
+class IsVisible
+{
+public:
+    IsVisible(int version) : _version(version) {}
+    bool operator()(const Property& prop) const {
+        return prop.visible(_version);
+    }
+private:
+    const int _version;
+};
+
+class Exists
+{
+public:
+    Exists() {}
+    bool operator()(const Property&) const {
+        return true;
+    }
+};
+
+class IsEnumerable
+{
+public:
+    IsEnumerable() {}
+    bool operator()(const Property& p) const {
+        return !p.getFlags().get_dont_enum();
+    }
+};
+
+/// Get url-encoded variables
+//
+/// This method will be used for loadVariables and loadMovie
+/// calls, to encode variables for sending over a network.
+/// Variables starting with a dollar sign will be skipped,
+/// as non-enumerable ones.
+//
+/// @param o        The object whose properties should be encoded.
+/// @param data     Output parameter, will be set to the url-encoded
+///                 variables string without any leading delimiter.
+void getURLEncodedVars(as_object& o, std::string& data);
+
+
+/// Comparator for ObjectURI so it can serve as a key in stdlib containers.
 inline bool
 operator<(const ObjectURI& a, const ObjectURI& b)
 {
@@ -1219,11 +1225,12 @@
     return relay;
 }
 
-/// An overload of isNativeType for DisplayObjects
+
+/// Return the DisplayObject part of an as_object
 //
-/// This uses the DisplayObject flag.
-bool
-isNativeType(as_object* obj, DisplayObject*& relay);
+/// @param obj      The object whose DisplayObject part should be returned
+/// @return         The DisplayObject if the object is one, otherwise 0.
+DisplayObject* getDisplayObject(as_object* obj);
 
 /// Ensure that the object is of a particular native type.
 //

=== modified file 'libcore/as_value.cpp'
--- a/libcore/as_value.cpp      2009-10-14 14:26:23 +0000
+++ b/libcore/as_value.cpp      2009-10-16 14:17:00 +0000
@@ -166,7 +166,7 @@
            _st(vm.getStringTable())
        {}
     
-    void accept(string_table::key key, const as_value& val) 
+    bool accept(string_table::key key, const as_value& val) 
     {
 
         // Test conducted with AMFPHP:
@@ -182,7 +182,7 @@
             log_debug(" skip serialization of specially-named property %s",
                     _st.value(key));
 #endif
-            return;
+            return true;
         }
 
         amf::AMF amf;
@@ -224,6 +224,7 @@
         if (el) {
             _obj.addProperty(el);
         }
+        return true;
     }
 
 private:
@@ -255,15 +256,15 @@
     
     bool success() const { return !_error; }
 
-    void accept(string_table::key key, const as_value& val) 
+    bool accept(string_table::key key, const as_value& val) 
     {
-        if ( _error ) return;
+        if ( _error ) return true;
 
         // Tested with SharedObject and AMFPHP
         if ( val.is_function() )
         {
             log_debug("AMF0: skip serialization of FUNCTION property");
-            return;
+            return true;
         }
 
         // Test conducted with AMFPHP:
@@ -279,7 +280,7 @@
             log_debug(" skip serialization of specially-named property %s",
                     _st.value(key));
 #endif
-            return;
+            return true;
         }
 
         // write property name
@@ -290,11 +291,11 @@
         boost::uint16_t namelen = name.size();
         _buf.appendNetworkShort(namelen);
         _buf.append(name.c_str(), namelen);
-        if ( ! val.writeAMF0(_buf, _offsetTable, _vm, _allowStrict) )
-        {
+        if (!val.writeAMF0(_buf, _offsetTable, _vm, _allowStrict)) {
             log_error("Problems serializing an object's member");
-            _error=true;
+            _error = true;
         }
+        return true;
     }
 private:
 
@@ -764,7 +765,7 @@
       {
          el->makeObject();
          PropsSerializer props(*el, vm);
-         ptr->visitPropertyValues(props);
+         ptr->visitProperties<Exists>(props);
          break;
       }
       case AS_FUNCTION:
@@ -2279,27 +2280,34 @@
 
                 Array_as* ary = dynamic_cast<Array_as*>(obj);
                 if (ary) {
-                    const size_t len = ary->size();
-                    if (allowStrict && ary->isStrict()) {
+                    string_table& st = vm.getStringTable();
+                    const size_t len = arrayLength(*ary);
+                    if (allowStrict) {
+                        IsStrictArray s(st);
+                        // Check if any non-hidden properties are non-numeric.
+                        ary->visitProperties<IsEnumerable>(s);
+                        if (s.strict()) {
+
 #ifdef GNASH_DEBUG_AMF_SERIALIZE
-                        log_debug(_("writeAMF0: serializing array of %d "
-                                    "elements as STRICT_ARRAY (index %d)"),
-                                    len, idx);
+                            log_debug(_("writeAMF0: serializing array of %d "
+                                        "elements as STRICT_ARRAY (index %d)"),
+                                        len, idx);
 #endif
-                        buf.appendByte(amf::Element::STRICT_ARRAY_AMF0);
-                        buf.appendNetworkLong(len);
+                            buf.appendByte(amf::Element::STRICT_ARRAY_AMF0);
+                            buf.appendNetworkLong(len);
 
-                        as_value elem;
-                        for (size_t i = 0; i < len; ++i) {
-                            elem = ary->at(i);
-                            if (!elem.writeAMF0(buf, offsetTable, vm,
-                                        allowStrict)) {
-                                log_error("Problems serializing strict array "
-                                        "member %d=%s", i, elem);
-                                return false;
+                            as_value elem;
+                            for (size_t i = 0; i < len; ++i) {
+                                elem = ary->getMember(arrayKey(st, i));
+                                if (!elem.writeAMF0(buf, offsetTable, vm,
+                                            allowStrict)) {
+                                    log_error("Problems serializing strict 
array "
+                                            "member %d=%s", i, elem);
+                                    return false;
+                                }
                             }
+                            return true;
                         }
-                        return true;
                     }
 
                     // A normal array.
@@ -2307,7 +2315,7 @@
                     log_debug(_("writeAMF0: serializing array of %d "
                                 "elements as ECMA_ARRAY (index %d) "
                                 "[allowStrict:%d, isStrict:%d]"),
-                                len, idx, allowStrict, ary->isStrict());
+                                len, idx, allowStrict, isStrict);
 #endif
                     buf.appendByte(amf::Element::ECMA_ARRAY_AMF0);
                     buf.appendNetworkLong(len);
@@ -2322,7 +2330,7 @@
                 }
 
                 PropsBufSerializer props(buf, vm, offsetTable, allowStrict);
-                obj->visitNonHiddenPropertyValues(props);
+                obj->visitProperties<IsEnumerable>(props);
                 if (!props.success()) {
                     log_error("Could not serialize object");
                     return false;

=== modified file 'libcore/asobj/Array_as.cpp'
--- a/libcore/asobj/Array_as.cpp        2009-10-15 13:25:00 +0000
+++ b/libcore/asobj/Array_as.cpp        2009-10-16 14:17:00 +0000
@@ -91,6 +91,7 @@
     as_value array_splice(const fn_call& fn);
 
     string_table::key getKey(const fn_call& fn, size_t i);
+       int isIndex(const std::string& name);
 
     /// Implementation of foreachArray that takes a start and end range.
     template<typename T> void foreachArray(as_object& array, int start,
@@ -108,6 +109,10 @@
 
     void pushIndices(as_object& o, const std::vector<indexed_as_value>& index);
 
+    /// Set the length property of an object only if it is a genuine array.
+    void setArrayLength(as_object& o, const int size);
+
+    void resizeArray(as_object& o, const int size);
 }
 
 /// Function objects for foreachArray()
@@ -647,17 +652,17 @@
 class as_value_multiprop
 {
 public:
-    typedef std::deque<as_cmp_fn> Comps;
+    typedef std::vector<as_cmp_fn> Comps;
     Comps& _cmps;
 
-    typedef std::deque<string_table::key> Props;
+    typedef std::vector<string_table::key> Props;
     Props& _prps;
     
     const as_object& _obj;
 
     // Note: all as_cmp_fns in *cmps must implement strict weak ordering
-    as_value_multiprop(std::deque<string_table::key>& prps, 
-        std::deque<as_cmp_fn>& cmps, const as_object& o)
+    as_value_multiprop(std::vector<string_table::key>& prps, 
+        std::vector<as_cmp_fn>& cmps, const as_object& o)
         :
         _cmps(cmps),
         _prps(prps),
@@ -669,7 +674,7 @@
     {
         if ( _cmps.empty() ) return false;
 
-        std::deque<as_cmp_fn>::iterator cmp = _cmps.begin();
+        std::vector<as_cmp_fn>::iterator cmp = _cmps.begin();
 
         // why do we cast ao/bo to objects here ?
         boost::intrusive_ptr<as_object> ao = a.to_object(*getGlobal(_obj));
@@ -696,8 +701,8 @@
 class as_value_multiprop_eq : public as_value_multiprop
 {
 public:
-    as_value_multiprop_eq(std::deque<string_table::key>& prps, 
-        std::deque<as_cmp_fn>& cmps, const as_object& o)
+    as_value_multiprop_eq(std::vector<string_table::key>& prps, 
+        std::vector<as_cmp_fn>& cmps, const as_object& o)
         :
         as_value_multiprop(prps, cmps, o),
         _obj(o)
@@ -741,39 +746,77 @@
     return flgs;
 }
 
-// Convenience function to process and extract flags from an as_value array
-// of flags (as passed to sortOn when sorting on multiple properties)
-std::deque<boost::uint8_t> 
-get_multi_flags(Array_as::const_iterator itBegin, 
-    Array_as::const_iterator itEnd, bool* uniq, bool* index)
+
+class GetKeys
 {
-    Array_as::const_iterator it = itBegin;
-    std::deque<boost::uint8_t> flgs;
-
-    // extract SORT_UNIQUE and SORT_RETURN_INDEX from first flag
-    if (it != itEnd)
-    {
-        boost::uint8_t flag = static_cast<boost::uint8_t>((*it++).to_number());
-        flag = flag_preprocess(flag, uniq, index);
-        flgs.push_back(flag);
+public:
+    GetKeys(std::vector<string_table::key>& v, string_table& st, int version)
+        :
+        _v(v),
+        _st(st),
+        _version(version)
+    {}
+    void operator()(const as_value& val) {
+        _v.push_back(_st.find(val.to_string_versioned(_version)));
     }
+private:
+    std::vector<string_table::key>& _v;
+    string_table& _st;
+    const int _version;
+};
 
-    while (it != itEnd)
-    {
-        boost::uint8_t flag = static_cast<boost::uint8_t>((*it++).to_number());
+/// Functor to extract flags from an array-like object.
+//
+/// I don't know how accurate this code is. It was copied from the previous
+/// implementation but without using Array_as.
+class GetMultiFlags
+{
+public:
+    GetMultiFlags(std::vector<boost::uint8_t>& v)
+        :
+        _v(v),
+        _i(0),
+        _uniq(false),
+        _index(false)
+    {}
+    void operator()(const as_value& val) {
+        // extract SORT_UNIQUE and SORT_RETURN_INDEX from first flag
+        if (!_i) {
+            boost::uint8_t flag = static_cast<boost::uint8_t>(val.to_number());
+            flag = flag_preprocess(flag, &_uniq, &_index);
+            _v.push_back(flag);
+            ++_i;
+            return;
+        }
+        boost::uint8_t flag = static_cast<boost::uint8_t>(val.to_number());
         flag &= ~(SORT_RETURN_INDEX);
         flag &= ~(SORT_UNIQUE);
-        flgs.push_back(flag);
+        _v.push_back(flag);
+        ++_i;
     }
-    return flgs;
+    bool unique() const { return _uniq; }
+    bool index() const { return _index; }
+
+private:
+    std::vector<boost::uint8_t>& _v;
+    size_t _i;
+    bool _uniq;
+    bool _index;
+};
+
 }
 
+bool
+IsStrictArray::accept(string_table::key key, const as_value& /*val*/)
+{
+    if (isIndex(_st.value(key)) >= 0) return true;
+    _strict = false;
+    return false;
 }
 
 Array_as::Array_as()
     :
-    as_object(getArrayInterface()), // pass Array inheritance
-    elements(0)
+    as_object(getArrayInterface())
 {
     init_member(NSV::PROP_LENGTH, 0.0);
 }
@@ -783,147 +826,36 @@
 {
 }
 
-Array_as::const_iterator
-Array_as::begin()
-{
-    return elements.begin();
-}
-
-Array_as::const_iterator
-Array_as::end()
-{
-    return elements.end();
-}
-
-int
-Array_as::index_requested(string_table::key name)
-{
-    const std::string& nameString = getStringTable(*this).value(name);
-
-    // Anything not in [0-9] makes this an invalid index
-    if ( nameString.find_first_not_of("0123456789") != std::string::npos )
-    {
-        return -1;
-    }
-
-    // TODO: do we need all this noise ? atol(3) should do !
-
-    as_value temp;
-    temp.set_string(nameString);
-    double value = temp.to_number();
-
-    // if we were sent a string that can't convert like "asdf", it returns as 
NaN. -1 means invalid index
-    if (!isFinite(value)) return -1;
-
-    return int(value);
-}
-
 unsigned int
 Array_as::size() const
 {
-    return elements.size();
+    return arrayLength(const_cast<Array_as&>(*this));
 }
 
 as_value
 Array_as::at(unsigned int index) const
 {
-    if ( index > elements.size()-1 ) return as_value();
-    else return elements[index];
-}
-
-/* virtual public, overriding as_object::get_member */
-bool
-Array_as::get_member(string_table::key name, as_value *val,
-    string_table::key nsname)
-{
-    // an index has been requested
-    int index = index_requested(name);
-
-    if ( index >= 0 ) // a valid index was requested
-    {
-        size_t i = index;
-        const_iterator it = elements.find(i);
-        if ( it != elements.end() && it.index() == i )
-        {
-            *val = *it;
-            return true;
-        }
-    }
-
-    return as_object::get_member(name, val, nsname);
-}
-
-bool
-Array_as::hasOwnProperty(string_table::key name, string_table::key nsname)
-{
-    // an index has been requested
-    int index = index_requested(name);
-
-    if ( index >= 0 ) // a valid index was requested
-    {
-        size_t i = index;
-        const_iterator it = elements.find(i);
-        if ( it != elements.end() && it.index() == i )
-        {
-            return true;
-        }
-    }
-
-    return as_object::hasOwnProperty(name, nsname);
-}
-
-std::pair<bool,bool> 
-Array_as::delProperty(string_table::key name, string_table::key nsname)
-{
-    // an index has been requested
-    int index = index_requested(name);
-
-    if ( index >= 0 ) // a valid index was requested
-    {
-        size_t i = index;
-        const_iterator it = elements.find(i);
-        if ( it != elements.end() && it.index() == i )
-        {
-            elements.erase_element(i);
-            return std::make_pair(true, true);
-        }
-    }
-
-    return as_object::delProperty(name, nsname);
-}
-
-void
-Array_as::resize(unsigned int newsize)
-{
-    elements.resize(newsize);
+    if (index > size() - 1) return as_value();
+    return 
const_cast<Array_as*>(this)->getMember(arrayKey(getStringTable(*this), index));
 }
 
 /* virtual public, overriding as_object::set_member */
 bool
-Array_as::set_member(string_table::key name,
-        const as_value& val, string_table::key nsname, bool ifFound)
+Array_as::set_member(string_table::key name, const as_value& val,
+        string_table::key nsname, bool ifFound)
 {
-    int index = index_requested(name);
-
-    // if we were sent a valid array index and not a normal member
-    if (index >= 0)
-    {
-        if (size_t(index) >= elements.size())
-        {
-            // if we're setting index (x), the vector
-            // must be size (x+1)
-            elements.resize(index+1);
-        }
-
-        as_object::set_member(NSV::PROP_LENGTH, elements.size());
-        // set the appropriate index and return
-        elements[index] = val;
-        return true;
-    }
 
     if (name == NSV::PROP_LENGTH) {
-        elements.resize(std::max(val.to_int(), 0));
-        // Don't return before as_object has set the value!
+        resizeArray(*this, val.to_int());
+    }
+    else {
+        int index = isIndex(getStringTable(*this).value(name));
+        // if we were sent a valid array index and not a normal member
+        if (index >= 0) {
+            if (static_cast<size_t>(index) >= arrayLength(*this)) {
+                setArrayLength(*this, index + 1);
+            }
+        }
     }
 
     return as_object::set_member(name,val, nsname, ifFound);
@@ -982,74 +914,6 @@
     where.init_member(getName(uri), cl, flags, getNamespace(uri));
 }
 
-void
-Array_as::enumerateNonProperties(as_environment& env) const
-{
-    std::stringstream ss; 
-    for (const_iterator it = elements.begin(),
-        itEnd = elements.end(); it != itEnd; ++it)
-    {
-        int idx = it.index();
-        // enumerated values need to be strings, not numbers
-        ss.str(""); ss << idx;
-        env.push(as_value(ss.str()));
-    }
-}
-
-#ifdef GNASH_USE_GC
-void
-Array_as::markReachableResources() const
-{
-    for (const_iterator i=elements.begin(), e=elements.end(); i!=e; ++i)
-    {
-        (*i).setReachable();
-    }
-    markAsObjectReachable();
-}
-#endif // GNASH_USE_GC
-
-void
-Array_as::visitPropertyValues(AbstractPropertyVisitor& visitor) const
-{
-    std::stringstream ss; 
-    string_table& st = getStringTable(*this);
-    for (const_iterator i=elements.begin(), ie=elements.end(); i!=ie; ++i)
-    {
-        int idx = i.index();
-        ss.str(""); ss << idx;
-        string_table::key k = st.find(ss.str());
-        visitor.accept(k, *i);
-    }
-
-    // visit proper properties
-    as_object::visitPropertyValues(visitor);
-}
-
-void
-Array_as::visitNonHiddenPropertyValues(AbstractPropertyVisitor& visitor) const
-{
-    std::stringstream ss; 
-    string_table& st = getStringTable(*this);
-    for (const_iterator i=elements.begin(), ie=elements.end(); i!=ie; ++i)
-    {
-        // TODO: skip hidden ones
-        int idx = i.index();
-        ss.str(""); ss << idx;
-        string_table::key k = st.find(ss.str());
-        visitor.accept(k, *i);
-    }
-
-    // visit proper properties
-    as_object::visitNonHiddenPropertyValues(visitor);
-}
-
-bool
-Array_as::isStrict() const
-{
-    if ( hasNonHiddenProperties() ) return false;
-    return true;
-}
-
 // Used by foreachArray, declared in Array_as.h
 string_table::key
 arrayKey(string_table& st, size_t i)
@@ -1260,8 +1124,10 @@
     int version = getSWFVersion(fn);
     string_table& st = getStringTable(fn);
 
+    if (fn.nargs == 0) return as_value();
+
     // cases: sortOn("prop) and sortOn("prop", Array.FLAG)
-    if (fn.nargs > 0 && fn.arg(0).is_string()) 
+    if (fn.arg(0).is_string()) 
     {
         string_table::key propField =
             st.find(fn.arg(0).to_string_versioned(version));
@@ -1290,66 +1156,62 @@
         return as_value(array);
     }
 
+#if 1
     // case: sortOn(["prop1", "prop2"] ...)
-    if (fn.nargs > 0 && fn.arg(0).is_object() ) 
+    if (fn.arg(0).is_object()) 
     {
-        boost::intrusive_ptr<Array_as> props = 
-            ensureType<Array_as>(fn.arg(0).to_object(*getGlobal(fn)));
-        std::deque<string_table::key> prp;
-        unsigned int optnum = props->size();
-        std::deque<as_cmp_fn> cmp;
-        std::deque<as_cmp_fn> eq;
+        as_object* props = fn.arg(0).to_object(*getGlobal(fn));
+        assert(props);
 
-        for (Array_as::const_iterator it = props->begin();
-            it != props->end(); ++it)
-        {
-            string_table::key s = st.find((*it).to_string_versioned(version));
-            prp.push_back(s);
-        }
+        std::vector<string_table::key> prp;
+        GetKeys gk(prp, st, version);
+        foreachArray(*props, gk);
+        
+        std::vector<as_cmp_fn> cmp;
+        std::vector<as_cmp_fn> eq;
+        
+        // Will be the same as arrayLength(*props);
+        const size_t optnum = prp.size();
         
         // case: sortOn(["prop1", "prop2"])
-        if (fn.nargs == 1)
-        {
+        if (fn.nargs == 1) {
             // assign each cmp function to the standard cmp fn
             as_cmp_fn c = get_basic_cmp(0, version);
             cmp.assign(optnum, c);
         }
         // case: sortOn(["prop1", "prop2"], [Array.FLAG1, Array.FLAG2])
-        else if ( fn.arg(1).is_object() )
-        {
-            boost::intrusive_ptr<Array_as> farray = 
-                ensureType<Array_as>(fn.arg(1).to_object(*getGlobal(fn)));
-            if (farray->size() == optnum)
-            {
-                Array_as::const_iterator 
-                    fBegin = farray->begin(),
-                    fEnd = farray->end();
-
-                std::deque<boost::uint8_t> flgs = 
-                    get_multi_flags(fBegin, fEnd, 
-                        &do_unique, &do_index);
-
-                std::deque<boost::uint8_t>::const_iterator it = 
+        else if (fn.arg(1).is_object()) {
+
+            as_object* farray = fn.arg(1).to_object(*getGlobal(fn));
+
+            if (arrayLength(*farray) == optnum) {
+
+                std::vector<boost::uint8_t> flgs;
+                GetMultiFlags mf(flgs);
+                foreachArray(*farray, mf);
+                do_unique = mf.unique();
+                do_index = mf.index();
+
+                std::vector<boost::uint8_t>::const_iterator it = 
                     flgs.begin();
 
-                while (it != flgs.end())
+                while (it != flgs.end()) {
                     cmp.push_back(get_basic_cmp(*it++, version));
+                }
 
-                if (do_unique)
-                {
+                if (do_unique) {
                     it = flgs.begin();
                     while (it != flgs.end())
                         eq.push_back(get_basic_eq(*it++, version));
                 }
             }
-            else
-            {
+            else {
                 as_cmp_fn c = get_basic_cmp(0, version);
                 cmp.assign(optnum, c);
             }
         }
         // case: sortOn(["prop1", "prop2"], Array.FLAG)
-        else if ( fn.arg(1).is_number() )
+        else if (fn.arg(1).is_number())
         {
             boost::uint8_t flags = 
                 static_cast<boost::uint8_t>(fn.arg(1).to_number());
@@ -1358,13 +1220,11 @@
 
             cmp.assign(optnum, c);
             
-            if (do_unique)
-            {
+            if (do_unique) {
                 as_cmp_fn e = get_basic_eq(flags, version);
                 eq.assign(optnum, e);
             }
         }
-
         as_value_multiprop avc(prp, cmp, *getGlobal(fn));
 
         if (do_unique)
@@ -1378,11 +1238,10 @@
         return as_value(array);
 
     }
+#endif
     IF_VERBOSE_ASCODING_ERRORS(
-    log_aserror(_("SortOn called with invalid arguments."));
+        log_aserror(_("SortOn called with invalid arguments."));
     )
-    if (fn.nargs == 0 )
-        return as_value();
 
     return as_value(array);
 }
@@ -1399,12 +1258,11 @@
 
     const size_t size = arrayLength(*array);
 
-    for (size_t i = 0; i < fn.nargs; ++i) {
+    for (size_t i = 0; i < shift; ++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);
+ 
+    log_debug("size: %s, shift :%s", size, shift);
 
     return as_value(size + shift);
 }
@@ -1437,8 +1295,7 @@
         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);
+    setArrayLength(*array, size + shift);
 
     return as_value(size + shift);
 }
@@ -1457,8 +1314,7 @@
     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);
+    setArrayLength(*array, size - 1);
 
     return ret;
 }
@@ -1482,8 +1338,7 @@
         array->set_member(currentkey, array->getMember(nextkey));
     }
     
-    // TODO: this is wrong, but Gnash relies on it.
-    array->set_member(NSV::PROP_LENGTH, size - 1);
+    setArrayLength(*array, size - 1);
 
     return ret;
 }
@@ -1705,6 +1560,44 @@
     foreachArray(array, pv);
 }
 
+void
+resizeArray(as_object& o, const int size)
+{
+    // Only positive indices are deleted.
+    size_t realSize = std::max(size, 0);
+
+    const size_t currentSize = arrayLength(o);
+    if (realSize < currentSize) {
+        string_table& st = getStringTable(o);
+        for (size_t i = realSize; i < currentSize; ++i) {
+            o.delProperty(arrayKey(st, i));
+        }
+    }
+}
+
+void
+setArrayLength(as_object& o, const int size)
+{
+    Array_as* array = dynamic_cast<Array_as*>(&o);
+    if (!array) return;
+
+    resizeArray(*array, size);
+
+    // Do not call Array_as::set_member because that calls this!
+    array->as_object::set_member(NSV::PROP_LENGTH, size);
+}
+
+int
+isIndex(const std::string& nameString)
+{
+    try {
+        return boost::lexical_cast<int>(nameString);
+    }
+    catch (boost::bad_lexical_cast& e) {
+        return -1;
+    }
+}
+
 } // anonymous namespace
 
 } // end of gnash namespace

=== modified file 'libcore/asobj/Array_as.h'
--- a/libcore/asobj/Array_as.h  2009-10-15 13:25:00 +0000
+++ b/libcore/asobj/Array_as.h  2009-10-16 14:17:00 +0000
@@ -26,8 +26,6 @@
 #include <deque>
 #include <vector>
 #include <memory> // for auto_ptr
-#include <boost/numeric/ublas/vector_sparse.hpp>
-
 #include <string>
 
 // Forward declarations
@@ -38,93 +36,62 @@
 
 namespace gnash {
 
+/// Get the length of an object as though it were an array
+//
+/// It may well be an array, but this also works on normal objects with a 
+/// length property
+//
+/// @param array    The object whose array length is needed.
+/// @return         The array length of the object or 0 if no length is
+///                 found.
 size_t arrayLength(as_object& array);
+
+/// Convert an integral value into an array key
+//
+/// NB this function adds a string value to the string_table for each separate
+/// integral value. It's the way the string_table works.
+//
+/// @param i        The integral value to find
+/// @return         The string table key to look up.
 string_table::key arrayKey(string_table& st, size_t i);
 
+
+/// A visitor to check whether an array is strict or not.
+//
+/// Strict arrays have no non-hidden non-numeric properties. Only real arrays
+/// are strict arrays; any users of this functor should check that first.
+class IsStrictArray : public AbstractPropertyVisitor
+{
+public:
+    IsStrictArray(string_table& st) : _strict(true), _st(st) {}
+    virtual bool accept(string_table::key key, const as_value& val);
+
+    bool strict() const {
+        return _strict;
+    }
+private:
+    bool _strict;
+    string_table& _st;
+};
+
 /// The Array ActionScript object
 class Array_as : public as_object
 {
 
-    /// Other classes shouldn't care about this, but should rather use
-    /// the public iterator / const_iterator members.
-       typedef boost::numeric::ublas::mapped_vector<as_value> ArrayContainer;
-
 public:
 
-       typedef ArrayContainer::const_iterator const_iterator;
-       typedef ArrayContainer::iterator iterator;
-
-    // see dox in as_object.h
-       virtual void visitPropertyValues(AbstractPropertyVisitor& visitor) 
const;
-
-    // see dox in as_object.h
-       virtual void visitNonHiddenPropertyValues(AbstractPropertyVisitor& 
visitor) const;
-
-
        Array_as();
 
        ~Array_as();
 
-    /// Return true if this is a strict array
-    //
-    /// Strict arrays are those whose enumerable
-    /// properties are only valid positive integer.
-    /// Telling strict apart from non-strict is needed
-    /// for AMF encoding in remoting.
-    ///
-    bool isStrict() const;
-
-       Array_as::const_iterator begin();
-
-       Array_as::const_iterator end();
-
        as_value at(unsigned int index) const;
 
        unsigned int size() const;
 
-       void resize(unsigned int);
-
-    /// Why is this overridden?
-       virtual bool get_member(string_table::key name, as_value* val,
-               string_table::key nsname = 0);
-
        /// Overridden to provide array[#]=x semantic
        virtual bool set_member(string_table::key name,
                const as_value& val, string_table::key nsname=0, bool 
ifFound=false);
 
-       /// Overridden to deal with indexed elements
-       virtual std::pair<bool,bool> delProperty(string_table::key name, 
string_table::key nsname = 0);
-
-       /// Overridden to expose indexed elements
-       virtual bool hasOwnProperty(string_table::key name, string_table::key 
nsname = 0);
-
-       /// Enumerate elements
-       //
-       /// See as_object::enumerateNonProperties(as_environment&) for more 
info.
-       ///
-       virtual void enumerateNonProperties(as_environment&) const;
-
-protected:
-
-#ifdef GNASH_USE_GC
-       /// Mark array-specific reachable resources and invoke
-       /// the parent's class version (markAsObjectReachable)
-       //
-       /// array-specific reachable resources are:
-       ///     - The elements values (elements)
-       ///
-       virtual void markReachableResources() const;
-#endif // GNASH_USE_GC
-
-private:
-
-       ArrayContainer elements;
-
-       // this function is used internally by set_member and get_member
-       // it takes a string that is the member name of the array and returns -1
-       // 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);
-
 };
 
 template<typename T>

=== modified file 'libcore/asobj/Color_as.cpp'
--- a/libcore/asobj/Color_as.cpp        2009-10-14 08:47:08 +0000
+++ b/libcore/asobj/Color_as.cpp        2009-10-16 06:31:31 +0000
@@ -274,7 +274,8 @@
     const as_value& target = obj->getMember(NSV::PROP_TARGET);
     MovieClip* sp = target.to_sprite();
     if (sp) return sp;
-    DisplayObject* d = fn.env().find_target(target.to_string());
+    as_object* o = fn.env().find_target(target.to_string());
+    DisplayObject* d = getDisplayObject(o);
     if (d) return d->to_movie();
     return 0;
 }

=== modified file 'libcore/asobj/flash/display/MovieClip_as.cpp'
--- a/libcore/asobj/flash/display/MovieClip_as.cpp      2009-10-14 08:47:08 
+0000
+++ b/libcore/asobj/flash/display/MovieClip_as.cpp      2009-10-16 06:31:31 
+0000
@@ -1012,9 +1012,8 @@
 
     // This is just an optimization if we aren't going
     // to send the data anyway. It might be wrong, though.
-    if (method != MovieClip::METHOD_NONE)
-    {
-        movieclip->getURLEncodedVars(data);
+    if (method != MovieClip::METHOD_NONE) {
+        getURLEncodedVars(*movieclip, data);
     }
  
     mr.loadMovie(urlstr, target, data, method);
@@ -1240,7 +1239,7 @@
 
     if (method != MovieClip::METHOD_NONE) {
         // Get encoded vars.
-        movieclip->getURLEncodedVars(vars);
+        getURLEncodedVars(*movieclip, vars);
     }
 
     movie_root& m = getRoot(fn);
@@ -1254,8 +1253,8 @@
 as_value
 movieclip_getSWFVersion(const fn_call& fn)
 {
-    DisplayObject* o;
-    if (!isNativeType(fn.this_ptr, o)) return as_value(-1);
+    DisplayObject* o = getDisplayObject(fn.this_ptr);
+    if (!o) return as_value(-1);
     return as_value(o->getDefinitionVersion());
 }
 

=== modified file 'libcore/asobj/flash/net/SharedObject_as.cpp'
--- a/libcore/asobj/flash/net/SharedObject_as.cpp       2009-10-14 08:47:08 
+0000
+++ b/libcore/asobj/flash/net/SharedObject_as.cpp       2009-10-16 14:17:00 
+0000
@@ -104,7 +104,7 @@
         _st(vm.getStringTable())
     {};
 
-    void accept(string_table::key key, const as_value& val) 
+    bool accept(string_table::key key, const as_value& val) 
     {
         AMF amf;
         boost::shared_ptr<amf::Element> el;
@@ -137,6 +137,7 @@
         if (el) {
             _sol.addObj(el);
         }
+        return true;
     }
 
 private:
@@ -165,14 +166,13 @@
     
     bool success() const { return !_error; }
 
-    virtual void accept(string_table::key key, const as_value& val) 
+    virtual bool accept(string_table::key key, const as_value& val) 
     {
-        if ( _error ) return;
+        assert(!_error);
 
-        if ( val.is_function() )
-        {
+        if ( val.is_function()) {
             log_debug("SOL: skip serialization of FUNCTION property");
-            return;
+            return true;
         }
 
         // Test conducted with AMFPHP:
@@ -188,7 +188,7 @@
             log_debug(" skip serialization of specially-named property %s",
                     _st.value(key));
 #endif
-            return;
+            return true;
         }
 
         // write property name
@@ -200,14 +200,18 @@
         _buf.appendNetworkShort(namelen);
         _buf.append(name.c_str(), namelen);
         // Strict array are never encoded in SharedObject
-        if ( ! val.writeAMF0(_buf, _offsetTable, _vm, false) )
+        if (!val.writeAMF0(_buf, _offsetTable, _vm, false))
         {
             log_error("Problems serializing an object's member %s=%s",
                     name, val);
             _error = true;
+
+            // Stop visiting....
+            return false;
         }
-
-        _buf.appendByte(0); // SOL-specific
+        // SOL-specific
+        _buf.appendByte(0); 
+        return true;
     }
 
 private:
@@ -373,9 +377,8 @@
 
     std::map<as_object*, size_t> offsetTable;
     SOLPropsBufSerializer props(buf, vm, offsetTable);
-    _data->visitPropertyValues(props);
-    if ( ! props.success() ) 
-    {
+    _data->visitProperties<Exists>(props);
+    if (!props.success()) {
         log_error("Could not serialize object");
         return false;
     }

=== modified file 'libcore/vm/ASHandlers.cpp'
--- a/libcore/vm/ASHandlers.cpp 2009-10-15 09:00:29 +0000
+++ b/libcore/vm/ASHandlers.cpp 2009-10-16 07:09:56 +0000
@@ -2207,12 +2207,11 @@
         //         is the target to load the resource into).
         //
         DisplayObject* curtgt = env.get_target();
-        if ( ! curtgt )
-        {
+        if (!curtgt) {
             log_error(_("CommonGetUrl: current target is undefined"));
             return;
         }
-        curtgt->getURLEncodedVars(varsToSend);
+        getURLEncodedVars(*curtgt, varsToSend);
     }
 
 
@@ -2874,23 +2873,20 @@
 void
 SWFHandlers::ActionTargetPath(ActionExec& thread)
 {
-    
 
     as_environment& env = thread.env;
 
-    boost::intrusive_ptr<MovieClip> sp = env.top(0).to_sprite();
-    if ( sp )
-    {
+    DisplayObject* sp = env.top(0).toDisplayObject();
+    if (sp) {
         env.top(0).set_string(sp->getTarget());
-    }
-    else
-    {
-        IF_VERBOSE_ASCODING_ERRORS(
-        log_aserror(_("Argument to TargetPath(%s) doesn't cast to a 
MovieClip"),
-            env.top(0));
-        );
-        env.top(0).set_undefined();
-    }
+        return;
+    }
+
+    IF_VERBOSE_ASCODING_ERRORS(
+        log_aserror(_("Argument to TargetPath(%s) doesn't cast "
+                "to a DisplayObject"), env.top(0));
+    );
+    env.top(0).set_undefined();
 }
 
 // Push a each object's member value on the stack
@@ -3008,7 +3004,6 @@
 SWFHandlers::ActionDup(ActionExec& thread)
 {
     as_environment& env = thread.env;
-    
     env.push(env.top(0));
 }
 
@@ -3016,10 +3011,7 @@
 SWFHandlers::ActionSwap(ActionExec& thread)
 {
     as_environment& env = thread.env;
-    
-    as_value    temp = env.top(1);
-    env.top(1) = env.top(0);
-    env.top(0) = temp;
+    std::swap(env.top(1), env.top(0));
 }
 
 void
@@ -3031,7 +3023,8 @@
     as_value member_name = env.top(0);
     as_value target = env.top(1);
 
-    boost::intrusive_ptr<as_object> obj = 
convertToObject(*getGlobal(thread.env), target);
+    boost::intrusive_ptr<as_object> obj =
+        convertToObject(*getGlobal(thread.env), target);
     if (!obj)
     {
         IF_VERBOSE_ASCODING_ERRORS(
@@ -3080,18 +3073,15 @@
     const std::string& member_name = env.top(1).to_string();
     const as_value& member_value = env.top(0);
 
-    if ( member_name.empty() )
-    {
+    if (member_name.empty()) {
         IF_VERBOSE_ASCODING_ERRORS (
             // Invalid object, can't set.
-            log_aserror(_("ActionSetMember: %s.%s=%s: member name evaluates to 
invalid (empty) string"),
-                env.top(2),
-                env.top(1),
-                env.top(0));
+            log_aserror(_("ActionSetMember: %s.%s=%s: member name "
+                    "evaluates to invalid (empty) string"),
+                    env.top(2), env.top(1), env.top(0));
         );
     }
-    else if (obj)
-    {
+    else if (obj) {
         thread.setObjectMember(*(obj.get()), member_name, member_value);
 
         IF_VERBOSE_ACTION (
@@ -3103,14 +3093,13 @@
     }
     else
     {
-        // Malformed SWF ? (don't think this is possible to do with 
ActionScript syntax)
+        // Malformed SWF ? (don't think this is possible to do with
+        // ActionScript syntax)
         // FIXME, should this be log_swferror?
         IF_VERBOSE_ASCODING_ERRORS (
             // Invalid object, can't set.
             log_aserror(_("-- set_member %s.%s=%s on invalid object!"),
-                env.top(2),
-                member_name,
-                member_value);
+                env.top(2), member_name, member_value);
         );
     }
 
@@ -3121,14 +3110,14 @@
 SWFHandlers::ActionIncrement(ActionExec& thread)
 {
     as_environment& env = thread.env;
-    env.top(0).set_double(env.top(0).to_number()+1);
+    env.top(0).set_double(env.top(0).to_number() + 1);
 }
 
 void
 SWFHandlers::ActionDecrement(ActionExec& thread)
 {
     as_environment& env = thread.env;
-    env.top(0).set_double(env.top(0).to_number()-1);
+    env.top(0).set_double(env.top(0).to_number() - 1);
 }
 
 void

=== modified file 'testsuite/actionscript.all/array.as'
--- a/testsuite/actionscript.all/array.as       2009-10-15 12:28:05 +0000
+++ b/testsuite/actionscript.all/array.as       2009-10-16 14:18:01 +0000
@@ -770,10 +770,10 @@
 c[10] = 'ten';
 check_equals(c.length, 11);
 ASSetPropFlags(c, "2", 7, 0); // protect from deletion
-xcheck( ! delete c[2] ); // gnash doesn't store prop flags here..
-xcheck_equals(c[2], 30); // so won't respect delete-protection
+check( ! delete c[2] ); // gnash doesn't store prop flags here..
+check_equals(c[2], 30); // so won't respect delete-protection
 c.length = 2;
-xcheck_equals(c[2], 30); // was protected !
+check_equals(c[2], 30); // was protected !
 check_equals(typeof(c[10]), 'undefined'); // was not protected..
 c.length = 11;
 check_equals(typeof(c[10]), 'undefined'); // and won't come back
@@ -1357,18 +1357,18 @@
 getCalls=0; setCalls=0;
 a[1] = 1;
 check_equals(getCalls, 0);
-xcheck_equals(setCalls, 1);
+check_equals(setCalls, 1);
 
 ret = a.addProperty('2', get, set);
 check_equals(ret, true);
 getCalls=0; setCalls=0;
 junk = a[2];
-xcheck_equals(getCalls, 1);
+check_equals(getCalls, 1);
 check_equals(setCalls, 0);
 getCalls=0; setCalls=0;
 a[2] = 2;
 check_equals(getCalls, 0);
-xcheck_equals(setCalls, 1);
+check_equals(setCalls, 1);
 
 check_equals(a.length, 3);
 ret = a.addProperty('3', get, set);
@@ -1378,7 +1378,7 @@
 getCalls=0; setCalls=0;
 a.push(2);
 check_equals(getCalls, 0);
-check_equals(setCalls, 0);
+xcheck_equals(setCalls, 0);
 
 #endif // OUTPUT_VERSION > 5
 
@@ -1394,7 +1394,7 @@
 f = a.shift();
 check_equals(a.length, 1); 
 check_equals(f, 'zero');
-xcheck_equals(a[0], 'zero'); // could not delete for override
+check_equals(a[0], 'zero'); // could not delete for override
 check_equals(typeof(a[1]), 'undefined');
 #if OUTPUT_VERSION > 5
  check(!a.hasOwnProperty(1)); 
@@ -1409,10 +1409,10 @@
 check_equals(a.length, 1);
 check_equals(f, 'zero');
 check_equals(a[0], 'one'); // could replace
-xcheck_equals(a[1], 'one'); // couldn't delete
+check_equals(a[1], 'one'); // couldn't delete
 #if OUTPUT_VERSION > 5
  check(a.hasOwnProperty(0)); 
- xcheck(a.hasOwnProperty(1)); 
+ check(a.hasOwnProperty(1)); 
 #endif
 
 //--------------------------------------------------------
@@ -1425,10 +1425,10 @@
 ASSetPropFlags(a, "0", 4, 0); // protect 0 from override
 check_equals(a.length, 2);
 a[0] = 'overridden';
-xcheck_equals(a[0], 'zero'); // was protected..
+check_equals(a[0], 'zero'); // was protected..
 f = a.shift();
 check_equals(a.length, 1); 
-xcheck_equals(f, 'zero');
+check_equals(f, 'zero');
 check_equals(a[0], 'one'); // 0 was replaced anyway, didn't care about 
protection
 check_equals(typeof(a[1]), 'undefined');
 a[0] = 'overridden';
@@ -1443,12 +1443,12 @@
 a[2] = 'two';
 ASSetPropFlags(a, "1", 4, 0); // protect 1 from override
 a[1] = 'overridden';
-xcheck_equals(a[1], 'one'); // was protected
+check_equals(a[1], 'one'); // was protected
 check_equals(a.length, 3);
 f = a.shift();
 check_equals(a.length, 2);
 check_equals(f, 'zero');
-xcheck_equals(a[0], 'one'); // 0 was replaced anyway, didn't care about 
protection
+check_equals(a[0], 'one'); // 0 was replaced anyway, didn't care about 
protection
 check_equals(a[1], 'two');
 check_equals(typeof(a[2]), 'undefined');
 a[1] = 'overridden';
@@ -1492,7 +1492,7 @@
 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);
+check_equals(o.length, 6);
 
 o = fakeArray();
 o.unshift = Array.prototype.unshift;
@@ -1503,7 +1503,7 @@
 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);
+check_equals(o.length, 6);
 
 
 o = fakeArray();
@@ -1516,7 +1516,7 @@
 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);
+check_equals(o.length, 6);
 
 
 o = fakeArray();


reply via email to

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