gnash-commit
[Top][All Lists]
Advanced

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

[Gnash-commit] gnash ChangeLog libbase/string_table.cpp libbas...


From: Chad Musick
Subject: [Gnash-commit] gnash ChangeLog libbase/string_table.cpp libbas...
Date: Thu, 18 Oct 2007 11:47:57 +0000

CVSROOT:        /sources/gnash
Module name:    gnash
Changes by:     Chad Musick <cmusick>   07/10/18 11:47:56

Modified files:
        .              : ChangeLog 
        libbase        : string_table.cpp string_table.h 
        server         : Makefile.am Property.h PropertyList.cpp 
                         PropertyList.h array.cpp array.h asClass.cpp 
                         asClass.h as_function.cpp as_object.cpp 
                         as_object.h as_prop_flags.h as_value.cpp 
                         as_value.h edit_text_character.cpp 
                         edit_text_character.h movie_root.cpp 
                         namedStrings.cpp namedStrings.h 
                         sprite_instance.cpp sprite_instance.h 
                         stream.cpp 
        server/asobj   : ClassHierarchy.cpp ClassHierarchy.h Object.cpp 
                         xml.cpp xml.h 
        server/parser  : abc_block.cpp abc_block.h 
        server/swf     : tag_loaders.cpp 
        server/vm      : Machine.cpp Machine.h Makefile.am SafeStack.h 
                         VM.h 
        testsuite/server: Makefile.am 
Added files:
        server         : Property.cpp 
        server/vm      : asName.h 
Removed files:
        server         : GetterSetter.cpp GetterSetter.h 
        testsuite/server: GetterSetterTest.cpp 

Log message:
        Many, many changes for AS3. Also rewrote Property and PropertyList to 
allow
        for the addition of namespaces and ordered retrievals. See ChangeLog for
        complete details.

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.4628&r2=1.4629
http://cvs.savannah.gnu.org/viewcvs/gnash/libbase/string_table.cpp?cvsroot=gnash&r1=1.2&r2=1.3
http://cvs.savannah.gnu.org/viewcvs/gnash/libbase/string_table.h?cvsroot=gnash&r1=1.4&r2=1.5
http://cvs.savannah.gnu.org/viewcvs/gnash/server/Makefile.am?cvsroot=gnash&r1=1.128&r2=1.129
http://cvs.savannah.gnu.org/viewcvs/gnash/server/Property.h?cvsroot=gnash&r1=1.9&r2=1.10
http://cvs.savannah.gnu.org/viewcvs/gnash/server/PropertyList.cpp?cvsroot=gnash&r1=1.21&r2=1.22
http://cvs.savannah.gnu.org/viewcvs/gnash/server/PropertyList.h?cvsroot=gnash&r1=1.19&r2=1.20
http://cvs.savannah.gnu.org/viewcvs/gnash/server/array.cpp?cvsroot=gnash&r1=1.81&r2=1.82
http://cvs.savannah.gnu.org/viewcvs/gnash/server/array.h?cvsroot=gnash&r1=1.36&r2=1.37
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asClass.cpp?cvsroot=gnash&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asClass.h?cvsroot=gnash&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/gnash/server/as_function.cpp?cvsroot=gnash&r1=1.44&r2=1.45
http://cvs.savannah.gnu.org/viewcvs/gnash/server/as_object.cpp?cvsroot=gnash&r1=1.68&r2=1.69
http://cvs.savannah.gnu.org/viewcvs/gnash/server/as_object.h?cvsroot=gnash&r1=1.74&r2=1.75
http://cvs.savannah.gnu.org/viewcvs/gnash/server/as_prop_flags.h?cvsroot=gnash&r1=1.8&r2=1.9
http://cvs.savannah.gnu.org/viewcvs/gnash/server/as_value.cpp?cvsroot=gnash&r1=1.87&r2=1.88
http://cvs.savannah.gnu.org/viewcvs/gnash/server/as_value.h?cvsroot=gnash&r1=1.70&r2=1.71
http://cvs.savannah.gnu.org/viewcvs/gnash/server/edit_text_character.cpp?cvsroot=gnash&r1=1.125&r2=1.126
http://cvs.savannah.gnu.org/viewcvs/gnash/server/edit_text_character.h?cvsroot=gnash&r1=1.55&r2=1.56
http://cvs.savannah.gnu.org/viewcvs/gnash/server/movie_root.cpp?cvsroot=gnash&r1=1.109&r2=1.110
http://cvs.savannah.gnu.org/viewcvs/gnash/server/namedStrings.cpp?cvsroot=gnash&r1=1.3&r2=1.4
http://cvs.savannah.gnu.org/viewcvs/gnash/server/namedStrings.h?cvsroot=gnash&r1=1.5&r2=1.6
http://cvs.savannah.gnu.org/viewcvs/gnash/server/sprite_instance.cpp?cvsroot=gnash&r1=1.369&r2=1.370
http://cvs.savannah.gnu.org/viewcvs/gnash/server/sprite_instance.h?cvsroot=gnash&r1=1.144&r2=1.145
http://cvs.savannah.gnu.org/viewcvs/gnash/server/stream.cpp?cvsroot=gnash&r1=1.32&r2=1.33
http://cvs.savannah.gnu.org/viewcvs/gnash/server/Property.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/server/GetterSetter.cpp?cvsroot=gnash&r1=1.9&r2=0
http://cvs.savannah.gnu.org/viewcvs/gnash/server/GetterSetter.h?cvsroot=gnash&r1=1.9&r2=0
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/ClassHierarchy.cpp?cvsroot=gnash&r1=1.3&r2=1.4
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/ClassHierarchy.h?cvsroot=gnash&r1=1.3&r2=1.4
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/Object.cpp?cvsroot=gnash&r1=1.31&r2=1.32
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/xml.cpp?cvsroot=gnash&r1=1.49&r2=1.50
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/xml.h?cvsroot=gnash&r1=1.19&r2=1.20
http://cvs.savannah.gnu.org/viewcvs/gnash/server/parser/abc_block.cpp?cvsroot=gnash&r1=1.7&r2=1.8
http://cvs.savannah.gnu.org/viewcvs/gnash/server/parser/abc_block.h?cvsroot=gnash&r1=1.5&r2=1.6
http://cvs.savannah.gnu.org/viewcvs/gnash/server/swf/tag_loaders.cpp?cvsroot=gnash&r1=1.145&r2=1.146
http://cvs.savannah.gnu.org/viewcvs/gnash/server/vm/Machine.cpp?cvsroot=gnash&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/gnash/server/vm/Machine.h?cvsroot=gnash&r1=1.4&r2=1.5
http://cvs.savannah.gnu.org/viewcvs/gnash/server/vm/Makefile.am?cvsroot=gnash&r1=1.15&r2=1.16
http://cvs.savannah.gnu.org/viewcvs/gnash/server/vm/SafeStack.h?cvsroot=gnash&r1=1.3&r2=1.4
http://cvs.savannah.gnu.org/viewcvs/gnash/server/vm/VM.h?cvsroot=gnash&r1=1.17&r2=1.18
http://cvs.savannah.gnu.org/viewcvs/gnash/server/vm/asName.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/testsuite/server/Makefile.am?cvsroot=gnash&r1=1.33&r2=1.34
http://cvs.savannah.gnu.org/viewcvs/gnash/testsuite/server/GetterSetterTest.cpp?cvsroot=gnash&r1=1.17&r2=0

Patches:
Index: ChangeLog
===================================================================
RCS file: /sources/gnash/gnash/ChangeLog,v
retrieving revision 1.4628
retrieving revision 1.4629
diff -u -b -r1.4628 -r1.4629
--- ChangeLog   18 Oct 2007 11:23:20 -0000      1.4628
+++ ChangeLog   18 Oct 2007 11:47:52 -0000      1.4629
@@ -1,3 +1,56 @@
+2007-10-18 Chad Musick <address@hidden>
+
+       * server/Property.cpp: New file -- Definition of properties now requires
+         some support functions.
+       * server/GetterSetter.cpp,.h -- Obsolete file removal, functionality 
moved
+         to Property
+       * server/vm/asName.h -- New file, split and combined from abc_block.h 
and
+         asClass.h
+       * libbase/string_table.cpp,.h -- Make all empty strings return 0, make a
+         new function for combining two values with a dot.
+       * server/Makefile.am -- Remove GetterSetter files, add Property.cpp
+       * server/Property.h -- Combine all 3 types (ordinary, getter/setter,
+         destructive getter/setter) into a single class, Property, using 
boost::
+         variant. Remove all virtual functions. Add key and namespace.
+       * server/PropertyList.h,.cpp -- Change container to a multi-index 
storing
+         properties by value rather than by pointer, add functions for 
retrieval
+         by order number (for AS3). Remove all virtual functions.
+       * server/array.cpp,.h -- Change get_member signature to match the one in
+         as_object which now includes a namespace.
+       * server/asClass.cpp -- Change asMethod and asClass to use an as_object
+         backend
+       * server/asClass.h -- Move asName out. Change asMethod and asClass to 
new
+         signatures.
+       * server/as_function.cpp -- Add checks for prototype.
+       * server/as_object.cpp -- Chnage to new PropertyList style, some early
+         code for interfaces (ImplementsOp) which should be working soon.
+       * server/as_object.h -- Support for new PropertyList. Unfinished support
+         for AS3.
+       * server/as_prop_flags.h -- Added flag for static members, changed
+         protected variable to a flag.
+       * server/as_value.cpp,.h -- Stubs for implements and namespace support.
+       * server/edit_text_character.cpp,.h -- Change to namespace get_member
+       * server/namedStrings.cpp,.h -- Add some anonymous strings. These can
+         only be used if you already know their number and are invisible to
+         clients of the object.
+       * server/sprite_instance.cpp,.h -- Change to namespace get_member
+       * server/stream.cpp -- Depends on Property
+       * server/asobj/ClassHierarchy.cpp,.h -- Use SafeStack instead of
+         memoryDispenser, change to conform to new definitions of some classes.
+       * server/asobj/Object.cpp -- Make sure construct has Object prototype
+         set as "prototype" members.
+       * server/asobj/xml.cpp,.h -- Use namespace get_member.
+       * server/parser/abc_block.cpp,.h -- Change to conform to new asClass and
+         asMethod. No longer safe to call read() in non-AS thread. 
abc_Multiname
+         became asName (merged with asName from asClass.h) and was moved to its
+         own file. Double pool changed from 'long double' to 'double'.
+       * server/swf/tag_loaders.cpp -- Remove read() call from loading 
abc_block,
+         since this is no longer safe to do in loader thread.
+       * server/vm/Machine.cpp,.h -- Numerous steps towards completion.
+       * server/vm/VM.h -- Add Machine member to VM object.
+       * testsuite/server/Makefile.am -- Remove obsolete GetterSetterTest
+       * testsuite/server/GetterSetterTest.cpp -- Removed as obsolete.
+
 2007-10-17 Bastiaan Jacques <address@hidden>
 
        * backend/render_handler_cairo.cpp: Implement getPixel and

Index: libbase/string_table.cpp
===================================================================
RCS file: /sources/gnash/gnash/libbase/string_table.cpp,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -b -r1.2 -r1.3
--- libbase/string_table.cpp    19 Sep 2007 14:20:48 -0000      1.2
+++ libbase/string_table.cpp    18 Oct 2007 11:47:53 -0000      1.3
@@ -26,6 +26,10 @@
 string_table::key
 string_table::find(const std::string& to_find, bool insert_unfound)
 {
+       // Empty strings all map to 0
+       if (to_find.empty())
+               return 0;
+
        table::nth_index<0>::type::iterator i = mTable.get<0>().find(to_find);
 
        if (i == mTable.end() && insert_unfound)
@@ -54,6 +58,17 @@
 }
 
 string_table::key
+string_table::find_dot_pair(string_table::key left, string_table::key right, 
+       bool insert_unfound)
+{
+       if (!right)
+               return left;
+
+       std::string isit = value(left) + "." + value(right);
+       return find(isit, insert_unfound);
+}
+
+string_table::key
 string_table::insert(const std::string& to_insert)
 {
        boost::mutex::scoped_lock aLock(mLock);

Index: libbase/string_table.h
===================================================================
RCS file: /sources/gnash/gnash/libbase/string_table.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -r1.4 -r1.5
--- libbase/string_table.h      20 Sep 2007 10:01:02 -0000      1.4
+++ libbase/string_table.h      18 Oct 2007 11:47:53 -0000      1.5
@@ -75,13 +75,19 @@
        /// not yet in the table and insert_unfound was false.
        key find(const std::string& to_find, bool insert_unfound = true);
 
+       /// \brief
+       /// Find a string which is the concatentation of two known strings
+       /// with a dot between them. (Used for namespaces.)
+       /// Otherwise, just like find.
+       key find_dot_pair(key left, key right, bool insert_unfound = true);
+
        /// Find a string by its key.
        ///
        /// @return
        /// The string which matches key or "" if an invalid key is given.
        const std::string& value(key to_find)
        { 
-               if (mTable.empty())
+               if (mTable.empty() || !to_find)
                        return mEmpty;
                table::nth_index<1>::type::iterator r = 
mTable.get<1>().find(to_find);
                return (r == mTable.get<1>().end()) ? mEmpty : r->mValue;

Index: server/Makefile.am
===================================================================
RCS file: /sources/gnash/gnash/server/Makefile.am,v
retrieving revision 1.128
retrieving revision 1.129
diff -u -b -r1.128 -r1.129
--- server/Makefile.am  3 Oct 2007 21:43:05 -0000       1.128
+++ server/Makefile.am  18 Oct 2007 11:47:53 -0000      1.129
@@ -18,7 +18,7 @@
 # 
 #
 
-# $Id: Makefile.am,v 1.128 2007/10/03 21:43:05 tgc Exp $
+# $Id: Makefile.am,v 1.129 2007/10/18 11:47:53 cmusick Exp $
 
 AUTOMAKE_OPTIONS = 
 
@@ -57,7 +57,7 @@
 
 libgnashserver_la_SOURCES = \
        BitmapMovieInstance.cpp \
-       GetterSetter.cpp \
+       Property.cpp \
        PropertyList.cpp \
        URLAccessManager.cpp \
        as_environment.cpp \
@@ -115,7 +115,6 @@
        $(NULL)
 
 noinst_HEADERS = \
-       GetterSetter.h \
        Property.h \
        PropertyList.h \
        Sprite.h \

Index: server/Property.h
===================================================================
RCS file: /sources/gnash/gnash/server/Property.h,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -b -r1.9 -r1.10
--- server/Property.h   23 Sep 2007 08:48:17 -0000      1.9
+++ server/Property.h   18 Oct 2007 11:47:53 -0000      1.10
@@ -25,51 +25,102 @@
 #include "config.h"
 #endif
 
+#include <boost/variant.hpp>
+
 #include "as_prop_flags.h"
 #include "as_value.h"
-#include "GetterSetter.h" // for GetterSetterProperty
+#include "string_table.h"
 
 namespace gnash {
 
+class as_function;
+class PropertyList;
+
+/// Simple Holder for getter/setter functions
+class as_accessors
+{
+public:
+       as_function* mGetter;
+       as_function* mSetter;
+
+       as_accessors(as_function* getter, as_function* setter) : 
mGetter(getter),
+               mSetter(setter)
+       {/**/}
+};
 
 /// An abstract property
-//
-/// This is intended for use only by PropertyList class
-///
 class Property
 {
-protected: // For DestructiveGetterSetterProperty
+private:
+       friend class PropertyList; // For index access
+
        /// Properties flags
        as_prop_flags _flags;
 
+       // Store the various types of things that can be held.
+       typedef boost::variant<boost::blank, as_value, as_accessors> boundType;
+       // Changing this doesn't change the identity of the property, so it is
+       // mutable.
+       mutable boundType mBound;
+
+       // If true, as soon as getValue has been invoked once, the
+       // returned value becomes a fixed return (though it can be
+       // overwritten if not readOnly)
+       mutable bool mDestructive;
+       
+       string_table::key mName;
+       string_table::key mNamespace;
+       // An ordering number, for access by order
+       // (AS3 enumeration and slots, AS2 arrays)
+       int mOrderId;
+
+       /// Get a value from a getter function.
+       as_value getDelayedValue(const as_object& this_ptr) const;
+
+       /// Set a value using a setter function.
+       void setDelayedValue(as_object& this_ptr, const as_value& value);
+
 public:
        /// Default constructor
-       Property()
-       {
-       }
+       Property(string_table::key name = 0, string_table::key nsId = 0) : 
+               mName(name), mNamespace(nsId)
+       {/**/}
 
-       Property(const Property& p)
-               :
-               _flags(p._flags)
-       {
-       }
+       /// Copy constructor
+       Property(const Property& p) :
+               _flags(p._flags), mBound(p.mBound), 
mDestructive(p.mDestructive),
+               mName(p.mName), mNamespace(p.mNamespace)
+       {/**/}
 
        /// Constructor taking initial flags
-       Property(const as_prop_flags& flags)
-               :
-               _flags(flags)
-       {
-       }
+       Property(string_table::key name, string_table::key nsId,
+               const as_prop_flags& flags) : _flags(flags),
+               mBound(as_value()), mDestructive(false), mName(name), 
mNamespace(nsId)
+       {/**/}
 
-       /// \brief
-       /// Virtual destructor, to make sure the appropriate
-       /// destructor is called for derivated classes
-       //
-       /// We've nothing to do here, as our only member is
-       /// the as_prop_flags which should take care of it's
-       /// destruction.
-       ///
-       virtual ~Property() {}
+       Property(string_table::key name, string_table::key nsId, 
+               const as_value& value) : mBound(value), mDestructive(false),
+               mName(name), mNamespace(nsId)
+       {/**/}
+
+       Property(string_table::key name, string_table::key nsId,
+               const as_value& value, const as_prop_flags& flags) :
+               _flags(flags), mBound(value), mDestructive(false),
+               mName(name), mNamespace(nsId)
+       {/**/}
+
+       Property(string_table::key name, string_table::key nsId,
+               as_function *getter, as_function *setter, 
+               const as_prop_flags& flags, bool destroy = false) :
+               _flags(flags), mBound(as_accessors(getter, setter)),
+               mDestructive(destroy), mName(name), mNamespace(nsId)
+       {/**/}
+
+       Property(string_table::key name, string_table::key nsId,
+               as_function *getter, as_function *setter, bool destroy = false) 
:
+               _flags(), mBound(as_accessors(getter, setter)), 
mDestructive(destroy),
+               mName(name), mNamespace(nsId)
+       {/**/}
 
        /// accessor to the properties flags
        const as_prop_flags& getFlags() const { return _flags; }
@@ -88,7 +139,19 @@
        ///
        /// @return the value of this property
        ///
-       virtual as_value getValue(as_object& this_ptr) const=0;
+       as_value getValue(const as_object& this_ptr) const
+       {
+               switch (mBound.which())
+               {
+               case 0: // blank, nothing to do.
+                       return as_value();
+               case 1: // Bound value
+                       return boost::get<as_value>(mBound);
+               case 2: // Getter/setter
+                       return getDelayedValue(this_ptr);
+               } // end of switch
+               return as_value(); // Not reached.
+       }
 
        /// Set value of this property
        //
@@ -106,204 +169,59 @@
        ///     argument of the 'setter' function if this is a Getter/Setter
        ///     property. @see isGetterSetter().
        ///
-       /// TODO: have this function check for readOnly property...
-       ///
-       virtual void setValue(as_object& this_ptr, const as_value &value)=0;
-
-       // clone this property
-       virtual Property* clone() const=0;
-       
-       /// is this a read-only member ?
-       bool isReadOnly() const { return _flags.get_read_only(); }
-
-       /// is this a Getter/Setter property ?
-       virtual bool isGetterSetter() const { return false; }
-
-       /// Mark this property as being reachable (for the GC)
-       virtual void setReachable() const=0;
-};
-
-/// A simple property, consisting only of an as_value
-//
-/// This is intended for use only by PropertyList class
-///
-class SimpleProperty: public Property
-{
-       /// value
-       as_value _value;
-
-public:
-
-       SimpleProperty()
-               :
-               Property(),
-               _value()
-       {
-       }
-
-       SimpleProperty(const SimpleProperty& p)
-               :
-               Property(p),
-               _value(p._value)
-       {
-       }
-
-       SimpleProperty(const as_value& value)
-               :
-               Property(),
-               _value(value)
+       void setValue(as_object& this_ptr, const as_value &value)
        {
-       }
-
-       SimpleProperty(const as_value &value, const as_prop_flags& flags)
-               :
-               Property(flags),
-               _value(value)
+               switch (mBound.which())
        {
-       }
-
-       Property* clone() const { return new SimpleProperty(*this); }
-
-       as_value getValue(as_object&) const { return _value; }
-
-       void setValue(as_object&, const as_value &value)  { _value = value; }
-
-       void setReachable() const { _value.setReachable(); }
-
-};
-
-/// A Getter/Setter property
-//
-/// Basically a small wrapper around GetterSetter.
-/// This is intended for use only by PropertyList.
-///
-class GetterSetterProperty: public Property
-{
-protected: // For use in DestructiveGetterSetterProperty
-       /// Actual Getter / Setter  (the workhorse)
-       GetterSetter _getset;
-
-public:
-
-       /// Construct a GetterSetterProperty given a GetterSetter
-       GetterSetterProperty(const GetterSetter& getset)
-               :
-               Property(),
-               _getset(getset)
+               case 0: // As yet unbound, so make it a simple
+               case 1: // Bound value, set. Trust our callers to check 
read-only.
+                       mBound = value;
+                       return;
+               case 2: // Getter/setter
+                       // Destructive are always overwritten.
+                       if (mDestructive)
        {
+                               mDestructive = false;
+                               mBound = value;
        }
-
-       /// Overridden constructor to allow flags specification
-       GetterSetterProperty(const GetterSetter& getset,
-                       const as_prop_flags& flags)
-               :
-               Property(flags),
-               _getset(getset)
-       {
+                       else
+                               setDelayedValue(this_ptr, value);
+                       return;
        }
-
-       // Copy constructor
-       GetterSetterProperty(const GetterSetterProperty& o)
-               :
-               Property(o),
-               _getset(o._getset)
-       {
        }
 
-       Property* clone() const { return new GetterSetterProperty(*this); }
+       /// Set the order id
+       void setOrder(int order) { mOrderId = order; }
 
-       /// Get the value (invokes the getter)
-       as_value getValue(as_object& this_ptr) const
-       {
-               return _getset.getValue(&this_ptr);
-       }
+       /// Get the order id
+       int getOrder() const { return mOrderId; }
 
-       /// Set the value (invokes the setter)
-       void setValue(as_object& this_ptr, const as_value &value) 
-       {
-               _getset.setValue(&this_ptr, value);
-       }
+       /// Set the setter
+       void setSetter(as_function*);
 
-       /// This *is* a Getter/Setter property !
-       virtual bool isGetterSetter() const { return true; }
+       /// Set the getter
+       void setGetter(as_function*);
 
-       /// Set GetterSetter as reachable (for GC)
-       void setReachable() const
-       {
-               _getset.setReachable();
-       }
-};
+       /// is this a read-only member ?
+       bool isReadOnly() const { return _flags.get_read_only(); }
 
-/// A destructive Getter/Setter property.
-///
-/// Just like a regular Getter/Setter property, but you only get one chance
-/// to call its getValue -- it then becomes a simple property whose value is
-/// the value returned by getValue.
-///
-class DestructiveGetterSetterProperty : public GetterSetterProperty
-{
-private:
-       mutable bool mDestroyed;
-       mutable as_value mValue;
+       /// Is this a getter/setter property?
+       bool isGetterSetter() const { return mBound.which() == 2; }
 
-public:
-       /// Construct a DestructiveGetterSetterProperty
-       DestructiveGetterSetterProperty(const GetterSetter& getset)
-               :
-               GetterSetterProperty(getset),
-               mDestroyed(false),
-               mValue()
-       {/**/}
+       /// is this a destructive property ?
+       bool isDestructive() const { return mDestructive; }
 
-       /// Allow specific flags.
-       DestructiveGetterSetterProperty(const GetterSetter& getset,
-                       const as_prop_flags& flags)
-               :
-               GetterSetterProperty(getset, flags),
-               mDestroyed(false),
-               mValue()
-       {/**/}
+       /// Is this a static property?
+       bool isStatic() const { return _flags.get_static(); }
 
-       /// Copy constructor
-       DestructiveGetterSetterProperty(const DestructiveGetterSetterProperty& 
o)
-               :
-               GetterSetterProperty(o),
-               mDestroyed(o.mDestroyed),
-               mValue(o.mValue)
-       {/**/}
+       /// What is the name of this property?
+       string_table::key getName() const { return mName; }
 
-       Property* clone() const
-       {
-               if (mDestroyed) 
-                       return new SimpleProperty(mValue, _flags);
-               return new DestructiveGetterSetterProperty(*this);
-       }
-
-       /// The point of the destructive type: Only call getter once.
-       as_value getValue(as_object& this_ptr) const
-       {
-               if (!mDestroyed)
-               {
-                       mDestroyed = true; // Be sure we can set in get if we 
like.
-                       mValue = _getset.getValue(&this_ptr);
-               }
-               return mValue;
-       }
+       /// What is the namespace of this property?
+       string_table::key getNamespace() const { return mNamespace; }
 
-       /// Set the value (destroys)
-       void setValue(as_object& /*this_ptr*/, const as_value &value) 
-       {
-               // Destroy, if not already.
-               mValue = value;
-               mDestroyed = true;
-       }
-
-       /// Set GetterSetter, mValue as reachable (for GC)
-       void setReachable() const
-       {
-               _getset.setReachable();
-               mValue.setReachable();
-       }
+       /// Mark this property as being reachable (for the GC)
+       void setReachable() const;
 };
 
 } // namespace gnash

Index: server/PropertyList.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/PropertyList.cpp,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -b -r1.21 -r1.22
--- server/PropertyList.cpp     26 Sep 2007 12:09:07 -0000      1.21
+++ server/PropertyList.cpp     18 Oct 2007 11:47:53 -0000      1.22
@@ -24,7 +24,6 @@
 #include "PropertyList.h"
 #include "Property.h" 
 
-
 #include "log.h"
 
 #include "as_function.h"
@@ -39,10 +38,6 @@
 
 namespace gnash {
 
-PropertyList::PropertyList()
-{
-}
-
 PropertyList::PropertyList(const PropertyList& pl)
 {
        import(pl);
@@ -59,65 +54,135 @@
        return *this;
 }
 
+// Should find in any namespace if nsId is 0, and any namespace should find
+// something in namespace 0.
+static inline
+PropertyList::container::iterator
+iterator_find(PropertyList::container &p, string_table::key name,
+       string_table::key nsId)
+{
+       if (nsId)
+       {
+               PropertyList::container::iterator i =
+                       p.find(boost::make_tuple(name, nsId));
+               if (i != p.end())
+                       return i;
+               return p.find(boost::make_tuple(name, 0));
+       }
 
+       return p.find(boost::make_tuple(name));
+}
+
+typedef PropertyList::container::index<PropertyList::oType>::type::iterator
+       orderIterator;
+
+static inline
+orderIterator
+iterator_find(PropertyList::container &p, int order)
+{
+       return p.get<1>().find(order);
+}
 
 bool
-PropertyList::getValue(const string_table::key key, as_value& val,
+PropertyList::getValueByOrder(int order, as_value& val,
                as_object& this_ptr) 
 {
-       const_iterator found = _props.find( key );
-       if ( found == _props.end() )
+       orderIterator i = iterator_find(_props, order);
+       if (i == _props.get<1>().end())
+               return false;
+
+       val = i->getValue(this_ptr);
+       return true;
+}
+
+const Property*
+PropertyList::getPropertyByOrder(int order)
+{
+       orderIterator i = iterator_find(_props, order);
+       if (i == _props.get<1>().end())
+               return NULL;
+
+       return &(*i);
+}
+
+const Property*
+PropertyList::getOrderAfter(int order)
+{
+       orderIterator i = iterator_find(_props, order);
+
+       if (i == _props.get<1>().end())
+               return NULL; // Not found at all.
+
+       do
        {
+               ++i;
+               if (i == _props.get<1>().end())
+                       return NULL;
+       } while (i->getFlags().get_dont_enum());
+
+       return &(*i);
+}
+
+bool
+PropertyList::reserveSlot(unsigned short slotId, string_table::key name,
+       string_table::key nsId)
+{
+       orderIterator found = iterator_find(_props, slotId + 1);
+       if (found != _props.get<1>().end())
                return false;
-       }
 
-       val=found->second->getValue(this_ptr);
+       Property a(name, nsId, as_value());
+       a.setOrder(slotId + 1);
+       _props.insert(a);
+       return true;
+}
 
-       //log_msg(_("Property %s found, value is (%s)"), key.c_str(), 
val.to_string());
+bool
+PropertyList::getValue(const string_table::key key, as_value& val,
+               as_object& this_ptr, const string_table::key nsId) 
+{
+       container::iterator found = iterator_find(_props, key, nsId);
+       if (found == _props.end())
+               return false;
 
+       val = found->getValue(this_ptr);
        return true;
 }
 
 bool
-PropertyList::setValue(string_table::key key, const as_value& val,
-               as_object& this_ptr)
+PropertyList::setValue(string_table::key key, as_value val,
+               as_object& this_ptr, string_table::key nsId)
 {
-       iterator found = _props.find( key );
-       if ( found == _props.end() )
+       container::iterator found = iterator_find(_props, key, nsId);
+       
+       if (found == _props.end())
        {
                // create a new member
-               SimpleProperty* prop = new SimpleProperty(val);
-#ifdef DEBUG_PROPERTY_ALLOC
-               log_debug("SimpleProperty %s = %p", 
VM::get().getStringTable().value(key).c_str(), (void*)prop);
-#endif // DEBUG_PROPERTY_ALLOC
-               _props[key] = prop;
+               Property a(key, nsId, val);
+               // Non slot properties are negative ordering in insertion order
+               a.setOrder(- ++mDefaultOrder - 1);
+               _props.insert(a);
                return true;
        }
-
-       Property* prop = found->second;
-
-       if ( prop->isReadOnly() )
+       if (found->isReadOnly())
        {
                log_error(_("Property %s is read-only, not setting it to %s"), 
                        VM::get().getStringTable().value(key).c_str(), 
val.to_string().c_str());
                return false;
        }
 
-       //log_msg(_("Property %s set to value %s"), key.c_str(), 
val.to_string());
-       prop->setValue(this_ptr, val);
+       const_cast<Property*>(&(*found))->setValue(this_ptr, val);
        return true;
 }
 
 bool
 PropertyList::setFlags(string_table::key key,
-               int setFlags, int clearFlags)
+               int setFlags, int clearFlags, string_table::key nsId)
 {
-       iterator found = _props.find( key );
+       container::iterator found = iterator_find(_props, key, nsId);
        if ( found == _props.end() ) return false;
 
-       Property* prop = found->second;
-
-       as_prop_flags& f = prop->getFlags();
+       as_prop_flags& f = const_cast<as_prop_flags&>(found->getFlags());
        return f.set_flags(setFlags, clearFlags);
 }
 
@@ -127,42 +192,43 @@
        size_t success=0;
        size_t failure=0;
 
-       for ( iterator it=_props.begin(), far=_props.end(); it != far; ++it)
+       for (container::iterator it=_props.begin(), far=_props.end(); it != 
far; ++it)
        {
-               Property* prop = it->second;
-               as_prop_flags& f = prop->getFlags();
-               if ( f.set_flags(setFlags, clearFlags) ) ++success;
-               else ++failure;
+               as_prop_flags& f = const_cast<as_prop_flags&>(it->getFlags());
+               if (f.set_flags(setFlags, clearFlags))
+                       ++success;
+               else
+                       ++failure;
        }
 
        return std::make_pair(success,failure);
 }
 
 Property*
-PropertyList::getProperty(string_table::key key)
+PropertyList::getProperty(string_table::key key, string_table::key nsId)
 {
-       iterator it=find(key);
-       if ( it == end() ) return NULL;
-       return it->second;
+       container::iterator found = iterator_find(_props, key, nsId);
+       if (found == _props.end()) return NULL;
+       return const_cast<Property*>(&(*found));
 }
 
 std::pair<bool,bool>
-PropertyList::delProperty(string_table::key key)
+PropertyList::delProperty(string_table::key key, string_table::key nsId)
 {
        //GNASH_REPORT_FUNCTION;
-       iterator it=find(key);
-       if ( it == end() ){
+       container::iterator found = iterator_find(_props, key, nsId);
+       if (found == _props.end())
+       {
                return std::make_pair(false,false);
        }
 
        // check if member is protected from deletion
-       if ( it->second->getFlags().get_dont_delete() )
+       if (found->getFlags().get_dont_delete())
        {
                return std::make_pair(true,false);
        }
 
-       delete it->second;
-       _props.erase(it);
+       _props.erase(found);
        return std::make_pair(true,true);
 }
 
@@ -173,11 +239,12 @@
        size_t success=0;
        size_t failure=0;
 
-       for (const_iterator it = props.begin(), itEnd = props.end(); it != 
itEnd; ++it )
+       for (container::const_iterator it = props._props.begin(),
+               itEnd = props._props.end(); it != itEnd; ++it )
        {
-               string_table::key key = it->first;
+               string_table::key key = it->mName;
 
-               if ( setFlags(key, flagsSet, flagsClear) ) ++success;
+               if (setFlags(key, flagsSet, flagsClear, it->mNamespace)) 
++success;
                else ++failure;
        }
 
@@ -186,16 +253,21 @@
 }
 
 void
-PropertyList::enumerateKeys(as_environment& env) const
+PropertyList::enumerateKeys(as_environment& env, propNameSet& donelist) const
 {
        string_table& st = VM::get().getStringTable();
-       for ( const_iterator i=begin(), ie=end(); i != ie; ++i)
+       for (container::const_iterator i=_props.begin(), ie=_props.end(); i != 
ie; ++i)
        {
-               const Property* prop = i->second;
-
-               if ( prop->getFlags().get_dont_enum() ) continue;
+               if (i->getFlags().get_dont_enum())
+                       continue;
 
-               env.push(as_value(st.value(i->first).c_str()));
+               if (donelist.insert(std::make_pair(i->mName, 
i->mNamespace)).second)
+               {
+                       if (i->mNamespace)
+                               env.push(as_value(st.value(i->mName) + "." + 
st.value(i->mNamespace)));
+                       else
+                               env.push(as_value(st.value(i->mName)));
+               }
        }
 }
 
@@ -203,14 +275,13 @@
 PropertyList::enumerateKeyValue(as_object& this_ptr, std::map<std::string, 
std::string>& to) 
 {
        string_table& st = VM::get().getStringTable();
-       for ( const_iterator i=begin(), ie=end(); i != ie; ++i)
+       for (container::const_iterator i=_props.begin(), ie=_props.end(); i != 
ie; ++i)
        {
-               const Property* prop = i->second;
-
-               if ( prop->getFlags().get_dont_enum() ) continue;
+               if (i->getFlags().get_dont_enum())
+                       continue;
 
-               to.insert(make_pair(st.value(i->first),
-                               prop->getValue(this_ptr).to_string()));
+               to.insert(make_pair(st.value(i->mName),
+                               i->getValue(this_ptr).to_string()));
        }
 }
 
@@ -218,10 +289,9 @@
 PropertyList::dump(as_object& this_ptr, std::map<std::string, as_value>& to) 
 {
        string_table& st = VM::get().getStringTable();
-       for ( const_iterator i=begin(), ie=end(); i != ie; ++i)
+       for (container::const_iterator i=_props.begin(), ie=_props.end(); i != 
ie; ++i)
        {
-               const Property* prop = i->second;
-               to.insert(make_pair(st.value(i->first), 
prop->getValue(this_ptr)));
+               to.insert(make_pair(st.value(i->mName), i->getValue(this_ptr)));
        }
 }
 
@@ -229,84 +299,80 @@
 PropertyList::dump(as_object& this_ptr)
 {
        string_table& st = VM::get().getStringTable();
-       for ( const_iterator it=begin(), itEnd=end(); it != itEnd; ++it )
+       for (container::const_iterator it=_props.begin(), itEnd=_props.end(); 
it != itEnd; ++it )
        {
-               log_msg("  %s: %s", st.value(it->first).c_str(),
-                       it->second->getValue(this_ptr).to_string().c_str());
+               log_msg("  %s: %s", st.value(it->mName).c_str(),
+                       it->getValue(this_ptr).to_string().c_str());
        }
 }
 
 void
 PropertyList::import(const PropertyList& o) 
 {
-       for (const_iterator it = o.begin(), itEnd = o.end(); it != itEnd; ++it)
+       for (container::const_iterator it = o._props.begin(),
+               itEnd = o._props.end(); it != itEnd; ++it)
        {
-               string_table::key key = it->first;
-               const Property* prop = it->second;
-
-               // Delete any previous property with this name
-               iterator found = _props.find(key);
-               if ( found != _props.end() )
+               // overwrite any previous property with this name
+               container::iterator found = iterator_find(_props, it->mName, 
it->mNamespace);
+               if (found != _props.end())
                {
-                       delete found->second;
-                       found->second = prop->clone();
+                       Property a = *it;
+                       a.setOrder(found->getOrder());
+                       _props.replace(found, a);
                }
                else
                {
-                       _props[key] = prop->clone();
+                       Property a = *it;
+                       a.setOrder(- ++mDefaultOrder - 1);
+                       _props.insert(a);
                }
        }
 }
 
 bool
 PropertyList::addGetterSetter(string_table::key key, as_function& getter,
-       as_function& setter)
+       as_function& setter, string_table::key nsId)
 {
-       iterator found = _props.find( key );
-       if ( found != _props.end() ) return false; // already exists !!
+       container::iterator found = iterator_find(_props, key, nsId);
+       if (found != _props.end())
+       {
+               assert(0);
+               return false; // already exists !!
+       }
 
-       GetterSetterProperty* prop = new 
GetterSetterProperty(GetterSetter(getter, setter));
-#ifdef DEBUG_PROPERTY_ALLOC
-       log_debug("GetterSetterProperty %s = %p", 
V::get().getStringTable().value(key).c_str(), (void*)prop);
-#endif // DEBUG_PROPERTY_ALLOC
-       _props[key] = prop;
+       Property a(key, nsId, &getter, &setter);
+       a.setOrder(- ++mDefaultOrder - 1);
+       _props.insert(a);
        return true;
 }
 
 bool
 PropertyList::addDestructiveGetterSetter(string_table::key key,
-       as_function& getter, as_function& setter)
+       as_function& getter, as_function& setter, string_table::key nsId)
 {
-       iterator found = _props.find(key);
+       container::iterator found = iterator_find(_props, key, nsId);
        if (found != _props.end())
                return false; // Already exists.
 
-       DestructiveGetterSetterProperty* prop =
-               new DestructiveGetterSetterProperty(GetterSetter(getter, 
setter));
-       _props[key] = prop;
+       Property a(key, nsId, &getter, &setter, 1);
+       a.setOrder(- ++mDefaultOrder - 1);
+       _props.insert(a);
        return true;
 }
 
 void
 PropertyList::clear()
 {
-       for (iterator it = begin(), itEnd = end(); it != itEnd; ++it)
-               delete it->second;
        _props.clear();
 }
 
-PropertyList::~PropertyList()
-{
-       for (iterator it = begin(), itEnd = end(); it != itEnd; ++it)
-               delete it->second;
-}
-
 void
 PropertyList::setReachable() const
 {
-       for (const_iterator it = begin(), itEnd = end(); it != itEnd; ++it)
+       for (container::const_iterator it = _props.begin();
+                       it != _props.end(); ++it)
        {
-               it->second->setReachable();
+               it->setReachable();
        }
 }
 

Index: server/PropertyList.h
===================================================================
RCS file: /sources/gnash/gnash/server/PropertyList.h,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -b -r1.19 -r1.20
--- server/PropertyList.h       26 Sep 2007 12:09:07 -0000      1.19
+++ server/PropertyList.h       18 Oct 2007 11:47:53 -0000      1.20
@@ -31,6 +31,10 @@
 #include <cassert> // for inlines
 #include <cctype> // for toupper
 #include <utility> // for std::pair
+#include <set> // for propNameSet
+#include <boost/multi_index_container.hpp>
+#include <boost/multi_index/ordered_index.hpp>
+#include <boost/multi_index/key_extractors.hpp>
 
 // Forward declaration
 namespace gnash {
@@ -41,7 +45,6 @@
 
 namespace gnash {
 
-
 /// Set of properties associated to an ActionScript object.
 //
 /// The PropertyList container is the sole owner of the Property
@@ -50,52 +53,39 @@
 ///
 class PropertyList
 {
-
-private:
+public:
+       /// A tag type for multi-index
+       struct oType {/**/};
 
        /// The actual container
-       //
-       /// We store Property objects by pointer to allow polymorphism
-       /// so that we can store either SimpleProperty or GetterSetterProperty
-       /// the destructor will take care of deleting all elements.
-       ///
-       /// TODO: change this to a <boost/ptr_container/ptr_map.hpp>
-       ///       so we can store as_member by pointer allowing polymorphism
-       ///       of it (planning to add a getset_as_member) w/out much
-       ///       overhead and with manager ownerhips. See:
-       /// http://www.boost.org/libs/ptr_container/doc/ptr_container.html
-       ///
-       typedef std::map<string_table::key, Property*> container;
-       typedef container::iterator iterator;
-       typedef container::const_iterator const_iterator;
-       typedef container::reverse_iterator reverse_iterator;
-       typedef container::const_reverse_iterator const_reverse_iterator;
-
-       container _props;
-
-       iterator find(string_table::key key) {
-               return _props.find(key);
-       }
-       const_iterator find(string_table::key key) const {
-               return _props.find(key);
-       }
-       iterator end() {
-               return _props.end();
-       }
-       const_iterator end() const {
-               return _props.end();
-       }
-       iterator begin() {
-               return _props.begin();
-       }
-       const_iterator begin() const {
-               return _props.begin();
-       }
-
-public:
+       /// index 0 is the fully indexed name/namespace pairs, which are unique
+       /// Because of the way searching works, this index can also be used to 
search
+       /// for the names alone (composite keys are sorted lexographically, 
beginning
+       /// with the first element specified)
+       ///
+       /// index 1 is an ordered sequence, and it is used for the AS3 style
+       /// enumeration (which requires an order number for each property),
+       /// for slot access, and for array access.
+       typedef boost::multi_index_container<
+               Property,
+               boost::multi_index::indexed_by<
+                       boost::multi_index::ordered_unique<
+                               boost::multi_index::composite_key<
+                                       Property,
+                                       
boost::multi_index::member<Property,string_table::key,&Property::mName>,
+                                       
boost::multi_index::member<Property,string_table::key,&Property::mNamespace>
+                               >
+                       >,
+                       boost::multi_index::ordered_unique<
+                               boost::multi_index::tag<PropertyList::oType>,
+                               
boost::multi_index::member<Property,int,&Property::mOrderId>
+                       >
+               >
+       > container;
 
        /// Construct the PropertyList 
-       PropertyList();
+       PropertyList() : _props()
+       {/**/}
 
        /// Copy constructor
        PropertyList(const PropertyList& pl);
@@ -103,9 +93,6 @@
        /// Assignment operator
        PropertyList& operator=(const PropertyList&);
 
-       /// Delete all Property objects in the container
-       ~PropertyList();
-
        /// Visit the list of properties 
        //
        /// The method will invoke the given visitor method
@@ -123,14 +110,11 @@
        template <class V>
        void visitValues(V& visitor, as_object& this_ptr) const
        {
-               for (const_iterator it = begin(), itEnd = end();
-                               it != itEnd; ++it)
+               for (container::const_iterator it = _props.begin(),
+                       itEnd = _props.end(); it != itEnd; ++it)
                {
-                       string_table::key key = it->first;
-                       const Property* prop = it->second;
-                       as_value val = prop->getValue(this_ptr);
-
-                       visitor(key, val);
+                       as_value val = it->getValue(this_ptr);
+                       visitor(it->mName, val);
                }
        }
 
@@ -163,7 +147,28 @@
        ///         otherwise (and value will be untouched)
        ///
        bool getValue(string_table::key key, as_value& value,
-                       as_object& this_ptr);
+                       as_object& this_ptr, string_table::key nsId = 0);
+
+       /// Get the as_value value of an ordered property
+       ///
+       /// getter/setter will be invoked, just as for getValue
+       ///
+       /// @param order
+       /// The order number: negative for default values,  non-negative for
+       /// properties which were specifically positioned.
+       ///
+       bool getValueByOrder(int order, as_value& val, as_object& this_ptr);
+       
+       /// Get the order number just after the passed order number.
+       ///
+       /// @param order
+       /// 0 is a special value indicating the first order should be returned,
+       /// otherwise, this should be the result of a previous call to
+       /// getOrderAfter
+       ///
+       /// @return
+       /// A value which can be used for ordered access. 
+       const Property* getOrderAfter(int order);
 
        /// Set the value of a property, creating a new one if unexistent.
        //
@@ -187,22 +192,52 @@
        ///     eventual "Setter" function from actually modifying it,
        ///     so we can't promise constness.
        ///
+       /// @param namespaceId
+       /// The namespace in which this should be entered. If 0 is given,
+       /// this will use the first value found, if it exists.
+       ///
        /// @return true if the value was successfully set, false
        ///         otherwise (found a read-only property, most likely).
        ///
-       bool setValue(string_table::key key, const as_value& value,
-                       as_object& this_ptr);
+       bool setValue(string_table::key key, as_value value,
+                       as_object& this_ptr, string_table::key namespaceId = 0);
+
+       /// Reserves a slot number for a property
+       ///
+       /// @param slotId
+       /// The slot id to use. (Note that getOrder() on this property will 
return
+       /// this slot number + 1 if the assignment was successful.)
+       ///
+       /// @param key
+       /// Name of the property.
+       ///
+       /// @param nsId
+       /// The namespace in which the property should be found.
+       ///
+       /// @return true if the slot did not previously exist.
+       bool reserveSlot(unsigned short slotId, string_table::key key,
+               string_table::key nsId = 0);
 
        /// Get a property, if existing
        //
        /// @param key
        ///     Name of the property. Search is case-*sensitive*
        ///
+       /// @param nsId
+       /// The id of the namespace to search
+       ///
        /// @return a Property or NULL, if no such property exists
        ///     ownership of returned Propery is kept by the PropertyList,
        ///     so plase *don't* delete it !
        ///
-       Property* getProperty(string_table::key key);
+       Property* getProperty(string_table::key key, string_table::key nsId = 
0);
+
+       /// Get a property, if existing, by order
+       ///
+       /// @param order
+       /// The ordering id
+       ///
+       const Property* getPropertyByOrder(int order);
 
        /// Delete a propery, if exising and not protected from deletion.
        //
@@ -210,6 +245,9 @@
        /// @param key
        ///     Name of the property. Search is case-*sensitive*
        ///
+       /// @param nsId
+       /// Name of the namespace
+       ///
        /// @return a pair of boolean values expressing whether the property
        ///     was found (first) and whether it was deleted (second).
        ///     Of course a pair(false, true) would be invalid (deleted
@@ -218,7 +256,8 @@
        ///     - (true, false) : property protected from deletion
        ///     - (true, true) : property successfully deleted
        ///
-       std::pair<bool,bool> delProperty(string_table::key key);
+       std::pair<bool,bool> delProperty(string_table::key key,
+               string_table::key nsId = 0);
 
        /// \brief
        /// Add a getter/setter property, if not already existing
@@ -239,7 +278,7 @@
        ///         otherwise (property already existent?)
        ///
        bool addGetterSetter(string_table::key key, as_function& getter,
-               as_function& setter);
+               as_function& setter, string_table::key ns = 0);
 
        /// \brief
        /// Add a destructive getter/setter property, if not already extant.
@@ -257,7 +296,7 @@
        /// otherwise.
        ///
        bool addDestructiveGetterSetter(string_table::key key,
-               as_function& getter, as_function& setter);
+               as_function& getter, as_function& setter, string_table::key ns 
= 0);
 
        /// Set the flags of a property.
        //
@@ -273,7 +312,8 @@
        /// @return true if the value was successfully set, false
        ///         otherwise (either not found or protected)
        ///
-       bool setFlags(string_table::key key, int setTrue, int setFalse);
+       bool setFlags(string_table::key key, int setTrue, int setFalse,
+               string_table::key ns = 0);
 
        /// Set the flags of all properties.
        //
@@ -324,10 +364,17 @@
        ///
        void import(const PropertyList& props);
 
+       // Used to keep track of which properties have been enumerated.
+       typedef std::set<std::pair<string_table::key, string_table::key> > 
propNameSet;
+
        /// \brief
        /// Enumerate all non-hidden properties pushing
        /// their keys to the given as_environment.
-       void enumerateKeys(as_environment& env) const;
+       ///
+       /// @param donelist
+       /// Don't enumerate those in donelist. Add those done to donelist.
+       ///
+       void enumerateKeys(as_environment& env, propNameSet& donelist) const;
 
        /// \brief
        /// Enumerate all non-hidden properties inserting
@@ -391,6 +438,10 @@
        /// Mark all simple properties, getters and setters
        /// as being reachable (for the GC)
        void setReachable() const;
+
+private:
+       container _props;
+       unsigned short mDefaultOrder;
 };
 
 

Index: server/array.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/array.cpp,v
retrieving revision 1.81
retrieving revision 1.82
diff -u -b -r1.81 -r1.82
--- server/array.cpp    2 Oct 2007 12:52:49 -0000       1.81
+++ server/array.cpp    18 Oct 2007 11:47:53 -0000      1.82
@@ -795,7 +795,8 @@
 
 /* virtual public, overriding as_object::get_member */
 bool
-as_array_object::get_member(string_table::key name, as_value *val)
+as_array_object::get_member(string_table::key name, as_value *val,
+       string_table::key nsname)
 {
        // an index has been requested
        int index = index_requested(name);
@@ -805,7 +806,7 @@
                return true;
        }
 
-       return get_member_default(name, val);
+       return get_member_default(name, val, nsname);
 }
 
 void
@@ -814,10 +815,24 @@
        elements.resize(newsize);
 }
 
+void
+as_array_object::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 */
 void
 as_array_object::set_member(string_table::key name,
-               const as_value& val )
+               const as_value& val, string_table::key nsname)
 {
        int index = index_requested(name);
 
@@ -836,7 +851,7 @@
                return;
        }
 
-       as_object::set_member_default(name,val);
+       as_object::set_member_default(name,val, nsname);
 }
 
 as_array_object*

Index: server/array.h
===================================================================
RCS file: /sources/gnash/gnash/server/array.h,v
retrieving revision 1.36
retrieving revision 1.37
diff -u -b -r1.36 -r1.37
--- server/array.h      18 Sep 2007 07:35:02 -0000      1.36
+++ server/array.h      18 Oct 2007 11:47:54 -0000      1.37
@@ -127,6 +127,8 @@
 
        void reverse();
 
+       void set_indexed(unsigned int index, const as_value &v);
+
        /// @param env
        ///     If not-null will be used to properl invoke the toString()
        ///     method against member values.
@@ -290,11 +292,12 @@
        /// Overridden to provide 'length' member
        //
        /// TODO: use a property for handling 'length'
-       virtual bool get_member(string_table::key name, as_value* val);
+       virtual bool get_member(string_table::key name, as_value* val,
+               string_table::key nsname = 0);
 
        /// Overridden to provide array[#]=x semantic
        virtual void set_member(string_table::key name,
-               const as_value& val );
+               const as_value& val, string_table::key nsname = 0);
 
        /// Enumerate elements
        //

Index: server/asClass.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/asClass.cpp,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- server/asClass.cpp  29 Sep 2007 08:24:21 -0000      1.1
+++ server/asClass.cpp  18 Oct 2007 11:47:54 -0000      1.2
@@ -16,324 +16,318 @@
 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
 #include "asClass.h"
+#include "as_object.h"
 #include "ClassHierarchy.h"
 #include "VM.h"
+#include "namedStrings.h"
+#include "as_value.h"
 
 namespace gnash {
-
 #define STV(x) VM::get().getStringTable().value(x).c_str()
 
+asMethod::asMethod()
+{
+//TODO
+}
+
 void
-asNamespace::stubPrototype(string_table::key name)
+asMethod::setOwner(asClass *pOwner)
 {
-       asClass *pClass = VM::get().getClassHierarchy()->newClass();
-       pClass->setName(name);
-       addClass(name, pClass);
+       mPrototype->set_member(NSV::PROP_PROTOTYPE, pOwner->getPrototype());
 }
 
-bool
-asMethod::addValue(string_table::key name, asNamespace *ns, uint32_t slotId,
-       asClass *type, as_value& val, bool isconst, ClassHierarchy *CH)
+void
+asMethod::setReturnType(asClass */*type*/)
 {
-       asBoundValue *bv = CH->newBoundValue();
-       bv->setType(type);
-       bv->setValue(val);
-       return addBinding(name, asBinding(ns, bv, slotId, isconst, false));
+       /* No-op */
 }
 
 bool
-asMethod::addSlot(string_table::key name, asNamespace *ns, uint32_t slotId,
-       asClass *type, ClassHierarchy *CH)
+asMethod::addValue(string_table::key name, asNamespace *ns, uint32_t slotId,
+       asClass *type, as_value& val, bool isconst)
 {
-       asBoundValue *bv = CH->newBoundValue();
-       bv->setType(type);
-       return addBinding(name, asBinding(ns, bv, slotId, false));
+       if (val.is_object())
+               val.to_object()->set_member(NSV::INTERNAL_TYPE, 
type->getName());
+
+       string_table::key nsname = ns ? ns->getURI() : 0;
+
+       int flags = as_prop_flags::dontDelete;
+
+       if (isconst)
+               flags |= as_prop_flags::readOnly;
+
+       mPrototype->init_member(name, val, flags, nsname, slotId);
+       return true;
 }
 
 bool
-asMethod::addMethod(string_table::key name, asNamespace *ns, asMethod *method)
+asClass::addValue(string_table::key name, asNamespace *ns, uint32_t slotId,
+       asClass *type, as_value& val, bool isconst, bool isstatic)
 {
-       return addBinding(name, asBinding(ns, method, false));
+       if (val.is_object())
+               val.to_object()->set_member(NSV::INTERNAL_TYPE, 
type->getName());
+
+       string_table::key nsname = ns ? ns->getURI() : 0;
+
+       int flags = as_prop_flags::dontDelete;
+       if (isconst)
+               flags |= as_prop_flags::readOnly;
+       if (isstatic)
+               flags |= as_prop_flags::staticProp;
+
+       mPrototype->init_member(name, val, flags, nsname, slotId);
+       return true;
 }
 
 bool
-asMethod::addGetter(string_table::key name, asNamespace *ns, asMethod *method,
-       ClassHierarchy *CH)
+asMethod::addMemberClass(string_table::key name, asNamespace *ns,
+       uint32_t slotId, asClass *type)
 {
-       asBinding *bv = getBinding(name);
-       if (bv)
-       {
-               asBoundAccessor *a = bv->getAccessor();
-               if (!a)
-               {
-                       // Okay if this is already bound to a value.
-                       asBoundValue *v = bv->getValue();
-                       if (!v)
-                       {
-                               // Let caller do the logging.
-                               return false;
-                       }
-                       a = CH->newBoundAccessor();
-                       a->setValue(v);
-                       bv->reset(a, bv->isStatic());
-               }
-               return a->setGetter(method);
-       }
-       asBoundAccessor *a = CH->newBoundAccessor();
-       a->setGetter(method);
-       return addBinding(name, asBinding(ns, a, false));
+       return addSlot(name, ns, slotId, type);
 }
 
 bool
-asMethod::addSetter(string_table::key name, asNamespace *ns, asMethod *method,
-       ClassHierarchy *CH)
+asClass::addMemberClass(string_table::key name, asNamespace *ns,
+       uint32_t slotId, asClass *type, bool isstatic)
 {
-       asBinding *bv = getBinding(name);
-       if (bv)
-       {
-               asBoundAccessor *a = bv->getAccessor();
-               if (!a)
-               {
-                       asBoundValue *v = bv->getValue();
-                       if (!v)
-                       {
-                               // Let caller do the logging.
-                               return false;
-                       }
-                       a = CH->newBoundAccessor();
-                       a->setValue(v);
-                       bv->reset(a, bv->isStatic());
-               }
-               return a->setSetter(method);
-       }
-       asBoundAccessor *a = CH->newBoundAccessor();
-       addBinding(name, asBinding(ns, a, false));
-       return a->setSetter(method);
+       return addSlot(name, ns, slotId, type, isstatic);
 }
 
 bool
-asMethod::addMemberClass(string_table::key name, asNamespace *ns,
-       uint32_t slotId, asClass *type)
+asMethod::addSlot(string_table::key name, asNamespace* ns, uint32_t slotId,
+       asClass */*type*/)
 {
-       return addBinding(name, asBinding(ns, type, slotId, false));
+       string_table::key nsname = ns ? ns->getURI() : 0;
+       int flags = as_prop_flags::dontDelete;
+
+       mPrototype->init_member(name, as_value(), flags, nsname, slotId);
+       return true;
 }
 
-// TODO: Figure out how this differs from addMethod
 bool
 asMethod::addSlotFunction(string_table::key name, asNamespace *ns,
        uint32_t slotId, asMethod *method)
 {
-       return addBinding(name, asBinding(ns, method, slotId, false));
+       asClass a;
+       a.setName(NSV::CLASS_FUNCTION);
+       as_value b(method->getPrototype());
+       return addValue(name, ns, slotId, &a, b, false);
 }
 
 bool
-asClass::addValue(string_table::key name, asNamespace *ns, uint32_t slotId,
-       asClass *type, as_value& val, bool isconst, bool isstatic,
-       ClassHierarchy *CH)
+asClass::addSlotFunction(string_table::key name, asNamespace *ns,
+       uint32_t slotId, asMethod *method, bool isstatic)
 {
-       asBoundValue *bv = CH->newBoundValue();
-       bv->setType(type);
-       bv->setValue(val);
-       if (!isstatic)
-               return addBinding(name, asBinding(ns, bv, slotId, isconst, 
isstatic));
-       return addStaticBinding(name, asBinding(ns, bv, slotId, isconst, 
isstatic));
+       asClass a;
+       a.setName(NSV::CLASS_FUNCTION);
+       as_value b(method->getPrototype());
+       return addValue(name, ns, slotId, &a, b, false, isstatic);
 }
 
 bool
-asClass::addSlot(string_table::key name, asNamespace *ns, uint32_t slotId,
-       asClass *type, bool isstatic, ClassHierarchy *CH)
+asClass::addSlot(string_table::key name, asNamespace* ns, uint32_t slotId,
+       asClass */*type*/, bool isstatic)
 {
-       asBoundValue *bv = CH->newBoundValue();
-       bv->setType(type);
-       if (!isstatic)
-               return addBinding(name, asBinding(ns, bv, slotId, isstatic));
-       return addStaticBinding(name, asBinding(ns, bv, slotId, isstatic));
+       string_table::key nsname = ns ? ns->getURI() : 0;
+       int flags = as_prop_flags::dontDelete;
+       if (isstatic)
+               flags |= as_prop_flags::staticProp;
+
+       mPrototype->init_member(name, as_value(), flags, nsname, slotId);
+       return true;
 }
 
 bool
-asClass::addMethod(string_table::key name, asNamespace *ns, asMethod *method,
+asMethod::addMethod(string_table::key name, asNamespace* ns, asMethod* method)
+{
+       string_table::key nsname = ns ? ns->getURI() : 0;
+       as_value val(method->getPrototype());
+
+       mPrototype->init_member(name, val, as_prop_flags::readOnly |
+               as_prop_flags::dontDelete | as_prop_flags::dontEnum, nsname);
+       return true;
+}
+
+bool
+asClass::addMethod(string_table::key name, asNamespace* ns, asMethod* method,
        bool isstatic)
 {
-       if (!isstatic)
-               return addBinding(name, asBinding(ns, method, isstatic));
-       else
-               return addStaticBinding(name, asBinding(ns, method, isstatic));
+       string_table::key nsname = ns ? ns->getURI() : 0;
+       as_value val(method->getPrototype());
+       int flags = as_prop_flags::readOnly | as_prop_flags::dontDelete
+               | as_prop_flags::dontEnum;
+       if (isstatic)
+               flags |= as_prop_flags::staticProp;
+
+       mPrototype->init_member(name, val, flags, nsname);
+       return true;
 }
 
 bool
 asClass::addGetter(string_table::key name, asNamespace *ns, asMethod *method,
-       bool isstatic, ClassHierarchy *CH)
+       bool isstatic)
 {
-       asBinding *bv;
-       if (!isstatic)
-               bv = getBinding(name);
+       string_table::key nsname = ns ? ns->getURI() : 0;
+
+       Property *getset = mPrototype->getOwnProperty(name, nsname);
+
+       if (getset)
+               getset->setGetter(method->getPrototype());
        else
-               bv = getStaticBinding(name);
-       if (bv)
-       {
-               asBoundAccessor *a = bv->getAccessor();
-               if (!a)
-               {
-                       // Okay if this is already bound to a value.
-                       asBoundValue *v = bv->getValue();
-                       if (!v)
                        {
-                               // Let caller do the logging.
-                               return false;
+               int flags = as_prop_flags::dontDelete | as_prop_flags::dontEnum;
+               if (isstatic)
+                       flags |= as_prop_flags::staticProp;
+               mPrototype->init_property(name, *method->getPrototype(), 
+                       *method->getPrototype(), flags, nsname);
                        }
-                       a = CH->newBoundAccessor();
-                       a->setValue(v);
-                       bv->reset(a, bv->isStatic());
-               }
-               return a->setGetter(method);
-       }
-       asBoundAccessor *a = CH->newBoundAccessor();
-       a->setGetter(method);
-       if (!isstatic)
-               return addBinding(name, asBinding(ns, a, isstatic));
-       return addStaticBinding(name, asBinding(ns, a, isstatic));
+       return true;
 }
 
 bool
 asClass::addSetter(string_table::key name, asNamespace *ns, asMethod *method,
-       bool isstatic, ClassHierarchy *CH)
+       bool isstatic)
 {
-       asBinding *bv;
-       if (!isstatic)
-               bv = getBinding(name);
-       else
-               bv = getStaticBinding(name);
+       string_table::key nsname = ns ? ns->getURI() : 0;
 
-       if (bv)
-       {
-               asBoundAccessor *a = bv->getAccessor();
-               if (!a)
-               {
-                       asBoundValue *v = bv->getValue();
-                       if (!v)
+       Property *getset = mPrototype->getOwnProperty(name, nsname);
+
+       if (getset)
+               getset->setSetter(method->getPrototype());
+       else
                        {
-                               // Let caller do the logging.
-                               return false;
-                       }
-                       a = CH->newBoundAccessor();
-                       a->setValue(v);
-                       bv->reset(a, bv->isStatic());
+               int flags = as_prop_flags::dontDelete | as_prop_flags::dontEnum;
+               if (isstatic)
+                       flags |= as_prop_flags::staticProp;
+               mPrototype->init_property(name, *method->getPrototype(), 
+                       *method->getPrototype(), flags, nsname);
                }
-               return a->setSetter(method);
-       }
-       asBoundAccessor *a = CH->newBoundAccessor();
-       a->setSetter(method);
-       if (!isstatic)
-               return addBinding(name, asBinding(ns, a, isstatic));
-       else
-               return addStaticBinding(name, asBinding(ns, a, isstatic));
+       return true;
 }
 
 bool
-asClass::addMemberClass(string_table::key name, asNamespace *ns,
-       uint32_t slotId, asClass *type, bool isstatic)
+asMethod::addGetter(string_table::key name, asNamespace *ns, asMethod *method)
 {
-       if (!isstatic)
-               return addBinding(name, asBinding(ns, type, slotId, isstatic));
-       return addStaticBinding(name, asBinding(ns, type, slotId, isstatic));
+       string_table::key nsname = ns ? ns->getURI() : 0;
+
+       Property *getset = mPrototype->getOwnProperty(name, nsname);
+
+       if (getset)
+               getset->setGetter(method->getPrototype());
+       else
+       {
+               int flags = as_prop_flags::dontDelete | as_prop_flags::dontEnum;
+               mPrototype->init_property(name, *method->getPrototype(), 
+                       *method->getPrototype(), flags, nsname);
+       }
+       return true;
 }
 
-// TODO: Figure out how this differs from addMethod
 bool
-asClass::addSlotFunction(string_table::key name, asNamespace *ns,
-       uint32_t slotId, asMethod *method, bool isstatic)
+asMethod::addSetter(string_table::key name, asNamespace *ns, asMethod *method)
 {
-       if (!isstatic)
-               return addBinding(name, asBinding(ns, method, slotId, 
isstatic));
-       return addStaticBinding(name, asBinding(ns, method, slotId, isstatic));
-}
+       string_table::key nsname = ns ? ns->getURI() : 0;
 
-void
-asNamespace::dump()
-{
-       container::iterator i;
-       for (i = mClasses.begin(); i != mClasses.end(); ++i)
-       {
-               if (!((*i->second).isDeclared()))
+       Property *getset = mPrototype->getOwnProperty(name, nsname);
+
+       if (getset)
+               getset->setSetter(method->getPrototype());
+       else
                {
-                       if (i->second->isSystem())
-                               fprintf(stderr, "(Known to internals) ");
-                       fprintf(stderr, "%s.%s\n", STV(getURI()),
-                               STV(i->second->getName()));
-//             else
-//                     (*i->second).dump();
-               }
+               int flags = as_prop_flags::dontDelete | as_prop_flags::dontEnum;
+               mPrototype->init_property(name, *method->getPrototype(), 
+                       *method->getPrototype(), flags, nsname);
        }
+       return true;
 }
 
 void
-asClass::dump()
+asNamespace::stubPrototype(string_table::key name)
 {
-       binding_container::iterator i;
-       fprintf(stderr, "Class: %s\n", STV(getName()));
-       for (i = mBindings.begin(); i != mBindings.end(); ++i)
-       {
-               fprintf(stderr, "    ");
-               i->second.dump(i->first);
-       }
+       asClass *pClass = VM::get().getClassHierarchy()->newClass();
+       pClass->setName(name);
+       addClass(name, pClass);
 }
 
+#if 0 // TODO
 void
-asBinding::dump(string_table::key name)
+asClass::buildFromPrototype(as_object *o, string_table::key name,
+       ClassHierarchy *pCH)
 {
-       if (mNamespace->isProtected())
-               fprintf(stderr, "+");
-       if (mNamespace->isPrivate())
-               fprintf(stderr, "#");
-       if (mConst)
-               fprintf(stderr, "@");
-       fprintf(stderr, "%s: ", STV(name));
-       switch (mType)
+       setName(name);
+       PropertyList *pList = &o->_members;
+       PropertyList::iterator i = pList->begin();
+
+       for ( ; i != pList->end(); ++i)
        {
-       case T_CLASS:
+               Property *pProp = i->second;
+               fprintf(stderr, "Evaluating property %s.\n", STV(i->first));
+               if (pProp->isDestructive())
        {
-               fprintf(stderr, "Class %s", STV(mClass->getName()));
-               break;
+                       fprintf(stderr, "%s is destructive.\n", STV(i->first));
        }
-       case T_METHOD:
+               if (pProp->isGetterSetter())
        {
-//             if (mConst)
-                       fprintf(stderr, "Member Function: %s", 
STV(mMethod->getReturnType()->getName()));
-//             else
-//                     fprintf(stderr, "Function Slot");
-               break;
+                       fprintf(stderr, "%s is a getset.\n", STV(i->first));
        }
-       case T_VALUE:
+               if (pProp->isReadOnly())
        {
-               if (mValue->getType())
-                       fprintf(stderr, "Value of type %s", 
STV(mValue->getType()->getName()));
-               else
-                       fprintf(stderr, "Value of unknown type.");
-               break;
+                       fprintf(stderr, "%s is read only.\n", STV(i->first));
        }
-       case T_ACCESS:
-       {
-               fprintf(stderr, "GetSet: ");
-               if (mAccess->getGetter())
-               {
-                       fprintf(stderr, "g:%s ", 
STV(mAccess->getGetter()->getReturnType()->getName()));
                }
-               if (mAccess->getSetter())
-               {
-                       fprintf(stderr, "s ");
-               }
-               if (mAccess->getValue())
-               {
-                       fprintf(stderr, "dv: ");
-                       if (mAccess->getValue()->getType())
-                               fprintf(stderr, "%s ", 
STV(mAccess->getValue()->getType()->getName()));
+}
+
+bool
+asClass::addValue(string_table::key name, asNamespace *ns, uint32_t slotId,
+       asClass *type, as_value& val, bool isconst, bool isstatic,
+       ClassHierarchy *CH)
+{
+       asBoundValue *bv = CH->newBoundValue();
+       bv->setType(type);
+       bv->setValue(val);
+       if (!isstatic)
+               return addBinding(name, asBinding(ns, bv, slotId, isconst, 
isstatic));
+       return addStaticBinding(name, asBinding(ns, bv, slotId, isconst, 
isstatic));
+}
+
+bool
+asClass::addSlot(string_table::key name, asNamespace *ns, uint32_t slotId,
+       asClass *type, bool isstatic, ClassHierarchy *CH)
+{
+       asBoundValue *bv = CH->newBoundValue();
+       bv->setType(type);
+       if (!isstatic)
+               return addBinding(name, asBinding(ns, bv, slotId, isstatic));
+       return addStaticBinding(name, asBinding(ns, bv, slotId, isstatic));
+}
+
+bool
+asClass::addMethod(string_table::key name, asNamespace *ns, asMethod *method,
+       bool isstatic)
+{
+       if (!isstatic)
+               return addBinding(name, asBinding(ns, method, isstatic));
                        else
-                               fprintf(stderr, "(unknown type)");
-               }
-               break;
-       }
-       }
-       fprintf(stderr, "\n");
+               return addStaticBinding(name, asBinding(ns, method, isstatic));
 }
 
+bool
+asClass::addMemberClass(string_table::key name, asNamespace *ns,
+       uint32_t slotId, asClass *type, bool isstatic)
+{
+       if (!isstatic)
+               return addBinding(name, asBinding(ns, type, slotId, isstatic));
+       return addStaticBinding(name, asBinding(ns, type, slotId, isstatic));
+}
+
+// TODO: Figure out how this differs from addMethod
+bool
+asClass::addSlotFunction(string_table::key name, asNamespace *ns,
+       uint32_t slotId, asMethod *method, bool isstatic)
+{
+       if (!isstatic)
+               return addBinding(name, asBinding(ns, method, slotId, 
isstatic));
+       return addStaticBinding(name, asBinding(ns, method, slotId, isstatic));
+}
+#endif /* 0 */
 } /* namespace gnash */

Index: server/asClass.h
===================================================================
RCS file: /sources/gnash/gnash/server/asClass.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- server/asClass.h    29 Sep 2007 08:24:21 -0000      1.1
+++ server/asClass.h    18 Oct 2007 11:47:54 -0000      1.2
@@ -23,6 +23,9 @@
 #include <vector>
 #include "string_table.h"
 #include "as_value.h"
+#include "CodeStream.h"
+#include "Property.h"
+#include "as_function.h"
 
 namespace gnash {
 
@@ -31,10 +34,14 @@
 class asMethod;
 class asClass;
 class asException;
-class asBinding;
+typedef Property asBinding;
+//class asBinding;
 class asBoundValue;
 class asBoundAccessor;
 class ClassHierarchy;
+class Property;
+
+class asName;
 
 class asException
 {
@@ -56,7 +63,7 @@
        asNamespace *mNamespace;
        string_table::key mName;
 };
-
+#if 0
 /// An abstract binding for ActionScript.
 class asBinding
 {
@@ -74,6 +81,22 @@
        uint32_t getSlotId() { return mSlotId; }
        void setSlotId(uint32_t s) { mSlotId = s; }
 
+       // Chad: Document
+       string_table::key getName() { return mName; }
+       void setLexOnly(bool) { /* TODO */ }
+
+       /// If true, the attribute has a setter, but no getter.
+       bool isWriteOnly();
+
+       /// If true, the attribute can be read, but not written. Might be
+       /// constant or might have a getter but no setter.
+       bool isReadOnly(); 
+
+       bool isGetSet() { return getAccessor() != NULL; }
+
+       // Conversion from Property
+       asBinding(Property *, string_table::key name);
+
        // As a member method.
        asBinding(asNamespace *ns, asMethod *pMethod, bool isstatic = false) :
                mNamespace(ns), mType(T_METHOD), mSlotId(0), mConst(true),
@@ -110,6 +133,9 @@
                mClass(NULL)
        {/**/}
 
+       asBinding(asMethod *);
+       asBinding(as_function *);
+
        void reset(asBoundAccessor *pAccess, bool isstatic)
        {
                mType = T_ACCESS;
@@ -130,13 +156,15 @@
        asClass* getClass()
        { return mType == T_CLASS ? mClass : NULL; }
 
-private:
+       as_function* getASFunction();
+
        asNamespace *mNamespace;
 
        typedef enum
        {
                T_CLASS,
                T_METHOD,
+               T_AS_FUNCTION,
                T_VALUE,
                T_ACCESS
        } types;
@@ -145,6 +173,8 @@
        uint32_t mSlotId;
        bool mConst;
        bool mStatic;
+       string_table::key mName;
+       as_object* mOwner;
 
        union
        {
@@ -154,16 +184,7 @@
                asBoundAccessor *mAccess;
        };
 };
-
-class asMethodBody
-{
-public:
-       void setSize(std::size_t s) { mData.resize(s); }
-       std::size_t getSize() { return mData.size(); }
-       char *getRaw() { return &mData.front(); }
-private:
-       std::vector<char> mData;
-};
+#endif // comment out of asBinding
 
 /// Represent an ActionScript namespace
 class asNamespace
@@ -219,8 +240,6 @@
                return found;
        }
 
-       void dump();
-
        void setPrivate() { mPrivate = true; }
        void unsetPrivate() { mPrivate = false; }
        bool isPrivate() { return mPrivate; }
@@ -255,7 +274,6 @@
 };
 
 class asBoundValue;
-class asBoundAccessor;
 
 class asBoundAccessor
 {
@@ -280,7 +298,7 @@
        asBoundValue() : mConst(false), mValue()
        { mValue.set_undefined(); }
        void setValue(as_value &v) { mValue = v; }
-       as_value& getCurrentValue() { return mValue; }
+       as_value getCurrentValue() { return mValue; }
 
        void setType(asClass *t) { mType = t; }
        asClass *getType() { return mType; }
@@ -297,6 +315,8 @@
 class asMethod
 {
 private:
+       as_function* mPrototype;
+
        typedef enum
        {
                FLAGS_FINAL = 0x01,
@@ -308,57 +328,45 @@
        typedef std::list<asClass*> argumentList;
        typedef std::map<string_table::key, asBinding> binding_container;
 
-       binding_container mBindings;
-       asClass *mReturnType;
-       asClass* mOwner;
-       asMethod* mSuper;
        int mMinArguments;
        int mMaxArguments;
+       bool mIsNative;
        argumentList mArguments;
        std::list<as_value> mOptionalArguments;
        as_function *mImplementation;
        unsigned char mFlags;
-       asMethodBody *mBody;
+       CodeStream *mBody;
 
-       bool addBinding(string_table::key name, asBinding b)
-       { mBindings[name] = b; return true; }
-
-       asBinding *getBinding(string_table::key name)
-       {
-               binding_container::iterator i;
-               if (mBindings.empty())
-                       return NULL;
-               i = mBindings.find(name);
-               if (i == mBindings.end())
-                       return NULL;
-               return &i->second;
-       }
+       bool addBinding(string_table::key name, asBinding b);
 
 public:
-       asMethod() : mBindings(), mReturnType(NULL),
-               mOwner(NULL), mSuper(NULL), mMinArguments(-1), 
mMaxArguments(-1),
-               mArguments(), mOptionalArguments(), mImplementation(NULL), 
mFlags(0),
-               mBody(NULL)
-       {/**/}
+       as_function* getPrototype() { return mPrototype; }
+
+       asBinding* getBinding(string_table::key name);
 
-       bool hasActivation() { return !mBindings.empty(); }
+       asMethod();
 
-       asMethodBody *getBody() { return mBody; }
-       void setBody(asMethodBody* b) { mBody = b; }
+       bool isNative() { return mIsNative; }
+       bool hasBody() const { return mBody != NULL; }
+
+       as_object* construct(as_object *base_scope) { /* TODO */ return NULL; }
+
+       bool hasActivation();
+
+       CodeStream *getBody() { return mBody; }
+       void setBody(CodeStream *b) { mBody = b; }
 
        bool addValue(string_table::key name, asNamespace *ns, uint32_t slotId,
-               asClass *type, as_value& val, bool isconst, ClassHierarchy *CH);
+               asClass *type, as_value& val, bool isconst);
 
        bool addSlot(string_table::key name, asNamespace *ns, uint32_t slotId,
-               asClass *type, ClassHierarchy *CH);
+               asClass *type);
 
        bool addMethod(string_table::key name, asNamespace *ns, asMethod 
*method);
 
-       bool addGetter(string_table::key name, asNamespace *ns, asMethod 
*method,
-               ClassHierarchy *CH);
+       bool addGetter(string_table::key name, asNamespace *ns, asMethod 
*method);
 
-       bool addSetter(string_table::key name, asNamespace *ns, asMethod 
*method,
-               ClassHierarchy *CH);
+       bool addSetter(string_table::key name, asNamespace *ns, asMethod 
*method);
 
        bool addMemberClass(string_table::key name, asNamespace *ns,
                uint32_t slotId, asClass *type);
@@ -367,26 +375,21 @@
                uint32_t slotId, asMethod *method);
 
        /// \brief
-       /// Get the unique identifier of the owning class.
-       /// 0 indicates that no class owns this.
-       asClass* getOwner() const { return mOwner; }
-
-       /// \brief
        /// Set the owner of this method.
-       void setOwner(asClass* s) { mOwner = s; }
+       void setOwner(asClass* s);
 
        /// \brief
        /// Get the unique identifier for the return type. 0 is 'anything'.
        /// (This is the value of any dynamic property.)
        /// Id reference: Type
-       asClass* getReturnType() const { return mReturnType; }
+       asClass* getReturnType() const;
 
        /// Set the return type
-       void setReturnType(asClass* t) { mReturnType = t; }
+       void setReturnType(asClass* t);
 
-       asMethod *getSuper() { return mSuper; }
+       asMethod *getSuper();
 
-       void setSuper(asMethod* s) { mSuper = s; }
+       void setSuper(asMethod* s);
 
        /// \brief
        /// Is the method final? If so, it may not be overridden.
@@ -464,35 +467,6 @@
        /// Note: This may be NULL, because we might have information about this
        /// function but not actually have it yet.
        as_function* getImplementation() { return mImplementation; }
-
-       /// \brief
-       /// Check to see whether m could override this.
-       ///
-       /// Check to see whether m could override this. This means:
-       /// Same return type. Same parameter types. Same access. At least as 
many
-       /// default arguments. this is not final or private. Should check, but
-       /// does not for information storing reasons: they are not in the same
-       /// override chain. (Can be checked in management object.)
-       /// have a super.
-       bool isOkayAsSuper(const asMethod &m) const
-       {
-               if (mMinArguments < m.mMinArguments
-                       || m.mMaxArguments < mMaxArguments
-                       || isFinal()
-                       || mFlags != m.mFlags
-                       || isPrivate())
-                       return false;
-               for (argumentList::const_iterator i, j; /**/; ++i, ++j)
-               {
-                       if (i == mArguments.end())
-                               return (j == mArguments.end());
-                       if (j == mArguments.end())
-                               return false;
-                       if (*i != *j)
-                               return false;
-               }
-               return true;
-       }
 };
 
 /// A class to represent, abstractly, ActionScript prototypes.
@@ -504,23 +478,24 @@
 class asClass
 {
 public:
+       as_object* getPrototype() { return mPrototype; }
+
        void dump();
 
        bool addValue(string_table::key name, asNamespace *ns, uint32_t slotId,
-               asClass *type, as_value& val, bool isconst, bool isstatic,
-               ClassHierarchy *CH);
+               asClass *type, as_value& val, bool isconst, bool isstatic);
 
        bool addSlot(string_table::key name, asNamespace *ns, uint32_t slotId,
-               asClass *type, bool isstatic, ClassHierarchy *CH);
+               asClass *type, bool isstatic);
 
        bool addMethod(string_table::key name, asNamespace *ns, asMethod 
*method,
                bool isstatic);
 
        bool addGetter(string_table::key name, asNamespace *ns, asMethod 
*method,
-               bool isstatic, ClassHierarchy *CH);
+               bool isstatic);
 
        bool addSetter(string_table::key name, asNamespace *ns, asMethod 
*method,
-               bool isstatic, ClassHierarchy *CH);
+               bool isstatic);
 
        bool addMemberClass(string_table::key name, asNamespace *ns,
                uint32_t slotId, asClass *type, bool isstatic);
@@ -587,11 +562,16 @@
 
        /// This is our constructor.
        void setConstructor(asMethod *m) { mConstructor = m; }
+       asMethod *getConstructor() { return mConstructor; }
 
        void setStaticConstructor(asMethod *m) { mStaticConstructor = m; }
 
        void setSuper(asClass *p) { mSuper = p; }
 
+       /// Try to build an asClass object from just a prototype.
+       void buildFromPrototype(as_object *o, string_table::key name,
+               ClassHierarchy *);
+
        void setDeclared() { mDeclared = true; }
        bool isDeclared() { return mDeclared; }
        void setInherited() { mInherited = true; }
@@ -608,7 +588,24 @@
                mSystem(false)
        {/**/}
 
+
+       asBinding *getBinding(string_table::key name)
+       {
+               binding_container::iterator i;
+               if (mBindings.empty())
+                       return NULL;
+               i = mBindings.find(name);
+               if (i == mBindings.end())
+                       return NULL;
+               return &i->second;
+       }
+
+       asBinding* getGetBinding(as_value& v, asName& n);
+       asBinding* getSetBinding(as_value& v, asName& n);
+
 private:
+       as_object *mPrototype;
+
        bool addBinding(string_table::key name, asBinding b)
        { mBindings[name] = b; return true; }
        bool addStaticBinding(string_table::key name, asBinding b)
@@ -625,17 +622,6 @@
                return &i->second;
        }
 
-       asBinding *getBinding(string_table::key name)
-       {
-               binding_container::iterator i;
-               if (mBindings.empty())
-                       return NULL;
-               i = mBindings.find(name);
-               if (i == mBindings.end())
-                       return NULL;
-               return &i->second;
-       }
-
        bool mFinal;
        bool mSealed;
        bool mDynamic;

Index: server/as_function.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/as_function.cpp,v
retrieving revision 1.44
retrieving revision 1.45
diff -u -b -r1.44 -r1.45
--- server/as_function.cpp      6 Oct 2007 06:28:29 -0000       1.44
+++ server/as_function.cpp      18 Oct 2007 11:47:54 -0000      1.45
@@ -347,6 +347,14 @@
 
        boost::intrusive_ptr<as_object> newobj;
 
+       as_value us;
+       bool has_proto = false;
+       get_member(NSV::PROP_PROTOTYPE, &us);
+       if (!us.is_undefined())
+       {
+               has_proto = true;
+       }
+
         // a built-in class takes care of assigning a prototype
        // TODO: change this
         if ( isBuiltin() )
@@ -409,6 +417,9 @@
                call(fn_call(newobj.get(), &env, nargs, first_arg_index));
        }
     
+       if (!has_proto)
+               set_member(NSV::PROP_PROTOTYPE, as_value(newobj));
+    
        return newobj;
 }
 

Index: server/as_object.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/as_object.cpp,v
retrieving revision 1.68
retrieving revision 1.69
diff -u -b -r1.68 -r1.69
--- server/as_object.cpp        6 Oct 2007 09:54:54 -0000       1.68
+++ server/as_object.cpp        18 Oct 2007 11:47:54 -0000      1.69
@@ -36,6 +36,8 @@
 #include <boost/algorithm/string/case_conv.hpp>
 #include <utility> // for std::pair
 #include "namedStrings.h"
+#include "asName.h"
+#include "asClass.h"
 
 // Anonymous namespace used for module-static defs
 namespace {
@@ -94,11 +96,12 @@
 
 /*protected*/
 bool
-as_object::get_member_default(string_table::key name, as_value* val)
+as_object::get_member_default(string_table::key name, as_value* val,
+       string_table::key nsname)
 {
        assert(val);
 
-       Property* prop = findProperty(name);
+       Property* prop = findProperty(name, nsname);
        if ( ! prop ) return false;
 
        try 
@@ -115,41 +118,103 @@
        
 }
 
+Property*
+as_object::getByIndex(int index)
+{
+       // The low byte is used to contain the depth of the property.
+       unsigned char depth = index & 0xFF;
+       index /= 256; // Signed
+       as_object *obj = this;
+       while (depth--)
+       {
+               obj = obj->get_prototype().get();
+               if (!obj)
+                       return NULL;
+       }
+
+       return const_cast<Property *>(obj->_members.getPropertyByOrder(index));
+}
+
+int
+as_object::nextIndex(int index, as_object **owner)
+{
+skip_duplicates:
+       unsigned char depth = index & 0xFF;
+       unsigned char i = depth;
+       index /= 256; // Signed
+       as_object *obj = this;
+       while (i--)
+       {
+               obj = obj->get_prototype().get();
+               if (!obj)
+                       return 0;
+       }
+       
+       const Property *p = obj->_members.getOrderAfter(index);
+       if (!p)
+       {
+               obj = obj->get_prototype().get();
+               if (!obj)
+                       return 0;
+               p = obj->_members.getOrderAfter(0);
+               ++depth;
+       }
+       if (p)
+       {
+               if (findProperty(p->getName(), p->getNamespace()) != p)
+               {
+                       index = p->getOrder() * 256 | depth;
+                       goto skip_duplicates; // Faster than recursion.
+               }
+               if (owner)
+                       *owner = obj;
+               return p->getOrder() * 256 | depth;
+       }
+       return 0;
+}
+
 /*private*/
 Property*
-as_object::findProperty(string_table::key key)
+as_object::findProperty(string_table::key key, string_table::key nsname, 
+       as_object **owner)
 {
        // don't enter an infinite loop looking for __proto__ ...
        if (key == NSV::PROP_uuPROTOuu)
        {
-               return _members.getProperty(key);
+               if (owner != NULL)
+                       *owner = this;
+               return _members.getProperty(key, nsname);
        }
 
-       // this set will keep track of visited objects,
-       // to avoid infinite loops
-       std::set< as_object* > visited;
+       // keep track of visited objects, avoid infinite loops.
+       std::set<as_object*> visited;
 
        boost::intrusive_ptr<as_object> obj = this;
-       while ( obj && visited.insert(obj.get()).second )
+       while (obj && visited.insert(obj.get()).second)
        {
                Property* prop = obj->_members.getProperty(key);
-               if ( prop ) return prop;
-               else obj = obj->get_prototype();
+               if (prop)
+               {
+                       if (owner != NULL)
+                               *owner = obj.get();
+                       return prop;
+               }
+               else
+                       obj = obj->get_prototype();
        }
 
        // No Property found
        return NULL;
-
 }
 
 /*private*/
 Property*
-as_object::findGetterSetter(string_table::key key)
+as_object::findGetterSetter(string_table::key key, string_table::key nsname)
 {
        // don't enter an infinite loop looking for __proto__ ...
        if (key == NSV::PROP_uuPROTOuu)
        {
-               Property* prop = _members.getProperty(key);
+               Property* prop = _members.getProperty(key, nsname);
                if ( ! prop ) return NULL;
                if ( ! prop->isGetterSetter() ) return NULL;
                return prop;
@@ -162,7 +227,7 @@
        boost::intrusive_ptr<as_object> obj = this;
        while ( obj && visited.insert(obj.get()).second )
        {
-               Property* prop = obj->_members.getProperty(key);
+               Property* prop = obj->_members.getProperty(key, nsname);
                if ( prop && prop->isGetterSetter() )
                {
                        // what if a property is found which is
@@ -174,7 +239,6 @@
 
        // No Getter/Setter property found
        return NULL;
-
 }
 
 /*protected*/
@@ -184,7 +248,7 @@
        static string_table::key key = NSV::PROP_uuPROTOuu;
 
        // TODO: check what happens if __proto__ is set as a user-defined 
getter/setter
-       if (_members.setValue(key, as_value(proto.get()), *this) )
+       if (_members.setValue(key, as_value(proto.get()), *this, 0) )
        {
                // TODO: optimize this, don't scan again !
                _members.setFlags(key, flags, 0);
@@ -192,75 +256,88 @@
 }
 
 void
-as_object::set_member_default(string_table::key key, const as_value& val )
+as_object::reserveSlot(string_table::key name, string_table::key nsId,
+       unsigned short slotId)
 {
-       //log_msg(_("set_member_default(%s)"), key.c_str());
+       _members.reserveSlot(name, nsId, slotId);
+}
 
-       // found a getter/setter property in the inheritance chain
-       // so set that and return
-       Property* prop = findGetterSetter(key);
-       if ( prop )
-       {
-               try 
+// Handles read_only and static properties properly.
+void
+as_object::set_member_default(string_table::key key, const as_value& val,
+       string_table::key nsname)
+{
+       //log_msg(_("set_member_default(%s)"), key.c_str());
+       Property* prop = findProperty(key, nsname);
+       if (prop)
                {
-                       //log_msg(_("Found a getter/setter property for key 
%s"), key.c_str());
                        if (prop->isReadOnly())
                        {
-                               IF_VERBOSE_ASCODING_ERRORS(
-                                       log_aserror(_("Attempt to set read-only 
property '%s'"),
-                                                   
_vm.getStringTable().value(key).c_str());
-                               );
-                       } else
+                       IF_VERBOSE_ASCODING_ERRORS(log_aserror(_(""
+                               "Attempt to set read-only property '%s'"),
+                               _vm.getStringTable().value(key).c_str()););
+                       return;
+               }
+
+               if (prop->isGetterSetter() || prop->isStatic())
+               {
+                       try
                        {
                                prop->setValue(*this, val);
-                       }
                        return;
                }
                catch (ActionException& exc)
                {
-                       log_msg(_("%s: Exception %s.  Will create a new 
member"), _vm.getStringTable().value(key).c_str(), exc.what());
+                               log_msg(_("%s: Exception %s. Will create a new 
member"),
+                                       
_vm.getStringTable().value(key).c_str(), exc.what());
+                       }
                }
        }
 
-       //log_msg(_("Found no getter/setter property for key %s"), key.c_str());
-
-       // No getter/setter property found, so set (or create) a
-       // SimpleProperty (if possible)
-       if (!_members.setValue(key, val, *this) )
+       // Property does not exist, so it won't be read-only. Set it.
+       if (!_members.setValue(key, const_cast<as_value&>(val), *this, nsname))
        {
                IF_VERBOSE_ASCODING_ERRORS(
-               log_aserror(_("Attempt to set read-only property ``%s''"
-                       " on object ``%p''"),
-                       _vm.getStringTable().value(key).c_str(), (void*)this);
-               );
+                       log_aserror(_("Unknown failure in setting property '%s' 
on "
+                       "object '%p'"), _vm.getStringTable().value(key).c_str(),
+                       (void*) this););
        }
-
 }
 
 void
-as_object::init_member(const std::string& key1, const as_value& val, int flags)
+as_object::init_member(const std::string& key1, const as_value& val, int flags,
+       string_table::key nsname)
 {
        if ( _vm.getSWFVersion() < 7 )
        {
                std::string keylower = key1;
                boost::to_lower(keylower, _vm.getLocale());
 
-               init_member(_vm.getStringTable().find(keylower), val, flags);
+               init_member(_vm.getStringTable().find(keylower), val, flags, 
nsname);
 
        }
        else
        {
-               init_member(_vm.getStringTable().find(key1), val, flags);
+               init_member(_vm.getStringTable().find(key1), val, flags, 
nsname);
        }
 }
 
 void
-as_object::init_member(string_table::key key, const as_value& val, int flags)
+as_object::init_member(string_table::key key, const as_value& val, int flags,
+       string_table::key nsname, int order)
 {
        //log_debug(_("Initializing member %s for object %p"), 
_vm.getStringTable().value(key).c_str(), (void*) this);
 
+       if (order >= 0 && !_members.
+               reserveSlot(static_cast<unsigned short>(order), key, nsname))
+       {
+               log_error(_("Attempt to set a slot for either a slot or a 
property "
+                       "which already exists."));
+               return;
+       }
+               
        // Set (or create) a SimpleProperty 
-       if (! _members.setValue(key, val, *this) )
+       if (! _members.setValue(key, const_cast<as_value&>(val), *this, nsname) 
)
        {
                log_error(_("Attempt to initialize read-only property ``%s''"
                        " on object ``%p'' twice"),
@@ -269,34 +346,34 @@
                assert(0);
        }
        // TODO: optimize this, don't scan again !
-       _members.setFlags(key, flags, 0);
+       _members.setFlags(key, flags, nsname);
 }
 
 void
 as_object::init_property(const std::string& key, as_function& getter,
-               as_function& setter, int flags)
+               as_function& setter, int flags, string_table::key nsname)
 {
        if ( _vm.getSWFVersion() < 7 )
        {
                std::string name = key;
                boost::to_lower(name, _vm.getLocale());
                string_table::key k = _vm.getStringTable().find(name);
-               init_property(k, getter, setter, flags);
+               init_property(k, getter, setter, flags, nsname);
        }
        else
        {
                string_table::key k = _vm.getStringTable().find(key);
-               init_property(k, getter, setter, flags);
+               init_property(k, getter, setter, flags, nsname);
        }
 
 }
 
 void
 as_object::init_property(string_table::key key, as_function& getter,
-               as_function& setter, int flags)
+               as_function& setter, int flags, string_table::key nsname)
 {
        bool success;
-       success = _members.addGetterSetter(key, getter, setter);
+       success = _members.addGetterSetter(key, getter, setter, nsname);
 
        // We shouldn't attempt to initialize a property twice, should we ?
        assert(success);
@@ -304,35 +381,40 @@
        //log_msg(_("Initialized property '%s'"), name.c_str());
 
        // TODO: optimize this, don't scan again !
-       _members.setFlags(key, flags, 0);
+       _members.setFlags(key, flags, nsname);
 
 }
 
 bool
 as_object::init_destructive_property(string_table::key key, as_function& 
getter,
-       as_function& setter, int flags)
+       as_function& setter, int flags, string_table::key nsname)
 {
        bool success;
 
        // No case check, since we've already got the key.
-       success = _members.addDestructiveGetterSetter(key, getter, setter);
-       _members.setFlags(key, flags, 0);
+       success = _members.addDestructiveGetterSetter(key, getter, setter, 
nsname);
+       _members.setFlags(key, flags, nsname);
        return success;
 }
 
 void
-as_object::init_readonly_property(const std::string& key, as_function& getter, 
int initflags)
+as_object::init_readonly_property(const std::string& key, as_function& getter,
+       int initflags, string_table::key nsname)
 {
-       init_property(key, getter, getter, initflags);
-
-       as_prop_flags& flags = 
getOwnProperty(_vm.getStringTable().find(key))->getFlags();
-
-       // ActionScript must not change the flags of this builtin property.
-       flags.set_is_protected(true);
-
-       // Make the property read-only; that is, the default no-op handler will
-       // be triggered when ActionScript tries to set it.
-       flags.set_read_only();
+       string_table::key k;
+       if ( _vm.getSWFVersion() < 7 )
+       {
+               std::string name = key;
+               boost::to_lower(name, _vm.getLocale());
+               k = _vm.getStringTable().find(name);
+       }
+       else
+       {
+               k = _vm.getStringTable().find(key);
+       }
+       init_property(k, getter, getter, initflags | as_prop_flags::readOnly
+               | as_prop_flags::isProtected, nsname);
+       assert(_members.getProperty(k, nsname));
 }
 
 std::string
@@ -350,10 +432,19 @@
 
 bool
 as_object::set_member_flags(string_table::key name,
-               int setTrue, int setFalse)
+               int setTrue, int setFalse, string_table::key nsname)
 {
        // TODO: accept a std::string directly
-       return _members.setFlags(name, setTrue, setFalse);
+       return _members.setFlags(name, setTrue, setFalse, nsname);
+}
+
+void
+as_object::add_interface(as_object* obj)
+{
+       if (std::find(mInterfaces.begin(), mInterfaces.end(), obj) == 
mInterfaces.end())
+               mInterfaces.push_back(obj);
+       else
+               fprintf(stderr, "Not adding duplicate interface.\n");
 }
 
 bool
@@ -363,8 +454,13 @@
 
        std::set< as_object* > visited;
 
+       if (this == ctor)
+       { assert(0); }
        while (obj && visited.insert(obj.get()).second )
        {
+               if (!mInterfaces.empty() &&
+                       std::find(mInterfaces.begin(), mInterfaces.end(), obj) 
!= mInterfaces.end())
+                       return true;
                if ( obj->get_prototype() == ctor->getPrototype() ) return true;
                obj = obj->get_prototype(); 
        }
@@ -513,11 +609,12 @@
        // this set will keep track of visited objects,
        // to avoid infinite loops
        std::set< as_object* > visited;
+       PropertyList::propNameSet named;
 
        boost::intrusive_ptr<as_object> obj = const_cast<as_object*>(this);
        while ( obj && visited.insert(obj.get()).second )
        {
-               obj->_members.enumerateKeys(env);
+               obj->_members.enumerateKeys(env, named);
                obj = obj->get_prototype();
        }
 
@@ -584,32 +681,32 @@
 }
 
 std::pair<bool,bool>
-as_object::delProperty(string_table::key name)
+as_object::delProperty(string_table::key name, string_table::key nsname)
 {
        if ( _vm.getSWFVersion() < 7 )
        {
                std::string key = _vm.getStringTable().value(name);
                boost::to_lower(key, _vm.getLocale());
-               return _members.delProperty(_vm.getStringTable().find(key));
+               return _members.delProperty(_vm.getStringTable().find(key), 
nsname);
        }
        else
        {
-               return _members.delProperty(name);
+               return _members.delProperty(name, nsname);
        }
 }
 
 Property*
-as_object::getOwnProperty(string_table::key name)
+as_object::getOwnProperty(string_table::key name, string_table::key nsname)
 {
        if ( _vm.getSWFVersion() < 7 )
        {
                std::string key = _vm.getStringTable().value(name);
                boost::to_lower(key, _vm.getLocale());
-               return _members.getProperty(_vm.getStringTable().find(key));
+               return _members.getProperty(_vm.getStringTable().find(key), 
nsname);
        }
        else
        {
-               return _members.getProperty(name);
+               return _members.getProperty(name, nsname);
        }
 }
 
@@ -685,10 +782,10 @@
 #endif 
 
 as_value
-as_object::getMember(string_table::key name)
+as_object::getMember(string_table::key name, string_table::key nsname)
 {
        as_value ret;
-       get_member(name, &ret);
+       get_member(name, &ret, nsname);
        //get_member(PROPNAME(name), &ret);
        return ret;
 }

Index: server/as_object.h
===================================================================
RCS file: /sources/gnash/gnash/server/as_object.h,v
retrieving revision 1.74
retrieving revision 1.75
diff -u -b -r1.74 -r1.75
--- server/as_object.h  6 Oct 2007 09:54:54 -0000       1.74
+++ server/as_object.h  18 Oct 2007 11:47:54 -0000      1.75
@@ -45,6 +45,7 @@
 
 #include <cmath>
 #include <utility> // for std::pair
+#include <set>
 
 // Forward declarations
 namespace gnash {
@@ -52,10 +53,14 @@
        class sprite_instance;
        class as_environment;
        class VM;
+       class Machine;
 }
 
 namespace gnash {
 
+class asClass;
+class asName;
+
 /// \brief
 /// A generic bag of attributes. Base class for all ActionScript-able objects.
 //
@@ -70,6 +75,10 @@
        public ref_counted
 #endif
 {
+       friend class asClass;
+       friend class Machine;
+
+       typedef std::set<std::pair<string_table::key, string_table::key> > 
propNameSet;
 private:
        /// Properties of this objects 
        PropertyList _members;
@@ -85,13 +94,21 @@
        //
        /// @returns a Getter/Setter propery if found, NULL if not found
        ///
-       Property* findGetterSetter(string_table::key name);
+       Property* findGetterSetter(string_table::key name, 
+               string_table::key nsname = 0);
 
        /// Find a property scanning the inheritance chain
-       //
+       ///
+       /// @param name
+       /// The string id to look for
+       ///
+       /// @param owner
+       /// If not null, this is set to the object which contained the property.
+       ///
        /// @returns a Propery if found, NULL if not found
        ///
-       Property* findProperty(string_table::key name);
+       Property* findProperty(string_table::key name, string_table::key nsname,
+               as_object **owner = NULL);
 
 public:
 
@@ -190,15 +207,22 @@
        /// @param val
        ///     Value to assign to the named property.
        ///
-       virtual void set_member(string_table::key name, const as_value& val)
+       virtual void set_member(string_table::key name, const as_value& val,
+               string_table::key nsname = 0)
        {
-               return set_member_default(name, val);
+               return set_member_default(name, val, nsname);
        }
 
 #ifdef NEW_KEY_LISTENER_LIST_DESIGN
        virtual bool on_event(const event_id& id );
 #endif
 
+       /// Reserve a slot
+       ///
+       /// Reserves a slot for a property to follow.
+       void reserveSlot(string_table::key name, string_table::key nsId,
+               unsigned short slotId);
+
        /// Initialize a member value by string
        //
        /// This is just a wrapper around the other init_member method
@@ -216,7 +240,12 @@
        ///     Flags for the new member. By default dontDelete and dontEnum.
        ///     See as_prop_flags::Flags.
        ///
-       void init_member(const std::string& name, const as_value& val, int 
flags=as_prop_flags::dontDelete|as_prop_flags::dontEnum);
+       /// @param nsname
+       /// The id of the namespace to which this member belongs. 0 is a 
wildcard
+       /// and will be matched by anything not asking for a specific namespace.
+       void init_member(const std::string& name, const as_value& val, 
+               int flags=as_prop_flags::dontDelete|as_prop_flags::dontEnum, 
+               string_table::key nsname = 0);
 
        /// Initialize a member value by key
        //
@@ -238,7 +267,18 @@
        ///     Flags for the new member. By default dontDelete and dontEnum.
        ///     See as_prop_flags::Flags.
        ///
-       void init_member(string_table::key key, const as_value& val, int 
flags=as_prop_flags::dontDelete|as_prop_flags::dontEnum);
+       /// @param nsname
+       /// The id of the namespace to which this member belongs. 0 is a 
wildcard
+       /// and will be matched by anything not asking for a specific namespace.
+       ///
+       /// @param slotId
+       /// If this is a non-negative value which will fit in an unsigned short,
+       /// this is used as the slotId and can be subsequently found with
+       /// get_slot
+       ///
+       void init_member(string_table::key key, const as_value& val, 
+               int flags=as_prop_flags::dontDelete|as_prop_flags::dontEnum,
+               string_table::key nsname = 0, int slotId = -1);
 
        /// \brief
        /// Initialize a getter/setter property by name
@@ -263,8 +303,12 @@
        ///     Flags for the new member. By default dontDelete and dontEnum.
        ///     See as_prop_flags::Flags.
        ///
+       /// @param nsname
+       /// The id of the namespace to which this member belongs. 0 is a 
wildcard
+       /// and will be matched by anything not asking for a specific namespace.
        void init_property(const std::string& key, as_function& getter,
-               as_function& setter, int 
flags=as_prop_flags::dontDelete|as_prop_flags::dontEnum);
+               as_function& setter, int 
flags=as_prop_flags::dontDelete|as_prop_flags::dontEnum,
+               string_table::key nsname = 0);
 
        /// \brief
        /// Initialize a getter/setter property by key
@@ -288,8 +332,12 @@
        ///     Flags for the new member. By default dontDelete and dontEnum.
        ///     See as_prop_flags::Flags.
        ///
+       /// @param nsname
+       /// The id of the namespace to which this member belongs. 0 is a 
wildcard
+       /// and will be matched by anything not asking for a specific namespace.
        void init_property(string_table::key key, as_function& getter,
-               as_function& setter, int 
flags=as_prop_flags::dontDelete|as_prop_flags::dontEnum);
+               as_function& setter, int 
flags=as_prop_flags::dontDelete|as_prop_flags::dontEnum,
+               string_table::key nsname = 0);
 
 
        /// \brief
@@ -316,9 +364,13 @@
        ///     Flags for the new member. By default dontDelete and dontEnum.
        ///     See as_prop_flags::Flags.
        ///
+       /// @param nsname
+       /// The id of the namespace to which this member belongs. 0 is a 
wildcard
+       /// and will be matched by anything not asking for a specific namespace.
        ///
        bool init_destructive_property(string_table::key key, as_function& 
getter,
-               as_function& setter, int flags=as_prop_flags::dontEnum);
+               as_function& setter, int flags=as_prop_flags::dontEnum,
+               string_table::key nsname = 0);
 
        /// \brief
        /// Use this method for read-only properties.
@@ -331,8 +383,12 @@
        /// The arguments are the same as the above init_property arguments,
        /// although the setter argument is omitted.
        ///
+       /// @param nsname
+       /// The id of the namespace to which this member belongs. 0 is a 
wildcard
+       /// and will be matched by anything not asking for a specific namespace.
        void init_readonly_property(const std::string& key, as_function& getter,
-                       int 
flags=as_prop_flags::dontDelete|as_prop_flags::dontEnum);
+                       int 
flags=as_prop_flags::dontDelete|as_prop_flags::dontEnum,
+                       string_table::key nsname = 0);
 
        /// Get a member as_value by name
        //
@@ -355,13 +411,23 @@
        ///     Will be untouched if no property with the given name
        ///     was found.
        ///
+       /// @param nsname
+       /// The id of the namespace to which this member belongs. 0 is a 
wildcard
+       /// and will be matched by anything not asking for a specific namespace.
+       ///
        /// @return true of the named property was found, false otherwise.
        ///
-       virtual bool get_member(string_table::key name, as_value* val)
+       virtual bool get_member(string_table::key name, as_value* val,
+               string_table::key nsname = 0)
        {
-               return get_member_default(name, val);
+               return get_member_default(name, val, nsname);
        }
 
+       /// Chad: Document
+       bool isQName() const { return false; /* TODO: Implement */ }
+       bool isXML() const { return false; /* TODO */ }
+       bool isDictionary() const { return false; /* TODO */ }
+
        /// Get a member as_value by name in an AS-compatible way
        //
        /// NOTE that this method is non-const becase a property
@@ -374,11 +440,15 @@
        ///     if the current VM is initialized for a  target
        ///     up to SWF6.
        ///
+       /// @param nsname
+       /// The id of the namespace to which this member belongs. 0 is a 
wildcard
+       /// and will be matched by anything not asking for a specific namespace.
+       ///
        /// @return value of the member (possibly undefined),
        ///     or undefined if not found. Use get_member if you
        ///     need to know wheter it was found or not.
        ///
-       as_value getMember(string_table::key name);
+       as_value getMember(string_table::key name, string_table::key nsname = 
0);
 
        /// Call a method of this object in an AS-compatible way
        //
@@ -414,6 +484,10 @@
        ///     Case insensitive up to SWF6,
        ///     case *sensitive* from SWF7 up.
        ///
+       /// @param nsname
+       /// The id of the namespace to which this member belongs. 0 is a 
wildcard
+       /// and will be matched by anything not asking for a specific namespace.
+       ///
        /// @return a pair of boolean values expressing whether the property
        ///     was found (first) and whether it was deleted (second).
        ///     Of course a pair(false, true) would be invalid (deleted
@@ -422,7 +496,7 @@
        ///     - (true, false) : property protected from deletion
        ///     - (true, true) : property successfully deleted
        ///
-       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.
        //
@@ -433,11 +507,40 @@
        ///     Case insensitive up to SWF6,
        ///     case *sensitive* from SWF7 up.
        ///
+       /// @param nsname
+       /// The id of the namespace to which this member belongs. 0 is a 
wildcard
+       /// and will be matched by anything not asking for a specific namespace.
+       ///
        /// @return
        ///     a Property pointer, or NULL if this object doesn't
        ///     contain the named property.
        ///
-       Property* getOwnProperty(string_table::key name);
+       Property* getOwnProperty(string_table::key name, string_table::key 
nsname = 0);
+
+       /// Get a property from this object (or a prototype) by ordering index.
+       ///
+       /// @param index
+       /// An index returned by nextIndex
+       ///
+       /// @return
+       /// The property associated with the order index.
+       Property *getByIndex(int index);
+
+       /// Get the next index after the one whose index was used as a 
parameter.
+       ///
+       /// @param index
+       /// 0 is a starter index -- use it to get the first index. Using the
+       /// return value in subsequent calls will walk through all enumerable
+       /// properties in the list.
+       ///
+       /// @param owner
+       /// If owner is not NULL, it will be set to the exact object to which
+       /// the property used for the value of index belongs, if such a property
+       /// exists, and left untouched otherwise.
+       ///
+       /// @return
+       /// A value which can be fed to getByIndex, or 0 if there are no more.
+       int nextIndex(int index, as_object **owner = NULL);
 
        /// Set member flags (probably used by ASSetPropFlags)
        //
@@ -452,11 +555,15 @@
        /// @param setFalse
        ///     the set of flags to clear
        ///
+       /// @param nsname
+       /// The id of the namespace to which this member belongs. 0 is a 
wildcard
+       /// and will be matched by anything not asking for a specific namespace.
+       ///
        /// @return true on success, false on failure
        ///     (non-existent or protected member)
        ///
        bool set_member_flags(string_table::key name,
-                       int setTrue, int setFalse=0);
+                       int setTrue, int setFalse=0, string_table::key nsname = 
0);
 
        /// Cast to a sprite, or return NULL
        virtual sprite_instance* to_movie() { return NULL; }
@@ -464,6 +571,10 @@
        /// Cast to a as_function, or return NULL
        virtual as_function* to_function() { return NULL; }
 
+       /// Add an interface to the list of interfaces.
+       /// Used by instanceOf
+       void add_interface(as_object* ctor);
+
        /// \brief
        /// Check whether this object is an instance of the given
        /// as_function constructor
@@ -625,7 +736,8 @@
        /// @param val
        ///     The as_value to store a found variable's value in.
        ///
-       bool get_member_default(string_table::key name, as_value* val);
+       bool get_member_default(string_table::key name, as_value* val, 
+               string_table::key nsname);
 
        /// Set a member value
        //
@@ -643,7 +755,8 @@
        /// @param val
        ///     Value to assign to the named property.
        ///
-       void set_member_default(string_table::key name, const as_value& val);
+       void set_member_default(string_table::key name, const as_value& val, 
+               string_table::key nsname);
 
 #ifdef GNASH_USE_GC
        /// Mark all reachable resources, override from GcResource.
@@ -673,6 +786,10 @@
 
 private:
 
+       /// The constructors of the objects which are the interfaces
+       /// implemented by this one.
+       std::list<as_object*> mInterfaces;
+
        /// Reference to this object's '__proto__'
        //boost::intrusive_ptr<as_object> m_prototype;
 

Index: server/as_prop_flags.h
===================================================================
RCS file: /sources/gnash/gnash/server/as_prop_flags.h,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -b -r1.8 -r1.9
--- server/as_prop_flags.h      1 Jul 2007 10:54:20 -0000       1.8
+++ server/as_prop_flags.h      18 Oct 2007 11:47:54 -0000      1.9
@@ -49,7 +49,13 @@
                dontDelete      = 1 << 1,
 
                /// Protect from assigning a value
-               readOnly        = 1 << 2
+               readOnly        = 1 << 2,
+
+               /// Property is static -- assignments change, not override.
+               staticProp      = 1 << 3,
+
+               /// Flags are protected from changes
+               isProtected     = 1 << 4
        };
 
        /// mask for flags
@@ -61,7 +67,7 @@
 
 
        /// Default constructor
-       as_prop_flags() : _flags(0), _protected(false)
+       as_prop_flags() : _flags(0)
        {
        }
 
@@ -70,27 +76,35 @@
                :
                _flags(((read_only) ? readOnly : 0) |
                                ((dont_delete) ? dontDelete : 0) |
-                               ((dont_enum) ? dontEnum : 0)),
-               _protected(false)
+                               ((dont_enum) ? dontEnum : 0))
        {
        }
 
        /// Constructor, from numerical value
        as_prop_flags(const int flags)
-               : _flags(flags), _protected(false)
+               : _flags(flags)
        {
        }
 
        bool operator== (const as_prop_flags& o) const
        {
-               return ( _flags == o._flags ) && ( _protected == o._protected );
+               return ( _flags == o._flags );
        }
 
        bool operator!= (const as_prop_flags& o) const
        {
-               return ( _flags != o._flags ) || ( _protected != o._protected );
+               return ( _flags != o._flags );
        }
 
+       /// Get "static" flag
+       bool get_static() const { return (_flags & staticProp) ? true : false; }
+
+       /// Set "static" flag
+       void set_static() { _flags |= staticProp; }
+
+       /// Clear "static" flag
+       void clear_static() { _flags &= ~staticProp; }
+
        /// Get "read-only" flag 
        bool get_read_only() const { return (((_flags & 
readOnly)!=0)?true:false); }
 
@@ -122,13 +136,17 @@
        int get_flags() const { return _flags; }
 
        /// Get "protected" flag
-       bool get_is_protected() const { return _protected; }
+       bool get_is_protected() const { return (_flags & isProtected) ? true : 
false; }
 
        /// Set "protected" flag
        //
-       /// @@ why isn't this a bitflag like the others ?
-       ///
-       void set_is_protected(const bool is_protected) { _protected = 
is_protected; }
+       void set_is_protected(const bool is_protected)
+       {
+               if (is_protected)
+                       _flags |= isProtected;
+               else
+                       _flags &= ~isProtected;
+       }
 
        /// set the numerical flags value (return the new value )
        /// If unlocked is false, you cannot un-protect from over-write,

Index: server/as_value.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/as_value.cpp,v
retrieving revision 1.87
retrieving revision 1.88
diff -u -b -r1.87 -r1.88
--- server/as_value.cpp 15 Oct 2007 23:02:54 -0000      1.87
+++ server/as_value.cpp 18 Oct 2007 11:47:54 -0000      1.88
@@ -611,6 +611,13 @@
 }
 
 bool
+as_value::conforms_to(string_table::key name)
+{
+       // TODO: Implement
+       return false;
+}
+
+bool
 as_value::equals(const as_value& v, as_environment& env) const
 {
     // Comments starting with numbers refer to the ECMA-262 document

Index: server/as_value.h
===================================================================
RCS file: /sources/gnash/gnash/server/as_value.h,v
retrieving revision 1.70
retrieving revision 1.71
diff -u -b -r1.70 -r1.71
--- server/as_value.h   8 Oct 2007 15:03:00 -0000       1.70
+++ server/as_value.h   18 Oct 2007 11:47:54 -0000      1.71
@@ -15,7 +15,7 @@
 // along with this program; if not, write to the Free Software
 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
-/* $Id: as_value.h,v 1.70 2007/10/08 15:03:00 strk Exp $ */
+/* $Id: as_value.h,v 1.71 2007/10/18 11:47:54 cmusick Exp $ */
 
 #ifndef GNASH_AS_VALUE_H
 #define GNASH_AS_VALUE_H
@@ -34,6 +34,8 @@
 #include <boost/variant.hpp>
 #include <ostream> // for inlined output operator
 
+#include "string_table.h"
+
 namespace gnash {
 
 class as_object;
@@ -41,6 +43,8 @@
 class as_function;
 class sprite_instance;
 class as_environment;
+class asNamespace;
+class asName;
 
 #ifndef HAVE_ISFINITE
 # ifndef isfinite 
@@ -83,6 +87,14 @@
 ///
 #define PROPNAME(x) ( VM::get().getSWFVersion() < 7 ? 
boost::to_lower_copy(std::string(x)) : (x) )
 
+/// These are the primitive types, see the ECMAScript reference.
+enum primitive_types
+{
+       PTYPE_STRING,
+       PTYPE_NUMBER,
+       PTYPE_BOOLEAN
+};
+
 /// ActionScript value type.
 //
 /// Any ActionScript value is stored into an instance of this
@@ -162,6 +174,9 @@
        /// Construct a NUMBER value
        as_value(unsigned long val);
 
+       /// Chad: Document this
+       as_value(asNamespace &) {/**/}
+
        /// Construct a NULL, OBJECT, MOVIECLIP or AS_FUNCTION value
        //
        /// See as_object::to_movie and as_object::to_function
@@ -195,6 +210,32 @@
        /// Return the primitive type of this value, as a string.
        const char* typeOf() const;
 
+       /// Get the primitive type of this value
+       primitive_types ptype() const
+       {
+               switch (m_type)
+               {
+               case STRING: return PTYPE_STRING;
+               case NUMBER: return PTYPE_NUMBER;
+               case AS_FUNCTION:
+               case UNDEFINED:
+               case NULLTYPE:
+               case MOVIECLIP:
+                       return PTYPE_NUMBER;
+               case OBJECT:
+                       // TODO: Date objects should return TYPE_STRING
+                       return PTYPE_NUMBER;
+               case BOOLEAN:
+                       return PTYPE_BOOLEAN;
+               default:
+                       break; // Should be only exceptions here.
+               }
+               return PTYPE_NUMBER;
+       }
+
+       // Chad: Document
+       bool conforms_to(string_table::key name);
+
        /// \brief
        /// Return true if this value is callable
        /// (AS_FUNCTION).

Index: server/edit_text_character.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/edit_text_character.cpp,v
retrieving revision 1.125
retrieving revision 1.126
diff -u -b -r1.125 -r1.126
--- server/edit_text_character.cpp      18 Oct 2007 09:07:18 -0000      1.125
+++ server/edit_text_character.cpp      18 Oct 2007 11:47:54 -0000      1.126
@@ -17,7 +17,7 @@
 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 //
 
-/* $Id: edit_text_character.cpp,v 1.125 2007/10/18 09:07:18 strk Exp $ */
+/* $Id: edit_text_character.cpp,v 1.126 2007/10/18 11:47:54 cmusick Exp $ */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -772,7 +772,7 @@
 
 void
 edit_text_character::set_member(string_table::key name,
-               const as_value& val)
+               const as_value& val, string_table::key nsname)
 {
        //log_msg("edit_text_character.set_member(%s, %s)", name.c_str(), 
val.to_string());
 
@@ -957,11 +957,12 @@
        }       // end switch
 
 
-       set_member_default(name, val);
+       set_member_default(name, val, nsname);
 }
 
 bool
-edit_text_character::get_member(string_table::key name, as_value* val)
+edit_text_character::get_member(string_table::key name, as_value* val,
+       string_table::key nsname)
 {
        //log_msg("edit_text_character.get_member(%s)", name.c_str());
 
@@ -1042,7 +1043,7 @@
        }
        }       // end switch
 
-       return get_member_default(name, val);
+       return get_member_default(name, val, nsname);
 }
        
 

Index: server/edit_text_character.h
===================================================================
RCS file: /sources/gnash/gnash/server/edit_text_character.h,v
retrieving revision 1.55
retrieving revision 1.56
diff -u -b -r1.55 -r1.56
--- server/edit_text_character.h        18 Oct 2007 09:07:18 -0000      1.55
+++ server/edit_text_character.h        18 Oct 2007 11:47:54 -0000      1.56
@@ -112,9 +112,11 @@
        std::string get_text_value() const;
 
        /// We have a "text" member.
-       void set_member(string_table::key name, const as_value& val);
+       void set_member(string_table::key name, const as_value& val, 
+               string_table::key nsname = 0);
 
-       bool get_member(string_table::key name, as_value* val);
+       bool get_member(string_table::key name, as_value* val, 
+               string_table::key nsname = 0);
 
        /// Draw the dynamic string.
        void    display();

Index: server/movie_root.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/movie_root.cpp,v
retrieving revision 1.109
retrieving revision 1.110
diff -u -b -r1.109 -r1.110
--- server/movie_root.cpp       10 Oct 2007 13:38:09 -0000      1.109
+++ server/movie_root.cpp       18 Oct 2007 11:47:54 -0000      1.110
@@ -378,7 +378,6 @@
 
        // Notify character key listeners.
        notify_key_listeners(k, down);
-
 #ifndef NEW_KEY_LISTENER_LIST_DESIGN
        // Notify both character and non-character Key listeners
        //      for user defined handerlers.

Index: server/namedStrings.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/namedStrings.cpp,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- server/namedStrings.cpp     29 Sep 2007 08:24:21 -0000      1.3
+++ server/namedStrings.cpp     18 Oct 2007 11:47:54 -0000      1.4
@@ -137,6 +137,8 @@
        { "flash.xml", NSV::NS_FLASH_XML },
        { "flash.ui", NSV::NS_FLASH_UI },
        { "adobe.utils", NSV::NS_ADOBE_UTILS },
+       { "", NSV::INTERNAL_TYPE },
+       { "", NSV::INTERNAL_STACK_PARENT }
 };
 
 void load_strings(string_table *table, int version)

Index: server/namedStrings.h
===================================================================
RCS file: /sources/gnash/gnash/server/namedStrings.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -b -r1.5 -r1.6
--- server/namedStrings.h       29 Sep 2007 08:24:21 -0000      1.5
+++ server/namedStrings.h       18 Oct 2007 11:47:55 -0000      1.6
@@ -41,7 +41,11 @@
 ///
 /// Names beginning with PROP_ have a lowercase initial letter
 /// Names beginning with CLASS_ have an uppercase initial letter
+/// Names beginning with NS_ have a lowercase initial letter and _ are
+///  . instead of uppercase.
 ///
+/// Names beginning with INTERNAL_ have no named string -- they can only
+/// be used if you know their key value already.
 namespace NSV {
 
 typedef enum {
@@ -154,7 +158,9 @@
                NS_FLASH_MEDIA,
                NS_FLASH_XML,
                NS_FLASH_UI,
-               NS_ADOBE_UTILS
+               NS_ADOBE_UTILS,
+               INTERNAL_TYPE, // The type name
+               INTERNAL_STACK_PARENT // Any public property is unsafe
        } named_strings;
 
 /// Load the prenamed strings.

Index: server/sprite_instance.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/sprite_instance.cpp,v
retrieving revision 1.369
retrieving revision 1.370
diff -u -b -r1.369 -r1.370
--- server/sprite_instance.cpp  17 Oct 2007 21:09:56 -0000      1.369
+++ server/sprite_instance.cpp  18 Oct 2007 11:47:55 -0000      1.370
@@ -1760,7 +1760,8 @@
 // Set *val to the value of the named member and
 // return true, if we have the named member.
 // Otherwise leave *val alone and return false.
-bool sprite_instance::get_member(string_table::key name_key, as_value* val)
+bool sprite_instance::get_member(string_table::key name_key, as_value* val,
+       string_table::key nsname)
 {
        const std::string& name = VM::get().getStringTable().value(name_key);
 
@@ -1803,7 +1804,7 @@
        //
        // TODO: simplify the next line when get_member_default takes
        //       a std::string
-       if ( get_member_default(name_key, val) )
+       if (get_member_default(name_key, val, nsname))
        {
 
 // ... trying to be useful to Flash coders ...
@@ -2210,7 +2211,7 @@
 }
 
 void sprite_instance::set_member(string_table::key name,
-               const as_value& val)
+               const as_value& val, string_table::key nsname)
 {
 #ifdef DEBUG_DYNTEXT_VARIABLES
        //log_debug(_("sprite[%p]::set_member(%s, %s)"), (void*)this, 
VM::get().getStringTable().value(name), val.to_debug_string().c_str());
@@ -2251,7 +2252,7 @@
 #endif
 
        // If that didn't work call the default set_member
-       set_member_default(name, val);
+       set_member_default(name, val, nsname);
 
 }
 

Index: server/sprite_instance.h
===================================================================
RCS file: /sources/gnash/gnash/server/sprite_instance.h,v
retrieving revision 1.144
retrieving revision 1.145
diff -u -b -r1.144 -r1.145
--- server/sprite_instance.h    4 Oct 2007 09:47:37 -0000       1.144
+++ server/sprite_instance.h    18 Oct 2007 11:47:55 -0000      1.145
@@ -538,13 +538,15 @@
        //
 
        // See dox in as_object.h
-       bool get_member(string_table::key name, as_value* val);
+       bool get_member(string_table::key name, as_value* val, 
+               string_table::key nsname = 0);
                
        /// Set the named member to the value. 
        //
        /// Return true if we have that member; false otherwise.
        ///
-       virtual void set_member(string_table::key name, const as_value& val);
+       virtual void set_member(string_table::key name, const as_value& val,
+               string_table::key nsname = 0);
 
        /// Overridden to look in DisplayList for a match
        virtual character* get_relative_target(const std::string& name);

Index: server/stream.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/stream.cpp,v
retrieving revision 1.32
retrieving revision 1.33
diff -u -b -r1.32 -r1.33
--- server/stream.cpp   21 Sep 2007 13:40:31 -0000      1.32
+++ server/stream.cpp   18 Oct 2007 11:47:55 -0000      1.33
@@ -15,6 +15,7 @@
 #include "swf.h"
 #include <cstring>
 //#include <iostream> // debugging only
+#include "Property.h"
 
 namespace gnash {
        

Index: server/asobj/ClassHierarchy.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/ClassHierarchy.cpp,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- server/asobj/ClassHierarchy.cpp     29 Sep 2007 08:24:21 -0000      1.3
+++ server/asobj/ClassHierarchy.cpp     18 Oct 2007 11:47:55 -0000      1.4
@@ -297,13 +297,6 @@
 void
 ClassHierarchy::dump()
 {
-       namespacesContainer::iterator i;
-
-       for (i = mNamespaces.begin(); i != mNamespaces.end(); ++i)
-       {
-               (i->second).dump();
-       }
-       getGlobalNs()->dump();
 }
 
 } /* namespace gnash */

Index: server/asobj/ClassHierarchy.h
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/ClassHierarchy.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- server/asobj/ClassHierarchy.h       29 Sep 2007 08:24:21 -0000      1.3
+++ server/asobj/ClassHierarchy.h       18 Oct 2007 11:47:55 -0000      1.4
@@ -24,59 +24,18 @@
 
 #include "as_object.h"
 #include "asClass.h"
+#include "SafeStack.h"
+#include "asNamespace.h"
 
 namespace gnash {
 
 class Extension;
 class asClass;
 class asMethod;
-class asNamespace;
 class asException;
-class asMethodBody;
 class asBoundValue;
 class asBoundAccessor;
-
-template <class T> class memoryDispenser
-{
-private:
-       typedef std::vector<T> block;
-       typedef std::list<block*> blocks;
-       blocks mMemory;
-       block *mCurrent;
-       std::size_t mBlockSize;
-       std::size_t mLeftInBlock;
-
-       void grow()
-       {
-               mLeftInBlock = mBlockSize;
-               mCurrent = new block(mBlockSize);
-               mCurrent->resize(mBlockSize);
-               mMemory.push_back(mCurrent);
-       }
-
-public:
-       memoryDispenser(std::size_t allocSize) : mBlockSize(allocSize),
-               mLeftInBlock(0)
-       {/**/}
-
-       T* newMemory()
-       {
-               if (!mLeftInBlock)
-                       grow();
-               --mLeftInBlock;
-               return &(*mCurrent)[mLeftInBlock];
-       }
-
-       // Done this way because an iterator won't compile right.
-       ~memoryDispenser()
-       { 
-               while (!mMemory.empty()) 
-               {
-                       delete mMemory.front();
-                       mMemory.pop_front();
-               }
-       }
-};
+class as_object;
 
 /// Register all of the ActionScript classes, with their dependencies.
 class ClassHierarchy
@@ -177,6 +136,9 @@
        /// else.
        asNamespace* getGlobalNs() { return mGlobalNamespace; }
 
+       // Chad: Document
+       as_object* newOfType(string_table::key whattype) { return NULL; }
+
        /// Find a namespace with the given uri.
        ///
        /// @return 
@@ -199,7 +161,12 @@
        /// objects.)
        ///
        asNamespace* anonNamespace(string_table::key uri)
-       { asNamespace* n = mAnonNamespaces.newMemory(); n->setURI(uri); return 
n; }
+       {
+               mAnonNamespaces.grow(1); 
+               asNamespace *n = &mAnonNamespaces.top(0); 
+               n->setURI(uri); 
+               return n; 
+       }
 
        /// \brief
        /// Add a namespace to the set. Don't use to add unnamed namespaces.
@@ -210,7 +177,7 @@
                asNamespace *n = findNamespace(uri);
                if (n)
                        return n;
-               mNamespaces[uri] = asNamespace();
+               // The set should create it automatically here. TODO: Make sure
                mNamespaces[uri].setURI(uri);
                return &mNamespaces[uri];
        }
@@ -226,34 +193,30 @@
 
        /// Create a new asClass object for use.
        asClass *newClass()
-       { return mClassMemory.newMemory(); }
+       { mClassMemory.grow(1); return &mClassMemory.top(0); }
 
        asException *newException()
-       { return mExceptionMemory.newMemory(); }
+       { mExceptionMemory.grow(1); return &mExceptionMemory.top(0); }
 
        /// Create a new asMethod object for use.
        asMethod *newMethod()
-       { return mMethodMemory.newMemory(); }
-
-       /// Create a new asMethodBody
-       asMethodBody *newMethodBody()
-       { return mMethodBodyMemory.newMemory(); }
+       { mMethodMemory.grow(1); return &mMethodMemory.top(0); }
 
        asBoundValue *newBoundValue()
-       { return mBoundValueMemory.newMemory(); }
+       { mBoundValueMemory.grow(1); return &mBoundValueMemory.top(0); }
 
        asBoundAccessor *newBoundAccessor()
-       { return mBoundAccessorMemory.newMemory(); }
+       { mBoundAccessorMemory.grow(1); return &mBoundAccessorMemory.top(0); }
 
        /// \brief
        /// Construct the declaration object. Later set the global and
        /// extension objects using setGlobal and setExtension
        ClassHierarchy() :
                mGlobal(NULL), mGlobalNamespace(NULL), mExtension(NULL),
-               mAnonNamespaces(100),
-               mClassMemory(100), mExceptionMemory(100),
-               mMethodMemory(100), mMethodBodyMemory(100),
-               mBoundValueMemory(100), mBoundAccessorMemory(100)
+               mAnonNamespaces(),
+               mClassMemory(), mExceptionMemory(),
+               mMethodMemory(),
+               mBoundValueMemory(), mBoundAccessorMemory()
        { mGlobalNamespace = anonNamespace(0); }
 
        /// \brief
@@ -269,13 +232,12 @@
 
        typedef std::map<string_table::key, asNamespace> namespacesContainer;
        namespacesContainer mNamespaces;
-       memoryDispenser<asNamespace> mAnonNamespaces;
-       memoryDispenser<asClass> mClassMemory;
-       memoryDispenser<asException> mExceptionMemory;
-       memoryDispenser<asMethod> mMethodMemory;
-       memoryDispenser<asMethodBody> mMethodBodyMemory;
-       memoryDispenser<asBoundValue> mBoundValueMemory;
-       memoryDispenser<asBoundAccessor> mBoundAccessorMemory;
+       SafeStack<asNamespace> mAnonNamespaces;
+       SafeStack<asClass> mClassMemory;
+       SafeStack<asException> mExceptionMemory;
+       SafeStack<asMethod> mMethodMemory;
+       SafeStack<asBoundValue> mBoundValueMemory;
+       SafeStack<asBoundAccessor> mBoundAccessorMemory;
 };
 
 } /* namespace gnash */

Index: server/asobj/Object.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/Object.cpp,v
retrieving revision 1.31
retrieving revision 1.32
diff -u -b -r1.31 -r1.32
--- server/asobj/Object.cpp     19 Sep 2007 14:20:50 -0000      1.31
+++ server/asobj/Object.cpp     18 Oct 2007 11:47:55 -0000      1.32
@@ -17,7 +17,7 @@
 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 //
 
-/* $Id: Object.cpp,v 1.31 2007/09/19 14:20:50 cmusick Exp $ */
+/* $Id: Object.cpp,v 1.32 2007/10/18 11:47:55 cmusick Exp $ */
 
 #include "tu_config.h"
 #include "Object.h"
@@ -148,6 +148,7 @@
                // replicate all interface to class, to be able to access
                // all methods as static functions
                attachObjectInterface(*cl);
+               cl->init_member("prototype", as_value(getObjectInterface()));
                     
        }
 

Index: server/asobj/xml.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/xml.cpp,v
retrieving revision 1.49
retrieving revision 1.50
diff -u -b -r1.49 -r1.50
--- server/asobj/xml.cpp        2 Oct 2007 13:17:29 -0000       1.49
+++ server/asobj/xml.cpp        18 Oct 2007 11:47:55 -0000      1.50
@@ -17,7 +17,7 @@
 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 //
 
-/* $Id: xml.cpp,v 1.49 2007/10/02 13:17:29 strk Exp $ */
+/* $Id: xml.cpp,v 1.50 2007/10/18 11:47:55 cmusick Exp $ */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -134,7 +134,7 @@
 }
 
 bool
-XML::get_member(string_table::key name, as_value *val)
+XML::get_member(string_table::key name, as_value *val, string_table::key 
nsname)
 {
         if (name == NSV::PROP_STATUS) 
         {
@@ -148,11 +148,12 @@
                 return true;
         }
 
-        return get_member_default(name, val);
+        return get_member_default(name, val, nsname);
 }
 
 void
-XML::set_member(string_table::key name, const as_value& val)
+XML::set_member(string_table::key name, const as_value& val, 
+       string_table::key nsname)
 {
         if (name == NSV::PROP_STATUS)
        {
@@ -176,7 +177,7 @@
                 return;
         }
 
-        set_member_default(name, val);
+        set_member_default(name, val, nsname);
 }
 
 XML::~XML()

Index: server/asobj/xml.h
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/xml.h,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -b -r1.19 -r1.20
--- server/asobj/xml.h  2 Oct 2007 13:17:30 -0000       1.19
+++ server/asobj/xml.h  18 Oct 2007 11:47:55 -0000      1.20
@@ -99,13 +99,15 @@
     /// which are NOT proper properties !
     /// See actionscript.all/XML.as
     ///
-    bool get_member(string_table::key name, as_value *val);
+    bool get_member(string_table::key name, as_value *val,
+               string_table::key nsname = 0);
 
     /// This is overridden to provide the 'status' and 'loaded' members,
     /// which are NOT proper properties !
     /// See actionscript.all/XML.as
     ///
-       void set_member(string_table::key name, const as_value& val );
+       void set_member(string_table::key name, const as_value& val,
+               string_table::key nsname = 0);
 
     // Methods
 

Index: server/parser/abc_block.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/parser/abc_block.cpp,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -b -r1.7 -r1.8
--- server/parser/abc_block.cpp 29 Sep 2007 08:24:21 -0000      1.7
+++ server/parser/abc_block.cpp 18 Oct 2007 11:47:55 -0000      1.8
@@ -25,6 +25,7 @@
 #include "ClassHierarchy.h"
 #include "asClass.h"
 #include "namedStrings.h"
+#include "CodeStream.h"
 
 //#define ERR(x) IF_VERBOSE_MALFORMED_SWF(log_swferror x;);
 #define ERR(x) printf x; fflush(stdout);
@@ -55,10 +56,10 @@
                // The name has been validated in read.
                if (mHasValue)
                        pClass->addValue(mName, mNamespace, mSlotId, pType, 
-                               mValue, mKind == KIND_CONST, do_static, 
pBlock->mCH);
+                               mValue, mKind == KIND_CONST, do_static);
                else
                        pClass->addSlot(mName, mNamespace, mSlotId, pType,
-                               do_static, pBlock->mCH);
+                               do_static);
                break;
        }
        case KIND_METHOD:
@@ -68,12 +69,12 @@
        }
        case KIND_GETTER:
        {
-               pClass->addGetter(mName, mNamespace, mMethod, do_static, 
pBlock->mCH);
+               pClass->addGetter(mName, mNamespace, mMethod, do_static);
                break;
        }
        case KIND_SETTER:
        {
-               pClass->addSetter(mName, mNamespace, mMethod, do_static, 
pBlock->mCH);
+               pClass->addSetter(mName, mNamespace, mMethod, do_static);
                break;
        }
        case KIND_CLASS:
@@ -117,9 +118,9 @@
                // The name has been validated in read.
                if (mHasValue)
                        pMethod->addValue(mName, mNamespace, mSlotId, pType, 
-                               mValue, mKind == KIND_CONST, pBlock->mCH);
+                               mValue, mKind == KIND_CONST);
                else
-                       pMethod->addSlot(mName, mNamespace, mSlotId, pType,     
pBlock->mCH);
+                       pMethod->addSlot(mName, mNamespace, mSlotId, pType);
                break;
        }
        case KIND_METHOD:
@@ -129,12 +130,12 @@
        }
        case KIND_GETTER:
        {
-               pMethod->addGetter(mName, mNamespace, mMethod, pBlock->mCH);
+               pMethod->addGetter(mName, mNamespace, mMethod);
                break;
        }
        case KIND_SETTER:
        {
-               pMethod->addSetter(mName, mNamespace, mMethod, pBlock->mCH);
+               pMethod->addSetter(mName, mNamespace, mMethod);
                break;
        }
        case KIND_CLASS:
@@ -166,13 +167,13 @@
                ERR((_("ABC: Bad name for trait.\n")));
                return false;
        }
-       if (!(pBlock->mMultinamePool[name].mFlags & abc_Multiname::FLAG_QNAME))
+       if (!pBlock->mMultinamePool[name].isQName())
        {
                ERR((_("ABC: Trait name must be fully qualified.\n")));
                return false;
        }
-       mName = pBlock->mMultinamePool[name].mName;
-       mNamespace = pBlock->mMultinamePool[name].mNamespace;
+       mName = pBlock->mMultinamePool[name].getName();
+       mNamespace = pBlock->mMultinamePool[name].getNamespace();
 
        uint8_t kind = in->read_u8();
        mKind = static_cast<kinds> (kind & 0x0F);
@@ -258,13 +259,13 @@
 using namespace abc_parsing;
 
 asClass *
-abc_block::locateClass(abc_Multiname &m)
+abc_block::locateClass(asName &m)
 {
        asClass *found = NULL;
 
-       if (m.mNamespace)
+       if (m.getNamespace())
        {
-               found = m.mNamespace->getClass(m.mName);
+               found = m.getNamespace()->getClass(m.getName());
                if (found)
                        return found;
        }
@@ -273,28 +274,28 @@
                std::vector<asNamespace*>::iterator i;
                for (i = m.mNamespaceSet->begin(); i != m.mNamespaceSet->end(); 
++i)
                {
-                       found = (*i)->getClass(m.mName);
+                       found = (*i)->getClass(m.getName());
                        if (found)
                                return found;
                }
        }
        // One last chance: Look globally.
-       found = mCH->getGlobalNs()->getClass(m.mName);
+       found = mCH->getGlobalNs()->getClass(m.getName());
        if (found)
                return found;
 
        // Fake it here for a while.
-       if (m.mNamespace)
+       if (m.getNamespace())
        {
-               m.mNamespace->stubPrototype(m.mName);
-               found = m.mNamespace->getClass(m.mName);
+               m.getNamespace()->stubPrototype(m.getName());
+               found = m.getNamespace()->getClass(m.getName());
                return found;
        }
        else
        {
                // Fake in global.
-               mCH->getGlobalNs()->stubPrototype(m.mName);
-               found = mCH->getGlobalNs()->getClass(m.mName);
+               mCH->getGlobalNs()->stubPrototype(m.getName());
+               found = mCH->getGlobalNs()->getClass(m.getName());
                return found;
        }
        return NULL;
@@ -465,8 +466,8 @@
        mMultinamePool.resize(count);
        if (count)
        {
-               mMultinamePool[0].mName = 0;
-               mMultinamePool[0].mNamespace = mCH->getGlobalNs();
+               mMultinamePool[0].setName(0);
+               mMultinamePool[0].setNamespace(mCH->getGlobalNs());
        }
        for (unsigned int i = 1; i < count; ++i)
        {
@@ -480,38 +481,38 @@
                // Read, but don't upper validate until after the switch.
                switch (kind)
                {
-        case abc_Multiname::KIND_Qname:
-        case abc_Multiname::KIND_QnameA:
+        case asName::KIND_Qname:
+        case asName::KIND_QnameA:
         {
             ns = mS->read_V32();
             name = mS->read_V32();
-            mMultinamePool[i].mFlags |= abc_Multiname::FLAG_QNAME;
-            if (kind == abc_Multiname::KIND_QnameA)
-                mMultinamePool[i].mFlags |= abc_Multiname::FLAG_ATTR;
+                       mMultinamePool[i].setQName();
+            if (kind == asName::KIND_QnameA)
+                               mMultinamePool[i].setAttr();
             break;
         }
-        case abc_Multiname::KIND_RTQname:
-        case abc_Multiname::KIND_RTQnameA:
+        case asName::KIND_RTQname:
+        case asName::KIND_RTQnameA:
         {
             name = mS->read_V32();
-            mMultinamePool[i].mFlags |= abc_Multiname::FLAG_QNAME
-                | abc_Multiname::FLAG_RTNS;
-            if (kind == abc_Multiname::KIND_RTQnameA)
-                mMultinamePool[i].mFlags |= abc_Multiname::FLAG_ATTR;
+            mMultinamePool[i].mFlags |= asName::FLAG_QNAME
+                | asName::FLAG_RTNS;
+            if (kind == asName::KIND_RTQnameA)
+                               mMultinamePool[i].setAttr();
             break;
         }
-        case abc_Multiname::KIND_RTQnameL:
-        case abc_Multiname::KIND_RTQnameLA:
+        case asName::KIND_RTQnameL:
+        case asName::KIND_RTQnameLA:
         {
-            mMultinamePool[i].mFlags |= abc_Multiname::FLAG_QNAME
-                | abc_Multiname::FLAG_RTNAME
-                | abc_Multiname::FLAG_RTNS;
-            if (kind == abc_Multiname::KIND_RTQnameLA)
-                mMultinamePool[i].mFlags |= abc_Multiname::FLAG_ATTR;
+            mMultinamePool[i].mFlags |= asName::FLAG_QNAME
+                | asName::FLAG_RTNAME
+                | asName::FLAG_RTNS;
+            if (kind == asName::KIND_RTQnameLA)
+                               mMultinamePool[i].setAttr();
             break;
         }
-        case abc_Multiname::KIND_Multiname:
-        case abc_Multiname::KIND_MultinameA:
+        case asName::KIND_Multiname:
+        case asName::KIND_MultinameA:
         {
             name = mS->read_V32();
             nsset = mS->read_V32();
@@ -521,13 +522,13 @@
                 ERR((_("ABC: 0 selection for namespace set is invalid.\n")));
                 return false;
             }
-            mMultinamePool[i].mFlags |= abc_Multiname::FLAG_NSSET;
-            if (kind == abc_Multiname::KIND_MultinameA)
-                mMultinamePool[i].mFlags |= abc_Multiname::FLAG_ATTR;
+            mMultinamePool[i].mFlags |= asName::FLAG_NSSET;
+            if (kind == asName::KIND_MultinameA)
+                mMultinamePool[i].mFlags |= asName::FLAG_ATTR;
             break;
         }
-        case abc_Multiname::KIND_MultinameL:
-        case abc_Multiname::KIND_MultinameLA:
+        case asName::KIND_MultinameL:
+        case asName::KIND_MultinameLA:
         {
             nsset = mS->read_V32();
             // 0 is not a valid nsset.
@@ -536,10 +537,10 @@
                 ERR((_("ABC: 0 selection for namespace set is invalid.\n")));
                 return false;
             }
-            mMultinamePool[i].mFlags |= abc_Multiname::FLAG_RTNAME
-                | abc_Multiname::FLAG_NSSET;
-            if (kind == abc_Multiname::KIND_MultinameLA)
-                mMultinamePool[i].mFlags |= abc_Multiname::FLAG_ATTR;
+            mMultinamePool[i].mFlags |= asName::FLAG_RTNAME
+                | asName::FLAG_NSSET;
+            if (kind == asName::KIND_MultinameLA)
+                               mMultinamePool[i].setAttr();
             break;
         }
         default:
@@ -571,10 +572,10 @@
                {
                        mStringPoolTableIds[name] = 
mStringTable->find(mStringPool[name]);
                }
-               mMultinamePool[i].mName = mStringPoolTableIds[name];
+               mMultinamePool[i].setName(mStringPoolTableIds[name]);
 
                if (ns)
-                       mMultinamePool[i].mNamespace = mNamespacePool[ns];
+                       mMultinamePool[i].setNamespace(mNamespacePool[ns]);
                if (nsset)
                        mMultinamePool[i].mNamespaceSet = 
&mNamespaceSetPool[nsset];
        } // End of main loop.
@@ -785,12 +786,12 @@
                        return false;
                }
                // This must be a QName.
-               if (!(mMultinamePool[index].mFlags & abc_Multiname::FLAG_QNAME))
+               if (!mMultinamePool[index].isQName())
                {
                        ERR((_("ABC: QName required for instance.\n")));
                        return false;
                }
-               if (mMultinamePool[index].mNamespace == NULL)
+               if (mMultinamePool[index].getNamespace() == NULL)
                {
                        ERR((_("ABC: No namespace to use for storing 
class.\n")));
                        return false;
@@ -800,8 +801,8 @@
                if (!pClass)
                {
                        pClass = mCH->newClass();
-                       if (!mMultinamePool[index].mNamespace->addClass(
-                               mMultinamePool[index].mName, pClass))
+                       if (!mMultinamePool[index].getNamespace()->addClass(
+                               mMultinamePool[index].getName(), pClass))
                        {
                                ERR((_("Duplicate class registration.\n")));
                                return false;
@@ -826,11 +827,11 @@
                        if (!pSuper)
                        {
                                ERR((_("ABC: Super type not found (%s), 
faking.\n"),
-                                       
mStringTable->value(mMultinamePool[super_index].mName).c_str()));
+                                       
mStringTable->value(mMultinamePool[super_index].getName()).c_str()));
                                // While testing, we will add a fake type, 
rather than abort.
                                pSuper = mCH->newClass();
-                               
pSuper->setName(mMultinamePool[super_index].mName);
-                               
mCH->getGlobalNs()->addClass(mMultinamePool[super_index].mName, pSuper);
+                               
pSuper->setName(mMultinamePool[super_index].getName());
+                               
mCH->getGlobalNs()->addClass(mMultinamePool[super_index].getName(), pSuper);
                                // return false;
                        }
 
@@ -912,11 +913,7 @@
                        ERR((_("ABC: Out of bounds method for 
initializer.\n")));
                        return false;
                }
-               if (mMethods[moffset]->getOwner())
-               {
-                       ERR((_("ABC: Initializer method already bound.\n")));
-                       return false;
-               }
+               // Don't validate for previous owner.
                pClass->setConstructor(mMethods[moffset]);
                mMethods[moffset]->setOwner(pClass);
 
@@ -949,11 +946,7 @@
                        ERR((_("ABC: Out of bound static constructor for 
class.\n")));
                        return false;
                }
-               if (mMethods[moffset]->getOwner())
-               {
-                       ERR((_("ABC: Static constructor method already 
bound.\n")));
-                       return false;
-               }
+               // Don't validate for previous owner.
                pClass->setStaticConstructor(mMethods[moffset]);
                mMethods[moffset]->setOwner(pClass);
                
@@ -988,11 +981,7 @@
                        ERR((_("ABC: Out of bounds method for script.\n")));
                        return false;
                }
-               if (mMethods[moffset]->getOwner())
-               {
-                       ERR((_("ABC: Global script initializer is already 
bound.\n")));
-                       return false;
-               }
+               // Don't validate for previous owner.
                mMethods[moffset]->setOwner(pScript);
                pScript->setConstructor(mMethods[moffset]);
                pScript->setSuper(mTheObject);
@@ -1017,8 +1006,6 @@
 
        for (unsigned int i = 0; i < count; ++i)
        {
-               asMethodBody *pBody = mCH->newMethodBody();
-
                uint32_t moffset = mS->read_V32();
                if (moffset >= mMethods.size())
                {
@@ -1030,7 +1017,7 @@
                        ERR((_("ABC: Only one body per method.\n")));
                        return false;
                }
-               mMethods[moffset]->setBody(pBody);
+               mMethods[moffset]->setBody(new CodeStream);
 
                // Maximum stack size.
                mS->skip_V32();
@@ -1043,14 +1030,17 @@
                // Code length
                uint32_t clength = mS->read_V32();
                // The code.
-               pBody->setSize(clength);
+               std::vector<char> body(clength);
+               body.resize(clength);
                unsigned int got_length;
-               if ((got_length = mS->read(pBody->getRaw(), clength)) != 
clength)
+               if ((got_length = mS->read(&body.front(), clength)) != clength)
                {
                        ERR((_("ABC: Not enough method body. Wanted %d but got 
%d.\n"),
-                               pBody->getSize(), got_length));
+                               clength, got_length));
                        return false;
                }
+               else
+                       
mMethods[moffset]->getBody()->reInitialize(&body.front(), clength, true);
 
                uint32_t ecount = mS->read_V32();
                for (unsigned int j = 0; j < ecount; ++j)
@@ -1081,7 +1071,7 @@
                                if (!pType)
                                {
                                        ERR((_("ABC: Unknown type of object to 
catch. (%s)\n"),
-                                               
mStringTable->value(mMultinamePool[catch_type].mName).c_str()));
+                                               
mStringTable->value(mMultinamePool[catch_type].getName()).c_str()));
                                        // return false;
                                        // Fake it, for now:
                                        pExcept->catchAny();
@@ -1102,8 +1092,8 @@
                                        ERR((_("ABC: Out of bound name for 
caught exception.\n")));
                                        return false;
                                }
-                               pExcept->setName(mMultinamePool[cvn].mName);
-                               
pExcept->setNamespace(mMultinamePool[cvn].mNamespace);
+                               pExcept->setName(mMultinamePool[cvn].getName());
+                               
pExcept->setNamespace(mMultinamePool[cvn].getNamespace());
                        }
                } // end of exceptions
 

Index: server/parser/abc_block.h
===================================================================
RCS file: /sources/gnash/gnash/server/parser/abc_block.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -b -r1.5 -r1.6
--- server/parser/abc_block.h   29 Sep 2007 08:24:21 -0000      1.5
+++ server/parser/abc_block.h   18 Oct 2007 11:47:55 -0000      1.6
@@ -29,6 +29,7 @@
 #include "stream.h"
 #include "string_table.h"
 #include "asClass.h"
+#include "asName.h"
 
 namespace gnash {
 
@@ -41,40 +42,6 @@
 
 class abc_Trait;
 
-class abc_Multiname
-{
-public:
-    typedef enum
-    {
-               KIND_Qname = 0x07,
-               KIND_QnameA = 0x0D,
-               KIND_RTQname = 0x0F,
-               KIND_RTQnameA = 0x10,
-               KIND_RTQnameL = 0x11,
-               KIND_RTQnameLA = 0x12,
-               KIND_Multiname = 0x09,
-               KIND_MultinameA = 0x0E,
-               KIND_MultinameL = 0x1B,
-               KIND_MultinameLA = 0x1C
-       } kinds;
-       typedef enum
-       {
-               FLAG_ATTR = 0x01,
-               FLAG_QNAME = 0x02,
-               FLAG_RTNS = 0x04,
-               FLAG_RTNAME = 0x08,
-               FLAG_NSSET = 0x10
-       } flags;
-
-       uint8_t mFlags;
-       string_table::key mName;
-       asNamespace* mNamespace;
-       std::vector<asNamespace*> *mNamespaceSet;
-
-       abc_Multiname() : mFlags(0), mName(0), mNamespace(NULL), 
mNamespaceSet(NULL)
-       {/**/}
-};
-
 class abc_Trait
 {
 public:
@@ -132,8 +99,7 @@
                        
 class abc_block
 {
-private:
-       friend class abc_parsing::abc_Trait;
+public:
        typedef enum
        {
                PRIVATE_NS = 0x05,
@@ -163,13 +129,13 @@
 
        std::vector<int32_t> mIntegerPool;
        std::vector<uint32_t> mUIntegerPool;
-       std::vector<long double> mDoublePool;
+       std::vector<double> mDoublePool;
        std::vector<std::string> mStringPool;
        std::vector<string_table::key> mStringPoolTableIds;
        std::vector<asNamespace*> mNamespacePool;
        std::vector<NamespaceSet> mNamespaceSetPool;
        std::vector<asMethod*> mMethods;
-       std::vector<abc_parsing::abc_Multiname> mMultinamePool;
+       std::vector<asName> mMultinamePool;
        std::vector<asClass*> mClasses; 
        std::vector<asClass*> mScripts;
        std::vector<abc_parsing::abc_Trait*> mTraits;
@@ -182,7 +148,7 @@
 
        uint32_t mVersion;
 
-       asClass *locateClass(abc_parsing::abc_Multiname &m);
+       asClass *locateClass(asName &m);
 
        abc_parsing::abc_Trait &newTrait()
        {

Index: server/swf/tag_loaders.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/swf/tag_loaders.cpp,v
retrieving revision 1.145
retrieving revision 1.146
diff -u -b -r1.145 -r1.146
--- server/swf/tag_loaders.cpp  27 Sep 2007 23:59:56 -0000      1.145
+++ server/swf/tag_loaders.cpp  18 Oct 2007 11:47:56 -0000      1.146
@@ -17,7 +17,7 @@
 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 //
 
-/* $Id: tag_loaders.cpp,v 1.145 2007/09/27 23:59:56 tgc Exp $ */
+/* $Id: tag_loaders.cpp,v 1.146 2007/10/18 11:47:56 cmusick Exp $ */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -1524,14 +1524,7 @@
                name.c_str();
        }
 
-       bool success = a.read(in);
-       if (success)
-       {
-               /* TODO: Run the script if needed. */
-               fprintf(stderr, "Block read was successful.\n");
-       }
-       else
-               fprintf(stderr, "Block read failed.\n");
+       //TODO: Move this to execution time so that as_object can be used. bool 
success = a.read(in);
 
        log_unimpl(_("Action Block tags are parsed but not yet used"));
 }

Index: server/vm/Machine.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/vm/Machine.cpp,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- server/vm/Machine.cpp       9 Oct 2007 16:21:37 -0000       1.1
+++ server/vm/Machine.cpp       18 Oct 2007 11:47:56 -0000      1.2
@@ -21,9 +21,92 @@
 #include "ClassHierarchy.h"
 #include "namedStrings.h"
 #include "array.h"
+#include "abc_block.h"
 
 namespace gnash {
 
+/// The type of exceptions thrown by ActionScript.
+class ASException
+{
+public:
+       as_value mValue;
+
+       ASException(as_value &v) { mValue = v; }
+       ASException() { mValue.set_undefined(); }
+};
+
+class ASReferenceError : public ASException
+{
+public:
+       ASReferenceError() : ASException()
+       {/**/}
+};
+
+class ASTypeError : public ASException
+{
+public:
+       ASTypeError() : ASException()
+       {/**/}
+};
+
+// Functions for getting pool constants.
+static inline std::string& pool_string(uint32_t index, abc_block *pool)
+{
+       if (!pool)
+               throw ASException();
+       return pool->mStringPool.at(index);
+}
+
+static inline int pool_int(uint32_t index, abc_block *pool)
+{
+       if (!pool)
+               throw ASException();
+       return pool->mIntegerPool.at(index);
+}
+
+static inline unsigned int pool_uint(uint32_t index, abc_block *pool)
+{
+       if (!pool)
+               throw ASException();
+       return pool->mUIntegerPool.at(index);
+}
+
+static inline double pool_double(uint32_t index, abc_block *pool)
+{
+       if (!pool)
+               throw ASException();
+       return pool->mDoublePool.at(index);
+}
+
+static inline asNamespace* pool_namespace(uint32_t index, abc_block *pool)
+{
+       if (!pool)
+               throw ASException();
+       return pool->mNamespacePool.at(index);
+}
+
+static inline asMethod* pool_method(uint32_t index, abc_block* pool)
+{
+       if (!pool)
+               throw ASException();
+       return pool->mMethods.at(index);
+}
+
+static inline asClass* pool_class(uint32_t index, abc_block* pool)
+{
+       if (!pool)
+               throw ASException();
+       return pool->mClasses.at(index);
+}
+
+// Don't make this a reference or you'll taint the pool.
+static inline asName pool_name(uint32_t index, abc_block* pool)
+{
+       if (!pool)
+               throw ASException();
+       return pool->mMultinamePool.at(index);
+}
+
 /// ENSURE_NUMBER makes sure that the given argument is a number,
 /// calling the valueOf method if necessary -- it's a macro so that
 /// the valueOf method may be pushed if needed, and then whatever
@@ -33,7 +116,7 @@
        as_value *e = &vte;                                                     
                                                \
        if (e->is_object())                                                     
                                                \
        {                                                                       
                                                                \
-               asBinding *b = e->to_object()->getBinding(NSV::PROP_VALUE_OF);  
\
+               Property *b = e->to_object()->findProperty(NSV::PROP_VALUE_OF, 
0);      \
                if (b)                                                          
                                                        \
                {                                                               
                                                                \
                        mStream->seekTo(opStart);                               
                                        \
@@ -61,7 +144,7 @@
        as_value *c = &vte; /* Don't call vte multiple times */                 
        \
        if (c->is_object())                                                     
                                                \
        {                                                                       
                                                                \
-               asBinding *d = c->to_object()->getBinding(NSV::PROP_TO_STRING); 
\
+               Property *d = c->to_object()->findProperty(NSV::PROP_TO_STRING, 
0);     \
                if (d)                                                          
                                                        \
                {                                                               
                                                                \
                        mStream->seekTo(opStart);                               
                                        \
@@ -141,6 +224,28 @@
                *store = false;                                                 
                                                \
 }                                                                              
   /* end of ABSTRACT_EQUALITY */
 
+#define ABSTRACT_TYPELATE(st, checkval, matchval)                              
                        \
+{                                                                              
                                                                        \
+       bool *store = &st;                                                      
                                                        \
+       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()->get_member(NSV::INTERNAL_TYPE, &v);              
                        \
+               if (!a.conforms_to(mST.find(v.to_string())))                    
                        \
+                       *store = false;                                         
                                                        \
+       }                                                                       
                                                                        \
+       else if (b.is_string())                                                 
                                                \
+       {                                                                       
                                                                        \
+               if (!a.conforms_to(mST.find(b.to_string())))                    
                        \
+                       *store = false;                                         
                                                        \
+       }                                                                       
                                                                        \
+       else                                                                    
                                                                \
+               *store = false;                                                 
                                                        \
+}                                                                              
           /* end of ABSTRACT_TYPELATE */
+
 #define JUMPIF(jtruth)                                                         
                                        \
 {                                                                              
                                                                \
        int32_t jumpOffset = mStream->read_S24();                               
                        \
@@ -149,30 +254,6 @@
        break;                                                                  
                                                        \
 }                                                                              
                          /* end of JUMPIF */
 
-/// The type of exceptions thrown by ActionScript.
-class ASException
-{
-public:
-       as_value mValue;
-
-       ASException(as_value &v) { mValue = v; }
-       ASException() { mValue.set_undefined(); }
-};
-
-class ASReferenceError : public ASException
-{
-public:
-       ASReferenceError() : ASException()
-       {/**/}
-};
-
-class ASTypeError : public ASException
-{
-public:
-       ASTypeError() : ASException()
-       {/**/}
-};
-
 void
 Machine::execute()
 {
@@ -230,16 +311,17 @@
        case SWF::ABC_ACTION_GETSUPER:
        {
                // Get the name.
-               asName a = mStream->read_V32();
+               asName a = pool_name(mStream->read_V32(), mPoolObject);
                // Finish it, if necessary.
                mStack.drop(completeName(a));
                // Get the target object.
-               as_value& vobj = mStack.top(0);
-               asClass *pClass = findSuper(vobj, true);
-               // If we don't have a class yet, throw.
-               if (!pClass)
+               ENSURE_OBJECT(mStack.top(0));
+               as_object *super = 
mStack.top(0).to_object()->get_prototype().get();
+               // If we don't have a super, throw.
+               if (!super)
                        throw ASReferenceError();
-               asBinding *b = pClass->getGetBinding(vobj, a);
+               Property *b = super->findProperty(a.getName(), 
+                       a.getNamespace()->getURI());
                // The object is on the top already.
                pushCall(1, &mStack.top(0), b);
                break;
@@ -256,16 +338,17 @@
        case SWF::ABC_ACTION_SETSUPER:
        {
                // Get and finish the name.
-               asName a = mStream->read_V32();
+               asName a = pool_name(mStream->read_V32(), mPoolObject);
                as_value vobj = mStack.pop(); // The value
 
                mStack.drop(completeName(a));
 
-               as_value target = mStack.pop();
-               asClass *pClass = findSuper(target, true);
-               if (!pClass)
+               ENSURE_OBJECT(mStack.top(0));
+               as_object* super = 
mStack.pop().to_object()->get_prototype().get();
+               if (!super)
                        throw ASReferenceError();
-               asBinding* b = pClass->getSetBinding(vobj, a);
+               Property* b = super->findProperty(a.getName(), 
+                       a.getNamespace()->getURI());
                // The object is on the top already.
                pushCall(1, &mStack.top(0), b);
                break;
@@ -278,7 +361,7 @@
        case SWF::ABC_ACTION_DXNS:
        {
                uint32_t soffset = mStream->read_V32();
-               std::string& uri = pool_string(soffset);
+               std::string& uri = pool_string(soffset, mPoolObject);
                mDefaultXMLNamespace = mCH->anonNamespace(mST.find(uri));
                break;
        }
@@ -580,19 +663,35 @@
                break;
        }
 /// 0x1C ABC_ACTION_PUSHWITH
+/// 0x30 ABC_ACTION_PUSHSCOPE
 /// Stack In:
 ///  scope -- a scope
 /// Stack Out:
 ///  .
-/// Do: Enter scope with previous scope as its base, unless it already had
-///  a base, in which case leave that alone.
+/// Do: Enter scope with previous scope as its base.
+/// If 0x1C, start a new base if the previous one was global.
        case SWF::ABC_ACTION_PUSHWITH:
        {
-               asScope a = mStack.top(0).to_scope();
+               // A scope object is just a regular object.
+               ENSURE_OBJECT(mStack.top(0));
+               as_object *a = mStack.top(0).to_object().get();
+
+               if (!mScopeStack.empty())
+                       a->set_prototype(mScopeStack.top(0).mScope);
+               else
+                       a->set_prototype(NULL);
+
+               if (opcode == SWF::ABC_ACTION_PUSHWITH &&
+                               mScopeStack.totalSize() == mScopeStack.size())
+               {
+                       mScopeStack.push(Scope(0, a));
+               }
+               else
+               {
+                       mScopeStack.push(Scope(mScopeStack.size(), a));
+               }
+               mCurrentScope = a;
                mStack.drop(1);
-               mScopeStack.push(a);
-               // If there wasn't a base scope, then this becomes it.
-               a.setBase(mCurrentScope);
                break;
        }
 /// 0x1D ABC_ACTION_POPSCOPE
@@ -600,7 +699,12 @@
 ///  shallower than the base's depth.
        case SWF::ABC_ACTION_POPSCOPE:
        {
-               mScopeStack.pop();
+               Scope &s = mScopeStack.pop();
+               mScopeStack.setDownstop(s.mHeightAfterPop);
+               if (mScopeStack.empty())
+                       mCurrentScope = NULL;
+               else
+                       mCurrentScope = mScopeStack.top(0).mScope;
                break;
        }
 /// 0x1E ABC_ACTION_NEXTNAME
@@ -616,9 +720,9 @@
                as_object *obj = mStack.top(1).to_object().get();
                uint32_t index = mStack.top(0).to_number<uint32_t>();
                mStack.drop(1);
-               asBinding *b = obj->bindingAtIndex(index);
+               Property *b = obj->getByIndex(index);
                if (b)
-                       mStack.top(0) = b->getNameString();
+                       mStack.top(0) = mST.value(b->getName());
                else
                        mStack.top(0) = "";
                break;
@@ -629,8 +733,9 @@
 ///  obj -- an object
 /// Stack Out:
 ///  next_index -- next index after index in obj, or 0 if none.
-/// Do: If there is a key/val pair after index, make next_index as it.
-///  Otherwise, make next_index 0.
+/// Do: If the index is 0, return the first logical property.
+/// We'll do this by name, since the name id can be used for this
+/// directly.
        case SWF::ABC_ACTION_HASNEXT:
        {
                ENSURE_NUMBER(mStack.top(0));
@@ -638,11 +743,7 @@
                as_object *obj = mStack.top(1).to_object().get();
                uint32_t index = mStack.top(0).to_number<uint32_t>();
                mStack.drop(1);
-               asBinding *next = obj->bindingAfterIndex(index);
-               if (next)
-                       mStack.top(0) = next->getDispatch();
-               else
-                       mStack.top(0) = 0;
+               mStack.top(0) = obj->nextIndex(index);
                break;
        }
 /// 0x20 ABC_ACTION_PUSHNULL
@@ -675,12 +776,12 @@
                ENSURE_OBJECT(mStack.top(1));
                as_object *obj = mStack.top(1).to_object().get();
                uint32_t index = mStack.top(0).to_number<uint32_t>();
-               asBinding *b = obj->bindingAtIndex(index);
+               const Property *b = obj->getByIndex(index);
                mStack.drop(1);
                if (!b)
                        mStack.top(0).set_undefined();
                else // The top of the stack is obj, as it should be.
-                       pushCall(1, &mStack.top(0), b);
+                       pushCall(1, &mStack.top(0), const_cast<Property*>(b));
                break;
        }
 /// 0x24 ABC_ACTION_PUSHBYTE
@@ -775,7 +876,7 @@
        case SWF::ABC_ACTION_PUSHSTRING:
        {
                mStack.grow(1);
-               mStack.top(0) = pool_string(mStream->read_V32());
+               mStack.top(0) = pool_string(mStream->read_V32(), mPoolObject);
                break;
        }
 /// 0x2D ABC_ACTION_PUSHINT
@@ -785,7 +886,7 @@
        case SWF::ABC_ACTION_PUSHINT:
        {
                mStack.grow(1);
-               mStack.top(0) = pool_int(mStream->read_V32());
+               mStack.top(0) = pool_int(mStream->read_V32(), mPoolObject);
                break;
        }
 /// 0x2E ABC_ACTION_PUSHUINT
@@ -795,7 +896,7 @@
        case SWF::ABC_ACTION_PUSHUINT:
        {
                mStack.grow(1);
-               mStack.top(0) = pool_uint(mStream->read_V32());
+               mStack.top(0) = pool_uint(mStream->read_V32(), mPoolObject);
                break;
        }
 /// 0x2F ABC_ACTION_PUSHDOUBLE
@@ -805,21 +906,7 @@
        case SWF::ABC_ACTION_PUSHDOUBLE:
        {
                mStack.grow(1);
-               mStack.top(0) = pool_double(mStream->read_V32());
-               break;
-       }
-/// 0x30 ABC_ACTION_PUSHSCOPE
-/// Stack In:
-///  scope -- a scope
-/// Stack Out:
-///  .
-/// Do: Enter scope without altering base.
-       case SWF::ABC_ACTION_PUSHSCOPE:
-       {
-               asScope a = mStack.top(0).to_scope();
-               mStack.drop(1);
-               a.setBase(mCurrentScope);
-               mScopeStack.push(a);
+               mStack.top(0) = pool_double(mStream->read_V32(), mPoolObject);
                break;
        }
 /// 0x31 ABC_ACTION_PUSHNAMESPACE
@@ -828,7 +915,7 @@
 ///  ns -- Namespace object from namespace_pool[index]
        case SWF::ABC_ACTION_PUSHNAMESPACE:
        {
-               asNamespace *ns = pool_namespace(mStream->read_V32());
+               asNamespace *ns = pool_namespace(mStream->read_V32(), 
mPoolObject);
                mStack.grow(1);
                mStack.top(0) = *ns;
                break;
@@ -841,6 +928,8 @@
 /// Frame:
 ///  Change at objloc to object which possessed next value.
 ///  Change at indexloc to index (as object) of the next value.
+/// N.B.: A value of '0' for indexloc initializes to the first logical
+/// property.
        case SWF::ABC_ACTION_HASNEXT2:
        {
                int32_t oindex = mStream->read_V32();
@@ -851,13 +940,17 @@
                ENSURE_NUMBER(indexv);
                as_object *obj = objv.to_object().get();
                uint32_t index = indexv.to_number<uint32_t>();
-               asBinding *next = obj->bindingAfterIndex(index);
+               as_object *owner = NULL;
+               int next = obj->nextIndex(index, &owner);
                mStack.grow(1);
                if (next)
                {
                        mStack.top(0).set_bool(true);
-                       mFrame.value(oindex) = next->getOwner();
-                       mFrame.value(iindex) = next->getDispatch();
+                       if (owner)
+                               mFrame.value(oindex) = owner;
+                       else
+                               mFrame.value(oindex).set_null();
+                       mFrame.value(iindex) = next;
                }
                else
                {
@@ -876,7 +969,7 @@
        case SWF::ABC_ACTION_NEWFUNCTION:
        {
                mStack.grow(1);
-               asMethod *m = pool_method(mStream->read_V32());
+               asMethod *m = pool_method(mStream->read_V32(), mPoolObject);
                mStack.top(0) = m->construct(mCurrentScope);
                break;
        }
@@ -896,7 +989,7 @@
                // argc + 1 will be dropped, and mStack.top(argc + 1)
                // will be the top of the stack, so that is where the
                // return value should go. (Currently it is the func)
-               asBinding b(f);
+               Property b(0, 0, f, NULL);
                pushCall(argc + 1, &mStack.top(argc + 1), &b);
                break;
        }
@@ -911,7 +1004,7 @@
        {
                uint32_t argc = mStream->read_V32();
                as_function *f = mStack.top(argc).to_as_function();
-               asBinding b(f);
+               Property b(0, 0, f, NULL);
                pushCall(argc, &mStack.top(argc), &b);
                break;
        }
@@ -928,7 +1021,7 @@
                uint32_t argc = mStream->read_V32();
                ENSURE_OBJECT(mStack.top(argc));
                as_object *obj = mStack.top(argc).to_object().get();
-               asBinding *b = obj->bindingAtIndex(dispatch_id);
+               Property *b = NULL; // TODO: obj->findProperty(dispatch_id);
                if (!b)
                {
                        mStack.drop(argc);
@@ -947,9 +1040,9 @@
 ///  value -- the value returned by obj->ABC::'method_id'(arg1, ..., argN)
        case SWF::ABC_ACTION_CALLSTATIC:
        {
-               asMethod *m = pool_method(mStream->read_V32());
+               asMethod *m = pool_method(mStream->read_V32(), mPoolObject);
                uint32_t argc = mStream->read_V32();
-               asBinding b(m);
+               Property b; //TODO: asBinding b(m);
                pushCall(argc + 1, &mStack.top(argc), &b);
                break;
        }
@@ -967,13 +1060,17 @@
        case SWF::ABC_ACTION_CALLSUPER:
        case SWF::ABC_ACTION_CALLSUPERVOID:
        {
-               asName a = mStream->read_V32();
+               asName a = pool_name(mStream->read_V32(), mPoolObject);
                uint32_t argc = mStream->read_V32();
                int dropsize = completeName(a);
                ENSURE_OBJECT(mStack.top(argc + dropsize));
                mStack.drop(dropsize);
-               asBinding *b = findSuper(mStack.top(argc), 
-                       true)->getBinding(mStack.top(argc), a);
+               ENSURE_OBJECT(mStack.top(argc));
+               as_object *super = 
mStack.top(argc).to_object()->get_prototype().get();
+               if (!super)
+                       throw ASReferenceError();
+               Property *b = super->findProperty(a.getName(), 
+                       a.getNamespace()->getURI());
                if (opcode == SWF::ABC_ACTION_CALLSUPER)
                        pushCall(argc + 1, &mStack.top(argc), b);
                else
@@ -998,7 +1095,7 @@
        case SWF::ABC_ACTION_CALLPROPVOID:
        {
                bool lex_only = (opcode == SWF::ABC_ACTION_CALLPROPLEX);
-               asName a = mStream->read_V32();
+               asName a = pool_name(mStream->read_V32(), mPoolObject);
                uint32_t argc = mStream->read_V32();
                int shift = completeName(a, argc);
                ENSURE_OBJECT(mStack.top(shift + argc));
@@ -1010,8 +1107,9 @@
                                mStack.top(i + shift) = mStack.top(i);
                        mStack.drop(shift);
                }
-               asBinding *b = mStack.top(argc).to_object()->getBinding(a);
-               b->setLexOnly(lex_only);
+               Property *b = mStack.top(argc).to_object()->
+                       findProperty(a.getName(), a.getNamespace()->getURI());
+               //TODO: b->setLexOnly(lex_only);
                if (opcode == SWF::ABC_ACTION_CALLPROPVOID)
                        pushCall(argc + 1, &mIgnoreReturn, b);
                else
@@ -1054,7 +1152,7 @@
                uint32_t argc = mStream->read_V32();
                ENSURE_OBJECT(mStack.top(argc));
                asMethod *m = findSuper(mStack.top(argc), 
true)->getConstructor();
-               asBinding b(m);
+               Property b; //TODO: asBinding b(m);
                pushCall(argc + 1, &mIgnoreReturn, &b);
                break;
        }
@@ -1069,7 +1167,7 @@
 ///   'name_offset'(arg1, ..., argN)
        case SWF::ABC_ACTION_CONSTRUCTPROP:
        {
-               asName a = mStream->read_V32();
+               asName a = pool_name(mStream->read_V32(), mPoolObject);
                uint32_t argc = mStream->read_V32();
                int shift = completeName(a, argc);
                ENSURE_OBJECT(mStack.top(argc + shift));
@@ -1153,9 +1251,9 @@
        case SWF::ABC_ACTION_NEWCLASS:
        {
                uint32_t cid = mStream->read_V32();
-               asClass *c = pool_class(cid);
+               asClass *c = pool_class(cid, mPoolObject);
                asMethod *m = c->getConstructor();
-               asBinding b(m);
+               Property b; //TODO: asBinding b(m);
                pushCall(1, &mStack.top(0), &b);
                break;
        }
@@ -1171,7 +1269,7 @@
 /// descendants of a class.
        case SWF::ABC_ACTION_GETDESCENDANTS:
        {
-               asName a = mStream->read_V32();
+               asName a = pool_name(mStream->read_V32(), mPoolObject);
                as_value &v = mStack.top(0);
                ENSURE_OBJECT(v);
                mStack.drop(1);
@@ -1201,10 +1299,10 @@
        case SWF::ABC_ACTION_FINDPROPSTRICT:
        case SWF::ABC_ACTION_FINDPROPERTY:
        {
-               asName a = mStream->read_V32();
+               asName a = pool_name(mStream->read_V32(), mPoolObject);
                mStack.drop(completeName(a));
-               asBinding *b = findProperty(a);
-               if (!b)
+               Property *b = NULL; //TODO: asBinding *b = findProperty(a);
+               if (0)//!b)
                        if (opcode == SWF::ABC_ACTION_FINDPROPSTRICT)
                                throw ASReferenceError();
                        else
@@ -1222,8 +1320,8 @@
 ///  def -- The definition of the name at name_id.
        case SWF::ABC_ACTION_FINDDEF:
        {
-               asName a = mStream->read_V32();
-               a.makeComplete();
+               asName a = pool_name(mStream->read_V32(), mPoolObject);
+               // The name is expected to be complete.
                // TODO
                break;
        }
@@ -1234,12 +1332,12 @@
 ///   + 0x66 (ABC_ACTION_GETPROPERTY)
        case SWF::ABC_ACTION_GETLEX:
        {
-               asName a = mStream->read_V32();
-               a.makeComplete();
-               asBinding *b = findProperty(a);
-               if (!b)
+               asName a = pool_name(mStream->read_V32(), mPoolObject);
+               // The name is expected to be complete.
+               Property *b = NULL; //TODO: asBinding *b = findProperty(a);
+               if (0)//!b)
                        throw ASReferenceError();
-               b->setLexOnly(b);
+               //TODO: b->setLexOnly(b);
                mStack.grow(1);
                pushCall(0, &mStack.top(0), b);
                break;
@@ -1261,7 +1359,7 @@
 /// key/value is set in the dictionary obj instead.
        case SWF::ABC_ACTION_SETPROPERTY:
        {
-               asName a = mStream->read_V32();
+               asName a = pool_name(mStream->read_V32(), mPoolObject);
                //as_value &v = mStack.pop();
                if (!a.isRuntime())
                {
@@ -1270,7 +1368,7 @@
                else
                {
                        if (a.isRtns() || !(mStack.top(0).is_object()
-                               && mStack.top(1).is_dictionary()))
+                               && mStack.top(1).to_object()->isDictionary()))
                        {
                                mStack.drop(completeName(a));
                                //TODO: mStack.top(0).setProperty(a, v);
@@ -1325,7 +1423,7 @@
        {
                uint8_t depth = mStream->read_u8();
                mStack.grow(1);
-               mStack.top(0) = &mScopeStack.top(depth);
+               mStack.top(0) = mScopeStack.top(depth).mScope;
                break;
        }
 /// 0x66 ABC_ACTION_GETPROPERTY
@@ -1340,7 +1438,7 @@
 /// NB: See 0x61 (ABC_ACTION_SETPROPETY) for the decision of ns/key.
        case SWF::ABC_ACTION_GETPROPERTY:
        {
-               asName a = mStream->read_V32();
+               asName a = pool_name(mStream->read_V32(), mPoolObject);
                if (!a.isRuntime())
                {
                        //TODO: mStack.top(0) = mStack.top(0).getProperty(a, v);
@@ -1348,7 +1446,7 @@
                else
                {
                        if (a.isRtns() || !(mStack.top(0).is_object()
-                               && mStack.top(1).is_dictionary()))
+                               && mStack.top(1).to_object()->isDictionary()))
                        {
                                mStack.drop(completeName(a));
                                //TODO: mStack.top(0) = 
mStack.top(0).getProperty(a);
@@ -1373,7 +1471,7 @@
 ///  Set obj::(resolve)'name_id' to value, set bindings from the context.
        case SWF::ABC_ACTION_INITPROPERTY:
        {
-               asName a = mStream->read_V32();
+               asName a = pool_name(mStream->read_V32(), mPoolObject);
                //as_value& v = mStack.pop();
                mStack.drop(completeName(a));
                //TODO: mStack.pop().to_object().setProperty(a, v, true); // 
true for init
@@ -1388,7 +1486,7 @@
 ///  truth -- True if property was deleted or did not exist, else False.
        case SWF::ABC_ACTION_DELETEPROPERTY:
        {
-               asName a = mStream->read_V32();
+               asName a = pool_name(mStream->read_V32(), mPoolObject);
                mStack.drop(completeName(a));
                //mStack.top(0) = mStack.top(0).deleteProperty(a);
                break;
@@ -1559,7 +1657,7 @@
 /// Do: If obj is not XML based, throw TypeError
        case SWF::ABC_ACTION_CHECKFILTER:
        {
-               if (!mStack.top(0).is_xml())
+               if (!mStack.top(0).is_object() || 
!mStack.top(0).to_object()->isXML())
                        throw ASTypeError();
                break;
        }
@@ -1572,7 +1670,7 @@
 ///  coerced_obj -- The object as the desired (resolve)'name_index' type.
        case SWF::ABC_ACTION_COERCE:
        {
-               asName a = mStream->read_V32();
+               asName a = pool_name(mStream->read_V32(), mPoolObject);
                mStack.drop(completeName(a));
                //TODO: mStack.top(0) = mStack.top(0).coerce(a);
                break;
@@ -1609,9 +1707,10 @@
 ///  cobj -- obj if obj is of type (resolve)'name_index', otherwise Null
        case SWF::ABC_ACTION_ASTYPE:
        {
-               asName a = mStream->read_V32();
+               asName a = pool_name(mStream->read_V32(), mPoolObject);
                mStack.drop(completeName(a));
-               if (!mStack.top(0).conforms_to(a))
+               // TODO: Might need some namespace stuff.
+               if (!mStack.top(0).conforms_to(a.getName()))
                        mStack.top(0).set_null();
                break;
        }
@@ -1623,7 +1722,9 @@
 ///  cobj -- obj if type of obj conforms to valid, otherwise Null
        case SWF::ABC_ACTION_ASTYPELATE:
        {
-               if (!mStack.top(1).conforms_to(mStack.top(0)))
+               bool truth;
+               ABSTRACT_TYPELATE(truth, mStack.top(1), mStack.top(0));
+               if (!truth)
                        mStack.top(1).set_null();
                mStack.drop(1);
                break;
@@ -1947,10 +2048,9 @@
 ///  truth -- Truth of "val is an instance of super"
        case SWF::ABC_ACTION_INSTANCEOF:
        {
-               if (mStack.top(1).is_null())
-                       mStack.top(1) = false;
-               else // Calling to_object intentionally causes an exception if 
super is not an object.
-                       mStack.top(1) = 
mStack.top(1).conforms_to(mStack.top(0));
+               bool truth;
+               ABSTRACT_TYPELATE(truth, mStack.top(1), mStack.top(0));
+               mStack.top(1).set_bool(truth);
                mStack.drop(1);
                break;
        }
@@ -1963,9 +2063,10 @@
 ///  truth -- Truth of "obj is of the type given in (resolve)'name_id'"
        case SWF::ABC_ACTION_ISTYPE:
        {
-               asName a = mStream->read_V32();
+               asName a = pool_name(mStream->read_V32(), mPoolObject);
                mStack.drop(completeName(a));
-               mStack.top(0).set_bool(mStack.top(0).conforms_to(a));
+               // TODO: Namespace stuff?
+               mStack.top(0).set_bool(mStack.top(0).conforms_to(a.getName()));
        }
 /// 0xB3 ABC_ACTION_ISTYPELATE
 /// Stack In:
@@ -1975,7 +2076,9 @@
 ///  truth -- Truth of "obj is of type"
        case SWF::ABC_ACTION_ISTYPELATE:
        {
-               
mStack.top(1).set_bool(mStack.top(1).conforms_to(mStack.top(0)));
+               bool truth;
+               ABSTRACT_TYPELATE(truth, mStack.top(1), mStack.top(0));
+               mStack.top(1).set_bool(truth);
                mStack.drop(1);
                break;
        }
@@ -2140,7 +2243,9 @@
        if (!instance.is_object())
                throw ASTypeError();
 
-       asBinding *pBinding = pDefinition->getBinding(instance, name);
+       return; // TODO:
+#if 0
+       asBinding *pBinding = pDefinition->getBinding(name.getName());
        if (pBinding->isWriteOnly())
                throw ASReferenceError();
 
@@ -2155,6 +2260,7 @@
        // And push the instance ('this')
        mStack.push(instance);
        pushCall(1, &mStack.top(0), pBinding); //TODO: pBinding->getGetter());
+#endif
 }
 
 void
@@ -2164,7 +2270,10 @@
        if (!instance.is_object())
                throw ASReferenceError();
 
-       asBinding *pBinding = pDefinition->getBinding(instance, name);
+       return;
+       // TODO:
+#if 0
+       asBinding *pBinding = pDefinition->getBinding(name.getName());
 
        if (pBinding->isReadOnly())
                throw ASReferenceError();
@@ -2179,6 +2288,7 @@
        mStack.push(instance);
        mStack.push(newvalue);
        pushCall(2, &mStack.top(1), pBinding); //TODO: pBinding->getSetter());
+#endif
 }
 
 int
@@ -2186,20 +2296,19 @@
 {
        int size = 0;
 
-       asName* uname = pool_name(name.id);
-       if (uname->isRuntime())
+       if (name.isRuntime())
        {
                as_value obj = mStack.top(offset);
                if (obj.is_object() && obj.to_object()->isQName())
                        name.fill(obj.to_object().get());
                ++size;
 
-               if (uname->isRtns())
+               if (name.isRtns())
                        ++size; // Ignore the Namespace.
        }
-       else if (uname->isRtns())
+       else if (name.isRtns())
        {
-               uname->setNamespace(mStack.top(offset));
+               //TODO: This should be a namespace 
//name.setNamespace(mStack.top(offset));
                ++size;
        }
        return size;
@@ -2231,9 +2340,27 @@
 }
 
 void
+Machine::immediateFunction(as_function *to_call, as_value& storage,
+       as_object *pThis)
+{
+       // TODO: Implement
+}
+
+void
+Machine::immediateProcedure(as_function *to_call, as_object *pthis,
+       const as_value *stackAdditions, unsigned int stackAdditionsCount)
+{
+       // TODO: Implement
+}
+
+void
 Machine::pushCall(unsigned int stack_in, as_value *return_slot,
-       asBinding *pBind)
+       Property *pBind)
 {
+       if (!pBind)
+               return;
+       //TODO
+#if 0
        switch (pBind->mType)
        {
        default:
@@ -2262,6 +2389,11 @@
                mStack.drop(stack_in);
        // We save that state.
        saveState();
+       // Set the 'this' object for the new call.
+       if (stack_in == 0)
+               mThis = mDefaultThis;
+       else
+               mThis = mStack.value(0).to_object().get(); // Checked in caller.
        // We make the stack appear empty.
        mStack.fixDownstop();
        // We grow to reclaim the parameters. Since this is a SafeStack, they
@@ -2279,7 +2411,10 @@
        // The scope stack should be fixed for non-native calls.
        mScopeStack.fixDownstop();
        //TODO: mScopeStack.push(m->getActivation());
-       mCurrentScope = &mScopeStack.top(0);
+       if (!mScopeStack.empty())
+               mCurrentScope = mScopeStack.top(0).mScope;
+       else
+               mCurrentScope = NULL;
 
        // We set the stream and return as given in the method and call.
        //TODO: mStream = m->getBody();
@@ -2287,6 +2422,7 @@
 
        // When control goes to the main loop of the interpreter, it will
        // automatically start executing the method.
+#endif
 }
 
 void
@@ -2299,6 +2435,7 @@
        mDefaultXMLNamespace = s.mDefaultXMLNamespace;
        mCurrentScope = s.mCurrentScope;
        mGlobalReturn = s.mGlobalReturn;
+       mThis = s.mThis;
        mStateStack.drop(1);
 }
 
@@ -2315,6 +2452,6 @@
        s.mDefaultXMLNamespace = mDefaultXMLNamespace;
        s.mCurrentScope = mCurrentScope;
        s.mGlobalReturn = mGlobalReturn;
+       s.mThis = mThis;
 }
-
 } // end of namespace gnash

Index: server/vm/Machine.h
===================================================================
RCS file: /sources/gnash/gnash/server/vm/Machine.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -b -r1.4 -r1.5
--- server/vm/Machine.h 9 Oct 2007 16:21:37 -0000       1.4
+++ server/vm/Machine.h 18 Oct 2007 11:47:56 -0000      1.5
@@ -28,28 +28,9 @@
 
 class character;
 class as_object;
-
-class asScope
-{
-public:
-       void setBase(asScope *);
-};
-
-class asName
-{
-public:
-       asName(uint32_t);
-       asName();
-       void makeComplete();
-
-       bool isRuntime();
-       bool isRtns();
-
-       void fill(as_object*);
-       void setNamespace(as_value&);
-
-       uint32_t id;
-};
+class abc_block;
+class asName;
+class Property;
 
 /// This machine is intended to work without relying on the C++ call stack,
 /// by resetting its Stream and Stack members (actually, by limiting the stack)
@@ -142,19 +123,7 @@
        /// Nothing.
        void setMember(asClass*, asName&, as_value& target, as_value& val);
 
-       std::string& pool_string(uint32_t);
-       int pool_int(uint32_t);
-       unsigned int pool_uint(uint32_t);
-       double pool_double(uint32_t);
-       asNamespace* pool_namespace(uint32_t);
-       asMethod* pool_method(uint32_t);
-       asClass* pool_class(uint32_t);
-       asName* pool_name(uint32_t);
-
-       asBinding* findProperty(asName&);
-
-       void pushScope(asScope*);
-       asScope* popScope();
+       asBinding* findProperty(asName&) { return NULL; }
 
        void execute();
 
@@ -178,10 +147,16 @@
        /// but mVoidSlot can be used for values that will be discarded.
        ///
        /// @param pBind
-       /// The non-null binding.  If this is only a partial binding, then
+       /// The binding.  If this is only a partial binding, then
        /// the 'this' value will be used to complete it, when possible.
+       /// Sending a null binding will result in a no-op, not an error.
        void pushCall(unsigned int stack_in, as_value *return_slot,
-               asBinding *pBind);
+               Property *pBind);
+
+       void immediateFunction(as_function *to_call, as_value& storage,
+               as_object *pThis);
+       void immediateProcedure(as_function *to_call, as_object *pthis,
+               const as_value *stackAdditions, unsigned int 
stackAdditionsCount);
 
        Machine(string_table &ST, ClassHierarchy *CH);
 
@@ -196,8 +171,21 @@
                unsigned int mScopeTotalSize;
                CodeStream *mStream;
                asNamespace *mDefaultXMLNamespace;
-               asScope *mCurrentScope;
+               as_object *mCurrentScope;
                as_value *mGlobalReturn;
+               as_object *mThis;
+       };
+
+       class Scope
+       {
+       public:
+               unsigned int mHeightAfterPop;
+               as_object *mScope;
+
+               Scope() : mHeightAfterPop(0), mScope(NULL) {/**/}
+               Scope(unsigned int i, as_object *o) : mHeightAfterPop(i),
+                       mScope(o)
+               {/**/}
        };
 
        void saveState();
@@ -205,7 +193,7 @@
 
        SafeStack<as_value> mStack;
        SafeStack<State> mStateStack;
-       SafeStack<asScope> mScopeStack;
+       SafeStack<Scope> mScopeStack;
        SafeStack<as_value> mFrame;
        CodeStream *mStream;
 
@@ -213,13 +201,16 @@
        string_table& mST;
 
        asNamespace* mDefaultXMLNamespace;
-       asScope *mGlobalScope;
-       asScope *mCurrentScope;
+       as_object* mCurrentScope;
+       as_object* mGlobalScope;
+       as_object* mDefaultThis;
+       as_object* mThis;
 
        as_value *mGlobalReturn;
        as_value mIgnoreReturn; // Throw away returns go here.
 
        bool mIsAS3; // Is the stream an AS3 stream.
+       abc_block* mPoolObject; // Where all of the pools are stored.
 };
 
 } // namespace gnash

Index: server/vm/Makefile.am
===================================================================
RCS file: /sources/gnash/gnash/server/vm/Makefile.am,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -b -r1.15 -r1.16
--- server/vm/Makefile.am       27 Sep 2007 23:59:56 -0000      1.15
+++ server/vm/Makefile.am       18 Oct 2007 11:47:56 -0000      1.16
@@ -15,7 +15,7 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
-# $Id: Makefile.am,v 1.15 2007/09/27 23:59:56 tgc Exp $
+# $Id: Makefile.am,v 1.16 2007/10/18 11:47:56 cmusick Exp $
 
 AUTOMAKE_OPTIONS = 
 
@@ -45,6 +45,7 @@
 
 libgnashvm_la_SOURCES = \
        ASHandlers.cpp \
+       Machine.cpp \
        ActionExec.cpp \
        VM.cpp          \
         action.cpp \
@@ -52,6 +53,10 @@
 
 noinst_HEADERS =               \
        ASHandlers.h            \
+       CodeStream.h            \
+       SafeStack.h                     \
+       Machine.h                       \
+       asName.h                        \
        ActionExec.h            \
        ExecutableCode.h        \
        VM.h                    \

Index: server/vm/SafeStack.h
===================================================================
RCS file: /sources/gnash/gnash/server/vm/SafeStack.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -b -r1.3 -r1.4
--- server/vm/SafeStack.h       9 Oct 2007 16:17:40 -0000       1.3
+++ server/vm/SafeStack.h       18 Oct 2007 11:47:56 -0000      1.4
@@ -74,7 +74,7 @@
        /// when you need more than that.
        void grow(unsigned int i)
        {
-               unsigned int available = (1 << mChunkShift) * mData.size() - 
mEnd - 1;
+               unsigned int available = (1 << mChunkShift) * mData.size() - 
mEnd + 1;
                while (available < i)
                {
                        mData.push_back(new T[1 << mChunkShift]);
@@ -88,6 +88,12 @@
        unsigned int getDownstop() const 
        { return mDownstop; }
 
+       /// Alias for getDownstop()
+       unsigned int size() const { return getDownstop(); }
+
+       /// Is the stack empty to us? (Check totalSize() != for actually empty)
+       bool empty() const { return mDownstop == 0; }
+
        /// Makes the stack appear empty to subsequent callers.  This can be 
used
        /// to simulate multiple stacks with a single stack, as in function
        /// calling. Returns the portion of the stack which is newly 
inaccessible.

Index: server/vm/VM.h
===================================================================
RCS file: /sources/gnash/gnash/server/vm/VM.h,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -b -r1.17 -r1.18
--- server/vm/VM.h      24 Sep 2007 15:39:31 -0000      1.17
+++ server/vm/VM.h      18 Oct 2007 11:47:56 -0000      1.18
@@ -36,6 +36,7 @@
 namespace gnash {
        class movie_definition;
        class as_object;
+       class Machine;
 }
 
 namespace gnash {
@@ -134,6 +135,8 @@
        mutable string_table mStringTable;
        /// Not mutable since changing this changes behavior of the VM.
        ClassHierarchy *mClassHierarchy;
+       /// A running execution thread.
+       Machine *mMachine;
 
 public:
 
@@ -177,6 +180,9 @@
        /// Get a reference to the string table used by the VM.
        string_table& getStringTable() const { return mStringTable; }
 
+       /// Get a pointer to the machine, if it exists.
+       Machine* getMachine() const { return mMachine; }
+
        /// Get version of the player, in a compatible representation
        //
        /// This information will be used for the System.capabilities.version

Index: testsuite/server/Makefile.am
===================================================================
RCS file: /sources/gnash/gnash/testsuite/server/Makefile.am,v
retrieving revision 1.33
retrieving revision 1.34
diff -u -b -r1.33 -r1.34
--- testsuite/server/Makefile.am        28 Aug 2007 08:45:11 -0000      1.33
+++ testsuite/server/Makefile.am        18 Oct 2007 11:47:56 -0000      1.34
@@ -40,7 +40,6 @@
        PointTest \
        EdgeTest \
        PropertyListTest \
-       GetterSetterTest \
        as_prop_flagsTest \
        DisplayListTest \
        $(NULL)
@@ -93,11 +92,6 @@
        $(GNASH_LIBS) \
        $(NULL)
 
-GetterSetterTest_SOURCES = GetterSetterTest.cpp
-GetterSetterTest_LDADD = \
-       $(GNASH_LIBS) \
-       $(NULL)
-
 as_prop_flagsTest_SOURCES = as_prop_flagsTest.cpp
 as_prop_flagsTest_LDADD = \
        $(GNASH_LIBS) \

Index: server/Property.cpp
===================================================================
RCS file: server/Property.cpp
diff -N server/Property.cpp
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ server/Property.cpp 18 Oct 2007 11:47:53 -0000      1.1
@@ -0,0 +1,115 @@
+// 
+//   Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
+// 
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+// 
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+// 
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+#include "Property.h"
+#include "VM.h"
+#include "as_function.h"
+#include "Machine.h"
+
+namespace gnash {
+
+as_value
+Property::getDelayedValue(const as_object& this_ptr) const
+{
+       const as_accessors* a = boost::get<const as_accessors>(&mBound);
+       as_environment env;
+       fn_call fn(const_cast<as_object*>(&this_ptr), &env, 0, 0);
+       if (mDestructive)
+       {
+               as_function *f = a->mGetter;
+               as_value ret = (*f)(fn);
+               // The getter might have called the setter, and we should not 
override.
+               if (mDestructive)
+               {
+                       mBound = ret;
+                       mDestructive = false;
+               }
+               return ret;
+       }
+       return (*a->mGetter)(fn);
+
+       as_value v;     
+       VM::get().getMachine()->immediateFunction(a->mGetter, v,
+               const_cast<as_object*>(&this_ptr));
+       if (mDestructive)
+       {
+               ((boundType) mBound) = v;
+               mDestructive = false;
+       }
+       return v;
+}
+
+void
+Property::setDelayedValue(as_object& this_ptr, const as_value& value)
+{
+       const as_accessors* a = boost::get<const as_accessors>(&mBound);
+       as_environment env;
+       env.push(value);
+       fn_call fn(&this_ptr, &env, 1, 0);
+       (*a->mSetter)(fn);
+       return;
+
+       VM::get().getMachine()->immediateProcedure(a->mSetter, &this_ptr,
+               &value, 1);
+}
+
+void
+Property::setSetter(as_function* func)
+{
+       if (isGetterSetter())
+       {
+               boost::get<as_accessors>(&mBound)->mSetter = func;
+       }
+       else
+               mBound = as_accessors(NULL, func);
+}
+
+void
+Property::setGetter(as_function* func)
+{
+       if (isGetterSetter())
+       {
+               boost::get<as_accessors>(&mBound)->mGetter = func;
+       }
+       else
+               mBound = as_accessors(func, NULL);
+}
+
+void
+Property::setReachable() const
+{
+       switch (mBound.which())
+       {
+       case 0: // Blank, nothing to do.
+               break;
+       case 1: // Simple property, value
+               boost::get<as_value>(mBound).setReachable();
+               break;
+       case 2: // Getter/setter
+       {
+               const as_accessors& a = boost::get<as_accessors>(mBound);
+               if (a.mGetter) a.mGetter->setReachable();
+               if (a.mSetter) a.mSetter->setReachable();
+               break;
+       }
+       default:
+               assert(0); // Not here.
+               break;
+       }
+};
+
+} // namespace gnash

Index: server/vm/asName.h
===================================================================
RCS file: server/vm/asName.h
diff -N server/vm/asName.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ server/vm/asName.h  18 Oct 2007 11:47:56 -0000      1.1
@@ -0,0 +1,85 @@
+//   Copyright (C) 2007 Free Software Foundation, Inc.
+// 
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+// 
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+// 
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+#ifndef GNASH_AS_NAME_H
+#define GNASH_AS_NAME_H
+
+#include <vector>
+
+namespace gnash {
+
+class as_object;
+
+class asName
+{
+public:
+       /// If true, the name needs a run-time string value to complete it.
+       bool isRuntime() { return (mFlags & FLAG_RTNAME) != 0; }
+
+       /// If true, the name needs a run-time namespace to complete it.
+       bool isRtns() { return (mFlags & FLAG_RTNS) != 0; }
+
+       bool isQName() { return (mFlags & FLAG_QNAME) != 0; }
+       void setQName() { mFlags |= FLAG_QNAME; }
+
+       void setNamespace(asNamespace *ns) { mNamespace = ns; mPairName = 0; }
+       asNamespace* getNamespace() const { return mNamespace; }
+
+       string_table::key getName() const { return mName; }
+       void setName(string_table::key n) { mName = n; mPairName = 0; }
+
+       void setAttr() { mFlags |= FLAG_ATTR; }
+
+       void fill(as_object*) {/*TODO*/}
+
+       Property* findProperty();
+
+       typedef enum
+       {
+               KIND_Qname = 0x07,
+               KIND_QnameA = 0x0D,
+               KIND_RTQname = 0x0F,
+               KIND_RTQnameA = 0x10,
+               KIND_RTQnameL = 0x11,
+               KIND_RTQnameLA = 0x12,
+               KIND_Multiname = 0x09,
+               KIND_MultinameA = 0x0E,
+               KIND_MultinameL = 0x1B,
+               KIND_MultinameLA = 0x1C
+       } kinds;
+       typedef enum
+       {
+               FLAG_ATTR = 0x01,
+               FLAG_QNAME = 0x02,
+               FLAG_RTNS = 0x04,
+               FLAG_RTNAME = 0x08,
+               FLAG_NSSET = 0x10
+       } flags;
+
+       uint8_t mFlags;
+       std::vector<asNamespace*> *mNamespaceSet;
+
+       asName() : mFlags(0), mNamespaceSet(NULL), mName(0), mPairName(0),
+               mNamespace(NULL)
+       {/**/}
+private:
+       string_table::key mName;
+       string_table::key mPairName; // Pre-computed ns.name value
+       asNamespace* mNamespace;
+};
+
+} // end of namespace gnash
+#endif /* GNASH_AS_NAME_H */

Index: server/GetterSetter.cpp
===================================================================
RCS file: server/GetterSetter.cpp
diff -N server/GetterSetter.cpp
--- server/GetterSetter.cpp     1 Jul 2007 10:54:18 -0000       1.9
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,124 +0,0 @@
-// 
-//   Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
-// 
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 3 of the License, or
-// (at your option) any later version.
-// 
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-// 
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-// 
-//
-//
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "GetterSetter.h"
-
-#include "as_environment.h"
-#include "fn_call.h"
-#include "as_value.h" 
-#include "as_function.h"
-
-#include "log.h"
-
-
-namespace gnash {
-
-as_value
-GetterSetter::getValue(as_object* this_ptr) const
-{
-       as_environment env;
-       fn_call fn(this_ptr, &env, 0, 0);
-       // TODO: need as_function::operator to be const..
-       return (*const_cast<as_function*>(_getter))(fn);
-}
-
-void
-GetterSetter::setValue(as_object* this_ptr, const as_value& val) const
-{
-       as_environment env;
-       env.push(val);
-       fn_call fn(this_ptr, &env, 1, 0);
-       // TODO: need as_function::operator to be const..
-       (*const_cast<as_function*>(_setter))(fn);
-}
-
-GetterSetter&
-GetterSetter::operator=(const GetterSetter& s)
-{
-       if ( s._getter != _getter )
-       {
-#ifndef GNASH_USE_GC
-               _getter->drop_ref();
-#endif // ndef GNASH_USE_GC
-               _getter = s._getter;
-#ifndef GNASH_USE_GC
-               _getter->add_ref();
-#endif // ndef GNASH_USE_GC
-       }
-       if ( s._setter != _setter )
-       {
-#ifndef GNASH_USE_GC
-               _setter->drop_ref();
-#endif // ndef GNASH_USE_GC
-               _setter = s._setter;
-#ifndef GNASH_USE_GC
-               _setter->add_ref();
-#endif // ndef GNASH_USE_GC
-       }
-       return *this;
-}
-
-GetterSetter::GetterSetter(const GetterSetter& s)
-       :
-       _getter(s._getter),
-       _setter(s._setter)
-{
-#ifndef GNASH_USE_GC
-       _getter->add_ref();
-       _setter->add_ref();
-#endif // ndef GNASH_USE_GC
-}
-
-GetterSetter::
-GetterSetter(as_function& getter, as_function& setter)
-       :
-       _getter(&getter),
-       _setter(&setter)
-{
-#ifndef GNASH_USE_GC
-       _getter->add_ref();
-       _setter->add_ref();
-#endif // ndef GNASH_USE_GC
-}
-
-GetterSetter::~GetterSetter()
-{
-#ifndef GNASH_USE_GC
-       _getter->drop_ref();
-       _setter->drop_ref();
-#endif // ndef GNASH_USE_GC
-}
-
-void
-GetterSetter::setReachable() const
-{
-#ifdef GNASH_USE_GC
-       _getter->setReachable();
-       _setter->setReachable();
-#endif
-}
-
-} // end of gnash namespace
-

Index: server/GetterSetter.h
===================================================================
RCS file: server/GetterSetter.h
diff -N server/GetterSetter.h
--- server/GetterSetter.h       1 Jul 2007 10:54:18 -0000       1.9
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,88 +0,0 @@
-// 
-//   Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
-// 
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 3 of the License, or
-// (at your option) any later version.
-// 
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-// 
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-// 
-//
-
-#ifndef GNASH_GETTERSETTER_H
-#define GNASH_GETTERSETTER_H
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-
-// Forward declarations
-namespace gnash {
-       class as_function;
-       class as_object;
-       class as_value;
-}
-
-namespace gnash {
-
-
-/// 
-class GetterSetter
-{
-       as_function* _getter;
-
-       as_function* _setter;
-
-public:
-
-       /// Copy constructor
-       //
-       /// updates ref count of getter/setter.
-       GetterSetter(const GetterSetter& s);
-
-       /// Assignment operator
-       //
-       /// updates ref count of getter/setter.
-       /// checks for self-assignment
-       ///
-       GetterSetter& operator=(const GetterSetter& s);
-
-       /// Construct a getter/setter parameter
-       //
-       /// @param getter
-       ///     getter function, takes no args, returns an as_value
-       ///     add_ref() will be called on it
-       ///
-       /// @param setter
-       ///     setter function, takes one arg, returns nothing
-       ///     add_ref() will be called on it
-       ///
-       GetterSetter(as_function& getter, as_function& setter);
-
-       /// call drop_ref on both getter/setter as_functions
-       ~GetterSetter();
-
-       /// invoke the getter function
-       as_value getValue(as_object* this_ptr) const;
-
-       /// invoke the setter function
-       void setValue(as_object* this_ptr, const as_value& val) const;
-
-       /// Mark both getter and setter as being reachable (for GC)
-       void setReachable() const;
-};
-
-
-} // namespace gnash
-
-#endif // GNASH_GETTERSETTER_H

Index: testsuite/server/GetterSetterTest.cpp
===================================================================
RCS file: testsuite/server/GetterSetterTest.cpp
diff -N testsuite/server/GetterSetterTest.cpp
--- testsuite/server/GetterSetterTest.cpp       19 Sep 2007 14:20:52 -0000      
1.17
+++ /dev/null   1 Jan 1970 00:00:00 -0000
@@ -1,142 +0,0 @@
-// 
-//   Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
-// 
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 3 of the License, or
-// (at your option) any later version.
-// 
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-// 
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "GetterSetter.h"
-#include "builtin_function.h"
-#include "as_object.h"
-#include "as_value.h"
-#include "fn_call.h"
-#include "log.h"
-#include "VM.h"
-#include "DummyMovieDefinition.h"
-
-#include <iostream>
-#include <sstream>
-#include <cassert>
-#include <string>
-
-#include "check.h" 
-
-using namespace std;
-using namespace gnash;
-
-/// return the object's text value
-static as_value getter(const fn_call& fn)
-{
-       boost::intrusive_ptr<as_object> o = fn.this_ptr;
-       assert(fn.nargs == 0);
-       std::string txt = o->get_text_value();
-       return as_value(txt);
-}
-
-/// set a new member to the object
-static as_value setter(const fn_call& fn)
-{
-       boost::intrusive_ptr<as_object> o = fn.this_ptr;
-       assert(fn.nargs == 1);
-       as_value& val = fn.arg(0);
-       
o->set_member(VM::get().getStringTable().find(val.to_string(&fn.env())), val);
-       return as_value();
-}
-
-struct test_object: public as_object {
-       std::string textval;
-
-       test_object(const char* initial_val)
-               :
-               textval(initial_val)
-       {
-       }
-
-       const string& getText() const { return textval; }
-
-       std::string get_text_value() const { return textval; }
-
-       void set_member(string_table::key, const as_value& val )
-       {
-               textval = val.to_string();
-       }
-};
-
-int
-main(int /*argc*/, char** /*argv*/)
-{
-
-       gnash::LogFile& dbglogfile = gnash::LogFile::getDefaultInstance();
-       dbglogfile.setVerbosity();
-
-       // Initialize gnash lib
-       gnashInit();
-
-       boost::intrusive_ptr<movie_definition> md6 ( new 
DummyMovieDefinition(6) );
-       VM& vm = VM::init(*md6);
-       vm.getRoot().setRootMovie( md6->create_movie_instance() );
-
-       boost::intrusive_ptr<test_object> obj(new test_object("initial text"));
-       boost::intrusive_ptr<test_object> obj2(new test_object("other obj"));
-
-       builtin_function* get = new builtin_function(getter);
-       builtin_function* set = new builtin_function(setter);
-
-       GetterSetter getset(*get, *set);
-
-       as_value val;
-        val = getset.getValue(obj.get());
-       check_equals(obj->getText(), string("initial text"));
-       check_equals(val, as_value("initial text"));
-
-       val.set_string("second try");
-       getset.setValue(obj.get(), val);
-       check_equals(obj->getText(), string("second try"));
-       val.set_string("");
-
-       val = getset.getValue(obj.get());
-       check_equals(val, as_value("second try"));
-
-       // Test copy ctor
-
-       GetterSetter getset2(getset);
-
-       val = getset2.getValue(obj2.get());
-       check_equals(obj2->getText(), string("other obj"));
-       check_equals(val, as_value("other obj"));
-
-       val.set_string("second try for other");
-       getset2.setValue(obj2.get(), val);
-       check_equals(obj2->getText(), string("second try for other"));
-       val.set_string("");
-
-       val = getset2.getValue(obj2.get());
-       check_equals(val, as_value("second try for other"));
-
-       val = getset2.getValue(obj.get());
-       check_equals(val, as_value("second try"));
-
-       // Test assignment
-       
-       GetterSetter tmp(getset);
-       val = tmp.getValue(obj.get());
-       check_equals(val, as_value("second try"));
-       tmp = getset2;
-       val = tmp.getValue(obj2.get());
-       check_equals(val, as_value("second try for other"));
-}
-




reply via email to

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