[Top][All Lists]
[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"));
-}
-
- [Gnash-commit] gnash ChangeLog libbase/string_table.cpp libbas...,
Chad Musick <=