gnash-commit
[Top][All Lists]
Advanced

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

[Gnash-commit] /srv/bzr/gnash/trunk r11582: Drop more static data, corr


From: Benjamin Wolsey
Subject: [Gnash-commit] /srv/bzr/gnash/trunk r11582: Drop more static data, correct native array construction.
Date: Wed, 21 Oct 2009 16:05:36 +0200
User-agent: Bazaar (1.16.1)

------------------------------------------------------------
revno: 11582 [merge]
committer: Benjamin Wolsey <address@hidden>
branch nick: trunk
timestamp: Wed 2009-10-21 16:05:36 +0200
message:
  Drop more static data, correct native array construction.
modified:
  libcore/as_function.cpp
  libcore/as_object.cpp
  libcore/as_object.h
  libcore/as_value.cpp
  libcore/asobj/Array_as.cpp
  libcore/asobj/Array_as.h
  libcore/asobj/Globals.cpp
  libcore/asobj/flash/text/TextSnapshot_as.cpp
  libcore/asobj/flash/text/TextSnapshot_as.h
  libcore/vm/ASHandlers.cpp
  libcore/vm/ActionExec.cpp
  libcore/vm/with_stack_entry.h
  testsuite/actionscript.all/array.as
  testsuite/swfdec/PASSING
=== modified file 'libcore/as_function.cpp'
--- a/libcore/as_function.cpp   2009-10-15 14:40:38 +0000
+++ b/libcore/as_function.cpp   2009-10-21 12:02:12 +0000
@@ -138,7 +138,7 @@
     // Create an empty object, with a ref to the constructor's prototype.
     // TODO: The prototype should not be converted to an object!
     as_object* newobj = new as_object();
-    if (has_proto) newobj->set_prototype(proto.to_object(*getGlobal(env)));
+    if (has_proto) newobj->set_prototype(proto);
     
     // Add a __constructor__ member to the new object, but only for SWF6 up
     // (to be checked). NOTE that we assume the builtin constructors

=== modified file 'libcore/as_object.cpp'
--- a/libcore/as_object.cpp     2009-10-16 14:17:00 +0000
+++ b/libcore/as_object.cpp     2009-10-21 12:48:16 +0000
@@ -273,6 +273,7 @@
 as_object::as_object(Global_as& gl)
        :
     _displayObject(false),
+    _array(false),
     _relay(0),
        _vm(getVM(gl)),
        _members(_vm)
@@ -282,6 +283,7 @@
 as_object::as_object()
        :
     _displayObject(false),
+    _array(false),
     _relay(0),
        _vm(VM::get()),
        _members(_vm)
@@ -291,6 +293,7 @@
 as_object::as_object(as_object* proto)
        :
     _displayObject(false),
+    _array(false),
     _relay(0),
        _vm(VM::get()),
        _members(_vm)
@@ -301,6 +304,7 @@
 as_object::as_object(boost::intrusive_ptr<as_object> proto)
        :
     _displayObject(false),
+    _array(false),
     _relay(0),
        _vm(VM::get()),
        _members(_vm)
@@ -686,6 +690,10 @@
         // We still need to set the member.
     }
 
+    // Handle the length property for arrays. NB: checkArrayLength() will
+    // call this function again if the key is a valid index.
+    if (array()) checkArrayLength(*this, key, val, nsname);
+
     const ObjectURI uri(key, nsname);
     
     PrototypeRecursor<Exists> pr(this, uri);

=== modified file 'libcore/as_object.h'
--- a/libcore/as_object.h       2009-10-16 14:17:00 +0000
+++ b/libcore/as_object.h       2009-10-21 13:16:04 +0000
@@ -961,7 +961,12 @@
     /// constructors and special creation functions like
     /// MovieClip.createTextField(). As Relay objects are not available to
     /// ActionScript, this should never appear in built-in functions.
+    //
+    /// This function also removes Array typing from an object when a Relay
+    /// is assigned. There are tests verifying this behaviour in
+    /// actionscript.all and the swfdec testsuite.
     void setRelay(Relay* p) {
+        if (p) _array = false;
         _relay.reset(p);
     }
 
@@ -979,6 +984,14 @@
         return _relay.get();
     }
 
+    bool array() const {
+        return _array;
+    }
+
+    void setArray() {
+        _array = true;
+    }
+
     /// Return true if this is a DisplayObject.
     bool displayObject() const {
         return _displayObject;
@@ -1076,6 +1089,15 @@
     /// object is a DisplayObject
     bool _displayObject;
 
+    /// An array is a special type of object.
+    //
+    /// Like DisplayObjects, Arrays handle property setting differently. We
+    /// use an extra flag to avoid checking Relay type on every property
+    /// set, but tests show that the Array constructor removes the Relay. It
+    /// would be possible to implement using a Relay, but as an Array stores
+    /// no extra native data, it's not clear what the point is.
+    bool _array;
+
     /// The polymorphic Relay object for native types.
     //
     /// This is owned by the as_object and destroyed when the as_object's

=== modified file 'libcore/as_value.cpp'
--- a/libcore/as_value.cpp      2009-10-16 14:17:00 +0000
+++ b/libcore/as_value.cpp      2009-10-21 11:35:19 +0000
@@ -2278,14 +2278,13 @@
                     return true;
                 }
 
-                Array_as* ary = dynamic_cast<Array_as*>(obj);
-                if (ary) {
+                if (obj->array()) {
                     string_table& st = vm.getStringTable();
-                    const size_t len = arrayLength(*ary);
+                    const size_t len = arrayLength(*obj);
                     if (allowStrict) {
                         IsStrictArray s(st);
                         // Check if any non-hidden properties are non-numeric.
-                        ary->visitProperties<IsEnumerable>(s);
+                        obj->visitProperties<IsEnumerable>(s);
                         if (s.strict()) {
 
 #ifdef GNASH_DEBUG_AMF_SERIALIZE
@@ -2298,7 +2297,7 @@
 
                             as_value elem;
                             for (size_t i = 0; i < len; ++i) {
-                                elem = ary->getMember(arrayKey(st, i));
+                                elem = obj->getMember(arrayKey(st, i));
                                 if (!elem.writeAMF0(buf, offsetTable, vm,
                                             allowStrict)) {
                                     log_error("Problems serializing strict 
array "

=== modified file 'libcore/asobj/Array_as.cpp'
--- a/libcore/asobj/Array_as.cpp        2009-10-16 14:17:00 +0000
+++ b/libcore/asobj/Array_as.cpp        2009-10-21 13:15:42 +0000
@@ -814,51 +814,23 @@
     return false;
 }
 
-Array_as::Array_as()
-    :
-    as_object(getArrayInterface())
-{
-    init_member(NSV::PROP_LENGTH, 0.0);
-}
-
-
-Array_as::~Array_as() 
-{
-}
-
-unsigned int
-Array_as::size() const
-{
-    return arrayLength(const_cast<Array_as&>(*this));
-}
-
-as_value
-Array_as::at(unsigned int index) const
-{
-    if (index > size() - 1) return as_value();
-    return 
const_cast<Array_as*>(this)->getMember(arrayKey(getStringTable(*this), index));
-}
-
-/* virtual public, overriding as_object::set_member */
-bool
-Array_as::set_member(string_table::key name, const as_value& val,
-        string_table::key nsname, bool ifFound)
-{
-
+void
+checkArrayLength(as_object& array, string_table::key name, const as_value& val,
+        string_table::key /*nsname*/)
+{
     if (name == NSV::PROP_LENGTH) {
-        resizeArray(*this, val.to_int());
+        resizeArray(array, val.to_int());
+        return;
     }
-    else {
-        int index = isIndex(getStringTable(*this).value(name));
-        // if we were sent a valid array index and not a normal member
-        if (index >= 0) {
-            if (static_cast<size_t>(index) >= arrayLength(*this)) {
-                setArrayLength(*this, index + 1);
-            }
+
+    const int index = isIndex(getStringTable(array).value(name));
+
+    // if we were sent a valid array index
+    if (index >= 0) {
+        if (static_cast<size_t>(index) >= arrayLength(array)) {
+            setArrayLength(array, index + 1);
         }
     }
-
-    return as_object::set_member(name,val, nsname, ifFound);
 }
 
 size_t
@@ -894,21 +866,20 @@
 void
 array_class_init(as_object& where, const ObjectURI& uri)
 {
-    static as_object* cl = 0;
-
-    if (cl == NULL) {
-
-        // This is going to be the global Array "class"/"function"
-        VM& vm = getVM(where);
-
-        as_object* proto = getArrayInterface();
-        cl = vm.getNative(252, 0);
-        cl->init_member(NSV::PROP_PROTOTYPE, proto);
-        proto->init_member(NSV::PROP_CONSTRUCTOR, cl);
-
-        // Attach static members
-        attachArrayStatics(*cl);
-    }
+
+    // This is going to be the global Array "class"/"function"
+    VM& vm = getVM(where);
+    Global_as* gl = getGlobal(where);
+
+    as_object* proto = gl->createObject();
+
+    as_object* cl = vm.getNative(252, 0);
+
+    cl->init_member(NSV::PROP_PROTOTYPE, proto);
+    proto->init_member(NSV::PROP_CONSTRUCTOR, cl);
+
+    attachArrayInterface(*proto);
+    attachArrayStatics(*cl);
 
     const int flags = PropFlags::dontEnum; 
     where.init_member(getName(uri), cl, flags, getNamespace(uri));
@@ -953,20 +924,6 @@
     proto.init_member("sortOn", vm.getNative(252, 12));
 }
 
-as_object*
-getArrayInterface()
-{
-    static boost::intrusive_ptr<as_object> proto = NULL;
-    if ( proto == NULL )
-    {
-        proto = new as_object(getObjectInterface());
-        getVM(*proto).addStatic(proto.get());
-
-        attachArrayInterface(*proto);
-    }
-    return proto.get();
-}
-
 as_value
 array_splice(const fn_call& fn)
 {
@@ -1262,8 +1219,6 @@
         array->set_member(getKey(fn, size + i), fn.arg(i));
     }
  
-    log_debug("size: %s, shift :%s", size, shift);
-
     return as_value(size + shift);
 }
 
@@ -1461,15 +1416,17 @@
 as_value
 array_new(const fn_call& fn)
 {
-    IF_VERBOSE_ACTION (
-        log_action(_("array_new called, nargs = %d"), fn.nargs);
-    );
-
-    // TODO: use the this_ptr
-    as_object* ao = new Array_as;
+
+    as_object* ao = fn.isInstantiation() ? ensureType<as_object>(fn.this_ptr) :
+                                           getGlobal(fn)->createArray();
+
+    ao->setRelay(0);
+    ao->setArray();
+
+    ao->init_member(NSV::PROP_LENGTH, 0.0);
 
     if (fn.nargs == 0) {
-        return ao;
+        return as_value(ao);
     }
 
     if (fn.nargs == 1 && fn.arg(0).is_number()) {
@@ -1478,13 +1435,14 @@
         else {
             ao->set_member(NSV::PROP_LENGTH, newSize);
         }
-        return ao;
+        return as_value(ao);
     }
 
     // Use the arguments as initializers.
     for (size_t i = 0; i < fn.nargs; i++) {
         ao->callMethod(NSV::PROP_PUSH, fn.arg(i));
     }
+    
 
     return as_value(ao);
 }
@@ -1576,15 +1534,13 @@
 }
 
 void
-setArrayLength(as_object& o, const int size)
+setArrayLength(as_object& array, const int size)
 {
-    Array_as* array = dynamic_cast<Array_as*>(&o);
-    if (!array) return;
-
-    resizeArray(*array, size);
-
-    // Do not call Array_as::set_member because that calls this!
-    array->as_object::set_member(NSV::PROP_LENGTH, size);
+    if (!array.array()) return;
+
+    resizeArray(array, size);
+
+    array.set_member(NSV::PROP_LENGTH, size);
 }
 
 int

=== modified file 'libcore/asobj/Array_as.h'
--- a/libcore/asobj/Array_as.h  2009-10-16 14:17:00 +0000
+++ b/libcore/asobj/Array_as.h  2009-10-21 11:35:19 +0000
@@ -18,19 +18,11 @@
 #ifndef GNASH_ARRAY_H
 #define GNASH_ARRAY_H
 
-#include "as_object.h" // for inheritance
-#include "smart_ptr.h" // GNASH_USE_GC
-#include "namedStrings.h"
+#include "as_object.h" 
 #include "Global_as.h"
 
-#include <deque>
-#include <vector>
-#include <memory> // for auto_ptr
-#include <string>
-
 // Forward declarations
 namespace gnash {
-       class fn_call;
        class as_value;
 }
 
@@ -55,7 +47,6 @@
 /// @return         The string table key to look up.
 string_table::key arrayKey(string_table& st, size_t i);
 
-
 /// A visitor to check whether an array is strict or not.
 //
 /// Strict arrays have no non-hidden non-numeric properties. Only real arrays
@@ -74,25 +65,14 @@
     string_table& _st;
 };
 
-/// The Array ActionScript object
-class Array_as : public as_object
-{
-
-public:
-
-       Array_as();
-
-       ~Array_as();
-
-       as_value at(unsigned int index) const;
-
-       unsigned int size() const;
-
-       /// Overridden to provide array[#]=x semantic
-       virtual bool set_member(string_table::key name,
-               const as_value& val, string_table::key nsname=0, bool 
ifFound=false);
-
-};
+
+/// Genuine arrays handle the length property in a special way.
+//
+/// The only distinction between Arrays and Objects is that the length
+/// property is changed when an element is added, and that changing the length
+/// can result in deleted properties.
+void checkArrayLength(as_object& array, string_table::key name,
+        const as_value& val, string_table::key nsname = 0);
 
 template<typename T>
 void foreachArray(as_object& array, T& pred)

=== modified file 'libcore/asobj/Globals.cpp'
--- a/libcore/asobj/Globals.cpp 2009-10-15 14:40:38 +0000
+++ b/libcore/asobj/Globals.cpp 2009-10-21 13:16:25 +0000
@@ -28,12 +28,12 @@
 #include "as_value.h"
 #include "as_function.h" // for function_class_init
 #include "NativeFunction.h" 
-#include "Array_as.h"
 #include "AsBroadcaster.h"
 #include "Boolean_as.h"
 #include "Color_as.h"
 #include "CustomActions.h"
 #include "Date_as.h" 
+#include "Array_as.h" 
 #include "Error_as.h"
 #include "String_as.h"
 #include "Selection_as.h"
@@ -249,15 +249,28 @@
 
 }
 
-/// This serves the purpose of hiding the Array_as type from the
-/// implementation, which at least enforces good behaviour from users.
+/// Construct an Array.
 //
-/// TODO: it could well already call the Array constructor.
+/// This uses the _global Array class to initialize the "constructor" and
+/// "__proto__" properties. If Array.prototype is undefined, those properties
+/// are not added.
 as_object*
 AVM1Global::createArray()
 {
-    as_object* array = new Array_as;
-    array->init_member(NSV::PROP_CONSTRUCTOR, getMember(NSV::CLASS_ARRAY));
+    as_object* array = new as_object(*this);
+
+    as_value ctor = getMember(NSV::CLASS_ARRAY);
+    as_object* obj = ctor.to_object(*this);
+    if (obj) {
+        as_value proto;
+        if (obj->get_member(NSV::PROP_PROTOTYPE, &proto)) {
+            array->init_member(NSV::PROP_CONSTRUCTOR, ctor);
+            array->set_prototype(obj->getMember(NSV::PROP_PROTOTYPE));
+        }
+    }
+
+    array->init_member(NSV::PROP_LENGTH, 0.0);
+    array->setArray();
     return array;
 }
 
@@ -322,7 +335,8 @@
 as_object*
 AVM2Global::createArray()
 {
-    as_object* array = new Array_as;
+    as_object* array = new as_object(*this);
+    array->setArray();
     array->init_member(NSV::PROP_CONSTRUCTOR, getMember(NSV::CLASS_ARRAY));
     return array;
 }
@@ -510,7 +524,7 @@
         (N(Keyboard_as::init, NSV::CLASS_KEY, NSV::CLASS_OBJECT, NS_GLOBAL, 5))
         (N(AsBroadcaster::init, NSV::CLASS_AS_BROADCASTER, NSV::CLASS_OBJECT,
            NS_GLOBAL, 5))
-        (N(TextSnapshot_as::init, NSV::CLASS_TEXT_SNAPSHOT, NSV::CLASS_OBJECT,
+        (N(textsnapshot_class_init, NSV::CLASS_TEXT_SNAPSHOT, 
NSV::CLASS_OBJECT,
            NS_GLOBAL, 5))
         (N(video_class_init, NSV::CLASS_VIDEO, NSV::CLASS_OBJECT, NS_GLOBAL, 
6))
         (N(camera_class_init, NSV::CLASS_CAMERA, NSV::CLASS_OBJECT,
@@ -596,7 +610,7 @@
            NSV::CLASS_INTERACTIVEOBJECT, NSV::NS_FLASH_TEXT, 3))
         (N(textformat_class_init, NSV::CLASS_TEXT_FORMAT, NSV::CLASS_OBJECT,
            NSV::NS_FLASH_TEXT, 5))
-        (N(TextSnapshot_as::init, NSV::CLASS_TEXT_SNAPSHOT, NSV::CLASS_OBJECT,
+        (N(textsnapshot_class_init, NSV::CLASS_TEXT_SNAPSHOT, 
NSV::CLASS_OBJECT,
            NSV::NS_FLASH_TEXT, 5))
         (N(textfieldautosize_class_init, NSV::CLASS_TEXTFIELDAUTOSIZE,
            NSV::CLASS_OBJECT, NSV::NS_FLASH_TEXT, 5))

=== modified file 'libcore/asobj/flash/text/TextSnapshot_as.cpp'
--- a/libcore/asobj/flash/text/TextSnapshot_as.cpp      2009-10-14 14:50:52 
+0000
+++ b/libcore/asobj/flash/text/TextSnapshot_as.cpp      2009-10-21 13:16:25 
+0000
@@ -46,8 +46,81 @@
 
 namespace gnash {
 
+class TextSnapshot_as : public Relay
+{
+
+public:
+
+    typedef std::vector<const SWF::TextRecord*> Records;
+
+    /// Should remain in the order of insertion
+    /// We should only ever iterate from begin to end, so there's no
+    /// performance issue.
+    typedef std::vector<std::pair<StaticText*, Records> > TextFields;
+
+    /// Construct a TextSnapshot_as from a MovieClip.
+    //
+    /// @param mc       The MovieClip to search for static text. If 0, the
+    ///                 TextSnapshot is invalid, which should be reflected in
+    ///                 AS return values.
+    TextSnapshot_as(const MovieClip* mc);
+
+    std::string getText(boost::int32_t start, boost::int32_t end,
+            bool nl) const;
+
+    boost::int32_t findText(boost::int32_t start, const std::string& text,
+            bool ignoreCase) const;
+
+    bool valid() const { return _valid; }
+
+    size_t getCount() const { return _count; }
+
+    void setSelected(size_t start, size_t end, bool selected);
+    
+    bool getSelected(size_t start, size_t end) const;
+
+    std::string getSelectedText(bool newlines) const;
+
+    void getTextRunInfo(size_t start, size_t end, as_object& ri) const;
+
+protected:
+
+    virtual void setReachable() const;
+
+private:
+
+    /// Generate a string from the TextRecords in this TextSnapshot.
+    //
+    /// @param to           The string to write to
+    /// @param newline      If true, newlines are written after every
+    ///                     StaticText in this TextSnapshot
+    /// @param selectedOnly Only write DisplayObject that are selected to.
+    /// @param start        The start index
+    /// @param len          The number of StaticText DisplayObjects to 
traverse.
+    ///                     This includes non-selected DisplayObjects.
+    void makeString(std::string& to, bool newline = false,
+            bool selectedOnly = false,
+            std::string::size_type start = 0,
+            std::string::size_type len = std::string::npos) const;
+
+    TextFields _textFields;
+
+    /// Whether the object is valid, i.e. it was constructed with a MovieClip.
+    //
+    /// This should be deducible from another member, but since there seems
+    /// to be no point in storing the MovieClip this bool will do instead.
+    const bool _valid;
+
+    /// The number of DisplayObjects
+    //
+    /// There is no need to store this, but it is quicker than counting
+    /// afresh every time.
+    const size_t _count;
+
+};
 // Forward declarations
 namespace {
+
     void attachTextSnapshotStaticInterface(as_object& o);
     
     as_value textsnapshot_findText(const fn_call& fn);
@@ -62,7 +135,6 @@
     as_value textsnapshot_ctor(const fn_call& fn);
 
     void attachTextSnapshotInterface(as_object& o);
-    as_object* getTextSnapshotInterface();
 
     size_t getTextFields(const MovieClip* mc,
             TextSnapshot_as::TextFields& fields);
@@ -71,19 +143,19 @@
 
 }
 
+
 // extern (used by Global.cpp)
 void
-TextSnapshot_as::init(as_object& where, const ObjectURI& uri)
+textsnapshot_class_init(as_object& where, const ObjectURI& uri)
 {
 
-    static boost::intrusive_ptr<as_object> cl;
-    if (!cl) {
-        Global_as* gl = getGlobal(where);
-        as_object* proto = getTextSnapshotInterface();
-        cl = gl->createClass(&textsnapshot_ctor, proto);
-        attachTextSnapshotStaticInterface(*cl);
-   }
-   where.init_member(getName(uri), cl.get(), as_object::DefaultFlags,
+    Global_as* gl = getGlobal(where);
+    as_object* proto = gl->createObject();
+    as_object* cl = gl->createClass(&textsnapshot_ctor, proto);
+    attachTextSnapshotStaticInterface(*cl);
+    attachTextSnapshotInterface(*proto);
+
+   where.init_member(getName(uri), cl, as_object::DefaultFlags,
                getNamespace(uri));
 }
 
@@ -91,7 +163,6 @@
 /// that it is constructed before it is used.
 TextSnapshot_as::TextSnapshot_as(const MovieClip* mc)
     :
-    as_object(getTextSnapshotInterface()),
     _textFields(),
     _valid(mc),
     _count(getTextFields(mc, _textFields))
@@ -163,10 +234,9 @@
 }
 
 void
-TextSnapshot_as::markReachableResources() const
+TextSnapshot_as::setReachable() const
 {
     std::for_each(_textFields.begin(), _textFields.end(), setTextReachable);
-    markAsObjectReachable();
 }
 
 void
@@ -427,23 +497,11 @@
        o.init_member("getTextRunInfo", vm.getNative(1067, 9), flags);
 }
 
-as_object*
-getTextSnapshotInterface()
-{
-       static boost::intrusive_ptr<as_object> o;
-       if ( ! o )
-       {
-               o = new as_object(getObjectInterface());
-               attachTextSnapshotInterface(*o);
-       }
-       return o.get();
-}
 
 as_value
 textsnapshot_getTextRunInfo(const fn_call& fn)
 {
-    boost::intrusive_ptr<TextSnapshot_as> ts =
-        ensureType<TextSnapshot_as>(fn.this_ptr);
+    TextSnapshot_as* ts = ensureNativeType<TextSnapshot_as>(fn.this_ptr);
     
     if (!ts->valid()) return as_value();
 
@@ -465,8 +523,7 @@
 as_value
 textsnapshot_findText(const fn_call& fn)
 {
-    boost::intrusive_ptr<TextSnapshot_as> ts =
-        ensureType<TextSnapshot_as>(fn.this_ptr);
+    TextSnapshot_as* ts = ensureNativeType<TextSnapshot_as>(fn.this_ptr);
     
     if (!ts->valid()) return as_value();
 
@@ -490,8 +547,7 @@
 as_value
 textsnapshot_getCount(const fn_call& fn)
 {
-    boost::intrusive_ptr<TextSnapshot_as> ts =
-        ensureType<TextSnapshot_as>(fn.this_ptr);
+    TextSnapshot_as* ts = ensureNativeType<TextSnapshot_as>(fn.this_ptr);
     
     if (!ts->valid()) return as_value();
 
@@ -509,8 +565,7 @@
 as_value
 textsnapshot_getSelected(const fn_call& fn)
 {
-    boost::intrusive_ptr<TextSnapshot_as> ts =
-        ensureType<TextSnapshot_as>(fn.this_ptr);
+    TextSnapshot_as* ts = ensureNativeType<TextSnapshot_as>(fn.this_ptr);
 
     if (!ts->valid()) return as_value();
 
@@ -528,8 +583,7 @@
 as_value
 textsnapshot_getSelectedText(const fn_call& fn)
 {
-    boost::intrusive_ptr<TextSnapshot_as> ts =
-        ensureType<TextSnapshot_as>(fn.this_ptr);
+    TextSnapshot_as* ts = ensureNativeType<TextSnapshot_as>(fn.this_ptr);
 
     if (!ts->valid()) return as_value();
 
@@ -546,8 +600,7 @@
 as_value
 textsnapshot_getText(const fn_call& fn)
 {
-    boost::intrusive_ptr<TextSnapshot_as> ts =
-        ensureType<TextSnapshot_as>(fn.this_ptr);
+    TextSnapshot_as* ts = ensureNativeType<TextSnapshot_as>(fn.this_ptr);
 
     if (!ts->valid()) return as_value();
     
@@ -573,8 +626,7 @@
 as_value
 textsnapshot_hitTestTextNearPos(const fn_call& fn)
 {
-    boost::intrusive_ptr<TextSnapshot_as> ts =
-        ensureType<TextSnapshot_as>(fn.this_ptr);
+    TextSnapshot_as* ts = ensureNativeType<TextSnapshot_as>(fn.this_ptr);
 
     if (!ts->valid()) return as_value();
 
@@ -586,8 +638,9 @@
 as_value
 textsnapshot_setSelectColor(const fn_call& fn)
 {
-    boost::intrusive_ptr<TextSnapshot_as> ts =
-        ensureType<TextSnapshot_as>(fn.this_ptr);
+
+    TextSnapshot_as* ts = ensureNativeType<TextSnapshot_as>(fn.this_ptr);
+    UNUSED(ts);
 
     log_unimpl (__FUNCTION__);
     return as_value();
@@ -598,8 +651,7 @@
 as_value
 textsnapshot_setSelected(const fn_call& fn)
 {
-    boost::intrusive_ptr<TextSnapshot_as> ts =
-        ensureType<TextSnapshot_as>(fn.this_ptr);
+    TextSnapshot_as* ts = ensureNativeType<TextSnapshot_as>(fn.this_ptr);
 
     if (fn.nargs < 2 || fn.nargs > 3) {
         return as_value();
@@ -618,8 +670,12 @@
 as_value
 textsnapshot_ctor(const fn_call& fn)
 {
+    as_object* ptr = ensureType<as_object>(fn.this_ptr);
+
     MovieClip* mc = (fn.nargs == 1) ? fn.arg(0).to_sprite() : 0;
-    return as_value(new TextSnapshot_as(mc));
+
+    ptr->setRelay(new TextSnapshot_as(mc));
+    return as_value();
 }
 
 size_t

=== modified file 'libcore/asobj/flash/text/TextSnapshot_as.h'
--- a/libcore/asobj/flash/text/TextSnapshot_as.h        2009-10-14 14:50:52 
+0000
+++ b/libcore/asobj/flash/text/TextSnapshot_as.h        2009-10-21 13:16:25 
+0000
@@ -29,89 +29,10 @@
 
 namespace gnash {
 
-       class StaticText;
-    namespace SWF {
-        class TextRecord;
-    }
-
-// Forward declarations
-class TextSnapshot_as: public as_object
-{
-
-public:
-
-    typedef std::vector<const SWF::TextRecord*> Records;
-
-    /// Should remain in the order of insertion
-    /// We should only ever iterate from begin to end, so there's no
-    /// performance issue.
-    typedef std::vector<std::pair<StaticText*, Records> > TextFields;
-
-    /// Construct a TextSnapshot_as from a MovieClip.
-    //
-    /// @param mc       The MovieClip to search for static text. If 0, the
-    ///                 TextSnapshot is invalid, which should be reflected in
-    ///                 AS return values.
-    TextSnapshot_as(const MovieClip* mc);
-
-    static void init(as_object& where, const ObjectURI& uri);
-
-    std::string getText(boost::int32_t start, boost::int32_t end,
-            bool nl) const;
-
-    boost::int32_t findText(boost::int32_t start, const std::string& text,
-            bool ignoreCase) const;
-
-    bool valid() const { return _valid; }
-
-    size_t getCount() const { return _count; }
-
-    void setSelected(size_t start, size_t end, bool selected);
-    
-    bool getSelected(size_t start, size_t end) const;
-
-    std::string getSelectedText(bool newlines) const;
-
-    void getTextRunInfo(size_t start, size_t end, as_object& ri) const;
-
-protected:
-
-    void markReachableResources() const;
-
-private:
-
-    /// Generate a string from the TextRecords in this TextSnapshot.
-    //
-    /// @param to           The string to write to
-    /// @param newline      If true, newlines are written after every
-    ///                     StaticText in this TextSnapshot
-    /// @param selectedOnly Only write DisplayObject that are selected to.
-    /// @param start        The start index
-    /// @param len          The number of StaticText DisplayObjects to 
traverse.
-    ///                     This includes non-selected DisplayObjects.
-    void makeString(std::string& to, bool newline = false,
-            bool selectedOnly = false,
-            std::string::size_type start = 0,
-            std::string::size_type len = std::string::npos) const;
-
-    TextFields _textFields;
-
-    /// Whether the object is valid, i.e. it was constructed with a MovieClip.
-    //
-    /// This should be deducible from another member, but since there seems
-    /// to be no point in storing the MovieClip this bool will do instead.
-    const bool _valid;
-
-    /// The number of DisplayObjects
-    //
-    /// There is no need to store this, but it is quicker than counting
-    /// afresh every time.
-    const size_t _count;
-
-};
-
 void registerTextSnapshotNative(as_object& global);
 
+void textsnapshot_class_init(as_object& where, const ObjectURI& uri);
+
 } // gnash namespace
 
 // GNASH_ASOBJ3_TEXTSNAPSHOT_H

=== modified file 'libcore/vm/ASHandlers.cpp'
--- a/libcore/vm/ASHandlers.cpp 2009-10-16 07:09:56 +0000
+++ b/libcore/vm/ASHandlers.cpp 2009-10-21 12:23:49 +0000
@@ -2629,18 +2629,16 @@
 
     as_value function = thread.getVariable(funcname, &this_ptr);
 
-    if ( ! function.is_object() )
-    {
+    if (!function.is_object()) {
         IF_VERBOSE_ASCODING_ERRORS (
         log_aserror(_("ActionCallFunction: %s is not an object"), funcname);
         )
     }
-    else if ( ! function.is_function() )
-    {
+    else if (!function.is_function()) {
         log_error(_("ActionCallFunction: function name %s evaluated to "
                 "non-function value %s"), funcname, function);
         // Calling super ? 
-        boost::intrusive_ptr<as_object> obj = 
convertToObject(*getGlobal(thread.env), function);
+        as_object* obj = convertToObject(*getGlobal(thread.env), function);
         this_ptr = thread.getThisPointer();
         if (!obj->get_member(NSV::PROP_CONSTRUCTOR, &function) )
         {
@@ -2809,10 +2807,7 @@
     
     Global_as* gl = getGlobal(env);
 
-    as_value result = gl->createArray();
-
-    as_object* ao = convertToObject(*getGlobal(thread.env), result);
-    assert(ao);
+    as_object* ao = gl->createArray();
 
     // Fill the elements with the initial values from the stack.
     for (int i = 0; i < array_size; i++) {
@@ -2821,7 +2816,7 @@
                 env.pop());
     }
 
-    env.push(result);
+    env.push(ao);
 
 }
 
@@ -3735,7 +3730,6 @@
 void
 SWFHandlers::ActionWith(ActionExec& thread)
 {
-    
 
     as_environment& env = thread.env;
     const action_buffer& code = thread.code;
@@ -3745,9 +3739,8 @@
     assert(thread.atActionTag(SWF::ACTION_WITH));
 #endif
 
-    as_value with_obj_val = convertToObject(*getGlobal(thread.env), env.pop());
-    boost::intrusive_ptr<as_object> with_obj =
-        convertToObject(*getGlobal(thread.env), with_obj_val);
+    const as_value& val = env.pop();
+    as_object* with_obj = val.to_object(*getGlobal(thread.env));
 
     ++pc; // skip tag code
 
@@ -3774,21 +3767,20 @@
     // now we should be on the first action of the 'with' body
     assert(thread.getNextPC() == pc);
 
-    if ( ! with_obj )
-    {
+    if (!with_obj) {
         IF_VERBOSE_ASCODING_ERRORS(
         log_aserror(_("with(%s) : first argument doesn't cast to an object!"),
-            with_obj_val);
+            val);
         );
         // skip the full block
         thread.adjustNextPC(block_length);
         return;
     }
 
-    // where does the 'with' block ends ?
-    unsigned block_end = thread.getNextPC() + block_length;
+    // where does the 'with' block end?
+    const size_t block_end = thread.getNextPC() + block_length;
 
-    if ( ! thread.pushWithEntry(with_stack_entry(with_obj, block_end)) )
+    if (!thread.pushWithEntry(with_stack_entry(with_obj, block_end)))
     {
         // skip the full block
         thread.adjustNextPC(block_length);

=== modified file 'libcore/vm/ActionExec.cpp'
--- a/libcore/vm/ActionExec.cpp 2009-10-09 06:16:57 +0000
+++ b/libcore/vm/ActionExec.cpp 2009-10-21 08:51:44 +0000
@@ -757,12 +757,10 @@
 as_object*
 ActionExec::getTarget()
 {
-    if ( ! _withStack.empty() )
-    {
+    if (!_withStack.empty()) {
         return _withStack.back().object();
     }
-    else
-    {
+    else {
         return env.get_target();
     }
 }

=== modified file 'libcore/vm/with_stack_entry.h'
--- a/libcore/vm/with_stack_entry.h     2009-02-25 22:33:03 +0000
+++ b/libcore/vm/with_stack_entry.h     2009-10-21 08:51:44 +0000
@@ -39,13 +39,6 @@
        {
        }
 
-       with_stack_entry(boost::intrusive_ptr<as_object> obj, size_t end)
-               :
-               _object(obj),
-               _block_end_pc(end)
-       {
-       }
-
        size_t end_pc()
        {
                return _block_end_pc;
@@ -53,22 +46,20 @@
 
        const as_object* object() const
        {
-               return _object.get();
+               return _object;
        }
 
        as_object* object() 
        {
-               return _object.get();
+               return _object;
        }
 
 private:
 
-       boost::intrusive_ptr<as_object> _object;
+       as_object* _object;
        
        size_t _block_end_pc;
 
-       
-
 };
 
 }      // end namespace gnash

=== modified file 'testsuite/actionscript.all/array.as'
--- a/testsuite/actionscript.all/array.as       2009-10-16 14:18:01 +0000
+++ b/testsuite/actionscript.all/array.as       2009-10-21 12:43:52 +0000
@@ -1605,9 +1605,84 @@
 
 check_equals(o.length, 6);
 o.sort();
-xcheck_equals(traceProps(o), "5,4,2,1,0,sort,length,7,6,3,");
+#if OUTPUT_VERSION > 6
+ xcheck_equals(traceProps(o), "5,4,2,1,0,sort,length,7,6,3,");
+#else
+ xcheck_equals(traceProps(o), "5,4,3,2,1,sort,length,7,6,");
+#endif
 o.sort();
-xcheck_equals(traceProps(o), "5,4,2,1,0,sort,length,7,6,3,");
+#if OUTPUT_VERSION > 6
+ xcheck_equals(traceProps(o), "5,4,2,1,0,sort,length,7,6,3,");
+#else
+ xcheck_equals(traceProps(o), "5,4,3,2,1,sort,length,7,6,");
+#endif
+
+#if OUTPUT_VERSION > 5
+
+/// This checks that Array and relay objects are not compatible (unlike
+/// DisplayObjects).
+CA = function () {
+  backup = this;
+  this.__proto__.__constructor__ = Date;
+  super ();
+  check_equals(this.length, undefined);
+  this.__proto__.__constructor__ = Array;
+  super ();
+  check_equals(backup, this);
+  check_equals(this.length, 0);
+  this[2] = 3;
+  check_equals(this.length, 3);
+  this.__proto__.__constructor__ = Date;
+  super ();
+  check_equals(this.length, 3);
+  this[6] = 3;
+  check_equals(this.length, 3);
+};
+
+o = new CA();
+
+
+/// Test what happens with []
+backup = _global.Array;
+delete _global.Array;
+
+_global.Array = 8;
+ar = [];
+check_equals(typeof(ar.constructor), "undefined");
+
+h = function() {};
+h.prototype = 8;
+
+_global.Array = h;
+
+ar = [];
+check_equals(typeof(ar.constructor), "function");
+check_equals(typeof(ar.__proto__), "number");
+check_equals(ar.__proto__, 8);
+
+/// If we use the constructor, it's set to anything you like.
+ar = new Array();
+check_equals(typeof(ar.__proto__), "number");
+
+/// Properties are only set if there is a _global.Array.prototype
+
+_global.Array = {};
+
+ar = [];
+check_equals(typeof(ar.constructor), "undefined");
+check_equals(typeof(ar.__proto__), "undefined");
+check_equals(ar.__proto__, undefined);
+
+_global.Array.prototype = "string";
+
+ar = [];
+check_equals(typeof(ar.constructor), "object");
+check_equals(typeof(ar.__proto__), "string");
+check_equals(ar.__proto__, "string");
+
+#endif
+
+
 
 // TODO: test ASnative-returned functions:
 //
@@ -1630,8 +1705,8 @@
  check_totals(538);
 #else
 # if OUTPUT_VERSION < 7
-  check_totals(599);
+  check_totals(616);
 # else
-  check_totals(609);
+  check_totals(626);
 # endif
 #endif

=== modified file 'testsuite/swfdec/PASSING'
--- a/testsuite/swfdec/PASSING  2009-10-15 12:29:22 +0000
+++ b/testsuite/swfdec/PASSING  2009-10-21 13:17:14 +0000
@@ -55,6 +55,10 @@
 array-new-7.swf:77c4510eed0fd37d8654f761800edcce
 array-new-8.swf:8b26fcd892b0cd7a1cd2832d3844d00d
 array-new-override-5.swf:5016b51c60e30ee262b3cb022ba4c58f
+array-no-object-5.swf:5ed032608114aab258046f7b03a600a1
+array-no-object-6.swf:024a80f84a2f9ec3c465e38d1e5c4e69
+array-no-object-7.swf:57e4d1f02420a4cbb67ce4376ff2c431
+array-no-object-8.swf:d79cc40101cf7aa9c549c56625520d00
 array-properties-5.swf:e4b9235bdad5543e29893d8166c16a9a
 array-properties-6.swf:822c1697e2f36bdfc87574a100583c78
 array-properties-7.swf:bd3778e753752345ae8c2d72b3ccaf3a


reply via email to

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