gnash-commit
[Top][All Lists]
Advanced

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

[Gnash-commit] /srv/bzr/gnash/trunk r11431: Add Proxy member of as_objec


From: Benjamin Wolsey
Subject: [Gnash-commit] /srv/bzr/gnash/trunk r11431: Add Proxy member of as_object to handle type-dependent data. This replaces
Date: Wed, 19 Aug 2009 18:19:01 +0200
User-agent: Bazaar (1.16.1)

------------------------------------------------------------
revno: 11431 [merge]
committer: Benjamin Wolsey <address@hidden>
branch nick: trunk
timestamp: Wed 2009-08-19 18:19:01 +0200
message:
  Add Proxy member of as_object to handle type-dependent data. This replaces
  the practice of using subclasses and allows the type to be assigned by
  a constructor. It also removes the need for static prototypes.
  
  Currently String, Boolean, Number, and Date are implemented like this, passing
  new and old tests.
  
  Test super more and correct the implementation so that construction of
  objects derived from native classes works (as long as these use the proxy
  object implementation).
  
  Implement various native functions.
  
  Further cleanups are needed.
modified:
  libcore/as_function.h
  libcore/as_object.cpp
  libcore/as_object.h
  libcore/as_value.cpp
  libcore/as_value.h
  libcore/asobj/Array_as.h
  libcore/asobj/Boolean_as.cpp
  libcore/asobj/Boolean_as.h
  libcore/asobj/Date_as.cpp
  libcore/asobj/Date_as.h
  libcore/asobj/Globals.cpp
  libcore/asobj/Number_as.cpp
  libcore/asobj/Number_as.h
  libcore/asobj/Object.cpp
  libcore/asobj/String_as.cpp
  libcore/asobj/String_as.h
  libcore/asobj/flash/filters/DisplacementMapFilter_as.cpp
  libcore/asobj/flash/geom/Rectangle_as.cpp
  libcore/asobj/flash/media/Microphone_as.cpp
  libcore/asobj/flash/net/FileReferenceList_as.cpp
  libcore/asobj/flash/net/FileReference_as.cpp
  libcore/asobj/flash/text/TextRenderer_as.cpp
  libcore/vm/ASHandlers.cpp
  testsuite/actionscript.all/ASnative.as
  testsuite/actionscript.all/Inheritance.as
  testsuite/actionscript.all/Instance.as
  testsuite/actionscript.all/MovieClip.as
  testsuite/actionscript.all/String.as
  testsuite/actionscript.all/toString_valueOf.as
  testsuite/swfdec/PASSING
=== modified file 'libcore/as_function.h'
--- a/libcore/as_function.h     2009-08-18 08:00:20 +0000
+++ b/libcore/as_function.h     2009-08-19 08:48:14 +0000
@@ -99,13 +99,6 @@
        /// Return true if this is a built-in class.
        virtual bool isBuiltin() { return false; }
 
-       /// TODO: check if a user-defined 'toString'
-       ///       will be used when available.
-       std::string get_text_value() const
-       {
-               return "[type Function]";
-       }
-
        /// Return the built-in Function constructor
        static NativeFunction* getFunctionConstructor();
 

=== modified file 'libcore/as_object.cpp'
--- a/libcore/as_object.cpp     2009-08-18 05:26:43 +0000
+++ b/libcore/as_object.cpp     2009-08-19 13:35:42 +0000
@@ -67,29 +67,24 @@
 {
 public:
 
-       as_super(Global_as& gl, as_function* ctor, as_object* proto)
+       as_super(Global_as& gl, as_object* super)
                :
         as_function(gl),
-               _ctor(ctor),
-               _proto(proto)
+               _super(super)
        {
-               set_prototype(proto);
+               set_prototype(prototype());
        }
 
        virtual bool isSuper() const { return true; }
 
        virtual as_object* get_super(const char* fname=0);
 
-       std::string get_text_value() const
-       {
-               return "[object Object]";
-       }
-
        // Fetching members from 'super' yelds a lookup on the associated 
prototype
        virtual bool get_member(string_table::key name, as_value* val,
                string_table::key nsname = 0)
        {
-               if ( _proto ) return _proto->get_member(name, val, nsname);
+        as_object* proto = prototype();
+               if (proto) return proto->get_member(name, val, nsname);
                log_debug("Super has no associated prototype");
                return false;
        }
@@ -108,8 +103,12 @@
        /// Dispatch.
        virtual as_value operator()(const fn_call& fn)
        {
-               //log_debug("Super call operator. fn.this_ptr is %p", 
fn.this_ptr);
-               if ( _ctor ) return _ctor->call(fn);
+        std::auto_ptr<std::vector<as_value> > args(
+            new std::vector<as_value>(fn.getArgs()));
+        fn_call fn2(fn.this_ptr.get(), fn.env(), args, fn.super, true);
+        assert(fn2.isInstantiation());
+        as_function* ctor = constructor();
+               if (ctor) return ctor->call(fn2);
                log_debug("Super has no associated constructor");
                return as_value();
        }
@@ -118,15 +117,21 @@
 
        virtual void markReachableResources() const
        {
-               if ( _ctor ) _ctor->setReachable();
-               if ( _proto ) _proto->setReachable();
+               if (_super) _super->setReachable();
                markAsFunctionReachable();
        }
 
 private:
 
-       as_function* _ctor;
-       as_object* _proto;
+    as_object* prototype() {
+        return _super ? _super->get_prototype().get() : 0;
+    }
+
+    as_function* constructor() {
+        return _super ? _super->get_constructor() : 0;
+    }
+
+       as_object* _super;
 };
 
 as_object*
@@ -138,83 +143,37 @@
 
        // Our class prototype is __proto__.
        as_object* proto = get_prototype().get(); 
-       if ( ! proto )
-       {
-               return new as_super(*getGlobal(*this), 0, 0);
-       }
-
-       // proto's __proto__ is superProto 
-       as_object* superProto = proto->get_prototype().get();
-
-       // proto's __constructor__ is superCtor
-       as_function* superCtor = proto->get_constructor();
-       assert(superCtor == get_constructor());
-
-       //log_debug("super %p proto is %p, its prototype %p", this, proto, 
proto->get_prototype());
-
-       if ( fname && getSWFVersion(*this) > 6)
-       {
-               as_object* owner = 0;
-               string_table& st = getStringTable(*this);
-               string_table::key k = st.find(fname);
-
-               proto->findProperty(k, 0, &owner);
-               if ( ! owner )
-               {
-                       //log_debug("get_super: can't find property %s", fname);
-                       return 0;
-               }
-
-               //log_debug("object containing method %s is %p, its __proto__ 
is %p", fname, owner, owner->get_prototype());
-
-               assert(owner);
-
-               if ( owner != proto )
-               {
-                       as_object* tmp = proto;
-                       while (tmp && tmp->get_prototype() != owner) tmp = 
tmp->get_prototype().get();
-                       // ok, now 'tmp' should be the object whose __proto__ 
member contains
-                       // the actual named method.
-                       //
-                       // in the C:B:A:F case this would be B when calling 
super.myName() from
-                       // C.prototype.myName()
-                       //
-
-                       assert(tmp); // well, since we found the property, it 
must be somewhere!
-
-                       //log_debug("tmp is %p", tmp);
-
-                       if ( tmp != proto )
-                       {
-                               //assert(superProto == 
tmp->get_prototype().get());
-
-                               //superCtor = superProto->get_constructor();
-                               superCtor = tmp->get_constructor();
-                               //if ( ! superCtor ) log_debug("superProto 
(owner) has no __constructor__");
-                       }
-                       else
-                       {
-                               //log_debug("tmp == proto");
-                               superCtor = owner->get_constructor(); // most 
likely..
-                               if ( superProto ) superProto = 
superProto->get_prototype().get();
-                       }
-               }
-               else
-               {
-                       // TODO: check if we've anything to do here...
-                       //log_debug("owner == proto == %p", owner);
-                       //if ( superProto ) superProto = 
superProto->get_prototype().get();
-                       //superCtor = superProto->get_constructor();
-                       //if ( superProto )
-                       //{
-                       //      superCtor = superProto->get_constructor();
-                       //} // else superCtor = NULL ?
-               }
-       }
-
-       as_object* super = new as_super(*getGlobal(*this), superCtor, 
superProto);
-
-       return super;
+       if (!proto) return new as_super(*getGlobal(*this), 0);
+
+    if (!fname || getSWFVersion(*this) <= 6) {
+        return new as_super(*getGlobal(*this), proto);
+    }
+
+    string_table& st = getStringTable(*this);
+    string_table::key k = st.find(fname);
+
+    as_object* owner = 0;
+    proto->findProperty(k, 0, &owner);
+    if (!owner) return 0;
+
+    if (owner == proto) return new as_super(*getGlobal(*this), proto);
+
+    as_object* tmp = proto;
+    while (tmp && tmp->get_prototype() != owner) {
+        tmp = tmp->get_prototype().get();
+    }
+    // ok, now 'tmp' should be the object whose __proto__ member
+    // contains the actual named method.
+    //
+    // in the C:B:A:F case this would be B when calling
+    // super.myName() from C.prototype.myName()
+    
+    // well, since we found the property, it must be somewhere!
+    assert(tmp); 
+
+    if (tmp != proto) { return new as_super(*getGlobal(*this), tmp); }
+    return new as_super(*getGlobal(*this), owner);
+
 }
 
 
@@ -252,6 +211,7 @@
 
 as_object::as_object(Global_as& gl)
        :
+    _proxy(0),
        _vm(getVM(gl)),
        _members(_vm)
 {
@@ -259,6 +219,7 @@
 
 as_object::as_object()
        :
+    _proxy(0),
        _vm(VM::get()),
        _members(_vm)
 {
@@ -266,6 +227,7 @@
 
 as_object::as_object(as_object* proto)
        :
+    _proxy(0),
        _vm(VM::get()),
        _members(_vm)
 {
@@ -274,6 +236,7 @@
 
 as_object::as_object(boost::intrusive_ptr<as_object> proto)
        :
+    _proxy(0),
        _vm(VM::get()),
        _members(_vm)
 {
@@ -287,6 +250,7 @@
 #else
        GcResource(), 
 #endif
+    _proxy(0),
        _vm(VM::get()),
        _members(other._members)
 {
@@ -432,13 +396,7 @@
                if (owner != this) proto = owner; 
        }
 
-       // proto's __proto__ is superProto 
-       as_object* superProto = proto ? proto->get_prototype().get() : 0;
-
-       // proto's __constructor__ is superCtor
-       as_function* superCtor = proto ? proto->get_constructor() : 0;
-
-       as_object* super = new as_super(*getGlobal(*this), superCtor, 
superProto);
+       as_object* super = new as_super(*getGlobal(*this), proto);
 
        return super;
 }
@@ -1131,23 +1089,6 @@
        return getOwnProperty(key, nsname) != NULL;
 }
 
-as_value
-as_object::tostring_method(const fn_call& fn)
-{
-       boost::intrusive_ptr<as_object> obj = fn.this_ptr;
-
-       std::string text_val = obj->get_text_value();
-       return as_value(text_val);
-}
-
-as_value
-as_object::valueof_method(const fn_call& fn)
-{
-       boost::intrusive_ptr<as_object> obj = fn.this_ptr;
-
-       return obj->get_primitive_value();
-}
-
 boost::intrusive_ptr<as_object>
 as_object::get_prototype()
 {

=== modified file 'libcore/as_object.h'
--- a/libcore/as_object.h       2009-08-18 05:27:02 +0000
+++ b/libcore/as_object.h       2009-08-19 11:27:23 +0000
@@ -36,6 +36,7 @@
 #include <utility> // for std::pair
 #include <set>
 #include <sstream>
+#include <boost/scoped_ptr.hpp>
 
 // Forward declarations
 namespace gnash {
@@ -151,6 +152,12 @@
 
 };
 
+class Proxy
+{
+public:
+    virtual ~Proxy() {};
+};
+
 
 /// \brief
 /// A generic bag of attributes. Base class for all ActionScript-able objects.
@@ -268,36 +275,6 @@
     /// does nothing.
     virtual void queueLoad(std::auto_ptr<IOChannel> /*str*/) {};
 
-    /// Return the numeric value of this object
-    //
-    /// The default implementation converts the text value
-    /// to a number, override for a more performant implementation
-    ///
-    virtual double get_numeric_value() const
-    {
-        double d = 0;
-        std::istringstream is(get_text_value());
-        is >> d;
-        return d;
-    }
-
-    /// Return the "primitive" value of this object
-    //
-    /// The default implementation returns an Object value,
-    /// other objects can override this function
-    /// to provide another "preferred" primitive. Primitive
-    /// values are: undefined, null, boolean, string, number, object.
-    ///
-    /// See ECMA-2.6.2 (section 4.3.2).
-    ///
-    virtual as_value get_primitive_value() const
-    {
-        // Since as_value(const as_object*) doesn't exist
-        // we have to cast the value to non-const, or
-        // the as_value will result as beeing a BOOLEAN ! (?)
-        return as_value(const_cast<as_object*>(this)); 
-    }
-
     /// Set a member value
     //
     ///
@@ -1063,12 +1040,13 @@
     ///
     void set_prototype(const as_value& proto, int flags = DefaultFlags);
 
-    /// @{ Common ActionScript methods for DisplayObjects
-    /// TODO: make protected
-
-    static as_value tostring_method(const fn_call& fn);
-
-    static as_value valueof_method(const fn_call& fn);
+    void setProxy(Proxy* p) {
+        _proxy.reset(p);
+    }
+
+    Proxy* proxy() const {
+        return _proxy.get();
+    }
 
 protected:
 
@@ -1138,6 +1116,8 @@
 
 private:
  
+    boost::scoped_ptr<Proxy> _proxy;
+
     /// The global object whose scope contains this object.
     VM& _vm;   
 
@@ -1219,6 +1199,41 @@
     return ret;
 }
 
+
+/// Check whether the object is an instance of a known type.
+//
+/// This is used to check the type of certain objects when it can't be
+/// done through ActionScript and properties. Examples include conversion
+/// of Date and String objects.
+template<typename T>
+bool
+isInstanceOf(as_object* obj, T*& proxy)
+{
+    proxy = dynamic_cast<T*>(obj->proxy());
+    return proxy;
+}
+
+/// An equivalent to ensureType that works with the proxy object.
+template<typename T>
+T*
+checkType(as_object* obj)
+{
+    if (!obj) throw ActionTypeError();
+
+    T* ret = dynamic_cast<T*>(obj->proxy());
+
+    if (!ret) {
+        std::string target = typeName(ret);
+        std::string source = typeName(obj);
+
+        std::string msg = "builtin method or gettersetter for " +
+            target + " called from " + source + " instance.";
+
+        throw ActionTypeError(msg);
+    }
+    return ret;
+}
+
 /// Get the VM from an as_object
 VM& getVM(const as_object& o);
 

=== modified file 'libcore/as_value.cpp'
--- a/libcore/as_value.cpp      2009-07-15 09:10:56 +0000
+++ b/libcore/as_value.cpp      2009-08-19 12:14:57 +0000
@@ -39,6 +39,7 @@
 #include "SimpleBuffer.h"
 #include "StringPredicates.h"
 #include "Global_as.h"
+#include "String_as.h"
 
 #include <boost/shared_ptr.hpp>
 #include <cmath> 
@@ -54,7 +55,7 @@
 //#define GNASH_DEBUG_EQUALITY 1
 
 // Define the macro below to make to_primitive verbose
-// #define GNASH_DEBUG_CONVERSION_TO_PRIMITIVE 1
+//#define GNASH_DEBUG_CONVERSION_TO_PRIMITIVE 1
 
 // Define this macro to make soft references activity verbose
 #define GNASH_DEBUG_SOFT_REFERENCES
@@ -378,6 +379,11 @@
                case AS_FUNCTION:
                case OBJECT:
                {
+            as_object* obj = m_type == AS_FUNCTION ? getFun().get() :
+                                                     getObj().get();
+            String_as* s;
+            if (isInstanceOf(obj, s)) return s->value();
+
                        try
                        {
                                as_value ret = to_primitive(STRING);
@@ -385,9 +391,7 @@
                                // specification, but seems required for 
compatibility with the
                                // reference player.
 #if GNASH_DEBUG_CONVERSION_TO_PRIMITIVE
-                               log_debug(" %s.to_primitive(STRING) returned 
%s", 
-                                               *this,
-                                               ret);
+                               log_debug(" %s.to_primitive(STRING) returned 
%s", *this, ret);
 #endif
                                if ( ret.is_string() ) return ret.to_string();
                        }
@@ -428,34 +432,29 @@
        return to_string();
 }
 
+/// This is only used in AVM2.
 primitive_types
 as_value::ptype() const
 {
-       VM& vm = VM::get();
-       int swfVersion = vm.getSWFVersion();
 
        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:
-       {
-               as_object* obj = getObj().get();
-               // Date objects should return TYPE_STRING (but only from SWF6 
up)
-               // See ECMA-262 8.6.2.6
-               if ( swfVersion > 5 && obj->isDateObject() ) return 
PTYPE_STRING;
-               return PTYPE_NUMBER;
-       }
-       case BOOLEAN:
-               return PTYPE_BOOLEAN;
-       default:
-               break; // Should be only exceptions here.
-       }
+        case STRING: return PTYPE_STRING;
+        case NUMBER: return PTYPE_NUMBER;
+        case AS_FUNCTION:
+        case UNDEFINED:
+        case NULLTYPE:
+        case MOVIECLIP:
+            return PTYPE_NUMBER;
+        case OBJECT:
+        {
+            return PTYPE_NUMBER;
+        }
+        case BOOLEAN:
+            return PTYPE_BOOLEAN;
+        default:
+            break; // Should be only exceptions here.
+        }
        return PTYPE_NUMBER;
 }
 
@@ -468,10 +467,10 @@
 
        AsType hint = NUMBER;
 
-       if ( m_type == OBJECT && swfVersion > 5 && getObj()->isDateObject() )
-       {
-               hint = STRING;
-       }
+       if (m_type == OBJECT && swfVersion > 5) {
+        Date_as* d;
+        if (isInstanceOf(getObj().get(), d)) hint = STRING;
+    }
 
        return to_primitive(hint);
 }
@@ -484,12 +483,13 @@
 
        AsType hint = NUMBER;
 
-       if ( m_type == OBJECT && swfVersion > 5 && getObj()->isDateObject() )
-       {
-               hint = STRING;
-       }
+       if (m_type == OBJECT && swfVersion > 5) {
+        Date_as* d;
+        if (isInstanceOf<Date_as>(getObj().get(), d)) hint = STRING;
+    }
 
-       return convert_to_primitive(hint);
+    *this = to_primitive(hint);
+    return *this;
 }
 
 // Conversion to primitive value.
@@ -518,7 +518,7 @@
                if ( m_type == OBJECT ) obj = getObj().get();
                else obj = getFun().get();
 
-               if ( (!obj->get_member(NSV::PROP_VALUE_OF, &method)) || 
(!method.is_object()) ) // ECMA says ! is_object()
+               if ((!obj->get_member(NSV::PROP_VALUE_OF, &method)) || 
(!method.is_function())) 
                {
 #if GNASH_DEBUG_CONVERSION_TO_PRIMITIVE
                        log_debug(" valueOf not found");
@@ -550,14 +550,6 @@
                // text representation for that object is used
                // instead.
                //
-               if ( ! obj->useCustomToString() )
-               {
-#if GNASH_DEBUG_CONVERSION_TO_PRIMITIVE
-                       log_debug(" not using custom toString");
-#endif
-                       return as_value(obj->get_text_value());
-               }
-
                if ( (!obj->get_member(NSV::PROP_TO_STRING, &method)) ||
                 (!method.is_function()) ) // ECMA says ! is_object()
                {
@@ -592,112 +584,6 @@
 
 }
 
-// Conversion to primitive value.
-as_value&
-as_value::convert_to_primitive(AsType hint) 
-{
-       if ( m_type != OBJECT && m_type != AS_FUNCTION ) return *this; 
-       //if ( ! is_object() ) return *this; // include MOVIECLIP !!
-
-#if GNASH_DEBUG_CONVERSION_TO_PRIMITIVE
-       log_debug("to_primitive(%s)", hint==NUMBER ? "NUMBER" : "STRING");
-#endif 
-
-       // TODO: implement as_object::DefaultValue (ECMA-262 - 8.6.2.6)
-
-       as_value method;
-       as_object* obj = NULL;
-
-       if (hint == NUMBER)
-       {
-               if ( m_type == MOVIECLIP )
-               {
-                       set_double(NaN);
-                       return *this;
-               }
-               if ( m_type == OBJECT ) obj = getObj().get();
-               else obj = getFun().get();
-
-               if ( (!obj->get_member(NSV::PROP_VALUE_OF, &method)) ||
-                (!method.is_object()) ) // ECMA says ! is_object()
-               {
-#if GNASH_DEBUG_CONVERSION_TO_PRIMITIVE
-                       log_debug(" valueOf not found");
-#endif
-                       // Returning undefined here instead of throwing
-                       // a TypeError passes tests in 
actionscript.all/Object.as
-                       // and many swfdec tests, with no new failures (though
-                       // perhaps we aren't testing enough).
-                       set_undefined();
-                       return *this;
-            
-               }
-       }
-       else
-       {
-               assert(hint==STRING);
-
-               if ( m_type == MOVIECLIP )
-               {
-                       set_string(getCharacterProxy().getTarget());
-                       return *this;
-               }
-
-               if ( m_type == OBJECT ) obj = getObj().get();
-               else obj = getFun().get();
-
-               // @@ Moock says, "the value that results from
-               // calling toString() on the object".
-               //
-               // When the toString() method doesn't exist, or
-               // doesn't return a valid number, the default
-               // text representation for that object is used
-               // instead.
-               //
-               if ( ! obj->useCustomToString() )
-               {
-#if GNASH_DEBUG_CONVERSION_TO_PRIMITIVE
-                       log_debug(" not using custom toString");
-#endif
-                       set_string(obj->get_text_value());
-                       return *this;
-               }
-
-               if ( (!obj->get_member(NSV::PROP_TO_STRING, &method)) || 
-                (!method.is_function()) ) // ECMA says ! is_object()
-               {
-#if GNASH_DEBUG_CONVERSION_TO_PRIMITIVE
-                       log_debug(" toString not found");
-#endif
-                       if ( (!obj->get_member(NSV::PROP_VALUE_OF, &method)) || 
-                    (!method.is_function()) ) // ECMA says ! is_object()
-                       {
-#if GNASH_DEBUG_CONVERSION_TO_PRIMITIVE
-                               log_debug(" valueOf not found");
-#endif
-                               throw ActionTypeError();
-                       }
-               }
-       }
-
-       assert(obj);
-
-       as_environment env(getVM(*obj));
-       as_value ret = call_method0(method, env, obj);
-#if GNASH_DEBUG_CONVERSION_TO_PRIMITIVE
-       log_debug("to_primitive: method call returned %s", ret);
-#endif
-       if ( ret.m_type == OBJECT || ret.m_type == AS_FUNCTION ) // not a 
primitive 
-       {
-               throw ActionTypeError();
-       }
-
-       *this = ret;
-
-       return *this;
-}
-
-
 bool
 as_value::parseNonDecimalInt(const std::string& s, double& d, bool whole)
 {
@@ -2087,14 +1973,10 @@
                convert_to_string_versioned(version);
                string_concat(v2.to_string_versioned(version));
        }
-       else
-       {
+       else {
                // use numeric semantic
                double v2num = v2.to_number();
-               //log_debug(_("v2 num = %g"), v2num);
                double v1num = to_number();
-               //log_debug(_("v1 num = %g"), v1num);
-
                set_double(v2num + v1num); 
 
        }
@@ -2468,8 +2350,16 @@
 #ifdef GNASH_DEBUG_AMF_DESERIALIZE
                        log_debug("amf0 read date: %e", dub);
 #endif
-            as_object* obj = new Date_as(dub);
-                       ret.set_as_object(obj);
+
+            Global_as* gl = vm.getGlobal();
+            as_function* ctor = 
gl->getMember(NSV::CLASS_DATE).to_as_function();
+            if (ctor) {
+                std::auto_ptr<std::vector<as_value> > args(
+                        new std::vector<as_value>());
+                args->push_back(dub);
+                ret.set_as_object(ctor->constructInstance(as_environment(vm),
+                            args));
+            }
 
                        if (b + 2 > end) {
                                log_error(_("AMF0 read: premature end of input 
reading "
@@ -2526,52 +2416,14 @@
             as_object* obj = to_object(*vm.getGlobal()).get();
             assert(obj);
             OffsetTable::iterator it = offsetTable.find(obj);
-            if ( it == offsetTable.end() )
-            {
-                size_t idx = offsetTable.size()+1; // 1 for the first, etc...
+            if (it == offsetTable.end()) {
+                size_t idx = offsetTable.size() + 1; // 1 for the first, etc...
                 offsetTable[obj] = idx;
-
-                Array_as* ary = dynamic_cast<Array_as*>(obj);
-                if ( ary )
-                {
-                    size_t len = ary->size();
-                    if ( allowStrict && ary->isStrict() )
-                    {
-#ifdef GNASH_DEBUG_AMF_SERIALIZE
-                        log_debug(_("writeAMF0: serializing array of %d "
-                                    "elements as STRICT_ARRAY (index %d)"),
-                                    len, idx);
-#endif
-                        buf.appendByte(amf::Element::STRICT_ARRAY_AMF0);
-                        buf.appendNetworkLong(len);
-
-                        as_value elem;
-                        for (size_t i=0; i<len; ++i)
-                        {
-                            elem = ary->at(i);
-                            if ( ! elem.writeAMF0(buf, offsetTable, vm, 
allowStrict) )
-                            {
-                                log_error("Problems serializing strict array 
member %d=%s", i, elem);
-                                return false;
-                            }
-                        }
-                        return true;
-                    }
-                    else 
-                    {
-#ifdef GNASH_DEBUG_AMF_SERIALIZE
-                        log_debug(_("writeAMF0: serializing array of %d "
-                                    "elements as ECMA_ARRAY (index %d) 
[allowStrict:%d, isStrict:%d]"),
-                                    len, idx, allowStrict, ary->isStrict());
-#endif
-                        buf.appendByte(amf::Element::ECMA_ARRAY_AMF0);
-                        buf.appendNetworkLong(len);
-                    }
-                }
-                else if ( obj->isDateObject() )
-                {
-                    const Date_as& date = dynamic_cast<const Date_as&>(*obj);
-                    double d = date.getTimeValue(); 
+                
+                Date_as* date;
+                if (isInstanceOf(obj, date))
+                {
+                    double d = date->getTimeValue(); 
 #ifdef GNASH_DEBUG_AMF_SERIALIZE
                     log_debug(_("writeAMF0: serializing date object "
                                 "with index %d and value %g"), idx, d);
@@ -2588,8 +2440,44 @@
 
                     return true;
                 }
-                else
-                {
+
+                Array_as* ary = dynamic_cast<Array_as*>(obj);
+                if (ary) {
+                    const size_t len = ary->size();
+                    if (allowStrict && ary->isStrict()) {
+#ifdef GNASH_DEBUG_AMF_SERIALIZE
+                        log_debug(_("writeAMF0: serializing array of %d "
+                                    "elements as STRICT_ARRAY (index %d)"),
+                                    len, idx);
+#endif
+                        buf.appendByte(amf::Element::STRICT_ARRAY_AMF0);
+                        buf.appendNetworkLong(len);
+
+                        as_value elem;
+                        for (size_t i = 0; i < len; ++i) {
+                            elem = ary->at(i);
+                            if (!elem.writeAMF0(buf, offsetTable, vm,
+                                        allowStrict)) {
+                                log_error("Problems serializing strict array "
+                                        "member %d=%s", i, elem);
+                                return false;
+                            }
+                        }
+                        return true;
+                    }
+
+                    // A normal array.
+#ifdef GNASH_DEBUG_AMF_SERIALIZE
+                    log_debug(_("writeAMF0: serializing array of %d "
+                                "elements as ECMA_ARRAY (index %d) "
+                                "[allowStrict:%d, isStrict:%d]"),
+                                len, idx, allowStrict, ary->isStrict());
+#endif
+                    buf.appendByte(amf::Element::ECMA_ARRAY_AMF0);
+                    buf.appendNetworkLong(len);
+                }
+                else {
+                    // It's a simple object
 #ifdef GNASH_DEBUG_AMF_SERIALIZE
                     log_debug(_("writeAMF0: serializing object (or function) "
                                 "with index %d"), idx);
@@ -2599,8 +2487,7 @@
 
                 PropsBufSerializer props(buf, vm, offsetTable, allowStrict);
                 obj->visitNonHiddenPropertyValues(props);
-                if ( ! props.success() ) 
-                {
+                if (!props.success()) {
                     log_error("Could not serialize object");
                     return false;
                 }
@@ -2608,17 +2495,13 @@
                 buf.appendByte(amf::Element::OBJECT_END_AMF0);
                 return true;
             }
-            else // object already seen
-            {
-                size_t idx = it->second;
+            size_t idx = it->second;
 #ifdef GNASH_DEBUG_AMF_SERIALIZE
-                log_debug(_("writeAMF0: serializing object (or function) "
-                            "as reference to %d"), idx);
+            log_debug(_("writeAMF0: serializing object (or function) "
+                        "as reference to %d"), idx);
 #endif
-                buf.appendByte(amf::Element::REFERENCE_AMF0);
-                buf.appendNetworkShort(idx);
-                return true;
-            }
+            buf.appendByte(amf::Element::REFERENCE_AMF0);
+            buf.appendNetworkShort(idx);
             return true;
         }
 

=== modified file 'libcore/as_value.h'
--- a/libcore/as_value.h        2009-07-15 09:10:56 +0000
+++ b/libcore/as_value.h        2009-08-19 12:14:57 +0000
@@ -294,6 +294,8 @@
        const char* typeOf() const;
 
        /// Get the primitive type of this value
+    //
+    /// Only used in AVM2
        primitive_types ptype() const;
 
        // Chad: Document
@@ -475,15 +477,6 @@
        /// or NULL if it is not an ActionScript function.
        as_function*    to_as_function() const;
 
-       /// Convert this value to a primitive type
-       //
-       /// Primitive types are: undefined, null, boolean, string, number.
-       /// See ECMA-2.6.2 (sections 4.3.2 and 8.6.2.6).
-       ///
-       /// @throw ActionTypeError if an object can't be converted to a 
primitive
-       ///
-       as_value& convert_to_primitive();
-
        /// Return value as a primitive type
        //
        /// Primitive types are: undefined, null, boolean, string, number.
@@ -515,7 +508,7 @@
        ///
        /// @throw ActionTypeError if an object can't be converted to a 
primitive
        ///
-       as_value& convert_to_primitive(AsType hint);
+       as_value& convert_to_primitive();
 
        /// Force type to number.
        void convert_to_number();

=== modified file 'libcore/asobj/Array_as.h'
--- a/libcore/asobj/Array_as.h  2009-07-16 08:30:06 +0000
+++ b/libcore/asobj/Array_as.h  2009-08-19 08:48:14 +0000
@@ -165,12 +165,6 @@
     /// Convert array to string.
        std::string toString() const;
 
-       // override from as_object
-       std::string get_text_value() const
-       {
-               return toString();
-       }
-
        unsigned int size() const;
 
        void resize(unsigned int);

=== modified file 'libcore/asobj/Boolean_as.cpp'
--- a/libcore/asobj/Boolean_as.cpp      2009-08-11 13:23:30 +0000
+++ b/libcore/asobj/Boolean_as.cpp      2009-08-19 14:08:49 +0000
@@ -27,8 +27,9 @@
 #include "Global_as.h"
 #include "smart_ptr.h" // for boost intrusive_ptr
 #include "builtin_function.h" // need builtin_function
+#include "NativeFunction.h"
 #include "GnashException.h"
-#include "VM.h" // for registering static GcResources (constructor and 
prototype)
+#include "VM.h" 
 #include "Object.h" // for getObjectInterface
 
 namespace gnash {
@@ -41,16 +42,15 @@
     as_object* getBooleanInterface();
 }
 
-class Boolean_as: public as_object
+class Boolean_as: public Proxy
 {
 
 public:
 
     explicit Boolean_as(bool val)
         :
-        as_object(getBooleanInterface())
+        _val(val)
     {
-        _val = val;
     }
     
     bool value() const { return _val; }
@@ -76,16 +76,24 @@
 
 }
 
+void
+registerBooleanNative(as_object& global)
+{
+    VM& vm = getVM(global);
+    vm.registerNative(boolean_valueof, 107, 0);
+    vm.registerNative(boolean_tostring, 107, 1);
+    vm.registerNative(boolean_ctor, 107, 2);
+}
+
 namespace {
 
 
 void
 attachBooleanInterface(as_object& o)
 {
-    Global_as* gl = getGlobal(o);
-
-    o.init_member("toString", gl->createFunction(boolean_tostring));
-    o.init_member("valueOf", gl->createFunction(boolean_valueof));
+    VM& vm = getVM(o);
+    o.init_member("valueOf", vm.getNative(107, 0));
+    o.init_member("toString", vm.getNative(107, 1));
 }
 
 as_object*
@@ -106,10 +114,8 @@
 as_value
 boolean_tostring(const fn_call& fn)
 {
-    boost::intrusive_ptr<Boolean_as> obj = ensureType<Boolean_as>(fn.this_ptr);
-    
+    Boolean_as* obj = checkType<Boolean_as>(fn.this_ptr.get());
     if (obj->value()) return as_value("true");
-
     return as_value("false");
 }
 
@@ -117,25 +123,24 @@
 as_value
 boolean_valueof(const fn_call& fn) 
 {
-    boost::intrusive_ptr<Boolean_as> obj = ensureType<Boolean_as>(fn.this_ptr);
-
+    Boolean_as* obj = checkType<Boolean_as>(fn.this_ptr.get());
     return as_value(obj->value());
 }
 
 as_value
 boolean_ctor(const fn_call& fn)
 {
-    if (fn.nargs > 0)
-    {
-        bool val = fn.arg(0).to_bool();
-        if ( ! fn.isInstantiation() ) return as_value(val);
-        
-        return as_value(new Boolean_as(val));
+
+    if (!fn.isInstantiation()) {
+        if (!fn.nargs) return as_value();
+        return as_value(fn.arg(0).to_bool());
     }
 
-    if (!fn.isInstantiation()) return as_value();
-        
-    return as_value(new Boolean_as(false));
+    const bool val = fn.nargs ? fn.arg(0).to_bool() : false;
+
+    as_object* obj = fn.this_ptr.get();
+    obj->setProxy(new Boolean_as(val));
+    return as_value();
 
 }
 

=== modified file 'libcore/asobj/Boolean_as.h'
--- a/libcore/asobj/Boolean_as.h        2009-08-11 09:16:57 +0000
+++ b/libcore/asobj/Boolean_as.h        2009-08-19 14:08:49 +0000
@@ -29,7 +29,9 @@
 
 /// Initialize the global Boolean class
 void boolean_class_init(as_object& global, const ObjectURI& uri);
-  
+
+void registerBooleanNative(as_object& global);
+
 } // end of gnash namespace
 
 #endif

=== modified file 'libcore/asobj/Date_as.cpp'
--- a/libcore/asobj/Date_as.cpp 2009-08-18 06:49:40 +0000
+++ b/libcore/asobj/Date_as.cpp 2009-08-19 10:01:05 +0000
@@ -163,7 +163,6 @@
 
 Date_as::Date_as(double value)
     :
-    as_object(getDateInterface()),
     _timeValue(value)
 {
 }
@@ -208,7 +207,7 @@
 }
 
 void
-Date_as::init(as_object& global, const ObjectURI& uri)
+date_class_init(as_object& global, const ObjectURI& uri)
 {
 
     Global_as* gl = getGlobal(global);
@@ -230,7 +229,7 @@
 }
 
 void
-Date_as::registerNative(as_object& global)
+registerDateNative(as_object& global)
 {
     VM& vm = getVM(global);
 
@@ -426,7 +425,13 @@
 date_new(const fn_call& fn)
 {
 
-       boost::intrusive_ptr<Date_as> date;
+    as_object* obj = fn.this_ptr.get();
+    if (!fn.isInstantiation()) {
+        obj = new as_object();
+        obj->set_prototype(getDateInterface());
+        obj->setProxy(new Date_as);
+        return obj;
+    }
 
     // Reject all date specifications containing Infinities and NaNs.
     // The commercial player does different things according to which
@@ -434,17 +439,17 @@
     // for now, we just use rogue_date_args' algorithm
     double foo;
     if (( foo = rogue_date_args(fn, 7)) != 0.0) {
-        date = new Date_as(foo);
-        return as_value(date.get());
+        obj->setProxy(new Date_as(foo));
+        return as_value();
     }
 
-    if (fn.nargs < 1 || fn.arg(0).is_undefined() || !(fn.isInstantiation()) ) {
+    if (fn.nargs < 1 || fn.arg(0).is_undefined()) {
         // Time now
-        date = new Date_as;
+        obj->setProxy(new Date_as);
     }
     else if (fn.nargs == 1) {
         // Set the value in milliseconds since 1970 UTC
-        date = new Date_as(fn.arg(0).to_number());
+        obj->setProxy(new Date_as(fn.arg(0).to_number()));
     }
     else {
         // Create a time from the supplied (at least 2) arguments.
@@ -495,11 +500,11 @@
         // due to shortcomings in the timezoneoffset calculation, but should
         // be internally consistent.
         double localTime = makeTimeValue(gt);
-        date = new Date_as(
-                localTime - clocktime::getTimeZoneOffset(localTime) * 60000);
+        obj->setProxy(new Date_as(
+                localTime - clocktime::getTimeZoneOffset(localTime) * 60000));
     }
     
-    return as_value(date.get());
+    return as_value();
 }
 
 //
@@ -543,7 +548,7 @@
 as_value
 date_getYear(const fn_call& fn)
 {
-    boost::intrusive_ptr<Date_as> date = ensureType<Date_as>(fn.this_ptr);
+    Date_as* date = checkType<Date_as>(fn.this_ptr.get());
     return timeElement(localTime, &GnashTime::year, date->getTimeValue());
 }
 
@@ -552,7 +557,7 @@
 as_value
 date_getFullYear(const fn_call& fn)
 {
-    boost::intrusive_ptr<Date_as> date = ensureType<Date_as>(fn.this_ptr);
+    Date_as* date = checkType<Date_as>(fn.this_ptr.get());
     return timeElement(
             localTime, &GnashTime::year, date->getTimeValue(), 1900);
 }
@@ -562,7 +567,7 @@
 as_value
 date_getMonth(const fn_call& fn)
 {
-    boost::intrusive_ptr<Date_as> date = ensureType<Date_as>(fn.this_ptr);
+    Date_as* date = checkType<Date_as>(fn.this_ptr.get());
     return timeElement(localTime, &GnashTime::month, date->getTimeValue());
 }
 
@@ -571,7 +576,7 @@
 as_value
 date_getDate(const fn_call& fn)
 {
-    boost::intrusive_ptr<Date_as> date = ensureType<Date_as>(fn.this_ptr);
+    Date_as* date = checkType<Date_as>(fn.this_ptr.get());
     return timeElement(localTime, &GnashTime::monthday, date->getTimeValue());
 }
 
@@ -581,7 +586,7 @@
 as_value
 date_getDay(const fn_call& fn)
 {
-    boost::intrusive_ptr<Date_as> date = ensureType<Date_as>(fn.this_ptr);
+    Date_as* date = checkType<Date_as>(fn.this_ptr.get());
     return timeElement(localTime, &GnashTime::weekday, date->getTimeValue());
 }
 
@@ -591,7 +596,7 @@
 as_value
 date_getHours(const fn_call& fn)
 {
-    boost::intrusive_ptr<Date_as> date = ensureType<Date_as>(fn.this_ptr);
+    Date_as* date = checkType<Date_as>(fn.this_ptr.get());
     return timeElement(localTime, &GnashTime::hour, date->getTimeValue());
 }
 
@@ -602,7 +607,7 @@
 as_value
 date_getMinutes(const fn_call& fn)
 {
-    boost::intrusive_ptr<Date_as> date = ensureType<Date_as>(fn.this_ptr);
+    Date_as* date = checkType<Date_as>(fn.this_ptr.get());
     return timeElement(localTime, &GnashTime::minute, date->getTimeValue());
 }
 
@@ -612,7 +617,7 @@
 as_value
 date_getSeconds(const fn_call& fn)
 {
-    boost::intrusive_ptr<Date_as> date = ensureType<Date_as>(fn.this_ptr);
+    Date_as* date = checkType<Date_as>(fn.this_ptr.get());
     return timeElement(localTime, &GnashTime::second, date->getTimeValue());
 }
 
@@ -624,7 +629,7 @@
 as_value
 date_getMilliseconds(const fn_call& fn)
 {
-    boost::intrusive_ptr<Date_as> date = ensureType<Date_as>(fn.this_ptr);
+    Date_as* date = checkType<Date_as>(fn.this_ptr.get());
     return timeElement(
             localTime, &GnashTime::millisecond, date->getTimeValue());
 }
@@ -635,7 +640,7 @@
 as_value
 date_getUTCFullYear(const fn_call& fn)
 {
-    boost::intrusive_ptr<Date_as> date = ensureType<Date_as>(fn.this_ptr);
+    Date_as* date = checkType<Date_as>(fn.this_ptr.get());
     return timeElement(universalTime, &GnashTime::year,
            date->getTimeValue(), 1900);
 }
@@ -643,21 +648,21 @@
 as_value
 date_getUTCYear(const fn_call& fn)
 {
-    boost::intrusive_ptr<Date_as> date = ensureType<Date_as>(fn.this_ptr);
+    Date_as* date = checkType<Date_as>(fn.this_ptr.get());
     return timeElement(universalTime, &GnashTime::year, date->getTimeValue());
 }
 
 as_value
 date_getUTCMonth(const fn_call& fn)
 {
-    boost::intrusive_ptr<Date_as> date = ensureType<Date_as>(fn.this_ptr);
+    Date_as* date = checkType<Date_as>(fn.this_ptr.get());
     return timeElement(universalTime, &GnashTime::month, date->getTimeValue());
 }
 
 as_value
 date_getutcdate(const fn_call& fn)
 {
-    boost::intrusive_ptr<Date_as> date = ensureType<Date_as>(fn.this_ptr);
+    Date_as* date = checkType<Date_as>(fn.this_ptr.get());
     return timeElement(
             universalTime, &GnashTime::monthday, date->getTimeValue());
 }
@@ -666,7 +671,7 @@
 as_value
 date_getUTCDay(const fn_call& fn)
 {
-    boost::intrusive_ptr<Date_as> date = ensureType<Date_as>(fn.this_ptr);
+    Date_as* date = checkType<Date_as>(fn.this_ptr.get());
     return timeElement(
                 universalTime, &GnashTime::weekday, date->getTimeValue());
 }
@@ -674,7 +679,7 @@
 as_value
 date_getUTCHours(const fn_call& fn)
 {
-    boost::intrusive_ptr<Date_as> date = ensureType<Date_as>(fn.this_ptr);
+    Date_as* date = checkType<Date_as>(fn.this_ptr.get());
     return timeElement(
                 universalTime, &GnashTime::hour, date->getTimeValue());
 }
@@ -682,7 +687,7 @@
 as_value
 date_getUTCMinutes(const fn_call& fn)
 {
-    boost::intrusive_ptr<Date_as> date = ensureType<Date_as>(fn.this_ptr);
+    Date_as* date = checkType<Date_as>(fn.this_ptr.get());
     return timeElement(universalTime, &GnashTime::minute, 
date->getTimeValue());
 }
 
@@ -705,7 +710,7 @@
 as_value
 date_getTimezoneOffset(const fn_call& fn)
 {
-    boost::intrusive_ptr<Date_as> date = ensureType<Date_as>(fn.this_ptr);
+    Date_as* date = checkType<Date_as>(fn.this_ptr.get());
     return as_value(-localTimeZoneOffset(date->getTimeValue()));
 }
 
@@ -727,7 +732,7 @@
 as_value
 date_setTime(const fn_call& fn)
 {
-    boost::intrusive_ptr<Date_as> date = ensureType<Date_as>(fn.this_ptr);
+    Date_as* date = checkType<Date_as>(fn.this_ptr.get());
 
     if (fn.nargs < 1 || fn.arg(0).is_undefined()) {
         IF_VERBOSE_ASCODING_ERRORS(
@@ -839,7 +844,7 @@
 as_value
 date_setfullyear(const fn_call& fn)
 {
-    boost::intrusive_ptr<Date_as> date = ensureType<Date_as>(fn.this_ptr);
+    Date_as* date = checkType<Date_as>(fn.this_ptr.get());
 
     if (fn.nargs < 1) {
         IF_VERBOSE_ASCODING_ERRORS(
@@ -890,7 +895,7 @@
 as_value
 date_setYear(const fn_call& fn)
 {
-    boost::intrusive_ptr<Date_as> date = ensureType<Date_as>(fn.this_ptr);
+    Date_as* date = checkType<Date_as>(fn.this_ptr.get());
 
     // assert(fn.nargs == 1);
     if (fn.nargs < 1) {
@@ -944,7 +949,7 @@
 as_value
 date_setmonth(const fn_call& fn)
 {
-    boost::intrusive_ptr<Date_as> date = ensureType<Date_as>(fn.this_ptr);
+    Date_as* date = checkType<Date_as>(fn.this_ptr.get());
 
     // assert(fn.nargs >= 1 && fn.nargs <= 2);
     if (fn.nargs < 1) {
@@ -1000,7 +1005,7 @@
 as_value
 date_setDate(const fn_call& fn)
 {
-  boost::intrusive_ptr<Date_as> date = ensureType<Date_as>(fn.this_ptr);
+  Date_as* date = checkType<Date_as>(fn.this_ptr.get());
 
   if (fn.nargs < 1) {
       IF_VERBOSE_ASCODING_ERRORS(
@@ -1040,7 +1045,7 @@
 as_value
 date_setHours(const fn_call& fn)
 {
-    boost::intrusive_ptr<Date_as> date = ensureType<Date_as>(fn.this_ptr);
+    Date_as* date = checkType<Date_as>(fn.this_ptr.get());
 
     // assert(fn.nargs >= 1 && fn.nargs <= 4);
     if (fn.nargs < 1) {
@@ -1085,7 +1090,7 @@
 as_value
 date_setMinutes(const fn_call& fn)
 {
-    boost::intrusive_ptr<Date_as> date = ensureType<Date_as>(fn.this_ptr);
+    Date_as* date = checkType<Date_as>(fn.this_ptr.get());
 
     //assert(fn.nargs >= 1 && fn.nargs <= 3);
     if (fn.nargs < 1) {
@@ -1126,7 +1131,7 @@
 as_value
 date_setSeconds(const fn_call& fn)
 {
-    boost::intrusive_ptr<Date_as> date = ensureType<Date_as>(fn.this_ptr);
+    Date_as* date = checkType<Date_as>(fn.this_ptr.get());
 
     // assert(fn.nargs >= 1 && fn.nargs <= 2);
     if (fn.nargs < 1) {
@@ -1165,7 +1170,7 @@
 as_value
 date_setMilliseconds(const fn_call& fn)
 {
-    boost::intrusive_ptr<Date_as> date = ensureType<Date_as>(fn.this_ptr);
+    Date_as* date = checkType<Date_as>(fn.this_ptr.get());
 
     if (fn.nargs < 1) {
         IF_VERBOSE_ASCODING_ERRORS(
@@ -1207,7 +1212,7 @@
 as_value
 date_tostring(const fn_call& fn) 
 {
-    boost::intrusive_ptr<Date_as> date = ensureType<Date_as>(fn.this_ptr);
+    Date_as* date = checkType<Date_as>(fn.this_ptr.get());
     return as_value(date->toString());
 }
 
@@ -1350,7 +1355,7 @@
 /// number of milliseconds.
 as_value date_getTime(const fn_call& fn)
 {
-    boost::intrusive_ptr<Date_as> date = ensureType<Date_as>(fn.this_ptr);
+    Date_as* date = checkType<Date_as>(fn.this_ptr.get());
     return as_value(date->getTimeValue());
 }
 

=== modified file 'libcore/asobj/Date_as.h'
--- a/libcore/asobj/Date_as.h   2009-07-16 08:30:06 +0000
+++ b/libcore/asobj/Date_as.h   2009-08-19 10:01:05 +0000
@@ -24,7 +24,7 @@
 
 namespace gnash {
 
-class Date_as : public as_object
+class Date_as : public Proxy
 {
 public:
 
@@ -34,10 +34,6 @@
 
     double getTimeValue() const { return _timeValue; }
 
-    static void registerNative(as_object& global);
-
-    static void init(as_object& where, const ObjectURI& uri);
-
     std::string toString() const;
 
     bool isDateObject() { return true; }
@@ -48,6 +44,9 @@
 
 };
 
+void registerDateNative(as_object& global);
+
+void date_class_init(as_object& where, const ObjectURI& uri);
 
 } // end of gnash namespace
 

=== modified file 'libcore/asobj/Globals.cpp'
--- a/libcore/asobj/Globals.cpp 2009-08-18 08:00:20 +0000
+++ b/libcore/asobj/Globals.cpp 2009-08-19 14:17:42 +0000
@@ -452,7 +452,7 @@
            NS_GLOBAL, 5))
         (N(xmlsocket_class_init, NSV::CLASS_XMLSOCKET, NSV::CLASS_OBJECT,
            NS_GLOBAL, 5))
-        (N(Date_as::init, NSV::CLASS_DATE, NSV::CLASS_OBJECT, NS_GLOBAL, 5))
+        (N(date_class_init, NSV::CLASS_DATE, NSV::CLASS_OBJECT, NS_GLOBAL, 5))
         (N(XMLDocument_as::init, NSV::CLASS_XML, NSV::CLASS_OBJECT,
            NS_GLOBAL, 5))
         (N(XMLNode_as::init, NSV::CLASS_XMLNODE, NSV::CLASS_OBJECT,
@@ -520,7 +520,7 @@
            NS_GLOBAL, 5))
         (N(qname_class_init, NSV::CLASS_QNAME, NSV::CLASS_OBJECT,
            NS_GLOBAL, 5))
-        (N(Date_as::init, NSV::CLASS_DATE, NSV::CLASS_OBJECT, NS_GLOBAL, 5))
+        (N(date_class_init, NSV::CLASS_DATE, NSV::CLASS_OBJECT, NS_GLOBAL, 5))
         (N(Error_class_init, NSV::CLASS_ERROR, NSV::CLASS_OBJECT,
            NS_GLOBAL, 5))
 
@@ -906,6 +906,50 @@
     return as_value();
 }
 
+// ASconstructor function
+// See: http://osflash.org/flashcoders/undocumented/asnative?s=asnative
+as_value
+global_asconstructor(const fn_call& fn)
+{
+
+    if (fn.nargs < 2)
+    {
+        IF_VERBOSE_ASCODING_ERRORS(    
+        log_aserror(_("ASNative(%s): needs at least two arguments"),
+            fn.dump_args());
+        )
+        return as_value();
+    }
+
+    const int sx = fn.arg(0).to_int();
+    const int sy = fn.arg(1).to_int();
+
+    if (sx < 0 || sy < 0) {
+        IF_VERBOSE_ASCODING_ERRORS(    
+            log_aserror(_("ASconstructor(%s): args must be 0 or above"),
+                fn.dump_args());
+        )
+        return as_value();
+    }
+
+    const unsigned int x = static_cast<unsigned int>(sx);
+    const unsigned int y = static_cast<unsigned int>(sy);
+
+    VM& vm = getVM(fn);
+    as_function* fun = vm.getNative(x, y);
+    if (!fun) {
+        log_debug(_("No ASnative(%d, %d) registered with the VM"), x, y);
+        return as_value();
+    }
+
+    Global_as* gl = getGlobal(fn);
+    as_object* proto = getObjectInterface();
+    fun->init_member(NSV::PROP_PROTOTYPE, gl->createObject(proto));
+
+    return as_value(fun);
+        
+}
+
 // ASNative function
 // See: http://osflash.org/flashcoders/undocumented/asnative?s=asnative
 as_value
@@ -926,19 +970,12 @@
     const int sx = fn.arg(0).to_int();
     const int sy = fn.arg(1).to_int();
 
-    if ( sx < 0 )
-    {
-        IF_VERBOSE_ASCODING_ERRORS(    
-        log_aserror(_("ASNative(%s): first arg must be >= 0"), fn.dump_args());
-        )
-        return ret;
-    }
-    if ( sy < 0 )
-    {
-        IF_VERBOSE_ASCODING_ERRORS(    
-        log_aserror(_("ASNative(%s): second arg must be >= 0"), 
fn.dump_args());
-        )
-        return ret;
+    if (sx < 0 || sy < 0) {
+        IF_VERBOSE_ASCODING_ERRORS(    
+            log_aserror(_("ASnative(%s): args must be 0 or above"),
+                fn.dump_args());
+        )
+        return as_value();
     }
 
     const unsigned int x = static_cast<unsigned int>(sx);
@@ -1048,15 +1085,6 @@
     return as_value();
 }
 
-// ASconstructor function
-// TODO: find dox 
-as_value
-global_asconstructor(const fn_call& /*fn*/)
-{
-    LOG_ONCE(log_unimpl("ASconstructor"));
-    return as_value();
-}
-
 
 // updateAfterEvent function
 as_value
@@ -1294,6 +1322,8 @@
     registerFunctionNative(global);
     registerStringNative(global);
     registerArrayNative(global);
+    registerNumberNative(global);
+    registerBooleanNative(global);
     registerMovieClipNative(global);
     registerSelectionNative(global);
     registerColorNative(global);
@@ -1305,7 +1335,7 @@
 
     AsBroadcaster::registerNative(global);
     TextFormat_as::registerNative(global);
-    Date_as::registerNative(global);
+    registerDateNative(global);
     Mouse_as::registerNative(global);
 
     // LoadableObject has natives shared between LoadVars and XML, so 

=== modified file 'libcore/asobj/Number_as.cpp'
--- a/libcore/asobj/Number_as.cpp       2009-08-11 13:23:40 +0000
+++ b/libcore/asobj/Number_as.cpp       2009-08-19 14:08:49 +0000
@@ -25,8 +25,9 @@
 #include "Global_as.h"
 #include "as_object.h" // for inheritance
 #include "as_value.h" // for doubleToString
-#include "builtin_function.h" // need builtin_function
-#include "VM.h" // for registering static GcResources (constructor and 
prototype)
+#include "builtin_function.h"
+#include "NativeFunction.h"
+#include "VM.h"
 #include "Object.h" // for getObjectInterface
 
 #include <sstream>
@@ -35,35 +36,17 @@
 
 namespace gnash {
 
-namespace {
-    as_object* getNumberInterface();
-}
-
-class Number_as : public as_object
+class Number_as : public Proxy
 {
 public:
 
     Number_as(double val)
         :
-        as_object(getNumberInterface()),
         _val(val)
     {
     }
 
-    // override from as_object
-    std::string get_text_value() const
-    {
-        return as_value::doubleToString(_val);
-    }
-
-    // override from as_object
-    double get_numeric_value() const
-    {
-        return _val;
-    }
-
-    as_value get_primitive_value() const 
-    {
+    double value() const {
         return _val;
     }
 
@@ -72,7 +55,6 @@
     // the number value
     double _val;
 
-
 };
 
 namespace {
@@ -82,9 +64,9 @@
 {
     // Number.toString must only work for number object, not generic ones.
     // This is so trace(Number.prototype) doesn't return 0 ...
-    boost::intrusive_ptr<Number_as> obj = ensureType<Number_as>(fn.this_ptr);
+    Number_as* obj = checkType<Number_as>(fn.this_ptr.get());
 
-    double val = obj->get_numeric_value();
+    double val = obj->value();
     unsigned radix = 10;
 
     if ( fn.nargs ) 
@@ -109,9 +91,9 @@
 {
     // Number.valueOf must only work for number object, not generic ones.
     // This is so trace(Number.prototype == Object) return true in swf5 ?
-    boost::intrusive_ptr<Number_as> obj = ensureType<Number_as>(fn.this_ptr);
+    Number_as* obj = checkType<Number_as>(fn.this_ptr.get());
 
-    return obj->get_primitive_value();
+    return obj->value();
 }
 
 as_value
@@ -128,17 +110,17 @@
         return as_value(val);
     }
 
-    Number_as* obj = new Number_as(val);
+    fn.this_ptr->setProxy(new Number_as(val));
     
-    return as_value(obj); // will keep alive
+    return as_value(); 
 }
 
 void
 attachNumberInterface(as_object& o)
 {
-    Global_as* gl = getGlobal(o);
-    o.init_member("toString", gl->createFunction(number_toString));
-    o.init_member("valueOf", gl->createFunction(number_valueOf));
+    VM& vm = getVM(o);
+    o.init_member("valueOf", vm.getNative(106, 0));
+    o.init_member("toString", vm.getNative(106, 1));
 }
 
 void
@@ -162,20 +144,6 @@
             as_value(-std::numeric_limits<double>::infinity()), cflags);
 }
 
-as_object*
-getNumberInterface()
-{
-    static boost::intrusive_ptr<as_object> o=NULL;
-    if ( o == NULL )
-    {
-        o = new as_object(getObjectInterface());
-        attachNumberInterface(*o);
-    }
-
-    return o.get();
-}
-
-
 } // anonymous namespace
 
 
@@ -184,8 +152,9 @@
 number_class_init(as_object& where, const ObjectURI& uri)
 {
     Global_as* gl = getGlobal(where);
-    as_object* proto = getNumberInterface();
+    as_object* proto = gl->createObject(getObjectInterface());
     as_object* cl = gl->createClass(&number_ctor, proto);
+    attachNumberInterface(*proto);
     attachNumberStaticInterface(*cl);
 
     // Register _global.Number
@@ -194,4 +163,13 @@
 
 }
 
+void
+registerNumberNative(as_object& global)
+{
+    VM& vm = getVM(global);
+    vm.registerNative(number_valueOf, 106, 0);
+    vm.registerNative(number_toString, 106, 1);
+    vm.registerNative(number_ctor, 106, 2);
+}
+
 } // namespace gnash

=== modified file 'libcore/asobj/Number_as.h'
--- a/libcore/asobj/Number_as.h 2009-08-11 09:17:11 +0000
+++ b/libcore/asobj/Number_as.h 2009-08-19 14:08:49 +0000
@@ -33,6 +33,8 @@
 /// Initialize the global Number class
 void number_class_init(as_object& global, const ObjectURI& uri);
 
+void registerNumberNative(as_object& global);
+
 }
 
 #endif // GNASH_NUMBER_H

=== modified file 'libcore/asobj/Object.cpp'
--- a/libcore/asobj/Object.cpp  2009-08-18 09:24:49 +0000
+++ b/libcore/asobj/Object.cpp  2009-08-19 08:37:19 +0000
@@ -50,6 +50,8 @@
     as_value object_unwatch(const fn_call&);
     as_value object_toLocaleString(const fn_call&);
     as_value object_ctor(const fn_call& fn);
+    as_value object_valueOf(const fn_call& fn);
+    as_value object_toString(const fn_call& fn);
 
     void attachObjectInterface(as_object& o);
 
@@ -70,8 +72,8 @@
        vm.registerNative(object_watch, 101, 0); 
        vm.registerNative(object_unwatch, 101, 1); 
        vm.registerNative(object_addproperty, 101, 2); 
-       vm.registerNative(as_object::valueof_method, 101, 3); 
-       vm.registerNative(as_object::tostring_method, 101, 4); 
+       vm.registerNative(object_valueOf, 101, 3); 
+       vm.registerNative(object_toString, 101, 4); 
        vm.registerNative(object_hasOwnProperty, 101, 5); 
        vm.registerNative(object_isPrototypeOf, 101, 6); 
        vm.registerNative(object_isPropertyEnumerable, 101, 7); 
@@ -192,6 +194,26 @@
     return gl->createObject(proto);
 }
 
+/// Object.toString returns one of two values: [type Function] if it is a 
+/// function, [object Object] if it is an object. Gnash wrongly regards super
+/// as a function, so we have to handle that too.
+as_value
+object_toString(const fn_call& fn)
+{
+    as_object* obj = fn.this_ptr.get();
+
+    if (obj && obj->to_function() && !obj->isSuper()) {
+        return as_value("[type Function]");
+    }
+    return as_value("[object Object]");
+}
+
+as_value
+object_valueOf(const fn_call& fn)
+{
+       return fn.this_ptr;
+}
+
 
 /// The return value is not dependent on the result of add_property (though
 /// this is always true anyway), but rather on the validity of the arguments.

=== modified file 'libcore/asobj/String_as.cpp'
--- a/libcore/asobj/String_as.cpp       2009-08-18 08:00:20 +0000
+++ b/libcore/asobj/String_as.cpp       2009-08-19 10:01:05 +0000
@@ -63,6 +63,7 @@
     as_value string_toUpperCase(const fn_call& fn);
     as_value string_toLowerCase(const fn_call& fn);
     as_value string_toString(const fn_call& fn);
+    as_value string_valueOf(const fn_call& fn);
     as_value string_oldToLower(const fn_call& fn);
     as_value string_oldToUpper(const fn_call& fn);
     as_value string_ctor(const fn_call& fn);
@@ -75,47 +76,18 @@
             const std::string& function);
 }
 
-class String_as : public as_object
+String_as::String_as(const std::string& s)
+    :
+    _string(s)
 {
-
-public:
-
-    explicit String_as(const std::string& s)
-            :
-            as_object(getStringInterface()),
-            _string(s)
-    {
-        std::wstring wstr = utf8::decodeCanonicalString(
-                _string, getSWFVersion(*this));
-        init_member(NSV::PROP_LENGTH, wstr.size(), 
-                PropFlags::dontDelete | PropFlags::dontEnum); 
-    }
-
-
-    bool useCustomToString() const { return false; }
-
-    std::string get_text_value() const {
-        return _string;
-    }
-
-    as_value get_primitive_value() const {
-        return as_value(_string);
-    }
-
-    const std::string& str() {
-        return _string;
-    }
-
-private:
-    std::string _string;
-};
+}
 
 void
 registerStringNative(as_object& global)
 {
     VM& vm = getVM(global);
     vm.registerNative(string_ctor, 251, 0);
-       vm.registerNative(as_object::tostring_method, 251, 1);
+       vm.registerNative(string_valueOf, 251, 1);
        vm.registerNative(string_toString, 251, 2);
        vm.registerNative(string_oldToUpper, 102, 0);
        vm.registerNative(string_toUpperCase, 251, 3);
@@ -813,12 +785,20 @@
     return as_value(str);
 }
 
+/// This returns as_value.toString() value of an object. For Strings this is
+/// a string, for objects "[type Object]" or "[type Function]", for Booleans
+/// "true" or "false", etc.
+as_value
+string_valueOf(const fn_call& fn)
+{
+    return as_value(fn.this_ptr).to_string();
+}
 
 as_value
 string_toString(const fn_call& fn)
 {
-    boost::intrusive_ptr<String_as> obj = ensureType<String_as>(fn.this_ptr);
-    return as_value(obj->str());
+    String_as* str = checkType<String_as>(fn.this_ptr.get());
+    return as_value(str->value());
 }
 
 
@@ -827,19 +807,22 @@
 {
        std::string str;
        
-       if (fn.nargs)
-       {
+       if (fn.nargs) {
                str = fn.arg(0).to_string();
        }
 
-       if ( ! fn.isInstantiation() )
+       if (!fn.isInstantiation())
        {
                return as_value(str);
        }
        
-       boost::intrusive_ptr<String_as> obj = new String_as(str);
-
-       return as_value(obj.get());
+    as_object* obj = fn.this_ptr.get();
+
+    obj->setProxy(new String_as(str));
+    std::wstring wstr = utf8::decodeCanonicalString(str, getSWFVersion(fn));
+    obj->init_member(NSV::PROP_LENGTH, wstr.size(), as_object::DefaultFlags);
+
+       return as_value();
 }
 
 /// Check the number of arguments, returning false if there

=== modified file 'libcore/asobj/String_as.h'
--- a/libcore/asobj/String_as.h 2009-08-11 08:35:50 +0000
+++ b/libcore/asobj/String_as.h 2009-08-19 11:27:23 +0000
@@ -21,6 +21,7 @@
 #define GNASH_STRING_H
 
 #include <string>
+#include "as_object.h"
 
 namespace gnash {
 
@@ -28,7 +29,22 @@
 class ObjectURI;
 class Global_as;
 
-// Initialize the global String class
+class String_as : public Proxy
+{
+
+public:
+
+    explicit String_as(const std::string& s);
+
+    const std::string& value() {
+        return _string;
+    }
+
+private:
+    std::string _string;
+};
+
+/// Initialize the global String class
 void string_class_init(as_object& global, const ObjectURI& uri);
 
 void registerStringNative(as_object& global);

=== modified file 'libcore/asobj/flash/filters/DisplacementMapFilter_as.cpp'
--- a/libcore/asobj/flash/filters/DisplacementMapFilter_as.cpp  2009-07-29 
05:40:20 +0000
+++ b/libcore/asobj/flash/filters/DisplacementMapFilter_as.cpp  2009-08-18 
15:31:33 +0000
@@ -99,12 +99,6 @@
                :
                as_object(getDisplacementMapFilterInterface())
        {}
-
-       // override from as_object ?
-       //std::string get_text_value() const { return "DisplacementMapFilter"; }
-
-       // override from as_object ?
-       //double get_numeric_value() const { return 0; }
 };
 
 

=== modified file 'libcore/asobj/flash/geom/Rectangle_as.cpp'
--- a/libcore/asobj/flash/geom/Rectangle_as.cpp 2009-07-29 06:12:04 +0000
+++ b/libcore/asobj/flash/geom/Rectangle_as.cpp 2009-08-18 15:30:47 +0000
@@ -125,12 +125,6 @@
         :
         as_object(getRectangleInterface())
     {}
-
-    // override from as_object ?
-    //std::string get_text_value() const { return "Rectangle"; }
-
-    // override from as_object ?
-    //double get_numeric_value() const { return 0; }
 };
 
 

=== modified file 'libcore/asobj/flash/media/Microphone_as.cpp'
--- a/libcore/asobj/flash/media/Microphone_as.cpp       2009-08-18 11:17:30 
+0000
+++ b/libcore/asobj/flash/media/Microphone_as.cpp       2009-08-18 15:24:05 
+0000
@@ -184,7 +184,7 @@
 
 // AS2 static accessor.
 as_value
-microphone_get(const fn_call& fn)
+microphone_get(const fn_call& /*fn*/)
 {
     static size_t newcount = 0;
     static boost::intrusive_ptr<microphone_as_object> permaMicPtr;

=== modified file 'libcore/asobj/flash/net/FileReferenceList_as.cpp'
--- a/libcore/asobj/flash/net/FileReferenceList_as.cpp  2009-07-29 05:40:20 
+0000
+++ b/libcore/asobj/flash/net/FileReferenceList_as.cpp  2009-08-18 15:30:47 
+0000
@@ -88,12 +88,6 @@
         :
         as_object(getFileReferenceListInterface())
     {}
-
-    // override from as_object ?
-    //std::string get_text_value() const { return "FileReferenceList"; }
-
-    // override from as_object ?
-    //double get_numeric_value() const { return 0; }
 };
 
 

=== modified file 'libcore/asobj/flash/net/FileReference_as.cpp'
--- a/libcore/asobj/flash/net/FileReference_as.cpp      2009-07-29 05:40:20 
+0000
+++ b/libcore/asobj/flash/net/FileReference_as.cpp      2009-08-18 15:30:47 
+0000
@@ -105,11 +105,6 @@
         as_object(getFileReferenceInterface())
     {}
 
-    // override from as_object ?
-    //std::string get_text_value() const { return "FileReference"; }
-
-    // override from as_object ?
-    //double get_numeric_value() const { return 0; }
 };
 
 

=== modified file 'libcore/asobj/flash/text/TextRenderer_as.cpp'
--- a/libcore/asobj/flash/text/TextRenderer_as.cpp      2009-07-29 05:40:20 
+0000
+++ b/libcore/asobj/flash/text/TextRenderer_as.cpp      2009-08-18 15:30:47 
+0000
@@ -84,12 +84,6 @@
         :
         as_object(getTextRendererInterface())
     {}
-
-    // override from as_object ?
-    //std::string get_text_value() const { return "TextRenderer"; }
-
-    // override from as_object ?
-    //double get_numeric_value() const { return 0; }
 };
 
 

=== modified file 'libcore/vm/ASHandlers.cpp'
--- a/libcore/vm/ASHandlers.cpp 2009-08-11 10:29:24 +0000
+++ b/libcore/vm/ASHandlers.cpp 2009-08-19 07:12:11 +0000
@@ -3153,7 +3153,7 @@
     const VM& vm = getVM(env);
 
     int swfVersion = vm.getSWFVersion();
-    if ( swfVersion <= 5 )
+    if (swfVersion <= 5)
     {
         as_value op1 = env.top(0);
         try { op1 = op1.to_primitive(); }

=== modified file 'testsuite/actionscript.all/ASnative.as'
--- a/testsuite/actionscript.all/ASnative.as    2009-08-18 10:05:43 +0000
+++ b/testsuite/actionscript.all/ASnative.as    2009-08-19 14:17:42 +0000
@@ -292,8 +292,8 @@
 
 // This is _global.Number
 f = ASconstructor(106, 2);
-xcheck_equals(typeof(f), "function");
-xcheck_equals(typeof(f.prototype), "object");
+check_equals(typeof(f), "function");
+check_equals(typeof(f.prototype), "object");
 
 // Attach number natives and it works.
 ASSetNative(f.prototype, 106, "valueOf,toString");
@@ -306,28 +306,28 @@
 check_equals(obj.__proto__, undefined);
 #endif
 
-xcheck_equals(typeof(obj), "object");
-xcheck_equals(obj.toString(), "6");
+check_equals(typeof(obj), "object");
+check_equals(obj.toString(), "6");
 
 // Attach boolean natives and it fails.
 ASSetNative(f.prototype, 107, "valueOf,toString");
-xcheck_equals(typeof(obj), "object");
+check_equals(typeof(obj), "object");
 check_equals(obj.toString(), undefined);
 
 // Attach number natives to prototype again and it works.
 ASSetNative(f.prototype, 106, "valueOf,toString");
-xcheck_equals(obj.toString(), "6");
+check_equals(obj.toString(), "6");
 
 g = ASnative(106, 2);
-xcheck_equals(typeof(g), "function");
+check_equals(typeof(g), "function");
 check_equals(typeof(g.prototype), "undefined");
 
 // This is the ASnative function Number.toString. It does not attach
 // Number.prototype, so the Number.toString function fails.
 f = ASconstructor(106, 1);
 ASSetNative(f.prototype, 106, "valueOf,toString");
-xcheck_equals(typeof(f), "function");
-xcheck_equals(typeof(f.prototype), "object");
+check_equals(typeof(f), "function");
+check_equals(typeof(f.prototype), "object");
 obj = new f(6);
 xcheck_equals(typeof(obj), "object");
 check_equals(obj.toString(), undefined);
@@ -340,8 +340,8 @@
 
 // ASconstructor doesn't rely on ASnative.
 f = ASconstructor(106, 2);
-xcheck_equals(typeof(f), "function");
-xcheck_equals(typeof(f.prototype), "object");
+check_equals(typeof(f), "function");
+check_equals(typeof(f.prototype), "object");
 
 g = ASnative(106, 2);
 check_equals(typeof(g), "undefined");

=== modified file 'testsuite/actionscript.all/Inheritance.as'
--- a/testsuite/actionscript.all/Inheritance.as 2009-02-25 22:33:03 +0000
+++ b/testsuite/actionscript.all/Inheritance.as 2009-08-19 13:34:39 +0000
@@ -560,6 +560,55 @@
 
 #endif // MING_SUPPORTS_ASM_IMPLEMENTS
 
+CtorA = function() {
+    this.a = 4;
+};
+
+CtorB = function() {
+    this.b = "string";
+};
+
+PrA = {};
+PrA.__proto__ = { vv:8 };
+
+PrB = {};
+PrB.__proto__ = { gg:"moo" };
+
+tests = 0;
+
+#if OUTPUT_VERSION > 5
+
+// Check that changing __proto__.__constructor also changes super(), and the
+// same for __proto__.__proto__
+Obj = function() {
+    check_equals(this.a, undefined);
+    check_equals(this.b, undefined);
+    check_equals(super.vv, 8);
+    check_equals(super.gg, undefined);
+    
+    this.__proto__.__constructor__ = CtorA;
+    super();
+    check_equals(this.a, 4);
+    check_equals(this.b, undefined);
+
+
+    this.__proto__.__constructor__ = CtorB;
+    super();
+    check_equals(this.a, 4);
+    check_equals(this.b, "string");
+
+    this.__proto__.__proto__ = PrB;
+    check_equals(super.vv, undefined);
+    check_equals(super.gg, "moo");
+
+    tests += 10;
+};  
+
+Obj.prototype = PrA;
+f = new Obj();
+
+#endif
+
 //------------------------------------------------
 // END OF TEST
 //------------------------------------------------
@@ -567,17 +616,17 @@
 #if OUTPUT_VERSION < 6
 
 # ifdef MING_SUPPORTS_ASM_IMPLEMENTS
-    check_totals(106); 
+    check_totals(106 + tests); 
 # else
-    check_totals(102); 
+    check_totals(102 + tests); 
 # endif
 
 #else // SWF6,7,8
 
 # ifdef MING_SUPPORTS_ASM_IMPLEMENTS
-    check_totals(163);
+    check_totals(163 + tests);
 # else
-    check_totals(159); 
+    check_totals(159 + tests); 
 # endif
 
 #endif

=== modified file 'testsuite/actionscript.all/Instance.as'
--- a/testsuite/actionscript.all/Instance.as    2009-08-17 11:52:24 +0000
+++ b/testsuite/actionscript.all/Instance.as    2009-08-19 13:20:05 +0000
@@ -119,13 +119,21 @@
 check_equals(typeof(String.prototype), "number");
 check_equals(String.prototype, 8);
 s = new String("hello");
+#if OUTPUT_VERSION == 5
+check_equals(s, undefined);
+#else
 xcheck_equals(s, undefined);
-xcheck_equals(s.__proto__, 8);
+#endif
+check_equals(s.__proto__, 8);
 check_equals(typeof(s), "object");
 check(!s instanceOf String);
 
 s = new Object("hello");
+#if OUTPUT_VERSION == 5
+check_equals(s, undefined);
+#else
 xcheck_equals(s, undefined);
+#endif
 
 Cl = function() {};
 Cl.prototype = 8;

=== modified file 'testsuite/actionscript.all/MovieClip.as'
--- a/testsuite/actionscript.all/MovieClip.as   2009-08-18 08:36:30 +0000
+++ b/testsuite/actionscript.all/MovieClip.as   2009-08-19 08:37:03 +0000
@@ -2339,10 +2339,11 @@
 createTextField("t1", 3, 0, 100, 100, 100);
 #if OUTPUT_VERSION > 5
 check_equals(_level0.t1.getSWFVersion(), undefined);
+check_equals(_level0.t1.toString(), "[object Object]");
 #else
 xcheck_equals(_level0.t1.getSWFVersion(), OUTPUT_VERSION);
-#endif
 xcheck_equals(_level0.t1.toString(), "[object Object]");
+#endif
 _level0.t1.getSWFVersion = MovieClip.prototype.getSWFVersion;
 xcheck_equals(_level0.t1.getSWFVersion(), OUTPUT_VERSION);
 

=== modified file 'testsuite/actionscript.all/String.as'
--- a/testsuite/actionscript.all/String.as      2009-03-04 20:30:04 +0000
+++ b/testsuite/actionscript.all/String.as      2009-08-19 07:10:05 +0000
@@ -1076,6 +1076,12 @@
 
 var stringInstance = new String();
 check (stringInstance.__proto__ != undefined);
+#if OUTPUT_VERSION > 5
+check_equals("" + stringInstance.__proto__.valueOf, "[type Function]");
+#else
+check_equals("" + stringInstance.__proto__.valueOf, "");
+#endif
+
 check (stringInstance.__proto__ == String.prototype);
 check_equals (typeOf(String.prototype.constructor), 'function');
 check (String.prototype.constructor == String);
@@ -1300,7 +1306,7 @@
 
 //----- END OF TESTS
 
-var baseTests = 319;
+var baseTests = 320;
 var asmTests = 23;
 var ge6Tests = 16;
 

=== modified file 'testsuite/actionscript.all/toString_valueOf.as'
--- a/testsuite/actionscript.all/toString_valueOf.as    2009-02-25 22:33:03 
+0000
+++ b/testsuite/actionscript.all/toString_valueOf.as    2009-08-19 08:37:03 
+0000
@@ -181,6 +181,20 @@
 check(str3 == "102"); 
 check(str3 == 102); 
 
+// Check what String.valueOf returns for non String objects.
+
+svo = String.prototype.valueOf;
+
+check_equals(svo(), "_level0");
+
+f = function() {};
+f.vo = svo;
+check_equals(f.vo(), "[type Function]");
+
+d = new Boolean(false);
+d.vo = svo;
+check_equals(d.vo(), "false");
+
 String.prototype.toString = function () {return "TO_STRING";};
 String.prototype.valueOf = function () {return "TO_VALUE";};
 
@@ -477,9 +491,15 @@
 check_equals(typeof(a), "string");
 check_equals(a, "[type Object]");
 
+// Check that Object.prototype.toString returns "[object Object]"
+ts = Object.prototype.toString;
+check_equals(ts(), "[object Object]");
+s = new String("hh");
+s.toString = ts;
+check_equals(s.toString(), "[object Object]");
 
 #if OUTPUT_VERSION < 6
- check_totals(126);
+ check_totals(131);
 #else
- check_totals(144);
+ check_totals(149);
 #endif

=== modified file 'testsuite/swfdec/PASSING'
--- a/testsuite/swfdec/PASSING  2009-08-13 09:21:40 +0000
+++ b/testsuite/swfdec/PASSING  2009-08-19 07:13:20 +0000
@@ -1172,6 +1172,9 @@
 string-trace-5.swf:14759c53a46b39e873a3f928a3e992f5
 string-trace-6.swf:286e55256f525f4220a324a7417e4051
 string-trace-7.swf:f6eac71a2fc50323a5bd4a74eec99dca
+string-valueof-6.swf:7bcdac29def7323dd9459bd3bfb326d7
+string-valueof-7.swf:e1c484796f8be86f35928b0a073a380d
+string-valueof-8.swf:24268122f0c9afbc5d89844dff2dabe5
 stylesheet-load-5.swf:0637e905afde46b96120c9a6014cb936
 stylesheet-load-6.swf:e3b34170df069108049f1381e93572c6
 stylesheet-parse-5.swf:f77505087f69427b13c91f30a9c103ad


reply via email to

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