gnash-commit
[Top][All Lists]
Advanced

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

[Gnash-commit] /srv/bzr/gnash/trunk r11433: Rename Proxy to Relay for co


From: Benjamin Wolsey
Subject: [Gnash-commit] /srv/bzr/gnash/trunk r11433: Rename Proxy to Relay for consistency with swfdec's similar class. They did
Date: Fri, 21 Aug 2009 11:59:08 +0200
User-agent: Bazaar (1.16.1)

------------------------------------------------------------
revno: 11433 [merge]
committer: Benjamin Wolsey <address@hidden>
branch nick: trunk
timestamp: Fri 2009-08-21 11:59:08 +0200
message:
  Rename Proxy to Relay for consistency with swfdec's similar class. They did
  invent it first, after all.
  
  Introduce ActiveRelay for native objects that require an update on each
  advance. Implement for Sound, LoadVars, XML, NetConnection, and NetStream.
  Allows subclassing of these built-in classes, fixing blip.tv (bug #27214).
  
  This involves some changes to XML and LoadVars that aren't automatically 
  tested, so there may be some uncaught regressions. Some were spotted and
  fixed during manual testing.
modified:
  libcore/Video.cpp
  libcore/Video.h
  libcore/as_function.cpp
  libcore/as_object.cpp
  libcore/as_object.h
  libcore/as_value.cpp
  libcore/asobj/Boolean_as.cpp
  libcore/asobj/Date_as.cpp
  libcore/asobj/Date_as.h
  libcore/asobj/Globals.cpp
  libcore/asobj/LoadVars_as.cpp
  libcore/asobj/LoadableObject.cpp
  libcore/asobj/LoadableObject.h
  libcore/asobj/NetConnection_as.cpp
  libcore/asobj/NetConnection_as.h
  libcore/asobj/NetStream_as.cpp
  libcore/asobj/NetStream_as.h
  libcore/asobj/Number_as.cpp
  libcore/asobj/String_as.cpp
  libcore/asobj/String_as.h
  libcore/asobj/flash/accessibility/AccessibilityProperties_as.cpp
  libcore/asobj/flash/media/Sound_as.cpp
  libcore/asobj/flash/media/Sound_as.h
  libcore/asobj/flash/net/FileReference_as.cpp
  libcore/asobj/flash/net/SharedObject_as.cpp
  libcore/asobj/flash/net/SharedObject_as.h
  libcore/asobj/flash/net/XMLSocket_as.cpp
  libcore/asobj/flash/xml/XMLDocument_as.cpp
  libcore/asobj/flash/xml/XMLDocument_as.h
  libcore/asobj/flash/xml/XMLNode_as.cpp
  libcore/movie_root.cpp
  libcore/movie_root.h
  libcore/vm/Machine.cpp
=== modified file 'libcore/Video.cpp'
--- a/libcore/Video.cpp 2009-08-18 09:24:49 +0000
+++ b/libcore/Video.cpp 2009-08-21 06:51:20 +0000
@@ -289,7 +289,7 @@
 }
 
 void
-Video::setStream(boost::intrusive_ptr<NetStream_as> ns)
+Video::setStream(NetStream_as* ns)
 {
        _ns = ns;
        _ns->setInvalidatedVideo(this);
@@ -322,7 +322,7 @@
 void
 Video::markReachableResources() const
 {
-       if ( _ns ) _ns->setReachable();
+       if (_ns) _ns->setReachable();
 
        // Invoke DisplayObject's version of reachability mark
        markDisplayObjectReachable();
@@ -429,15 +429,13 @@
                return as_value();
        }
 
-       boost::intrusive_ptr<NetStream_as> ns = 
-        boost::dynamic_pointer_cast<NetStream_as>(
-                fn.arg(0).to_object(*getGlobal(fn)));
-       if (ns)
-       {
+    as_object* obj = fn.arg(0).to_object(*getGlobal(fn)).get();
+       NetStream_as* ns;
+
+    if (isNativeType(obj, ns)) {
                video->setStream(ns);
        }
-       else
-       {
+       else {
                IF_VERBOSE_ASCODING_ERRORS(
                log_aserror(_("attachVideo(%s) first arg is not a NetStream 
instance"),
                        fn.arg(0));

=== modified file 'libcore/Video.h'
--- a/libcore/Video.h   2009-07-16 08:30:06 +0000
+++ b/libcore/Video.h   2009-08-20 12:19:38 +0000
@@ -78,7 +78,7 @@
        void add_invalidated_bounds(InvalidatedRanges& ranges, bool force);
 
        /// Set the input stream for this video
-       void setStream(boost::intrusive_ptr<NetStream_as> ns);
+       void setStream(NetStream_as* ns);
 
     void clear();
 
@@ -130,7 +130,7 @@
        const boost::intrusive_ptr<const SWF::DefineVideoStreamTag> m_def;
 
     // Who owns this ? Should it be an intrusive ptr ?
-       boost::intrusive_ptr<NetStream_as> _ns;
+       NetStream_as* _ns;
 
        /// Playing an embbeded video stream ?
        bool _embeddedStream;

=== modified file 'libcore/as_function.cpp'
--- a/libcore/as_function.cpp   2009-08-20 06:55:15 +0000
+++ b/libcore/as_function.cpp   2009-08-20 12:19:38 +0000
@@ -150,8 +150,6 @@
 
        as_value proto;
     bool has_proto = get_member(NSV::PROP_PROTOTYPE, &proto);
-    if (!has_proto) log_debug("No prototype");
-    else log_debug("Has prototype");
                
     // Create an empty object, with a ref to the constructor's prototype.
     // TODO: The prototype should not be converted to an object!

=== modified file 'libcore/as_object.cpp'
--- a/libcore/as_object.cpp     2009-08-20 06:55:15 +0000
+++ b/libcore/as_object.cpp     2009-08-21 07:28:09 +0000
@@ -212,11 +212,19 @@
 
 } // end of anonymous namespace
 
+
+/// Destructor of ActiveRelay needs definition of movie_root.
+ActiveRelay::~ActiveRelay()
+{
+    getRoot(*_owner).removeAdvanceCallback(this);
+}
+
+
 const int as_object::DefaultFlags;
 
 as_object::as_object(Global_as& gl)
        :
-    _proxy(0),
+    _relay(0),
        _vm(getVM(gl)),
        _members(_vm)
 {
@@ -224,7 +232,7 @@
 
 as_object::as_object()
        :
-    _proxy(0),
+    _relay(0),
        _vm(VM::get()),
        _members(_vm)
 {
@@ -232,7 +240,7 @@
 
 as_object::as_object(as_object* proto)
        :
-    _proxy(0),
+    _relay(0),
        _vm(VM::get()),
        _members(_vm)
 {
@@ -241,7 +249,7 @@
 
 as_object::as_object(boost::intrusive_ptr<as_object> proto)
        :
-    _proxy(0),
+    _relay(0),
        _vm(VM::get()),
        _members(_vm)
 {
@@ -255,7 +263,7 @@
 #else
        GcResource(), 
 #endif
-    _proxy(0),
+    _relay(0),
        _vm(VM::get()),
        _members(other._members)
 {
@@ -1325,6 +1333,9 @@
        {
                it->second.setReachable();
        }
+
+    /// Proxy objects can contain references to other as_objects.
+    if (_relay) _relay->setReachable();
 }
 #endif // GNASH_USE_GC
 

=== modified file 'libcore/as_object.h'
--- a/libcore/as_object.h       2009-08-19 11:27:23 +0000
+++ b/libcore/as_object.h       2009-08-21 08:48:47 +0000
@@ -152,13 +152,24 @@
 
 };
 
-class Proxy
+/// This is the base class for type-specific object data. 
+//
+/// ActionScript classes with particular type restrictions or type traits
+/// should set the Object's _relay member to a subclass of this class.
+//
+/// The simplest native types, such as Boolean or String, inherit from this
+/// type.
+class Relay
 {
 public:
-    virtual ~Proxy() {};
+    virtual ~Relay() {};
+
+    /// A Relay itself is not a GC object, but may point to GC resources.
+    virtual void setReachable() {}
 };
 
 
+
 /// \brief
 /// A generic bag of attributes. Base class for all ActionScript-able objects.
 //
@@ -212,12 +223,6 @@
     static const int DefaultFlags = PropFlags::dontDelete |
                                     PropFlags::dontEnum;
 
-    /// A function to be called on movie_root::advance()
-    //
-    /// This is used for requesting an object to update its state and if
-    /// required to notify any AS callbacks. 
-    virtual void advanceState() { }
-
     /// Is any non-hidden property in this object ?
     bool hasNonHiddenProperties() const {
         return _members.hasNonHiddenProperties();
@@ -271,10 +276,6 @@
     /// to a string.
     virtual bool useCustomToString() const { return true; }
 
-    /// Loads data from an IOChannel. The default implementation
-    /// does nothing.
-    virtual void queueLoad(std::auto_ptr<IOChannel> /*str*/) {};
-
     /// Set a member value
     //
     ///
@@ -1040,12 +1041,12 @@
     ///
     void set_prototype(const as_value& proto, int flags = DefaultFlags);
 
-    void setProxy(Proxy* p) {
-        _proxy.reset(p);
+    void setRelay(Relay* p) {
+        _relay.reset(p);
     }
 
-    Proxy* proxy() const {
-        return _proxy.get();
+    Relay* relay() const {
+        return _relay.get();
     }
 
 protected:
@@ -1116,7 +1117,7 @@
 
 private:
  
-    boost::scoped_ptr<Proxy> _proxy;
+    boost::scoped_ptr<Relay> _relay;
 
     /// The global object whose scope contains this object.
     VM& _vm;   
@@ -1172,6 +1173,51 @@
     return o.ns;
 }
 
+/// A type that requires periodic updates from the core (movie_root).
+//
+/// Objects with this type of relay can be registered with movie_root, and
+/// recieve a callback on every advance.
+//
+/// This type of Proxy holds a reference to its parent as_object (owner). 
+/// If a reference to this ActiveRelay is held by another object,
+/// it must be marked reachable so that its owner is not deleted by the GC.
+class ActiveRelay : public Relay
+{
+public:
+    ActiveRelay(as_object* owner)
+        :
+        _owner(owner)
+    {}
+
+    /// Make sure we are removed from the list of callbacks on destruction.
+    virtual ~ActiveRelay();
+
+    /// ActiveRelay objects must have an advanceState method.
+    virtual void update() = 0;
+
+    /// Mark any other reachable resources, and finally mark our owner
+    virtual void setReachable() {
+        markReachableResources();
+        _owner->setReachable();
+    }
+
+    as_object& owner() const {
+        return *_owner;
+    }
+
+protected:
+
+    virtual void markReachableResources() const {}
+
+private:
+
+    /// The as_object that owns this Proxy.
+    //
+    /// Because we are deleted on destruction of the owner, this pointer will
+    /// never be invalid.
+    as_object* _owner;
+
+};
 
 /// Template which does a dynamic cast for as_object pointers.
 //
@@ -1180,10 +1226,9 @@
 /// @tparam T the class to which the obj pointer should be cast.
 /// @param obj the pointer to be cast.
 /// @return If the cast succeeds, the pointer cast to the requested type.
-///         Otherwise, NULL.
 template <typename T>
 boost::intrusive_ptr<T>
-ensureType (boost::intrusive_ptr<as_object> obj)
+ensureType(boost::intrusive_ptr<as_object> obj)
 {
     boost::intrusive_ptr<T> ret = boost::dynamic_pointer_cast<T>(obj);
 
@@ -1205,29 +1250,45 @@
 /// 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.
+//
+/// @tparam T       The expected native type
+/// @param obj      The object whose type should be tested
+/// @param relay    This points to the native type information if the object
+///                 is of the expected type
+/// @return         If the object is of the expected type, true; otherwise
+///                 false.
 template<typename T>
 bool
-isInstanceOf(as_object* obj, T*& proxy)
+isNativeType(as_object* obj, T*& relay)
 {
-    proxy = dynamic_cast<T*>(obj->proxy());
-    return proxy;
+    if (!obj) return false;
+    relay = dynamic_cast<T*>(obj->relay());
+    return relay;
 }
 
-/// An equivalent to ensureType that works with the proxy object.
+/// Ensure that the object is of a particular native type.
+//
+/// This checks that the object's relay member is the expected type.
+/// If not, the function throws an exception, which results in an undefined
+/// value being returned from the AS function.
+/// @tparam T   The expected native type.
+/// @param obj  The object whose type should be tested.
+/// @return     If the cast succeeds, the pointer cast to the requested type,
+///             otherwise the function does not return.
 template<typename T>
 T*
-checkType(as_object* obj)
+ensureNativeType(as_object* obj)
 {
     if (!obj) throw ActionTypeError();
 
-    T* ret = dynamic_cast<T*>(obj->proxy());
+    T* ret = dynamic_cast<T*>(obj->relay());
 
     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.";
+        std::string msg = "Function for " + target + "object called from "
+            + source + " instance.";
 
         throw ActionTypeError(msg);
     }

=== modified file 'libcore/as_value.cpp'
--- a/libcore/as_value.cpp      2009-08-20 06:55:15 +0000
+++ b/libcore/as_value.cpp      2009-08-21 06:51:20 +0000
@@ -382,7 +382,7 @@
             as_object* obj = m_type == AS_FUNCTION ? getFun().get() :
                                                      getObj().get();
             String_as* s;
-            if (isInstanceOf(obj, s)) return s->value();
+            if (isNativeType(obj, s)) return s->value();
 
                        try
                        {
@@ -469,7 +469,7 @@
 
        if (m_type == OBJECT && swfVersion > 5) {
         Date_as* d;
-        if (isInstanceOf(getObj().get(), d)) hint = STRING;
+        if (isNativeType(getObj().get(), d)) hint = STRING;
     }
 
        return to_primitive(hint);
@@ -485,7 +485,7 @@
 
        if (m_type == OBJECT && swfVersion > 5) {
         Date_as* d;
-        if (isInstanceOf<Date_as>(getObj().get(), d)) hint = STRING;
+        if (isNativeType<Date_as>(getObj().get(), d)) hint = STRING;
     }
 
     *this = to_primitive(hint);
@@ -2420,7 +2420,7 @@
                 offsetTable[obj] = idx;
                 
                 Date_as* date;
-                if (isInstanceOf(obj, date))
+                if (isNativeType(obj, date))
                 {
                     double d = date->getTimeValue(); 
 #ifdef GNASH_DEBUG_AMF_SERIALIZE

=== modified file 'libcore/asobj/Boolean_as.cpp'
--- a/libcore/asobj/Boolean_as.cpp      2009-08-20 06:55:15 +0000
+++ b/libcore/asobj/Boolean_as.cpp      2009-08-21 07:28:09 +0000
@@ -42,7 +42,7 @@
     as_object* getBooleanInterface();
 }
 
-class Boolean_as: public Proxy
+class Boolean_as: public Relay
 {
 
 public:
@@ -65,11 +65,16 @@
 void
 boolean_class_init(as_object& where, const ObjectURI& uri)
 {
-    // This is going to be the global Boolean "class"/"function"
-    as_object* proto = getBooleanInterface();
+    VM& vm = getVM(where);
     Global_as* gl = getGlobal(where);
-    as_object* cl = gl->createClass(&boolean_ctor, proto);
-
+
+    as_object* proto = gl->createObject(getObjectInterface());
+    as_object* cl = vm.getNative(107, 2);
+    cl->init_member(NSV::PROP_PROTOTYPE, proto);
+    proto->init_member(NSV::PROP_CONSTRUCTOR, cl);
+
+    attachBooleanInterface(*proto);
+    
     // Register _global.Boolean
     where.init_member(getName(uri), cl, as_object::DefaultFlags,
             getNamespace(uri));
@@ -96,25 +101,10 @@
     o.init_member("toString", vm.getNative(107, 1));
 }
 
-as_object*
-getBooleanInterface()
-{
-    static boost::intrusive_ptr<as_object> o;
-    if ( ! o )
-    {
-        o = new as_object(getObjectInterface());
-        VM::get().addStatic(o.get());
-
-        attachBooleanInterface(*o);
-    }
-    return o.get();
-}
-
-
 as_value
 boolean_tostring(const fn_call& fn)
 {
-    Boolean_as* obj = checkType<Boolean_as>(fn.this_ptr);
+    Boolean_as* obj = ensureNativeType<Boolean_as>(fn.this_ptr);
     if (obj->value()) return as_value("true");
     return as_value("false");
 }
@@ -123,7 +113,7 @@
 as_value
 boolean_valueof(const fn_call& fn) 
 {
-    Boolean_as* obj = checkType<Boolean_as>(fn.this_ptr);
+    Boolean_as* obj = ensureNativeType<Boolean_as>(fn.this_ptr);
     return as_value(obj->value());
 }
 
@@ -139,7 +129,7 @@
     const bool val = fn.nargs ? fn.arg(0).to_bool() : false;
 
     as_object* obj = fn.this_ptr;
-    obj->setProxy(new Boolean_as(val));
+    obj->setRelay(new Boolean_as(val));
     return as_value();
 
 }

=== modified file 'libcore/asobj/Date_as.cpp'
--- a/libcore/asobj/Date_as.cpp 2009-08-20 08:09:04 +0000
+++ b/libcore/asobj/Date_as.cpp 2009-08-21 07:07:11 +0000
@@ -429,17 +429,17 @@
     // for now, we just use rogue_date_args' algorithm
     double foo;
     if (( foo = rogue_date_args(fn, 7)) != 0.0) {
-        obj->setProxy(new Date_as(foo));
+        obj->setRelay(new Date_as(foo));
         return as_value();
     }
 
     if (fn.nargs < 1 || fn.arg(0).is_undefined()) {
         // Time now
-        obj->setProxy(new Date_as);
+        obj->setRelay(new Date_as);
     }
     else if (fn.nargs == 1) {
         // Set the value in milliseconds since 1970 UTC
-        obj->setProxy(new Date_as(fn.arg(0).to_number()));
+        obj->setRelay(new Date_as(fn.arg(0).to_number()));
     }
     else {
         // Create a time from the supplied (at least 2) arguments.
@@ -490,7 +490,7 @@
         // due to shortcomings in the timezoneoffset calculation, but should
         // be internally consistent.
         double localTime = makeTimeValue(gt);
-        obj->setProxy(new Date_as(
+        obj->setRelay(new Date_as(
                 localTime - clocktime::getTimeZoneOffset(localTime) * 60000));
     }
     
@@ -538,7 +538,7 @@
 as_value
 date_getYear(const fn_call& fn)
 {
-    Date_as* date = checkType<Date_as>(fn.this_ptr);
+    Date_as* date = ensureNativeType<Date_as>(fn.this_ptr);
     return timeElement(localTime, &GnashTime::year, date->getTimeValue());
 }
 
@@ -547,7 +547,7 @@
 as_value
 date_getFullYear(const fn_call& fn)
 {
-    Date_as* date = checkType<Date_as>(fn.this_ptr);
+    Date_as* date = ensureNativeType<Date_as>(fn.this_ptr);
     return timeElement(
             localTime, &GnashTime::year, date->getTimeValue(), 1900);
 }
@@ -557,7 +557,7 @@
 as_value
 date_getMonth(const fn_call& fn)
 {
-    Date_as* date = checkType<Date_as>(fn.this_ptr);
+    Date_as* date = ensureNativeType<Date_as>(fn.this_ptr);
     return timeElement(localTime, &GnashTime::month, date->getTimeValue());
 }
 
@@ -566,7 +566,7 @@
 as_value
 date_getDate(const fn_call& fn)
 {
-    Date_as* date = checkType<Date_as>(fn.this_ptr);
+    Date_as* date = ensureNativeType<Date_as>(fn.this_ptr);
     return timeElement(localTime, &GnashTime::monthday, date->getTimeValue());
 }
 
@@ -576,7 +576,7 @@
 as_value
 date_getDay(const fn_call& fn)
 {
-    Date_as* date = checkType<Date_as>(fn.this_ptr);
+    Date_as* date = ensureNativeType<Date_as>(fn.this_ptr);
     return timeElement(localTime, &GnashTime::weekday, date->getTimeValue());
 }
 
@@ -586,7 +586,7 @@
 as_value
 date_getHours(const fn_call& fn)
 {
-    Date_as* date = checkType<Date_as>(fn.this_ptr);
+    Date_as* date = ensureNativeType<Date_as>(fn.this_ptr);
     return timeElement(localTime, &GnashTime::hour, date->getTimeValue());
 }
 
@@ -597,7 +597,7 @@
 as_value
 date_getMinutes(const fn_call& fn)
 {
-    Date_as* date = checkType<Date_as>(fn.this_ptr);
+    Date_as* date = ensureNativeType<Date_as>(fn.this_ptr);
     return timeElement(localTime, &GnashTime::minute, date->getTimeValue());
 }
 
@@ -607,7 +607,7 @@
 as_value
 date_getSeconds(const fn_call& fn)
 {
-    Date_as* date = checkType<Date_as>(fn.this_ptr);
+    Date_as* date = ensureNativeType<Date_as>(fn.this_ptr);
     return timeElement(localTime, &GnashTime::second, date->getTimeValue());
 }
 
@@ -619,7 +619,7 @@
 as_value
 date_getMilliseconds(const fn_call& fn)
 {
-    Date_as* date = checkType<Date_as>(fn.this_ptr);
+    Date_as* date = ensureNativeType<Date_as>(fn.this_ptr);
     return timeElement(
             localTime, &GnashTime::millisecond, date->getTimeValue());
 }
@@ -630,7 +630,7 @@
 as_value
 date_getUTCFullYear(const fn_call& fn)
 {
-    Date_as* date = checkType<Date_as>(fn.this_ptr);
+    Date_as* date = ensureNativeType<Date_as>(fn.this_ptr);
     return timeElement(universalTime, &GnashTime::year,
            date->getTimeValue(), 1900);
 }
@@ -638,21 +638,21 @@
 as_value
 date_getUTCYear(const fn_call& fn)
 {
-    Date_as* date = checkType<Date_as>(fn.this_ptr);
+    Date_as* date = ensureNativeType<Date_as>(fn.this_ptr);
     return timeElement(universalTime, &GnashTime::year, date->getTimeValue());
 }
 
 as_value
 date_getUTCMonth(const fn_call& fn)
 {
-    Date_as* date = checkType<Date_as>(fn.this_ptr);
+    Date_as* date = ensureNativeType<Date_as>(fn.this_ptr);
     return timeElement(universalTime, &GnashTime::month, date->getTimeValue());
 }
 
 as_value
 date_getutcdate(const fn_call& fn)
 {
-    Date_as* date = checkType<Date_as>(fn.this_ptr);
+    Date_as* date = ensureNativeType<Date_as>(fn.this_ptr);
     return timeElement(
             universalTime, &GnashTime::monthday, date->getTimeValue());
 }
@@ -661,7 +661,7 @@
 as_value
 date_getUTCDay(const fn_call& fn)
 {
-    Date_as* date = checkType<Date_as>(fn.this_ptr);
+    Date_as* date = ensureNativeType<Date_as>(fn.this_ptr);
     return timeElement(
                 universalTime, &GnashTime::weekday, date->getTimeValue());
 }
@@ -669,7 +669,7 @@
 as_value
 date_getUTCHours(const fn_call& fn)
 {
-    Date_as* date = checkType<Date_as>(fn.this_ptr);
+    Date_as* date = ensureNativeType<Date_as>(fn.this_ptr);
     return timeElement(
                 universalTime, &GnashTime::hour, date->getTimeValue());
 }
@@ -677,7 +677,7 @@
 as_value
 date_getUTCMinutes(const fn_call& fn)
 {
-    Date_as* date = checkType<Date_as>(fn.this_ptr);
+    Date_as* date = ensureNativeType<Date_as>(fn.this_ptr);
     return timeElement(universalTime, &GnashTime::minute, 
date->getTimeValue());
 }
 
@@ -700,7 +700,7 @@
 as_value
 date_getTimezoneOffset(const fn_call& fn)
 {
-    Date_as* date = checkType<Date_as>(fn.this_ptr);
+    Date_as* date = ensureNativeType<Date_as>(fn.this_ptr);
     return as_value(-localTimeZoneOffset(date->getTimeValue()));
 }
 
@@ -722,7 +722,7 @@
 as_value
 date_setTime(const fn_call& fn)
 {
-    Date_as* date = checkType<Date_as>(fn.this_ptr);
+    Date_as* date = ensureNativeType<Date_as>(fn.this_ptr);
 
     if (fn.nargs < 1 || fn.arg(0).is_undefined()) {
         IF_VERBOSE_ASCODING_ERRORS(
@@ -834,7 +834,7 @@
 as_value
 date_setfullyear(const fn_call& fn)
 {
-    Date_as* date = checkType<Date_as>(fn.this_ptr);
+    Date_as* date = ensureNativeType<Date_as>(fn.this_ptr);
 
     if (fn.nargs < 1) {
         IF_VERBOSE_ASCODING_ERRORS(
@@ -885,7 +885,7 @@
 as_value
 date_setYear(const fn_call& fn)
 {
-    Date_as* date = checkType<Date_as>(fn.this_ptr);
+    Date_as* date = ensureNativeType<Date_as>(fn.this_ptr);
 
     // assert(fn.nargs == 1);
     if (fn.nargs < 1) {
@@ -939,7 +939,7 @@
 as_value
 date_setmonth(const fn_call& fn)
 {
-    Date_as* date = checkType<Date_as>(fn.this_ptr);
+    Date_as* date = ensureNativeType<Date_as>(fn.this_ptr);
 
     // assert(fn.nargs >= 1 && fn.nargs <= 2);
     if (fn.nargs < 1) {
@@ -995,7 +995,7 @@
 as_value
 date_setDate(const fn_call& fn)
 {
-  Date_as* date = checkType<Date_as>(fn.this_ptr);
+  Date_as* date = ensureNativeType<Date_as>(fn.this_ptr);
 
   if (fn.nargs < 1) {
       IF_VERBOSE_ASCODING_ERRORS(
@@ -1035,7 +1035,7 @@
 as_value
 date_setHours(const fn_call& fn)
 {
-    Date_as* date = checkType<Date_as>(fn.this_ptr);
+    Date_as* date = ensureNativeType<Date_as>(fn.this_ptr);
 
     // assert(fn.nargs >= 1 && fn.nargs <= 4);
     if (fn.nargs < 1) {
@@ -1080,7 +1080,7 @@
 as_value
 date_setMinutes(const fn_call& fn)
 {
-    Date_as* date = checkType<Date_as>(fn.this_ptr);
+    Date_as* date = ensureNativeType<Date_as>(fn.this_ptr);
 
     //assert(fn.nargs >= 1 && fn.nargs <= 3);
     if (fn.nargs < 1) {
@@ -1121,7 +1121,7 @@
 as_value
 date_setSeconds(const fn_call& fn)
 {
-    Date_as* date = checkType<Date_as>(fn.this_ptr);
+    Date_as* date = ensureNativeType<Date_as>(fn.this_ptr);
 
     // assert(fn.nargs >= 1 && fn.nargs <= 2);
     if (fn.nargs < 1) {
@@ -1160,7 +1160,7 @@
 as_value
 date_setMilliseconds(const fn_call& fn)
 {
-    Date_as* date = checkType<Date_as>(fn.this_ptr);
+    Date_as* date = ensureNativeType<Date_as>(fn.this_ptr);
 
     if (fn.nargs < 1) {
         IF_VERBOSE_ASCODING_ERRORS(
@@ -1202,7 +1202,7 @@
 as_value
 date_tostring(const fn_call& fn) 
 {
-    Date_as* date = checkType<Date_as>(fn.this_ptr);
+    Date_as* date = ensureNativeType<Date_as>(fn.this_ptr);
     return as_value(date->toString());
 }
 
@@ -1345,7 +1345,7 @@
 /// number of milliseconds.
 as_value date_getTime(const fn_call& fn)
 {
-    Date_as* date = checkType<Date_as>(fn.this_ptr);
+    Date_as* date = ensureNativeType<Date_as>(fn.this_ptr);
     return as_value(date->getTimeValue());
 }
 

=== modified file 'libcore/asobj/Date_as.h'
--- a/libcore/asobj/Date_as.h   2009-08-19 10:01:05 +0000
+++ b/libcore/asobj/Date_as.h   2009-08-21 07:07:11 +0000
@@ -24,7 +24,7 @@
 
 namespace gnash {
 
-class Date_as : public Proxy
+class Date_as : public Relay
 {
 public:
 

=== modified file 'libcore/asobj/Globals.cpp'
--- a/libcore/asobj/Globals.cpp 2009-08-20 06:55:15 +0000
+++ b/libcore/asobj/Globals.cpp 2009-08-21 06:43:48 +0000
@@ -448,7 +448,7 @@
            NS_GLOBAL, 5))
         (N(selection_class_init, NSV::CLASS_SELECTION, NSV::CLASS_OBJECT,
            NS_GLOBAL, 5))
-        (N(Sound_as::init, NSV::CLASS_SOUND, NSV::CLASS_OBJECT,
+        (N(sound_class_init, NSV::CLASS_SOUND, NSV::CLASS_OBJECT,
            NS_GLOBAL, 5))
         (N(xmlsocket_class_init, NSV::CLASS_XMLSOCKET, NSV::CLASS_OBJECT,
            NS_GLOBAL, 5))
@@ -480,9 +480,9 @@
            NSV::CLASS_OBJECT, NS_GLOBAL, 6))
         (N(customactions_class_init, NSV::CLASS_CUSTOM_ACTIONS,
            NSV::CLASS_OBJECT, NS_GLOBAL, 6))
-        (N(NetConnection_as::init, NSV::CLASS_NET_CONNECTION,
+        (N(netconnection_class_init, NSV::CLASS_NET_CONNECTION,
            NSV::CLASS_OBJECT, NS_GLOBAL, 6))
-        (N(NetStream_as::init, NSV::CLASS_NET_STREAM, NSV::CLASS_OBJECT,
+        (N(netstream_class_init, NSV::CLASS_NET_STREAM, NSV::CLASS_OBJECT,
            NS_GLOBAL, 6))
         (N(contextmenu_class_init, NSV::CLASS_CONTEXTMENU, NSV::CLASS_OBJECT,
            NS_GLOBAL, 5))
@@ -588,7 +588,7 @@
            NSV::CLASS_OBJECT, NSV::NS_FLASH_TEXT, 5))
 
         // Media classes
-        (N(Sound_as::init, NSV::CLASS_SOUND, NSV::CLASS_OBJECT,
+        (N(sound_class_init, NSV::CLASS_SOUND, NSV::CLASS_OBJECT,
            NSV::NS_FLASH_MEDIA, 5))
         (N(video_class_init, NSV::CLASS_VIDEO, NSV::CLASS_DISPLAYOBJECT,
            NSV::NS_FLASH_MEDIA, 6))
@@ -604,9 +604,9 @@
            NSV::CLASS_OBJECT, NSV::NS_FLASH_NET, 5))
         (N(LocalConnection_as::init, NSV::CLASS_LOCALCONNECTION,
            NSV::CLASS_OBJECT, NSV::NS_FLASH_NET, 6))
-        (N(NetConnection_as::init, NSV::CLASS_NET_CONNECTION,
+        (N(netconnection_class_init, NSV::CLASS_NET_CONNECTION,
            NSV::CLASS_OBJECT, NSV::NS_FLASH_NET, 6))
-        (N(NetStream_as::init, NSV::CLASS_NET_STREAM, NSV::CLASS_OBJECT,
+        (N(netstream_class_init, NSV::CLASS_NET_STREAM, NSV::CLASS_OBJECT,
            NSV::NS_FLASH_NET, 6))
         
         // Error classes
@@ -1333,6 +1333,7 @@
     registerStageNative(global);
     registerSharedObjectNative(global);
     registerKeyboardNative(global);
+    registerNetStreamNative(global);
 
     AsBroadcaster::registerNative(global);
     TextFormat_as::registerNative(global);

=== modified file 'libcore/asobj/LoadVars_as.cpp'
--- a/libcore/asobj/LoadVars_as.cpp     2009-08-20 06:55:15 +0000
+++ b/libcore/asobj/LoadVars_as.cpp     2009-08-21 07:07:11 +0000
@@ -50,110 +50,14 @@
        as_value loadvars_getBytesLoaded(const fn_call& fn);
        as_value loadvars_getBytesTotal(const fn_call& fn);
        as_value loadvars_onData(const fn_call& fn);
-       as_value loadvars_onLoad(const fn_call& fn);
-       
-    as_object* getLoadVarsInterface();
        void attachLoadVarsInterface(as_object& o);
 }
 
-//--------------------------------------------
-
-/// LoadVars ActionScript class
-//
-class LoadVars_as : public LoadableObject
-{
-
-public:
-
-       /// @param env
-       ///     Environment to use for event handlers calls
-       ///
-       LoadVars_as();
-
-       ~LoadVars_as() {};
-
-    /// Convert the LoadVars Object to a string.
-    //
-    /// @param o        The ostream to write the string to.
-    /// @param encode   Whether URL encoding is necessary. This is
-    ///                 ignored because LoadVars objects are always
-    ///                 URL encoded.
-    void toString(std::ostream& o, bool encode) const;
-
-protected:
-
-#ifdef GNASH_USE_GC
-       /// Mark all reachable resources, for the GC
-       //
-       /// There are no special reachable resources here
-       ///
-       virtual void markReachableResources() const
-       {
-
-               // Invoke generic as_object marker
-               markAsObjectReachable();
-       }
-
-#endif // GNASH_USE_GC
-
-private:
-
-       boost::intrusive_ptr<as_function> _onLoad;
-
-};
-
-
-void
-LoadVars_as::toString(std::ostream& o, bool /*post*/) const
-{
-
-       typedef PropertyList::SortedPropertyList VarMap;
-       VarMap vars;
-
-       enumerateProperties(vars);
-
-    as_object* global = getGlobal(*this);
-    assert(global);
-
-    // LoadVars.toString() calls _global.escape().
-       for (VarMap::const_iterator it=vars.begin(), itEnd=vars.end();
-                       it != itEnd; ++it) {
-
-        if (it != vars.begin()) o << "&";
-        const std::string& var = 
-            global->callMethod(NSV::PROP_ESCAPE, it->first).to_string();
-        const std::string& val = 
-            global->callMethod(NSV::PROP_ESCAPE, it->second).to_string();
-        o << var << "=" << val;
-       }
-
-}
-
-
-
-LoadVars_as::LoadVars_as()
-               :
-               as_object(getLoadVarsInterface())
-{
-}
-
-
 // extern (used by Global.cpp)
 void
-loadvars_class_init(as_object& global, const ObjectURI& uri)
+loadvars_class_init(as_object& where, const ObjectURI& uri)
 {
-       // This is going to be the global LoadVars "class"/"function"
-    Global_as* gl = getGlobal(global);
-    as_object* proto = getLoadVarsInterface();
-    as_object* cl = gl->createClass(&loadvars_ctor, proto);
-
-       // Register _global.LoadVars, only visible for SWF6 up
-       int swf6flags = PropFlags::dontEnum | 
-                    PropFlags::dontDelete | 
-                    PropFlags::onlySWF6Up;
-
-       global.init_member(getName(uri), cl, swf6flags, getNamespace(uri));
-
+    registerBuiltinClass(where, loadvars_ctor, attachLoadVarsInterface, 0, 
uri);
 }
 
 namespace {
@@ -179,17 +83,6 @@
        o.init_member("onLoad", gl->createFunction(loadvars_onLoad));
 }
 
-as_object*
-getLoadVarsInterface()
-{
-       static boost::intrusive_ptr<as_object> o;
-       if (!o) {
-               o = new as_object(getObjectInterface());
-               attachLoadVarsInterface(*o);
-       }
-       return o.get();
-}
-
 as_value
 loadvars_onData(const fn_call& fn)
 {
@@ -230,12 +123,28 @@
 as_value
 loadvars_tostring(const fn_call& fn)
 {
-       boost::intrusive_ptr<LoadVars_as> ptr =
-        ensureType<LoadVars_as>(fn.this_ptr);
-
-    std::ostringstream data;
-    ptr->toString(data, true);
-    return as_value(data.str()); 
+       boost::intrusive_ptr<as_object> ptr = 
ensureType<as_object>(fn.this_ptr);
+
+       typedef PropertyList::SortedPropertyList VarMap;
+       VarMap vars;
+
+       ptr->enumerateProperties(vars);
+
+    as_object* global = getGlobal(*ptr);
+    std::ostringstream o;
+    
+    // LoadVars.toString() calls _global.escape().
+       for (VarMap::const_iterator it=vars.begin(), itEnd=vars.end();
+                       it != itEnd; ++it) {
+
+        if (it != vars.begin()) o << "&";
+        const std::string& var = 
+            global->callMethod(NSV::PROP_ESCAPE, it->first).to_string();
+        const std::string& val = 
+            global->callMethod(NSV::PROP_ESCAPE, it->second).to_string();
+        o << var << "=" << val;
+       }
+    return as_value(o.str()); 
 }
 
 as_value
@@ -244,19 +153,19 @@
 
     if (!fn.isInstantiation()) return as_value();
 
-       boost::intrusive_ptr<as_object> obj = new LoadVars_as;
+       as_object* obj = fn.this_ptr;
+    obj->setRelay(new LoadableObject(obj));
 
-       if ( fn.nargs )
-       {
-        IF_VERBOSE_ASCODING_ERRORS(
-                   std::ostringstream ss;
-                   fn.dump_args(ss);
-                   log_aserror("new LoadVars(%s) - arguments discarded",
+    IF_VERBOSE_ASCODING_ERRORS(
+        if (fn.nargs) {
+            std::ostringstream ss;
+            fn.dump_args(ss);
+            log_aserror("new LoadVars(%s) - arguments discarded",
                 ss.str());
-        );
-       }
+        }
+    );
        
-       return as_value(obj.get()); // will keep alive
+       return as_value(); // will keep alive
 }
 
 } // anonymous namespace

=== modified file 'libcore/asobj/LoadableObject.cpp'
--- a/libcore/asobj/LoadableObject.cpp  2009-08-18 06:49:40 +0000
+++ b/libcore/asobj/LoadableObject.cpp  2009-08-21 09:05:53 +0000
@@ -45,8 +45,9 @@
     as_value loadableobject_sendAndLoad(const fn_call& fn);
 }
 
-LoadableObject::LoadableObject()
+LoadableObject::LoadableObject(as_object* owner)
     :
+    ActiveRelay(owner),
     _bytesLoaded(-1),
     _bytesTotal(-1)
 {
@@ -56,7 +57,7 @@
 LoadableObject::~LoadableObject()
 {
     deleteAllChecked(_loadThreads);
-    getRoot(*this).removeAdvanceCallback(this);
+    getRoot(owner()).removeAdvanceCallback(this);
 }
 
 
@@ -64,20 +65,19 @@
 LoadableObject::send(const std::string& urlstr, const std::string& target,
         bool post)
 {
-    movie_root& m = getRoot(*this);
+    movie_root& m = getRoot(owner());
 
     // Encode the object for HTTP. If post is true,
     // XML should not be encoded. LoadVars is always
     // encoded.
     // TODO: test properly.
-    std::ostringstream data;
-    toString(data, !post);
+    const std::string& str = as_value(&owner()).to_string();
 
     // Only GET and POST are possible here.
     MovieClip::VariablesMethod method = post ? MovieClip::METHOD_POST :
                                                MovieClip::METHOD_GET;
 
-    m.getURL(urlstr, target, data.str(), method);
+    m.getURL(urlstr, target, str, method);
 
 }
 
@@ -90,7 +90,7 @@
     /// All objects get a loaded member, set to false.
     target.set_member(NSV::PROP_LOADED, false);
 
-    const RunResources& ri = getRunResources(*this);
+    const RunResources& ri = getRunResources(owner());
        URL url(urlstr, ri.baseURL());
 
        std::auto_ptr<IOChannel> str;
@@ -100,7 +100,7 @@
 
         NetworkAdapter::RequestHeaders headers;
 
-        if (get_member(NSV::PROP_uCUSTOM_HEADERS, &customHeaders))
+        if (owner().get_member(NSV::PROP_uCUSTOM_HEADERS, &customHeaders))
         {
 
             /// Read in our custom headers if they exist and are an
@@ -137,7 +137,7 @@
 
         as_value contentType;
 
-        if (get_member(NSV::PROP_CONTENT_TYPE, &contentType))
+        if (owner().get_member(NSV::PROP_CONTENT_TYPE, &contentType))
         {
             // This should not overwrite anything set in 
             // LoadVars.addRequestHeader();
@@ -148,20 +148,16 @@
         // Convert the object to a string to send. XML should
         // not be URL encoded for the POST method, LoadVars
         // is always URL encoded.
-        std::ostringstream data;
-        toString(data, false);
+        const std::string& strval = as_value(&owner()).to_string();
 
         /// It doesn't matter if there are no request headers.
-        str = ri.streamProvider().getStream(url, data.str(), headers);
+        str = ri.streamProvider().getStream(url, strval, headers);
     }
        else
     {
         // Convert the object to a string to send. XML should
         // not be URL encoded for the GET method.
-        std::ostringstream data;
-        toString(data, true);
-
-        const std::string& dataString = data.str();
+        const std::string& dataString = as_value(&owner()).to_string();
 
         // Any data must be added to the existing querystring.
         if (!dataString.empty()) {
@@ -169,7 +165,7 @@
             std::string existingQS = url.querystring();
             if (!existingQS.empty()) existingQS += "&";
 
-            url.set_querystring(existingQS + data.str());
+            url.set_querystring(existingQS + dataString);
         }
 
         log_debug("Using GET method for sendAndLoad: %s", url.str());
@@ -177,7 +173,11 @@
     }
 
        log_security(_("Loading from url: '%s'"), url.str());
-    target.queueLoad(str);
+       
+    LoadableObject* loadObject;
+    if (isNativeType(&target, loadObject)) {
+        loadObject->queueLoad(str);
+    }
        
 }
 
@@ -186,9 +186,9 @@
 {
     // Set loaded property to false; will be updated (hopefully)
     // when loading is complete.
-       set_member(NSV::PROP_LOADED, false);
+       owner().set_member(NSV::PROP_LOADED, false);
 
-    const RunResources& ri = getRunResources(*this);
+    const RunResources& ri = getRunResources(owner());
        URL url(urlstr, ri.baseURL());
 
     // Checks whether access is allowed.
@@ -203,10 +203,8 @@
 LoadableObject::queueLoad(std::auto_ptr<IOChannel> str)
 {
 
-    // We don't need to check before adding a timer, but
-    // this may optimize slightly (it was already in the code).
     if (_loadThreads.empty()) {
-        getRoot(*this).addAdvanceCallback(this);
+        getRoot(owner()).addAdvanceCallback(this);
     }
 
     std::auto_ptr<LoadThread> lt (new LoadThread(str));
@@ -224,7 +222,7 @@
 }
 
 void
-LoadableObject::advanceState()
+LoadableObject::update()
 {
 
     if (_loadThreads.empty()) return;
@@ -236,7 +234,7 @@
 
         /// An empty file is the same as a failure.
         if (lt->failed() || (lt->completed() && !lt->size())) {
-            callMethod(NSV::PROP_ON_DATA, as_value());
+            owner().callMethod(NSV::PROP_ON_DATA, as_value());
             it = _loadThreads.erase(it);
             delete lt; 
         }
@@ -269,12 +267,12 @@
             it = _loadThreads.erase(it);
             delete lt; // supposedly joins the thread...
 
-            string_table& st = getStringTable(*this);
-            set_member(st.find("_bytesLoaded"), _bytesLoaded);
-            set_member(st.find("_bytesTotal"), _bytesTotal);
+            string_table& st = getStringTable(owner());
+            owner().set_member(st.find("_bytesLoaded"), _bytesLoaded);
+            owner().set_member(st.find("_bytesTotal"), _bytesTotal);
             
             // might push_front on the list..
-            callMethod(NSV::PROP_ON_DATA, dataVal);
+            owner().callMethod(NSV::PROP_ON_DATA, dataVal);
 
         }
         else
@@ -282,17 +280,17 @@
             _bytesTotal = lt->getBytesTotal();
             _bytesLoaded = lt->getBytesLoaded();
             
-            string_table& st = getStringTable(*this);
-            set_member(st.find("_bytesLoaded"), _bytesLoaded);
+            string_table& st = getStringTable(owner());
+            owner().set_member(st.find("_bytesLoaded"), _bytesLoaded);
             // TODO: should this really be set on each iteration?
-            set_member(st.find("_bytesTotal"), _bytesTotal);
+            owner().set_member(st.find("_bytesTotal"), _bytesTotal);
             ++it;
         }
     }
 
     if (_loadThreads.empty()) 
     {
-        getRoot(*this).removeAdvanceCallback(this);
+        getRoot(owner()).removeAdvanceCallback(this);
     }
 
 }
@@ -338,13 +336,10 @@
 LoadableObject::loadableobject_addRequestHeader(const fn_call& fn)
 {
     
-    boost::intrusive_ptr<LoadableObject> ptr = 
-        ensureType<LoadableObject>(fn.this_ptr);   
-
     as_value customHeaders;
     as_object* array;
 
-    if (ptr->get_member(NSV::PROP_uCUSTOM_HEADERS, &customHeaders))
+    if (fn.this_ptr->get_member(NSV::PROP_uCUSTOM_HEADERS, &customHeaders))
     {
         array = customHeaders.to_object(*getGlobal(fn)).get();
         if (!array)
@@ -364,7 +359,7 @@
         const int flags = PropFlags::dontEnum |
                           PropFlags::dontDelete;
 
-        ptr->init_member(NSV::PROP_uCUSTOM_HEADERS, array, flags);
+        fn.this_ptr->init_member(NSV::PROP_uCUSTOM_HEADERS, array, flags);
     }
 
     if (fn.nargs == 0)
@@ -484,8 +479,7 @@
 as_value
 loadableobject_sendAndLoad(const fn_call& fn)
 {
-       boost::intrusive_ptr<LoadableObject> ptr =
-                       ensureType<LoadableObject>(fn.this_ptr);
+       LoadableObject* ptr = ensureNativeType<LoadableObject>(fn.this_ptr);
 
        if ( fn.nargs < 2 )
        {
@@ -513,7 +507,8 @@
                return as_value(false);
        }
 
-
+    // TODO: if this isn't an XML or LoadVars, it won't work, but we should
+    // check how far things get before it fails.
        boost::intrusive_ptr<as_object> target =
         fn.arg(1).to_object(*getGlobal(fn));
 
@@ -536,8 +531,7 @@
 as_value
 loadableobject_load(const fn_call& fn)
 {
-       boost::intrusive_ptr<LoadableObject> obj = 
-        ensureType<LoadableObject>(fn.this_ptr);
+       LoadableObject* obj = ensureNativeType<LoadableObject>(fn.this_ptr);
 
        if ( fn.nargs < 1 )
        {
@@ -559,8 +553,8 @@
        obj->load(urlstr);
     
     string_table& st = getStringTable(fn);
-    obj->set_member(st.find("_bytesLoaded"), 0.0);
-    obj->set_member(st.find("_bytesTotal"), as_value());
+    fn.this_ptr->set_member(st.find("_bytesLoaded"), 0.0);
+    fn.this_ptr->set_member(st.find("_bytesTotal"), as_value());
 
     return as_value(true);
 
@@ -570,8 +564,7 @@
 as_value
 loadableobject_send(const fn_call& fn)
 {
-    boost::intrusive_ptr<LoadableObject> ptr =
-        ensureType<LoadableObject>(fn.this_ptr);
+    LoadableObject* ptr = ensureNativeType<LoadableObject>(fn.this_ptr);
  
     std::ostringstream os;
     fn.dump_args(os);

=== modified file 'libcore/asobj/LoadableObject.h'
--- a/libcore/asobj/LoadableObject.h    2009-07-01 07:10:36 +0000
+++ b/libcore/asobj/LoadableObject.h    2009-08-21 08:41:59 +0000
@@ -36,11 +36,11 @@
 /// It is a virtual base class because XML_as also inherits from XMLNode.
 //
 /// It may not be copied.
-class LoadableObject : public virtual as_object, private boost::noncopyable
+class LoadableObject : public ActiveRelay
 {
 public:
 
-    LoadableObject();
+    LoadableObject(as_object* owner);
 
     virtual ~LoadableObject();
 
@@ -97,17 +97,10 @@
 
     /// Scan the LoadThread queue (_loadThreads) to see if any of
     /// them completed. If any did, invoke the onData event
-    virtual void advanceState();
+    virtual void update();
 
 protected:
 
-    /// Convert the Loadable Object to a string.
-    //
-    /// @param o        The ostream to write the string to.
-    /// @param encode   Whether URL encoding is necessary. How this
-    ///                 is done depends on the type of object.
-    virtual void toString(std::ostream& o, bool encode) const = 0;
-
     typedef std::list<LoadThread*> LoadThreadList;
 
     /// Queue of load requests

=== modified file 'libcore/asobj/NetConnection_as.cpp'
--- a/libcore/asobj/NetConnection_as.cpp        2009-08-18 10:32:14 +0000
+++ b/libcore/asobj/NetConnection_as.cpp        2009-08-21 08:51:23 +0000
@@ -53,7 +53,6 @@
 namespace {
     void attachProperties(as_object& o);
     void attachNetConnectionInterface(as_object& o);
-    as_object* getNetConnectionInterface();
     as_value netconnection_isConnected(const fn_call& fn);
     as_value netconnection_uri(const fn_call& fn);
     as_value netconnection_connect(const fn_call& fn);
@@ -71,7 +70,7 @@
 
 }
 
-//---- ConnectionHandler 
--------------------------------------------------------------
+//---- ConnectionHandler -------------------------------------------------
 
 /// Abstract connection handler class
 //
@@ -114,7 +113,12 @@
     ///
     /// Return true if wants to be advanced again, false otherwise.
     ///
-    virtual bool advance()=0;
+    virtual bool advance() = 0;
+
+    /// ConnectionHandlers may store references to as_objects
+    //
+    /// These include callback objects.
+    virtual void setReachable() const = 0;
 
     /// Return true if the connection has pending calls 
     //
@@ -123,19 +127,7 @@
     /// queued and only really dropped when advance returns
     /// false
     ///
-    virtual bool hasPendingCalls() const=0;
-
-    /// Mark reachable resources, if any. 
-    virtual void setReachable() const
-    {
-        // NOTE: usually this function gets
-        //       called *by* the _nc's setReachable
-        //       but we do this just to be safe
-        //       in case the _nc object is deleted
-        //       and doesn't properly drops us
-        //
-        _nc.setReachable();
-    }
+    virtual bool hasPendingCalls() const = 0;
 
     virtual ~ConnectionHandler() {}
 
@@ -144,7 +136,9 @@
     /// Construct a connection handler bound to the given NetConnection object
     //
     /// The binding is used to notify statuses and errors
-    ///
+    //
+    /// The NetConnection_as owns all ConnectionHandlers, so there is no
+    /// need to mark it reachable.
     ConnectionHandler(NetConnection_as& nc)
         :
         _nc(nc)
@@ -208,7 +202,6 @@
         {
             i->second->setReachable();
         }
-        ConnectionHandler::setReachable();
     }
 
     // See dox in NetworkHandler class
@@ -302,7 +295,7 @@
     if(_connection)
     {
 
-        VM& vm = getVM(_nc);
+        VM& vm = getVM(_nc.owner());
 
 #ifdef GNASH_DEBUG_REMOTING
         log_debug("have connection");
@@ -435,14 +428,14 @@
 
                         { // method call for each header
                           // FIXME: it seems to me that the call should happen
-                            VM& vm = getVM(_nc);
+                            VM& vm = getVM(_nc.owner());
                             string_table& st = vm.getStringTable();
                             string_table::key key = st.find(headerName);
 #ifdef GNASH_DEBUG_REMOTING
                             log_debug("Calling NetConnection.%s(%s)",
                                     headerName, tmp);
 #endif
-                            _nc.callMethod(key, tmp);
+                            _nc.owner().callMethod(key, tmp);
                         }
                     }
                 }
@@ -525,7 +518,7 @@
 
                             // if actionscript specified a callback object, 
call it
                             boost::intrusive_ptr<as_object> callback = 
pop_callback(id);
-                            if(callback) {
+                            if (callback) {
 
                                 string_table::key methodKey;
                                 if ( methodName == "onResult" ) {
@@ -585,7 +578,7 @@
         // TODO: it might be useful for a Remoting Handler to have a 
         // StreamProvider member
         const StreamProvider& sp =
-            getRunResources(_nc).streamProvider();
+            getRunResources(_nc.owner()).streamProvider();
 
         _connection.reset(sp.getStream(_url, postdata_str, 
_headers).release());
 
@@ -636,7 +629,7 @@
     buf->appendByte(amf::Element::STRICT_ARRAY_AMF0);
     buf->appendNetworkLong(args.size()-firstArg);
 
-    VM& vm = getVM(_nc);
+    VM& vm = getVM(_nc.owner());
 
     for (unsigned int i = firstArg; i < args.size(); ++i)
     {
@@ -675,29 +668,14 @@
 
 //----- NetConnection_as ----------------------------------------------------
 
-NetConnection_as::NetConnection_as()
+NetConnection_as::NetConnection_as(as_object* owner)
     :
-    as_object(getNetConnectionInterface()),
+    ActiveRelay(owner),
     _queuedConnections(),
     _currentConnection(0),
     _uri(),
     _isConnected(false)
 {
-    attachProperties(*this);
-}
-
-// extern (used by Global.cpp)
-void
-NetConnection_as::init(as_object& global, const ObjectURI& uri)
-{
-    // This is going to be the global NetConnection "class"/"function"
-    Global_as* gl = getGlobal(global);
-    as_object* proto = getNetConnectionInterface();
-    as_object* cl = gl->createClass(&netconnection_new, proto);
-
-    // Register _global.String
-    global.init_member(getName(uri), cl, as_object::DefaultFlags,
-            getNamespace(uri));
 }
 
 // here to have HTTPRemotingHandler definition available
@@ -706,18 +684,24 @@
     deleteAllChecked(_queuedConnections);
 }
 
+// extern (used by Global.cpp)
+void
+netconnection_class_init(as_object& where, const ObjectURI& uri)
+{
+    registerBuiltinClass(where, netconnection_new,
+            attachNetConnectionInterface, 0, uri);
+}
+
 
 void
 NetConnection_as::markReachableResources() const
 {
-    if ( _currentConnection.get() ) _currentConnection->setReachable();
-    for (std::list<ConnectionHandler*>::const_iterator
-            i=_queuedConnections.begin(), e=_queuedConnections.end();
-            i!=e; ++i)
-    {
-        (*i)->setReachable();
-    }
-    markAsObjectReachable();
+    owner().setReachable();
+
+    std::for_each(_queuedConnections.begin(), _queuedConnections.end(),
+            std::mem_fun(&ConnectionHandler::setReachable));
+
+    if (_currentConnection.get()) _currentConnection->setReachable();
 }
 
 
@@ -729,7 +713,7 @@
 NetConnection_as::validateURL() const
 {
 
-    URL uri(_uri, getRunResources(*this).baseURL());
+    URL uri(_uri, getRunResources(owner()).baseURL());
 
     std::string uriStr(uri.str());
     assert(uriStr.find("://") != std::string::npos);
@@ -759,7 +743,7 @@
     o->init_member("code", info.first, flags);
     o->init_member("level", info.second, flags);
 
-    callMethod(NSV::PROP_ON_STATUS, o);
+    owner().callMethod(NSV::PROP_ON_STATUS, o);
 
 }
 
@@ -834,7 +818,7 @@
         return;
     }
 
-    URL url(uri, getRunResources(*this).baseURL());
+    URL url(uri, getRunResources(owner()).baseURL());
 
     if ((url.protocol() != "rtmp")
         && (url.protocol() != "rtmpt")
@@ -905,7 +889,7 @@
 void
 NetConnection_as::setURI(const std::string& uri)
 {
-    init_readonly_property("uri", &netconnection_uri);
+    owner().init_readonly_property("uri", &netconnection_uri);
     _uri = uri;
 }
 
@@ -932,7 +916,7 @@
 std::auto_ptr<IOChannel>
 NetConnection_as::getStream(const std::string& name)
 {
-    const RunResources& ri = getRunResources(*this);
+    const RunResources& ri = getRunResources(owner());
 
     const StreamProvider& streamProvider = ri.streamProvider();
 
@@ -952,19 +936,19 @@
 void
 NetConnection_as::startAdvanceTimer() 
 {
-    getRoot(*this).addAdvanceCallback(this);
+    getRoot(owner()).addAdvanceCallback(this);
     log_debug("startAdvanceTimer: registered NetConnection timer");
 }
 
 void
 NetConnection_as::stopAdvanceTimer() 
 {
-    getRoot(*this).removeAdvanceCallback(this);
+    getRoot(owner()).removeAdvanceCallback(this);
     log_debug("stopAdvanceTimer: deregistered NetConnection timer");
 }
 
 void
-NetConnection_as::advanceState()
+NetConnection_as::update()
 {
     // Advance
 
@@ -973,28 +957,26 @@
             _queuedConnections.size());
 #endif
 
-    while ( ! _queuedConnections.empty() )
-    {
+    while (!_queuedConnections.empty()) {
         ConnectionHandler* ch = _queuedConnections.front();
-        if ( ! ch->advance() )
-        {
+
+        if (!ch->advance()) {
             log_debug("ConnectionHandler done, dropping");
             _queuedConnections.pop_front();
             delete ch;
         }
+
         else break; // queues handling is serialized
     }
 
-    if ( _currentConnection.get() ) 
-    {
+    if (_currentConnection.get()) {
         _currentConnection->advance();
     }
 
     // Advancement of a connection might trigger creation
     // of a new connection, so we won't stop the advance
     // timer in that case
-    if ( _queuedConnections.empty() && ! _currentConnection.get() )
-    {
+    if (_queuedConnections.empty() && ! _currentConnection.get()) {
 #ifdef GNASH_DEBUG_REMOTING
         log_debug("stopping advance timer");
 #endif
@@ -1037,8 +1019,7 @@
 as_value
 netconnection_call(const fn_call& fn)
 {
-    boost::intrusive_ptr<NetConnection_as> ptr = 
-        ensureType<NetConnection_as>(fn.this_ptr); 
+    NetConnection_as* ptr = ensureNativeType<NetConnection_as>(fn.this_ptr); 
 
     if (fn.nargs < 1)
     {
@@ -1081,8 +1062,7 @@
 as_value
 netconnection_close(const fn_call& fn)
 {
-    boost::intrusive_ptr<NetConnection_as> ptr =
-        ensureType<NetConnection_as>(fn.this_ptr); 
+    NetConnection_as* ptr = ensureNativeType<NetConnection_as>(fn.this_ptr); 
 
     ptr->close();
 
@@ -1094,8 +1074,7 @@
 as_value
 netconnection_isConnected(const fn_call& fn)
 {
-    boost::intrusive_ptr<NetConnection_as> ptr =
-        ensureType<NetConnection_as>(fn.this_ptr); 
+    NetConnection_as* ptr = ensureNativeType<NetConnection_as>(fn.this_ptr); 
 
     return as_value(ptr->isConnected());
 }
@@ -1103,8 +1082,7 @@
 as_value
 netconnection_uri(const fn_call& fn)
 {
-    boost::intrusive_ptr<NetConnection_as> ptr =
-        ensureType<NetConnection_as>(fn.this_ptr); 
+    NetConnection_as* ptr = ensureNativeType<NetConnection_as>(fn.this_ptr); 
 
     return as_value(ptr->getURI());
 }
@@ -1126,32 +1104,18 @@
     o.init_readonly_property("isConnected", &netconnection_isConnected);
 }
 
-as_object*
-getNetConnectionInterface()
-{
-
-    static boost::intrusive_ptr<as_object> o;
-    if ( o == NULL )
-    {
-        o = new as_object(getObjectInterface());
-        attachNetConnectionInterface(*o);
-    }
-
-    return o.get();
-}
-
 /// \brief callback to instantiate a new NetConnection object.
 /// \param fn the parameters from the Flash movie
 /// \return nothing from the function call.
 /// \note The return value is returned through the fn.result member.
 as_value
-netconnection_new(const fn_call& /* fn */)
+netconnection_new(const fn_call& fn)
 {
-    GNASH_REPORT_FUNCTION;
-
-    NetConnection_as* nc = new NetConnection_as;
-
-    return as_value(nc);
+
+    as_object* obj = fn.this_ptr;
+    obj->setRelay(new NetConnection_as(obj));
+    attachProperties(*obj);
+    return as_value();
 }
 
 
@@ -1171,8 +1135,7 @@
 netconnection_connect(const fn_call& fn)
 {
 
-    boost::intrusive_ptr<NetConnection_as> ptr =
-        ensureType<NetConnection_as>(fn.this_ptr); 
+    NetConnection_as* ptr = ensureNativeType<NetConnection_as>(fn.this_ptr); 
     
     if (fn.nargs < 1)
     {
@@ -1213,8 +1176,7 @@
 as_value
 netconnection_addHeader(const fn_call& fn)
 {
-    boost::intrusive_ptr<NetConnection_as> ptr =
-        ensureType<NetConnection_as>(fn.this_ptr); 
+    NetConnection_as* ptr = ensureNativeType<NetConnection_as>(fn.this_ptr); 
     UNUSED(ptr);
 
     log_unimpl("NetConnection.addHeader()");

=== modified file 'libcore/asobj/NetConnection_as.h'
--- a/libcore/asobj/NetConnection_as.h  2009-07-16 08:30:06 +0000
+++ b/libcore/asobj/NetConnection_as.h  2009-08-21 07:29:51 +0000
@@ -37,7 +37,7 @@
 //
 /// Provides interfaces to load data from an URL
 ///
-class NetConnection_as: public as_object
+class NetConnection_as : public ActiveRelay
 {
 public:
 
@@ -52,13 +52,11 @@
         CALL_BADVERSION
     };
 
-       NetConnection_as();
+       NetConnection_as(as_object* owner);
        ~NetConnection_as();
 
-    static void init(as_object& global, const ObjectURI& uri);
-
     /// Process connection stuff
-    virtual void advanceState();
+    virtual void update();
 
     /// Make the stored URI into a valid and checked URL.
        std::string validateURL() const;
@@ -91,8 +89,6 @@
     /// Get an stream by name
     std::auto_ptr<IOChannel> getStream(const std::string& name);
 
-protected:
-
        /// Mark responders associated with remoting calls
        void markReachableResources() const;
 

=== modified file 'libcore/asobj/NetStream_as.cpp'
--- a/libcore/asobj/NetStream_as.cpp    2009-08-07 14:01:58 +0000
+++ b/libcore/asobj/NetStream_as.cpp    2009-08-21 07:09:32 +0000
@@ -29,6 +29,7 @@
 #include "fn_call.h"
 #include "Global_as.h"
 #include "builtin_function.h"
+#include "NativeFunction.h"
 #include "GnashException.h"
 #include "NetConnection_as.h"
 #include "Object.h" // for getObjectInterface
@@ -67,20 +68,19 @@
     as_value netstream_receiveVideo(const fn_call& fn);
     as_value netstream_send(const fn_call& fn);
 
-    as_object* getNetStreamInterface();
     void attachNetStreamInterface(as_object& o);
     
     // TODO: see where this can be done more centrally.
-    void executeTag(const SimpleBuffer& _buffer, as_object* thisPtr, VM& vm);
+    void executeTag(const SimpleBuffer& _buffer, as_object& thisPtr);
 }
 
 /// Contruct a NetStream object.
 //
 /// The default size needed to begin playback (m_bufferTime) of media
 /// is 100 milliseconds.
-NetStream_as::NetStream_as()
+NetStream_as::NetStream_as(as_object* owner)
     :
-    as_object(getNetStreamInterface()),
+    ActiveRelay(owner),
     _netCon(0),
     m_bufferTime(100), 
     m_newFrameReady(false),
@@ -93,12 +93,10 @@
     _videoInfoKnown(false),
     _audioDecoder(0),
     _audioInfoKnown(false),
-
-    // TODO: figure out if we should take another path to get to the clock
     _playbackClock(
-            new InterruptableVirtualClock(getVM(*this).getClock())),
+            new InterruptableVirtualClock(getVM(*owner).getClock())),
     _playHead(_playbackClock.get()), 
-    _soundHandler(getRunResources(*this).soundHandler()),
+    _soundHandler(getRunResources(*owner).soundHandler()),
     _mediaHandler(media::MediaHandler::get()),
     _audioStreamer(_soundHandler),
     _statusCode(invalidStatus)
@@ -106,19 +104,32 @@
 }
 
 void
-NetStream_as::init(as_object& global, const ObjectURI& uri)
-{
-
-    Global_as* gl = getGlobal(global);
-    as_object* proto = getNetStreamInterface();
-    as_object* cl = gl->createClass(&netstream_new, proto);
-
-    // Register _global.String
-    global.init_member(getName(uri), cl, as_object::DefaultFlags,
-            getNamespace(uri));
-
-}
-
+netstream_class_init(as_object& where, const ObjectURI& uri)
+{
+    // NetStream is genuinely a built-in class, but its constructor calls
+    // several native functions. It also calls NetConnection.call.
+    registerBuiltinClass(where, netstream_new, attachNetStreamInterface,
+            0, uri);
+}
+
+void
+registerNetStreamNative(as_object& global)
+{
+    VM& vm = getVM(global);
+
+    vm.registerNative(netstream_close, 2101, 0);
+    vm.registerNative(netstream_attachAudio, 2101, 1);
+    vm.registerNative(netstream_attachVideo, 2101, 2);
+    vm.registerNative(netstream_send, 2101, 3);
+    vm.registerNative(netstream_setbuffertime, 2101, 4);
+
+    // TODO:
+    // ASnative(2101, 200): run in the constructor
+    // ASnative(2101, 201) [OnCreate.prototype] onResult - inner function
+    // ASnative(2101, 202) publish, play, receiveAudio, receiveVideo, pause,
+    //                     seek
+
+}
 
 void
 NetStream_as::processNotify(const std::string& funcname, as_object* info_obj)
@@ -130,9 +141,9 @@
   log_debug(" Invoking onMetaData");
 #endif
 
-    string_table::key func = getStringTable(*this).find(funcname);
+    string_table::key func = getStringTable(owner()).find(funcname);
 
-    callMethod(func, as_value(info_obj));
+    owner().callMethod(func, as_value(info_obj));
 }
 
 
@@ -156,7 +167,7 @@
     // Must be a new object every time.
     as_object* o = getStatusObject(code);
 
-    callMethod(NSV::PROP_ON_STATUS, o);
+    owner().callMethod(NSV::PROP_ON_STATUS, o);
 }
 
 void
@@ -278,30 +289,23 @@
 void
 NetStream_as::markReachableResources() const
 {
-
     if (_netCon) _netCon->setReachable();
-
     if (_statusHandler) _statusHandler->setReachable();
-
     if (_audioController) _audioController->setReachable();
-
     if (_invalidatedVideoCharacter) _invalidatedVideoCharacter->setReachable();
-
-    // Invoke generic as_object marker
-    markAsObjectReachable();
 }
 #endif // GNASH_USE_GC
 
 void
 NetStream_as::stopAdvanceTimer()
 {
-    getRoot(*this).removeAdvanceCallback(this);
+    getRoot(owner()).removeAdvanceCallback(this);
 }
 
 void
 NetStream_as::startAdvanceTimer()
 {
-    getRoot(*this).addAdvanceCallback(this);
+    getRoot(owner()).addAdvanceCallback(this);
 }
 
 
@@ -439,7 +443,7 @@
         log_error("NetStream: Could not create Video decoder: %s", e.what());
 
         // This is important enough to let the user know.
-        movie_root& m = getRoot(*this);
+        movie_root& m = getRoot(owner());
         m.errorInterface(e.what());
     }
 
@@ -467,7 +471,7 @@
         log_error("Could not create Audio decoder: %s", e.what());
 
         // This is important enough to let the user know.
-        movie_root& m = getRoot(*this);
+        movie_root& m = getRoot(owner());
         m.errorInterface(e.what());
     }
 
@@ -1222,7 +1226,7 @@
 
 
 void
-NetStream_as::advanceState()
+NetStream_as::update()
 {
     // Check if there are any new status messages, and if we should
     // pass them to a event handler
@@ -1362,7 +1366,7 @@
 
     for (media::MediaParser::OrderedMetaTags::iterator i = tags.begin(),
             e = tags.end(); i != e; ++i) {
-        executeTag(**i, this, getVM(*this));
+        executeTag(**i, owner());
     }
 }
 
@@ -1581,19 +1585,17 @@
 netstream_new(const fn_call& fn)
 {
 
-    boost::intrusive_ptr<NetStream_as> netstream_obj = new NetStream_as;
-
-    if (fn.nargs > 0)
-    {
-        boost::intrusive_ptr<NetConnection_as> ns =
-            boost::dynamic_pointer_cast<NetConnection_as>(
-                    fn.arg(0).to_object(*getGlobal(fn)));
-        if ( ns )
-        {
-            netstream_obj->setNetCon(ns);
+    as_object* obj = fn.this_ptr;
+
+    NetStream_as* ns = new NetStream_as(obj);
+
+    if (fn.nargs) {
+
+        NetConnection_as* nc;
+        if (isNativeType(fn.arg(0).to_object(*getGlobal(fn)).get(), nc)) {
+            ns->setNetCon(nc);
         }
-        else
-        {
+        else {
             IF_VERBOSE_ASCODING_ERRORS(
                 log_aserror(_("First argument "
                     "to NetStream constructor "
@@ -1602,15 +1604,17 @@
             );
         }
     }
-    return as_value(netstream_obj.get());
+    obj->setRelay(ns);
+
+
+    return as_value();
 
 }
 
 as_value
 netstream_close(const fn_call& fn)
 {
-    boost::intrusive_ptr<NetStream_as> ns =
-        ensureType<NetStream_as>(fn.this_ptr);
+    NetStream_as* ns = ensureNativeType<NetStream_as>(fn.this_ptr);
     ns->close();
     return as_value();
 }
@@ -1618,8 +1622,8 @@
 as_value
 netstream_pause(const fn_call& fn)
 {
-    boost::intrusive_ptr<NetStream_as> ns = 
-        ensureType<NetStream_as>(fn.this_ptr);
+    NetStream_as* ns = 
+        ensureNativeType<NetStream_as>(fn.this_ptr);
     
     // mode: -1 ==> toogle, 0==> pause, 1==> play
     NetStream_as::PauseMode mode = NetStream_as::pauseModeToggle;
@@ -1637,8 +1641,8 @@
 as_value
 netstream_play(const fn_call& fn)
 {
-    boost::intrusive_ptr<NetStream_as> ns =
-        ensureType<NetStream_as>(fn.this_ptr);
+    NetStream_as* ns =
+        ensureNativeType<NetStream_as>(fn.this_ptr);
 
     if (!fn.nargs)
     {
@@ -1665,8 +1669,8 @@
 as_value
 netstream_seek(const fn_call& fn)
 {
-    boost::intrusive_ptr<NetStream_as> ns = 
-        ensureType<NetStream_as>(fn.this_ptr);
+    NetStream_as* ns = 
+        ensureNativeType<NetStream_as>(fn.this_ptr);
 
     boost::uint32_t time = 0;
     if (fn.nargs > 0)
@@ -1684,8 +1688,8 @@
 
     //GNASH_REPORT_FUNCTION;
 
-    boost::intrusive_ptr<NetStream_as> ns =
-        ensureType<NetStream_as>(fn.this_ptr);
+    NetStream_as* ns =
+        ensureNativeType<NetStream_as>(fn.this_ptr);
 
     // TODO: should we do anything if given no args ?
     //       are we sure setting bufferTime to 0 is what we have to do ?
@@ -1705,8 +1709,8 @@
 as_value
 netstream_attachAudio(const fn_call& fn)
 {
-    boost::intrusive_ptr<NetStream_as> ns =
-        ensureType<NetStream_as>(fn.this_ptr);
+    NetStream_as* ns =
+        ensureNativeType<NetStream_as>(fn.this_ptr);
     UNUSED(ns);
 
     LOG_ONCE(log_unimpl("NetStream.attachAudio"));
@@ -1717,8 +1721,8 @@
 as_value
 netstream_attachVideo(const fn_call& fn)
 {
-    boost::intrusive_ptr<NetStream_as> ns =
-        ensureType<NetStream_as>(fn.this_ptr);
+    NetStream_as* ns =
+        ensureNativeType<NetStream_as>(fn.this_ptr);
     UNUSED(ns);
 
     LOG_ONCE(log_unimpl("NetStream.attachVideo"));
@@ -1729,8 +1733,8 @@
 as_value
 netstream_publish(const fn_call& fn)
 {
-    boost::intrusive_ptr<NetStream_as> ns = 
-        ensureType<NetStream_as>(fn.this_ptr);
+    NetStream_as* ns = 
+        ensureNativeType<NetStream_as>(fn.this_ptr);
     UNUSED(ns);
 
     LOG_ONCE(log_unimpl("NetStream.publish"));
@@ -1741,8 +1745,8 @@
 as_value
 netstream_receiveAudio(const fn_call& fn)
 {
-    boost::intrusive_ptr<NetStream_as> ns =
-        ensureType<NetStream_as>(fn.this_ptr);
+    NetStream_as* ns =
+        ensureNativeType<NetStream_as>(fn.this_ptr);
     UNUSED(ns);
 
     LOG_ONCE(log_unimpl("NetStream.receiveAudio"));
@@ -1753,8 +1757,8 @@
 as_value
 netstream_receiveVideo(const fn_call& fn)
 {
-    boost::intrusive_ptr<NetStream_as> ns =
-        ensureType<NetStream_as>(fn.this_ptr);
+    NetStream_as* ns =
+        ensureNativeType<NetStream_as>(fn.this_ptr);
     UNUSED(ns);
 
     LOG_ONCE(log_unimpl("NetStream.receiveVideo"));
@@ -1765,8 +1769,8 @@
 as_value
 netstream_send(const fn_call& fn)
 {
-    boost::intrusive_ptr<NetStream_as> ns =
-        ensureType<NetStream_as>(fn.this_ptr);
+    NetStream_as* ns =
+        ensureNativeType<NetStream_as>(fn.this_ptr);
     UNUSED(ns);
 
     LOG_ONCE(log_unimpl("NetStream.send"));
@@ -1780,8 +1784,8 @@
 {
     //GNASH_REPORT_FUNCTION;
 
-    boost::intrusive_ptr<NetStream_as> ns =
-        ensureType<NetStream_as>(fn.this_ptr);
+    NetStream_as* ns =
+        ensureNativeType<NetStream_as>(fn.this_ptr);
 
     assert(fn.nargs == 0); // we're a getter
     return as_value(double(ns->time()/1000.0));
@@ -1791,8 +1795,8 @@
 as_value
 netstream_bytesloaded(const fn_call& fn)
 {
-    boost::intrusive_ptr<NetStream_as> ns =
-        ensureType<NetStream_as>(fn.this_ptr);
+    NetStream_as* ns =
+        ensureNativeType<NetStream_as>(fn.this_ptr);
 
     if ( ! ns->isConnected() )
     {
@@ -1806,8 +1810,8 @@
 as_value
 netstream_bytestotal(const fn_call& fn)
 {
-    boost::intrusive_ptr<NetStream_as> ns = 
-        ensureType<NetStream_as>(fn.this_ptr);
+    NetStream_as* ns = 
+        ensureNativeType<NetStream_as>(fn.this_ptr);
 
     if ( ! ns->isConnected() )
     {
@@ -1821,8 +1825,8 @@
 as_value
 netstream_currentFPS(const fn_call& fn)
 {
-    boost::intrusive_ptr<NetStream_as> ns = 
-        ensureType<NetStream_as>(fn.this_ptr);
+    NetStream_as* ns = 
+        ensureNativeType<NetStream_as>(fn.this_ptr);
 
     if ( ! ns->isConnected() )
     {
@@ -1838,8 +1842,8 @@
 as_value
 netstream_bufferLength(const fn_call& fn)
 {
-    boost::intrusive_ptr<NetStream_as> ns = 
-        ensureType<NetStream_as>(fn.this_ptr);
+    NetStream_as* ns = 
+        ensureNativeType<NetStream_as>(fn.this_ptr);
 
     // NetStream_as::bufferLength returns milliseconds, we want
     // to return *fractional* seconds.
@@ -1851,8 +1855,8 @@
 as_value
 netstream_bufferTime(const fn_call& fn)
 {
-    boost::intrusive_ptr<NetStream_as> ns =
-        ensureType<NetStream_as>(fn.this_ptr);
+    NetStream_as* ns =
+        ensureNativeType<NetStream_as>(fn.this_ptr);
 
     // We return bufferTime in seconds
     double ret = ns->bufferTime() / 1000.0;
@@ -1863,39 +1867,34 @@
 as_value
 netstream_liveDelay(const fn_call& fn)
 {
-    boost::intrusive_ptr<NetStream_as> ns = 
-        ensureType<NetStream_as>(fn.this_ptr);
+    NetStream_as* ns = ensureNativeType<NetStream_as>(fn.this_ptr);
+    UNUSED(ns);
 
     LOG_ONCE(log_unimpl("NetStream.liveDelay getter/setter"));
 
-    if ( fn.nargs == 0 ) 
-    {
-        return as_value();
-    }
-    else 
-    {
-        return as_value();
-    }
+    if (fn.nargs == 0) {
+        return as_value();
+    }
+    return as_value();
 }
 
 void
 attachNetStreamInterface(as_object& o)
 {
     Global_as* gl = getGlobal(o);
-
-    o.init_member("close", gl->createFunction(netstream_close));
+    VM& vm = getVM(o);
+    
+    o.init_member("close", vm.getNative(2101, 0));
     o.init_member("pause", gl->createFunction(netstream_pause));
     o.init_member("play", gl->createFunction(netstream_play));
     o.init_member("seek", gl->createFunction(netstream_seek));
-    o.init_member("setBufferTime",
-            gl->createFunction(netstream_setbuffertime));
-
-    o.init_member("attachAudio", gl->createFunction(netstream_attachAudio));
-    o.init_member("attachVideo", gl->createFunction(netstream_attachVideo));
+    o.init_member("setBufferTime", vm.getNative(2101, 4));
+    o.init_member("attachAudio", vm.getNative(2101, 1));
+    o.init_member("attachVideo", vm.getNative(2101, 2));
     o.init_member("publish", gl->createFunction(netstream_publish));
     o.init_member("receiveAudio", gl->createFunction(netstream_receiveAudio));
     o.init_member("receiveVideo", gl->createFunction(netstream_receiveVideo));
-    o.init_member("send", gl->createFunction(netstream_send));
+    o.init_member("send", vm.getNative(2101, 3));
 
     // Properties
     // TODO: attach to each instance rather then to the class ? check it ..
@@ -1910,23 +1909,11 @@
 
 }
 
-as_object*
-getNetStreamInterface()
-{
-
-    static boost::intrusive_ptr<as_object> o;
-    if ( o == NULL )
-    {
-        o = new as_object(getObjectInterface());
-        attachNetStreamInterface(*o);
-    }
-
-    return o.get();
-}
-
 void
-executeTag(const SimpleBuffer& _buffer, as_object* thisPtr, VM& vm)
+executeTag(const SimpleBuffer& _buffer, as_object& thisPtr)
 {
+    VM& vm = getVM(thisPtr);
+
        const boost::uint8_t* ptr = _buffer.data();
        const boost::uint8_t* endptr = ptr + _buffer.size();
 
@@ -1947,19 +1934,19 @@
 
        log_debug("funcName: %s", funcName);
 
-       string_table& st = vm.getStringTable();
+       string_table& st = getStringTable(thisPtr);
        string_table::key funcKey = st.find(funcName);
 
        as_value arg;
        std::vector<as_object*> objRefs;
-       if ( ! arg.readAMF0(ptr, endptr, -1, objRefs, vm) )
+       if (!arg.readAMF0(ptr, endptr, -1, objRefs, vm))
        {
                log_error("Could not convert FLV metatag to as_value, but will 
try "
                 "passing it anyway. It's an %s", arg);
        }
 
        log_debug("Calling %s(%s)", funcName, arg);
-       thisPtr->callMethod(funcKey, arg);
+       thisPtr.callMethod(funcKey, arg);
 }
 
 } // anonymous namespace

=== modified file 'libcore/asobj/NetStream_as.h'
--- a/libcore/asobj/NetStream_as.h      2009-07-16 08:30:06 +0000
+++ b/libcore/asobj/NetStream_as.h      2009-08-21 07:09:32 +0000
@@ -168,7 +168,7 @@
 /// This class is responsible for handlign external
 /// media files. Provides interfaces for playback control.
 ///
-class NetStream_as : public as_object
+class NetStream_as : public ActiveRelay
 {
 
 public:
@@ -179,12 +179,10 @@
       pauseModeUnPause = 1  
     };
 
-    NetStream_as();
+    NetStream_as(as_object* owner);
 
     ~NetStream_as();
 
-    static void init(as_object& global, const ObjectURI& uri);
-
     PlayHead::PlaybackStatus playbackState() const {
         return _playHead.getState();
     }
@@ -241,7 +239,7 @@
     /// and (re)start after a buffering pause. In NetStreamFfmpeg it is also
     /// used to find the next video frame to be shown, though this might
     /// change.
-    void advanceState();
+    void update();
     
     /// Returns the current framerate in frames per second.
     double getCurrentFPS()  { return 0; }
@@ -251,7 +249,7 @@
     /// @param nc
     ///     The NetConnection object to use for network access
     ///
-    void setNetCon(boost::intrusive_ptr<NetConnection_as> nc) {
+    void setNetCon(NetConnection_as* nc) {
         _netCon = nc;
     }
 
@@ -308,6 +306,8 @@
         _invalidatedVideoCharacter = ch;
     }
 
+    virtual void markReachableResources() const;
+
     /// Callback used by sound_handler to get audio data
     //
     /// This is a sound_handler::aux_streamer_ptr type.
@@ -351,7 +351,7 @@
         invalidTime
     };
 
-    boost::intrusive_ptr<NetConnection_as> _netCon;
+    NetConnection_as* _netCon;
 
     boost::scoped_ptr<CharacterProxy> _audioController;
 
@@ -415,17 +415,6 @@
     // The position in the inputfile, only used when not playing a FLV
     long inputPos;
 
-#ifdef GNASH_USE_GC
-    /// Mark all reachable resources of a NetStream_as, for the GC
-    //
-    /// Reachable resources are:
-    /// - associated NetConnection object (_netCon)
-    /// - DisplayObject to invalidate on video updates 
(_invalidatedVideoCharacter)
-    /// - onStatus event handler (m_statusHandler)
-    ///
-    virtual void markReachableResources() const;
-#endif // GNASH_USE_GC
-
     /// Unplug the advance timer callback
     void stopAdvanceTimer();
 
@@ -492,7 +481,7 @@
 
     /// Update the image/videoframe to be returned by next get_video() call.
     //
-    /// Used by advanceState().
+    /// Used by update().
     ///
     /// Note that get_video will be called by Video::display(), which
     /// is usually called right after Video::advance(), so the result
@@ -598,6 +587,10 @@
 
 };
 
+void netstream_class_init(as_object& global, const ObjectURI& uri);
+
+void registerNetStreamNative(as_object& global);
+
 } // gnash namespace
 
 #endif

=== modified file 'libcore/asobj/Number_as.cpp'
--- a/libcore/asobj/Number_as.cpp       2009-08-20 06:55:15 +0000
+++ b/libcore/asobj/Number_as.cpp       2009-08-21 07:28:09 +0000
@@ -36,7 +36,7 @@
 
 namespace gnash {
 
-class Number_as : public Proxy
+class Number_as : public Relay
 {
 public:
 
@@ -64,7 +64,7 @@
 {
     // Number.toString must only work for number object, not generic ones.
     // This is so trace(Number.prototype) doesn't return 0 ...
-    Number_as* obj = checkType<Number_as>(fn.this_ptr);
+    Number_as* obj = ensureNativeType<Number_as>(fn.this_ptr);
 
     double val = obj->value();
     unsigned radix = 10;
@@ -91,7 +91,7 @@
 {
     // Number.valueOf must only work for number object, not generic ones.
     // This is so trace(Number.prototype == Object) return true in swf5 ?
-    Number_as* obj = checkType<Number_as>(fn.this_ptr);
+    Number_as* obj = ensureNativeType<Number_as>(fn.this_ptr);
 
     return obj->value();
 }
@@ -110,7 +110,7 @@
         return as_value(val);
     }
 
-    fn.this_ptr->setProxy(new Number_as(val));
+    fn.this_ptr->setRelay(new Number_as(val));
     
     return as_value(); 
 }
@@ -151,9 +151,14 @@
 void
 number_class_init(as_object& where, const ObjectURI& uri)
 {
+    VM& vm = getVM(where);
     Global_as* gl = getGlobal(where);
+
     as_object* proto = gl->createObject(getObjectInterface());
-    as_object* cl = gl->createClass(&number_ctor, proto);
+    as_object* cl = vm.getNative(106, 2);
+    cl->init_member(NSV::PROP_PROTOTYPE, proto);
+    proto->init_member(NSV::PROP_CONSTRUCTOR, cl);
+
     attachNumberInterface(*proto);
     attachNumberStaticInterface(*cl);
 

=== modified file 'libcore/asobj/String_as.cpp'
--- a/libcore/asobj/String_as.cpp       2009-08-20 07:43:09 +0000
+++ b/libcore/asobj/String_as.cpp       2009-08-21 07:07:11 +0000
@@ -769,7 +769,7 @@
 as_value
 string_toString(const fn_call& fn)
 {
-    String_as* str = checkType<String_as>(fn.this_ptr);
+    String_as* str = ensureNativeType<String_as>(fn.this_ptr);
     return as_value(str->value());
 }
 
@@ -790,7 +790,7 @@
        
     as_object* obj = fn.this_ptr;
 
-    obj->setProxy(new String_as(str));
+    obj->setRelay(new String_as(str));
     std::wstring wstr = utf8::decodeCanonicalString(str, getSWFVersion(fn));
     obj->init_member(NSV::PROP_LENGTH, wstr.size(), as_object::DefaultFlags);
 

=== modified file 'libcore/asobj/String_as.h'
--- a/libcore/asobj/String_as.h 2009-08-19 11:27:23 +0000
+++ b/libcore/asobj/String_as.h 2009-08-21 07:07:11 +0000
@@ -29,7 +29,7 @@
 class ObjectURI;
 class Global_as;
 
-class String_as : public Proxy
+class String_as : public Relay
 {
 
 public:

=== modified file 
'libcore/asobj/flash/accessibility/AccessibilityProperties_as.cpp'
--- a/libcore/asobj/flash/accessibility/AccessibilityProperties_as.cpp  
2009-08-17 11:46:48 +0000
+++ b/libcore/asobj/flash/accessibility/AccessibilityProperties_as.cpp  
2009-08-21 05:31:32 +0000
@@ -36,25 +36,15 @@
     as_value accessibilityproperties_ctor(const fn_call& fn);
     void attachAccessibilityPropertiesInterface(as_object& o);
     void attachAccessibilityPropertiesStaticInterface(as_object& o);
-    as_object* getAccessibilityPropertiesInterface();
-
 }
 
 // extern (used by Global.cpp)
 void
 accessibilityproperties_class_init(as_object& where, const ObjectURI& uri)
 {
-    Global_as* gl = getGlobal(where);
-    as_object* proto = gl->createObject();
-
-    as_object* cl = gl->createClass(&accessibilityproperties_ctor, proto);
-
-    attachAccessibilityPropertiesInterface(*proto);
-    attachAccessibilityPropertiesStaticInterface(*cl);
-
-    // Register _global.AccessibilityProperties
-    where.init_member(getName(uri), cl, as_object::DefaultFlags,
-            getNamespace(uri));
+    registerBuiltinClass(where, accessibilityproperties_ctor,
+            attachAccessibilityPropertiesInterface,
+            attachAccessibilityPropertiesStaticInterface, uri);
 }
 
 namespace {

=== modified file 'libcore/asobj/flash/media/Sound_as.cpp'
--- a/libcore/asobj/flash/media/Sound_as.cpp    2009-08-18 10:32:14 +0000
+++ b/libcore/asobj/flash/media/Sound_as.cpp    2009-08-21 07:09:32 +0000
@@ -81,14 +81,14 @@
     as_object* getSoundInterface();
 }
 
-Sound_as::Sound_as() 
+Sound_as::Sound_as(as_object* owner) 
     :
-    as_object(getSoundInterface()),
+    ActiveRelay(owner),
     _attachedCharacter(0),
     soundId(-1),
     externalSound(false),
     isStreaming(false),
-    _soundHandler(getRunResources(*this).soundHandler()),
+    _soundHandler(getRunResources(*owner).soundHandler()),
     _mediaHandler(media::MediaHandler::get()),
     _startTime(0),
     _leftOverData(),
@@ -115,7 +115,7 @@
 
 // extern (used by Global.cpp)
 void
-Sound_as::init(as_object& where, const ObjectURI& uri)
+sound_class_init(as_object& where, const ObjectURI& uri)
 {
 
     as_object* iface = getSoundInterface();
@@ -134,7 +134,7 @@
 Sound_as::startProbeTimer()
 {
     _probeTimer = 1;
-    getRoot(*this).addAdvanceCallback(this);
+    getRoot(owner()).addAdvanceCallback(this);
 }
 
 /*private*/
@@ -147,14 +147,14 @@
 
     if ( _probeTimer )
     {
-        getRoot(*this).removeAdvanceCallback(this);
+        getRoot(owner()).removeAdvanceCallback(this);
         log_debug(" sound callback removed");
         _probeTimer = 0;
     }
 }
 
 void
-Sound_as::advanceState()
+Sound_as::update()
 {
     probeAudio();
 }
@@ -180,7 +180,7 @@
             stopProbeTimer();
 
             // dispatch onSoundComplete 
-            callMethod(NSV::PROP_ON_SOUND_COMPLETE);
+            owner().callMethod(NSV::PROP_ON_SOUND_COMPLETE);
         }
     }
     else
@@ -226,8 +226,7 @@
 void
 Sound_as::markReachableResources() const
 {
-    if ( _attachedCharacter ) _attachedCharacter->setReachable();
-    markAsObjectReachable();
+    if (_attachedCharacter) _attachedCharacter->setReachable();
 }
 #endif // GNASH_USE_GC
 
@@ -288,8 +287,7 @@
     {
         //log_debug("Sound has an attached DisplayObject");
         DisplayObject* ch = _attachedCharacter->get();
-        if ( ! ch )
-        {
+        if (! ch) {
             log_debug("Character attached to Sound was unloaded and "
                     "couldn't rebind");
             return false;
@@ -297,13 +295,11 @@
         volume = ch->getVolume();
         return true;
     }
-    //else log_debug("Sound has NO attached DisplayObject, _soundHandler is 
%p, soundId is %d", _soundHandler, soundId);
 
     // If we're not attached to a DisplayObject we'll need to query
     // sound_handler for volume. If we have no sound handler, we
     // can't do much, so we'll return false
-    if (!_soundHandler)
-    {
+    if (!_soundHandler) {
         log_debug("We have no sound handler here...");
         return false;
     }
@@ -312,14 +308,8 @@
     // the final output as a whole.
     // If soundId is -1 we're controlling as a whole
     //
-    if ( soundId == -1 )
-    {
-        volume = _soundHandler->getFinalVolume();
-    }
-    else
-    {
-        volume = _soundHandler->get_volume(soundId);
-    }
+    if (soundId == -1) volume = _soundHandler->getFinalVolume(); 
+    else volume = _soundHandler->get_volume(soundId);
 
     return true;
 }
@@ -348,7 +338,7 @@
     /// changed that.
     _startTime=0;
 
-    const RunResources& rr = getRunResources(*this);
+    const RunResources& rr = getRunResources(owner());
     URL url(file, rr.baseURL());
 
     const RcInitFile& rcfile = RcInitFile::getDefaultInstance();
@@ -788,26 +778,28 @@
 as_value
 sound_new(const fn_call& fn)
 {
-    Sound_as* sound_obj = new Sound_as();
-
-    if ( fn.nargs )
-    {
+
+    as_object* so = fn.this_ptr;
+    Sound_as* s(new Sound_as(so));
+    so->setRelay(s);
+
+    if (fn.nargs) {
         IF_VERBOSE_ASCODING_ERRORS(
-        if ( fn.nargs > 1 )
-        {
-            std::stringstream ss; fn.dump_args(ss);
-            log_aserror("new Sound(%d) : args after first one ignored", 
ss.str());
-        }
+            if (fn.nargs > 1) {
+                std::stringstream ss; fn.dump_args(ss);
+                log_aserror("new Sound(%d) : args after first one ignored",
+                    ss.str());
+            }
         );
 
+
         const as_value& arg0 = fn.arg(0);
         if ( ! arg0.is_null() && ! arg0.is_undefined() )
         {
             as_object* obj = arg0.to_object(*getGlobal(fn)).get();
             DisplayObject* ch = obj ? obj->toDisplayObject() : 0;
             IF_VERBOSE_ASCODING_ERRORS(
-            if ( ! ch )
-            {
+            if (!ch) {
                 std::stringstream ss; fn.dump_args(ss);
                 log_aserror("new Sound(%s) : first argument isn't null "
                     "nor undefined, and doesn't cast to a DisplayObject. "
@@ -815,11 +807,11 @@
                     ss.str());
             }
             );
-            sound_obj->attachCharacter(ch);
+            s->attachCharacter(ch);
         }
     }
        
-    return as_value(sound_obj);
+    return as_value();
 }
 
 as_value
@@ -828,7 +820,7 @@
     IF_VERBOSE_ACTION (
     log_action(_("-- start sound"));
     )
-    boost::intrusive_ptr<Sound_as> so = ensureType<Sound_as>(fn.this_ptr);
+    Sound_as* so = ensureNativeType<Sound_as>(fn.this_ptr);
     int loop = 0;
     double secondOffset = 0;
 
@@ -853,7 +845,7 @@
     IF_VERBOSE_ACTION (
     log_action(_("-- stop sound "));
     )
-    boost::intrusive_ptr<Sound_as> so = ensureType<Sound_as>(fn.this_ptr);
+    Sound_as* so = ensureNativeType<Sound_as>(fn.this_ptr);
 
     int si = -1;
 
@@ -906,7 +898,7 @@
         return as_value();
     }
 
-    boost::intrusive_ptr<Sound_as> so = ensureType<Sound_as>(fn.this_ptr);
+    Sound_as* so = ensureNativeType<Sound_as>(fn.this_ptr);
 
     const std::string& name = fn.arg(0).to_string();
     if (name.empty()) {
@@ -954,7 +946,7 @@
 as_value
 sound_getbytesloaded(const fn_call& fn)
 {
-    boost::intrusive_ptr<Sound_as> so = ensureType<Sound_as>(fn.this_ptr);
+    Sound_as* so = ensureNativeType<Sound_as>(fn.this_ptr);
     long loaded = so->getBytesLoaded();
     if (loaded < 0) return as_value();
     return as_value(loaded);
@@ -963,7 +955,7 @@
 as_value
 sound_getbytestotal(const fn_call& fn)
 {
-    boost::intrusive_ptr<Sound_as> so = ensureType<Sound_as>(fn.this_ptr);
+    Sound_as* so = ensureNativeType<Sound_as>(fn.this_ptr);
     long total = so->getBytesTotal();
     if (total < 0) return as_value();
     return as_value(total);
@@ -1015,7 +1007,7 @@
 sound_getvolume(const fn_call& fn)
 {
 
-    boost::intrusive_ptr<Sound_as> so = ensureType<Sound_as>(fn.this_ptr);
+    Sound_as* so = ensureNativeType<Sound_as>(fn.this_ptr);
 
     if ( fn.nargs )
     {
@@ -1026,14 +1018,14 @@
     }
 
     int volume;
-    if ( so->getVolume(volume) ) return as_value(volume);
+    if (so->getVolume(volume)) return as_value(volume);
     return as_value();
 }
 
 as_value
 sound_loadsound(const fn_call& fn)
 {
-    boost::intrusive_ptr<Sound_as> so = ensureType<Sound_as>(fn.this_ptr);
+    Sound_as* so = ensureNativeType<Sound_as>(fn.this_ptr);
 
     if (!fn.nargs)
     {
@@ -1090,7 +1082,7 @@
         return as_value();
     }
 
-    boost::intrusive_ptr<Sound_as> so = ensureType<Sound_as>(fn.this_ptr);    
+    Sound_as* so = ensureNativeType<Sound_as>(fn.this_ptr);    
     int volume = (int) fn.arg(0).to_number();
 
     so->setVolume(volume);
@@ -1100,7 +1092,7 @@
 as_value
 sound_duration(const fn_call& fn)
 {
-    boost::intrusive_ptr<Sound_as> so = ensureType<Sound_as>(fn.this_ptr);
+    Sound_as* so = ensureNativeType<Sound_as>(fn.this_ptr);
     return as_value(so->getDuration());
 }
 
@@ -1127,7 +1119,7 @@
 as_value
 sound_position(const fn_call& fn)
 {
-    boost::intrusive_ptr<Sound_as> so = ensureType<Sound_as>(fn.this_ptr);
+    Sound_as* so = ensureNativeType<Sound_as>(fn.this_ptr);
 
     return as_value(so->getPosition());
 }
@@ -1136,8 +1128,7 @@
 as_value
 sound_load(const fn_call& fn)
 {
-    boost::intrusive_ptr<Sound_as> ptr =
-        ensureType<Sound_as>(fn.this_ptr);
+    Sound_as* ptr = ensureNativeType<Sound_as>(fn.this_ptr);
     UNUSED(ptr);
     log_unimpl (__FUNCTION__);
     return as_value();
@@ -1146,8 +1137,7 @@
 as_value
 sound_play(const fn_call& fn)
 {
-    boost::intrusive_ptr<Sound_as> ptr =
-        ensureType<Sound_as>(fn.this_ptr);
+    Sound_as* ptr = ensureNativeType<Sound_as>(fn.this_ptr);
     UNUSED(ptr);
     log_unimpl (__FUNCTION__);
     return as_value();
@@ -1156,8 +1146,7 @@
 as_value
 sound_complete(const fn_call& fn)
 {
-    boost::intrusive_ptr<Sound_as> ptr =
-        ensureType<Sound_as>(fn.this_ptr);
+    Sound_as* ptr = ensureNativeType<Sound_as>(fn.this_ptr);
     UNUSED(ptr);
     log_unimpl (__FUNCTION__);
     return as_value();
@@ -1166,8 +1155,7 @@
 as_value
 sound_id3(const fn_call& fn)
 {
-    boost::intrusive_ptr<Sound_as> ptr =
-        ensureType<Sound_as>(fn.this_ptr);
+    Sound_as* ptr = ensureNativeType<Sound_as>(fn.this_ptr);
     UNUSED(ptr);
     log_unimpl (__FUNCTION__);
     return as_value();
@@ -1176,8 +1164,7 @@
 as_value
 sound_ioError(const fn_call& fn)
 {
-    boost::intrusive_ptr<Sound_as> ptr =
-        ensureType<Sound_as>(fn.this_ptr);
+    Sound_as* ptr = ensureNativeType<Sound_as>(fn.this_ptr);
     UNUSED(ptr);
     log_unimpl (__FUNCTION__);
     return as_value();
@@ -1186,8 +1173,7 @@
 as_value
 sound_open(const fn_call& fn)
 {
-    boost::intrusive_ptr<Sound_as> ptr =
-        ensureType<Sound_as>(fn.this_ptr);
+    Sound_as* ptr = ensureNativeType<Sound_as>(fn.this_ptr);
     UNUSED(ptr);
     log_unimpl (__FUNCTION__);
     return as_value();
@@ -1196,19 +1182,18 @@
 as_value
 sound_progress(const fn_call& fn)
 {
-    boost::intrusive_ptr<Sound_as> ptr =
-        ensureType<Sound_as>(fn.this_ptr);
+    Sound_as* ptr = ensureNativeType<Sound_as>(fn.this_ptr);
     UNUSED(ptr);
     log_unimpl (__FUNCTION__);
     return as_value();
 }
 
 as_value
-sound_ctor(const fn_call& /*fn*/)
+sound_ctor(const fn_call& fn)
 {
-    boost::intrusive_ptr<as_object> obj = new Sound_as;
-
-    return as_value(obj.get()); // will keep alive
+    as_object* obj = fn.this_ptr;
+    obj->setRelay(new Sound_as(obj));
+    return as_value();
 }
 
 } // anonymous namespace 

=== modified file 'libcore/asobj/flash/media/Sound_as.h'
--- a/libcore/asobj/flash/media/Sound_as.h      2009-07-28 11:58:27 +0000
+++ b/libcore/asobj/flash/media/Sound_as.h      2009-08-21 07:09:32 +0000
@@ -47,17 +47,16 @@
        
        class fn_call;
        class as_object;
-class ObjectURI;
-       class Sound_as : public as_object
-       {
-
-       public:
-               Sound_as();
-               
-               ~Sound_as();
-               
-               static void init(as_object& where, const ObjectURI& uri);
-               
+    class ObjectURI;
+
+class Sound_as : public ActiveRelay
+{
+
+public:
+    Sound_as(as_object* owner);
+    
+    ~Sound_as();
+    
        /// Make this sound control the given DisplayObject
     //
     /// NOTE: 0 is accepted, to implement an "invalid"
@@ -168,7 +167,7 @@
     /// Unregister the probe timer
     void stopProbeTimer();
 
-    virtual void advanceState();
+    virtual void update();
 
     /// Probe audio
     void probeAudio();
@@ -186,7 +185,9 @@
     bool isAttached() const {
         return _inputStream!=0;
     }
-       };
+};
+
+void sound_class_init(as_object& where, const ObjectURI& uri);
 
 } // gnash namespace
 

=== modified file 'libcore/asobj/flash/net/FileReference_as.cpp'
--- a/libcore/asobj/flash/net/FileReference_as.cpp      2009-08-20 08:57:16 
+0000
+++ b/libcore/asobj/flash/net/FileReference_as.cpp      2009-08-21 08:59:14 
+0000
@@ -42,12 +42,12 @@
 static as_value filereference_download(const fn_call& fn);
 static as_value filereference_removeListener(const fn_call& fn);
 static as_value filereference_upload(const fn_call& fn);
-static as_value filereference_creationDate_getset(const fn_call& fn);
-static as_value filereference_creator_getset(const fn_call& fn);
-static as_value filereference_modificationDate_getset(const fn_call& fn);
-static as_value filereference_name_getset(const fn_call& fn);
-static as_value filereference_size_getset(const fn_call& fn);
-static as_value filereference_type_getset(const fn_call& fn);
+static as_value filereference_creationDate(const fn_call& fn);
+static as_value filereference_creator(const fn_call& fn);
+static as_value filereference_modificationDate(const fn_call& fn);
+static as_value filereference_name(const fn_call& fn);
+static as_value filereference_size(const fn_call& fn);
+static as_value filereference_type(const fn_call& fn);
 as_value filereference_ctor(const fn_call& fn);
 
 void attachFileReferenceStaticInterface(as_object& /*o*/)
@@ -65,18 +65,12 @@
     o.init_member("download", gl->createFunction(filereference_download));
     o.init_member("removeListener", 
gl->createFunction(filereference_removeListener));
     o.init_member("upload", gl->createFunction(filereference_upload));
-    o.init_property("creationDate", filereference_creationDate_getset, 
filereference_creationDate_getset);
-    o.init_property("creator", filereference_creator_getset, 
filereference_creator_getset);
-    o.init_property("modificationDate", filereference_modificationDate_getset, 
filereference_modificationDate_getset);
-    o.init_property("name", filereference_name_getset, 
filereference_name_getset);
-    o.init_property("size", filereference_size_getset, 
filereference_size_getset);
-    o.init_property("type", filereference_type_getset, 
filereference_type_getset);
-}
-
-static void
-attachFileReferenceStaticProperties(as_object& /*o*/)
-{
-   
+    o.init_property("creationDate", filereference_creationDate, 
filereference_creationDate);
+    o.init_property("creator", filereference_creator, filereference_creator);
+    o.init_property("modificationDate", filereference_modificationDate, 
filereference_modificationDate);
+    o.init_property("name", filereference_name, filereference_name);
+    o.init_property("size", filereference_size, filereference_size);
+    o.init_property("type", filereference_type, filereference_type);
 }
 
 static as_value
@@ -116,37 +110,37 @@
 }
 
 static as_value
-filereference_creationDate_getset(const fn_call& /*fn*/)
-{
-    return as_value();
-}
-
-static as_value
-filereference_creator_getset(const fn_call& /*fn*/)
-{
-    return as_value();
-}
-
-static as_value
-filereference_modificationDate_getset(const fn_call& /*fn*/)
-{
-    return as_value();
-}
-
-static as_value
-filereference_name_getset(const fn_call& /*fn*/)
-{
-    return as_value();
-}
-
-static as_value
-filereference_size_getset(const fn_call& /*fn*/)
-{
-    return as_value();
-}
-
-static as_value
-filereference_type_getset(const fn_call& /*fn*/)
+filereference_creationDate(const fn_call& /*fn*/)
+{
+    return as_value();
+}
+
+static as_value
+filereference_creator(const fn_call& /*fn*/)
+{
+    return as_value();
+}
+
+static as_value
+filereference_modificationDate(const fn_call& /*fn*/)
+{
+    return as_value();
+}
+
+static as_value
+filereference_name(const fn_call& /*fn*/)
+{
+    return as_value();
+}
+
+static as_value
+filereference_size(const fn_call& /*fn*/)
+{
+    return as_value();
+}
+
+static as_value
+filereference_type(const fn_call& /*fn*/)
 {
     return as_value();
 }

=== modified file 'libcore/asobj/flash/net/SharedObject_as.cpp'
--- a/libcore/asobj/flash/net/SharedObject_as.cpp       2009-08-18 06:49:40 
+0000
+++ b/libcore/asobj/flash/net/SharedObject_as.cpp       2009-08-21 07:32:00 
+0000
@@ -47,8 +47,8 @@
 #include "network.h"
 #include "rtmp_client.h"
 #include "URL.h"
-
 #include "NetConnection_as.h"
+
 #include <boost/scoped_array.hpp>
 #include <boost/shared_ptr.hpp>
 
@@ -61,7 +61,6 @@
 }
 
 using namespace amf;
-using namespace std;
 
 namespace gnash {
 
@@ -430,7 +429,7 @@
 
 /// Process the connect(uri) method.
 void
-SharedObject_as::connect(NetConnection_as */* obj */, const std::string& /* 
uri */)
+SharedObject_as::connect(NetConnection_as* /*obj*/, const std::string& /*uri*/)
 {
     GNASH_REPORT_FUNCTION;
    
@@ -880,12 +879,13 @@
 #endif
     }
     
-    boost::intrusive_ptr<NetConnection_as> nc =
-       boost::dynamic_pointer_cast<NetConnection_as>(
-            fn.arg(0).to_object(*getGlobal(fn)));
+    NetConnection_as* nc;
+    if (!isNativeType(fn.arg(0).to_object(*getGlobal(fn)).get(), nc)) {
+        return as_value();
+    }
 
     // This is always set without validification.fooc->setURI(uriStr);
-    string str = nc->getURI();
+    std::string str = nc->getURI();
     obj->setPath(str);
     URL uri = nc->getURI();
     Network *net = new Network;

=== modified file 'libcore/asobj/flash/net/SharedObject_as.h'
--- a/libcore/asobj/flash/net/SharedObject_as.h 2009-08-04 17:39:22 +0000
+++ b/libcore/asobj/flash/net/SharedObject_as.h 2009-08-21 07:32:00 +0000
@@ -22,13 +22,10 @@
 #include <string>
 #include <map>
 
-#include "NetConnection_as.h"
-
 // Forward declarations
 namespace gnash {
     class as_object;
     class Network;
-//     class NetConnection_as;
     class ObjectURI;
     class SharedObject_as;
     class VM;

=== modified file 'libcore/asobj/flash/net/XMLSocket_as.cpp'
--- a/libcore/asobj/flash/net/XMLSocket_as.cpp  2009-08-20 06:55:15 +0000
+++ b/libcore/asobj/flash/net/XMLSocket_as.cpp  2009-08-21 07:09:32 +0000
@@ -221,13 +221,13 @@
 
 }
 
-class XMLSocket_as : public as_object {
-
+class XMLSocket_as : public ActiveRelay
+{
 public:
 
     typedef std::vector<std::string> MessageList;
 
-    XMLSocket_as();
+    XMLSocket_as(as_object* owner);
     ~XMLSocket_as();
     
     /// True when the XMLSocket is not trying to connect.
@@ -258,7 +258,7 @@
     void close();
 
     /// Called on advance() when socket is connected
-    virtual void advanceState();
+    virtual void update();
 
 private:
 
@@ -276,9 +276,9 @@
 };
 
   
-XMLSocket_as::XMLSocket_as()
+XMLSocket_as::XMLSocket_as(as_object* owner)
     :
-    as_object(getXMLSocketInterface()),
+    ActiveRelay(owner),
     _ready(false)
 {
 }
@@ -291,7 +291,7 @@
 }
 
 void
-XMLSocket_as::advanceState()
+XMLSocket_as::update()
 {
     // Wait until something has happened with the connection
     if (!_connection.complete()) return;
@@ -303,15 +303,15 @@
         if (!connected()) {
 
             // If connection failed, notify onConnect and stop callback.
-            // This means advanceState() will not be called again until
+            // This means update() will not be called again until
             // XMLSocket.connect() is invoked.
-            callMethod(NSV::PROP_ON_CONNECT, false);
-            getRoot(*this).removeAdvanceCallback(this);
+            owner().callMethod(NSV::PROP_ON_CONNECT, false);
+            getRoot(owner()).removeAdvanceCallback(this);
             return;    
         }
 
         // Connection succeeded.
-        callMethod(NSV::PROP_ON_CONNECT, true);
+        owner().callMethod(NSV::PROP_ON_CONNECT, true);
         _ready = true;
     }
 
@@ -331,7 +331,7 @@
     _connection.connect(host, port);
     
     // Start callbacks on advance.
-    getRoot(*this).addAdvanceCallback(this);
+    getRoot(owner()).addAdvanceCallback(this);
     
     return true;
 }
@@ -339,7 +339,7 @@
 void
 XMLSocket_as::close()
 {
-    getRoot(*this).removeAdvanceCallback(this);
+    getRoot(owner()).removeAdvanceCallback(this);
     _connection.close();
     _ready = false;
 }
@@ -351,8 +351,8 @@
        boost::intrusive_ptr<as_function> ret;
 
        as_value tmp;
-       string_table& st = getStringTable(*this);
-       if (!get_member(st.find(name), &tmp) ) return ret;
+       string_table& st = getStringTable(owner());
+       if (!owner().get_member(st.find(name), &tmp) ) return ret;
        ret = tmp.to_as_function();
        return ret;
 }
@@ -375,7 +375,7 @@
     }
 #endif
 
-    as_environment env(getVM(*this)); 
+    as_environment env(getVM(owner())); 
 
     for (XMLSocket_as::MessageList::const_iterator it=msgs.begin(),
                     itEnd=msgs.end(); it != itEnd; ++it) {
@@ -392,7 +392,7 @@
         fn_call::Args args;
         args += s;
         
-        fn_call call(this, env, args);
+        fn_call call(&owner(), env, args);
 
         onDataHandler->call(call);
     }
@@ -420,19 +420,8 @@
 void
 xmlsocket_class_init(as_object& where, const ObjectURI& uri)
 {
-    // This is the global XMLSocket class
-    static boost::intrusive_ptr<as_object> cl;
-
-    if (!cl) {
-        Global_as* gl = getGlobal(where);
-        as_object* proto = getXMLSocketInterface();
-        cl = gl->createClass(&xmlsocket_new, proto);
-    }
-    
-    // Register _global.XMLSocket
-    where.init_member(getName(uri), cl.get(), as_object::DefaultFlags,
-            getNamespace(uri));
-
+    registerBuiltinClass(where, xmlsocket_new, attachXMLSocketInterface,
+            0, uri);
 }
 
 
@@ -450,8 +439,8 @@
     log_debug(_("XMLSocket.connect(%s) called"), ss.str());
 #endif
 
-    boost::intrusive_ptr<XMLSocket_as> ptr =
-        ensureType<XMLSocket_as>(fn.this_ptr);
+    XMLSocket_as* ptr =
+        ensureNativeType<XMLSocket_as>(fn.this_ptr);
 
     if (ptr->ready()) {
         log_error(_("XMLSocket.connect() called while already "
@@ -491,8 +480,8 @@
 as_value
 xmlsocket_send(const fn_call& fn)
 {
-    boost::intrusive_ptr<XMLSocket_as> ptr =
-        ensureType<XMLSocket_as>(fn.this_ptr);
+    XMLSocket_as* ptr =
+        ensureNativeType<XMLSocket_as>(fn.this_ptr);
 
     const std::string& str = fn.arg(0).to_string();
     ptr->send(str);
@@ -508,19 +497,20 @@
 {
     GNASH_REPORT_FUNCTION;
     
-    boost::intrusive_ptr<XMLSocket_as> ptr =
-        ensureType<XMLSocket_as>(fn.this_ptr);
+    XMLSocket_as* ptr =
+        ensureNativeType<XMLSocket_as>(fn.this_ptr);
 
     ptr->close();
     return as_value();
 }
 
 as_value
-xmlsocket_new(const fn_call& /*fn*/)
+xmlsocket_new(const fn_call& fn)
 {
 
-    boost::intrusive_ptr<as_object> xmlsock_obj = new XMLSocket_as;
-    return as_value(xmlsock_obj);
+    as_object* obj = fn.this_ptr;
+    obj->setRelay(new XMLSocket_as(obj));
+    return as_value();
 }
 
 as_value
@@ -528,9 +518,6 @@
 {
     GNASH_REPORT_FUNCTION;
    
-    boost::intrusive_ptr<XMLSocket_as> ptr = 
-        ensureType<XMLSocket_as>(fn.this_ptr);
-
     if (!fn.nargs) {
         IF_VERBOSE_ASCODING_ERRORS(
             log_aserror(_("Builtin XMLSocket.onData() needs an argument"));
@@ -553,7 +540,7 @@
     boost::intrusive_ptr<as_object> xml = new XMLDocument_as(xmlin);
     as_value arg(xml.get());
 
-    ptr->callMethod(NSV::PROP_ON_XML, arg);
+    fn.this_ptr->callMethod(NSV::PROP_ON_XML, arg);
 
     return as_value();
 }

=== modified file 'libcore/asobj/flash/xml/XMLDocument_as.cpp'
--- a/libcore/asobj/flash/xml/XMLDocument_as.cpp        2009-08-20 06:55:15 
+0000
+++ b/libcore/asobj/flash/xml/XMLDocument_as.cpp        2009-08-21 09:08:01 
+0000
@@ -53,7 +53,6 @@
     as_object* getXMLInterface();
        void attachXMLInterface(as_object& o);
        void attachXMLProperties(as_object& o);
-       //left as xml to not break everything else (these exist in AS2&3)
     as_value xml_new(const fn_call& fn);
     as_value xml_createElement(const fn_call& fn);
     as_value xml_createTextNode(const fn_call& fn);
@@ -588,15 +587,6 @@
 
 }
 
-bool
-XMLDocument_as::onLoad()
-{
-    log_debug(_("%s: FIXME: onLoad Default event handler"), __FUNCTION__);
-
-    return(_loaded);
-}
-
-
 void
 XMLDocument_as::clear()
 {
@@ -687,7 +677,15 @@
     static boost::intrusive_ptr<as_object> o;
     if ( o == NULL )
     {
-        o = new as_object(XMLNode_as::getXMLNodeInterface());
+        Global_as* gl = VM::get().getGlobal();
+        as_function* ctor = gl->getMember(NSV::CLASS_XMLNODE).to_as_function();
+        if (!ctor) return 0;
+
+        // XML.prototype is an XMLNode(1, "");
+        fn_call::Args args;
+        args += 1, "";
+        o = ctor->constructInstance(as_environment(VM::get()), args);
+
         VM::get().addStatic(o.get());
         attachXMLInterface(*o);
     }
@@ -698,7 +696,7 @@
 xml_new(const fn_call& fn)
 {
     boost::intrusive_ptr<XMLDocument_as> xml_obj;
-  
+
     if ( fn.nargs > 0 )
     {
         if ( fn.arg(0).is_object() )
@@ -724,16 +722,17 @@
         else
         {
             xml_obj = new XMLDocument_as(xml_in);
+            xml_obj->setRelay(new LoadableObject(xml_obj.get()));
             return as_value(xml_obj.get());
         }
     }
 
     xml_obj = new XMLDocument_as;
+    xml_obj->setRelay(new LoadableObject(xml_obj.get()));
 
     return as_value(xml_obj.get());
 }
 
-
 /// Only available as ASnative.
 as_value
 xml_escape(const fn_call& fn)

=== modified file 'libcore/asobj/flash/xml/XMLDocument_as.h'
--- a/libcore/asobj/flash/xml/XMLDocument_as.h  2009-07-28 11:58:27 +0000
+++ b/libcore/asobj/flash/xml/XMLDocument_as.h  2009-08-20 15:33:23 +0000
@@ -45,7 +45,7 @@
 //
 /// This class interface is identical in AS3 and AS2; it is probably 
 /// included in AS3 for backward compatibility.
-class XMLDocument_as : public XMLNode_as, public LoadableObject
+class XMLDocument_as : public XMLNode_as
 {
 public:
 
@@ -121,9 +121,6 @@
     ///
     void parseXML(const std::string& xml);
 
-    // An event handler that returns a what?
-    bool onLoad();
-
     /// Escape using XML entities.
     //
     /// Note this is not the same as a URL escape.

=== modified file 'libcore/asobj/flash/xml/XMLNode_as.cpp'
--- a/libcore/asobj/flash/xml/XMLNode_as.cpp    2009-08-18 10:32:14 +0000
+++ b/libcore/asobj/flash/xml/XMLNode_as.cpp    2009-08-21 08:41:59 +0000
@@ -750,7 +750,6 @@
 }
 
 
-// TODO: shouldn't overriding get_text_value() be fine ?
 as_value
 xmlnode_toString(const fn_call& fn)
 {

=== modified file 'libcore/movie_root.cpp'
--- a/libcore/movie_root.cpp    2009-08-17 11:47:12 +0000
+++ b/libcore/movie_root.cpp    2009-08-21 07:28:09 +0000
@@ -1680,13 +1680,13 @@
 }
 
 void
-movie_root::addAdvanceCallback(as_object* obj)
+movie_root::addAdvanceCallback(ActiveRelay* obj)
 {
     _objectCallbacks.insert(obj);
 }
 
 void
-movie_root::removeAdvanceCallback(as_object* obj)
+movie_root::removeAdvanceCallback(ActiveRelay* obj)
 {
     _objectCallbacks.erase(obj);
 }
@@ -1756,12 +1756,12 @@
 
     // Copy it, as the call can change the original, which is not only 
     // bad for invalidating iterators, but also allows infinite recursion.
-    std::vector<as_object*> currentCallbacks;
+    std::vector<ActiveRelay*> currentCallbacks;
     std::copy(_objectCallbacks.begin(), _objectCallbacks.end(),
             std::back_inserter(currentCallbacks));
 
     std::for_each(currentCallbacks.begin(), currentCallbacks.end(), 
-            std::mem_fun(&as_object::advanceState));
+            std::mem_fun(&ActiveRelay::update));
 
     processActionQueue();
 }
@@ -1849,7 +1849,7 @@
     }
 
     std::for_each(_objectCallbacks.begin(), _objectCallbacks.end(),
-            std::mem_fun(&as_object::setReachable));
+            std::mem_fun(&ActiveRelay::setReachable));
 
     // Mark resources reachable by queued action code
     for (int lvl=0; lvl<apSIZE; ++lvl)

=== modified file 'libcore/movie_root.h'
--- a/libcore/movie_root.h      2009-08-17 11:47:12 +0000
+++ b/libcore/movie_root.h      2009-08-21 07:09:32 +0000
@@ -343,9 +343,9 @@
     ///
     unsigned int add_interval_timer(std::auto_ptr<Timer> timer);
 
-    void addAdvanceCallback(as_object* obj);
+    void addAdvanceCallback(ActiveRelay* obj);
 
-    void removeAdvanceCallback(as_object* obj);
+    void removeAdvanceCallback(ActiveRelay* obj);
 
     /// Remove timer identified by given integer
     //
@@ -1034,7 +1034,7 @@
     MouseButtonState  m_mouse_button_state;
 
     /// Objects requesting a callback on every movie_root::advance()
-    typedef std::set<as_object*> ObjectCallbacks;
+    typedef std::set<ActiveRelay*> ObjectCallbacks;
     ObjectCallbacks _objectCallbacks;
 
     typedef std::map<int, Timer*> TimerMap;

=== modified file 'libcore/vm/Machine.cpp'
--- a/libcore/vm/Machine.cpp    2009-08-20 06:55:15 +0000
+++ b/libcore/vm/Machine.cpp    2009-08-21 05:39:19 +0000
@@ -870,11 +870,12 @@
                 {
                     as_value scope_value = pop_stack();
                     if (!scope_value.to_object(*_global).get()) {
+                        // Should throw an exception.
                         IF_VERBOSE_ASCODING_ERRORS(
                         log_aserror(_("Can't push a null value onto the "
                                 "scope stack (%s)."), scope_value);
                         );
-                        scope_value = as_value(_global->createObject());
+                        break;
                     }  
                     push_scope_stack(scope_value);
                     break;


reply via email to

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