[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gnash-commit] /srv/bzr/gnash/trunk r11567: Make more as_object function
From: |
Benjamin Wolsey |
Subject: |
[Gnash-commit] /srv/bzr/gnash/trunk r11567: Make more as_object functions non-virtual. Generally clean up and reduce the |
Date: |
Fri, 16 Oct 2009 16:46:54 +0200 |
User-agent: |
Bazaar (1.16.1) |
------------------------------------------------------------
revno: 11567 [merge]
committer: Benjamin Wolsey <address@hidden>
branch nick: trunk
timestamp: Fri 2009-10-16 16:46:54 +0200
message:
Make more as_object functions non-virtual. Generally clean up and reduce the
as_object class interface, which is still much too large.
Make arrays almost entirely independent of type. Properties are now genuine
properties.
modified:
libcore/MovieClip.cpp
libcore/MovieClip.h
libcore/PropertyList.h
libcore/as_object.cpp
libcore/as_object.h
libcore/as_value.cpp
libcore/asobj/Array_as.cpp
libcore/asobj/Array_as.h
libcore/asobj/Color_as.cpp
libcore/asobj/flash/display/MovieClip_as.cpp
libcore/asobj/flash/net/SharedObject_as.cpp
libcore/vm/ASHandlers.cpp
testsuite/actionscript.all/array.as
=== modified file 'libcore/MovieClip.cpp'
--- a/libcore/MovieClip.cpp 2009-10-14 08:47:08 +0000
+++ b/libcore/MovieClip.cpp 2009-10-16 06:56:48 +0000
@@ -812,15 +812,15 @@
}
if ( tmp.is_sprite() )
{
- return tmp.to_sprite(true);
+ return tmp.toDisplayObject(true);
}
return tmp.to_object(*getGlobal(*this));
}
bool
-MovieClip::set_member(string_table::key name,
- const as_value& val, string_table::key nsname, bool ifFound)
+MovieClip::setTextFieldVariables(string_table::key name, const as_value& val,
+ string_table::key /*nsname*/)
{
bool found = false;
@@ -853,9 +853,6 @@
}
#endif
- // If that didn't work call the default set_member
- if (as_object::set_member(name, val, nsname, ifFound)) found=true;
-
return found;
}
@@ -2181,7 +2178,7 @@
std::string postdata;
// Encode our vars for sending.
- if (sendVarsMethod != METHOD_NONE) getURLEncodedVars(postdata);
+ if (sendVarsMethod != METHOD_NONE) getURLEncodedVars(*this, postdata);
try
{
=== modified file 'libcore/MovieClip.h'
--- a/libcore/MovieClip.h 2009-10-14 06:55:13 +0000
+++ b/libcore/MovieClip.h 2009-10-16 05:29:23 +0000
@@ -526,6 +526,12 @@
/// simplify things if this function could be dropped.
bool getTextFieldVariables(string_table::key name, as_value& val);
+ // Set TextField variables
+ //
+ /// TODO: this is also unlikely to be the best way to do it.
+ bool setTextFieldVariables(string_table::key name, const as_value& val,
+ string_table::key nsname = 0);
+
/// Search for a named object on the DisplayList
//
/// These are properties, but not attached as genuine members to the
@@ -537,10 +543,6 @@
/// @return The object if found, otherwise 0.
DisplayObject* getDisplayListObject(string_table::key name);
- // See dox in as_object.h
- virtual bool set_member(string_table::key name, const as_value& val,
- string_table::key nsname = 0, bool ifFound=false);
-
/// Overridden to look in DisplayList for a match
as_object* get_path_element(string_table::key key);
=== modified file 'libcore/PropertyList.h'
--- a/libcore/PropertyList.h 2009-10-14 08:47:08 +0000
+++ b/libcore/PropertyList.h 2009-10-16 14:17:00 +0000
@@ -111,20 +111,25 @@
/// The method will invoke the given visitor method
/// passing it two arguments: name of the property and
/// value of it.
- ///
- /// @param visitor
- /// The visitor function. Must take a string_table::key
- /// reference as first argument and a const as_value reference
- /// as second argument. Scan by enumeration order.
+ //
+ /// @tparam V The type of the visitor.
+ /// @tparam U An object that may check property values. The object's
+ /// operator() should return false if the property is not
+ /// acceptable.
+ //
+ /// @param visitor The visitor function. It must have the function:
+ /// bool accept(string_table::key, const as_value&);
+ /// Scan is by enumeration order and stops if
accept()
+ /// returns false.
///
/// @param this_ptr
/// The object reference used to extract values from properties.
///
- template <class V>
- void visitValues(V& visitor, const as_object& this_ptr) const
+ template <class U, class V>
+ void visitValues(V& visitor, const as_object& this_ptr, U cmp = U())
const
{
typedef container::nth_index<1>::type ContainerByOrder;
-
+
// The template keyword is not required by the Standard here, but the
// OpenBSD compiler needs it. Use of the template keyword where it is
// not necessary is not an error.
@@ -132,56 +137,11 @@
it = _props.template get<1>().rbegin(),
ie = _props.template get<1>().rend(); it != ie; ++it)
{
- as_value val = it->getValue(this_ptr);
- visitor.accept(it->mName, val);
- }
- }
-
- /// Visit non hidden properties
- //
- /// The method will invoke the given visitor method
- /// passing it two arguments: name of the property and
- /// value of it. Scan by enumeration order.
- ///
- /// @param visitor
- /// The visitor function. Must take a string_table::key
- /// reference as first argument and a const as_value reference
- /// as second argument.
- ///
- /// @param this_ptr
- /// The object reference used to extract values from properties.
- ///
- template <class V>
- void visitNonHiddenValues(V& visitor, const as_object& this_ptr) const
- {
- typedef container::nth_index<1>::type ContainerByOrder;
-
- // The template keyword is not required by the Standard here, but the
- // OpenBSD compiler needs it. Use of the template keyword where it is
- // not necessary is not an error.
- for (ContainerByOrder::const_reverse_iterator it =
- _props.template get<1>().rbegin(),
- ie = _props.template get<1>().rend(); it != ie; ++it)
- {
- if (it->getFlags().get_dont_enum()) continue;
- as_value val = it->getValue(this_ptr);
- visitor.accept(it->mName, val);
- }
- }
-
- /// Is any non-hidden property in this list ?
- bool hasNonHiddenProperties() const
- {
- typedef container::nth_index<1>::type ContainerByOrder;
- for (ContainerByOrder::const_reverse_iterator it =
- _props.get<1>().rbegin(), ie=_props.get<1>().rend();
- it != ie; ++it)
- {
- if (! it->getFlags().get_dont_enum()) return true;
- }
- return false;
- }
-
+ if (!cmp(*it)) continue;
+ as_value val = it->getValue(this_ptr);
+ if (!visitor.accept(it->mName, val)) return;
+ }
+ }
/// Get the as_value value of a named property
//
=== modified file 'libcore/as_object.cpp'
--- a/libcore/as_object.cpp 2009-10-15 05:59:43 +0000
+++ b/libcore/as_object.cpp 2009-10-16 14:17:00 +0000
@@ -50,43 +50,18 @@
namespace gnash {
-
-namespace {
-
- class IsVisible
- {
- public:
- IsVisible(as_object* obj) : _version(getSWFVersion(*obj)) {}
- bool operator()(const Property* const prop) const {
- return prop->visible(_version);
- }
- private:
- const int _version;
-
- };
-
- class Exists
- {
- public:
- Exists(as_object*) {}
- bool operator()(const Property* const) const {
- return true;
- }
- };
-}
-
template<typename T>
class
as_object::PrototypeRecursor
{
public:
- PrototypeRecursor(as_object* top, const ObjectURI& property)
+ PrototypeRecursor(as_object* top, const ObjectURI& property, T cmp = T())
:
_object(top),
_name(getName(property)),
_ns(getNamespace(property)),
_iterations(0),
- _condition(top)
+ _condition(cmp)
{
_visited.insert(top);
}
@@ -112,7 +87,7 @@
// TODO: there is recursion prevention anyway; is this extra
// check for circularity really necessary?
if (!_visited.insert(_object).second) return 0;
- return _object && !_object->_displayObject;
+ return _object && !_object->displayObject();
}
/// Return the wanted property if it exists and satisfies the predicate.
@@ -123,7 +98,7 @@
assert(_object);
Property* prop = _object->_members.getProperty(_name, _ns);
- if (prop && _condition(prop)) {
+ if (prop && _condition(*prop)) {
if (owner) *owner = _object;
return prop;
}
@@ -178,17 +153,6 @@
return false;
}
- // Setting members on 'super' is a no-op
- virtual void set_member(string_table::key /*key*/, const as_value&
/*val*/,
- string_table::key /*nsname*/ = 0)
- {
- log_debug("set_member.");
- // can't assign to super
- IF_VERBOSE_ASCODING_ERRORS(
- log_aserror("Can't set members on the 'super' object");
- );
- }
-
/// Dispatch.
virtual as_value operator()(const fn_call& fn)
{
@@ -291,11 +255,12 @@
/// Use the set_member function to properly set *inherited* properties
/// of the given target object
///
- void accept(string_table::key name, const as_value& val)
+ bool accept(string_table::key name, const as_value& val)
{
- if (name == NSV::PROP_uuPROTOuu) return;
+ if (name == NSV::PROP_uuPROTOuu) return true;
//log_debug(_("Setting member '%s' to value '%s'"), name, val);
_tgt.set_member(name, val);
+ return true;
}
};
@@ -343,15 +308,6 @@
init_member(NSV::PROP_uuPROTOuu, as_value(proto));
}
-as_object::as_object(const as_object& other)
- :
- _displayObject(other._displayObject),
- _relay(0),
- _vm(VM::get()),
- _members(other._members)
-{
-}
-
std::pair<bool,bool>
as_object::delProperty(string_table::key name, string_table::key nsname)
{
@@ -430,11 +386,14 @@
{
assert(val);
- PrototypeRecursor<IsVisible> pr(this, ObjectURI(name, nsname));
+ const int version = getSWFVersion(*this);
+
+ PrototypeRecursor<IsVisible> pr(this, ObjectURI(name, nsname),
+ IsVisible(version));
Property* prop = pr.getProperty();
if (!prop) {
- if (_displayObject) {
+ if (displayObject()) {
if (getDisplayObjectProperty(*this, name, *val)) return true;
}
while (pr()) {
@@ -576,7 +535,10 @@
as_object **owner)
{
- PrototypeRecursor<IsVisible> pr(this, ObjectURI(key, nsname));
+ const int version = getSWFVersion(*this);
+
+ PrototypeRecursor<IsVisible> pr(this, ObjectURI(key, nsname),
+ IsVisible(version));
do {
Property* prop = pr.getProperty(owner);
@@ -591,8 +553,6 @@
as_object::findUpdatableProperty(const ObjectURI& uri)
{
- const int swfVersion = getSWFVersion(*this);
-
PrototypeRecursor<Exists> pr(this, uri);
Property* prop = pr.getProperty();
@@ -600,6 +560,8 @@
// We won't scan the inheritance chain if we find a member,
// even if invisible.
if (prop) return prop;
+
+ const int swfVersion = getSWFVersion(*this);
while (pr()) {
if ((prop = pr.getProperty())) {
@@ -613,12 +575,13 @@
}
void
-as_object::set_prototype(const as_value& proto, int flags)
+as_object::set_prototype(const as_value& proto)
{
// TODO: check what happens if __proto__ is set as a user-defined
// getter/setter
// TODO: check triggers !!
- _members.setValue(NSV::PROP_uuPROTOuu, proto, *this, 0, flags);
+ _members.setValue(NSV::PROP_uuPROTOuu, proto, *this, 0,
+ as_object::DefaultFlags);
}
void
@@ -705,6 +668,8 @@
/// Order of property lookup:
//
+/// 0. MovieClip textfield variables. TODO: this is a hack and should be
+/// eradicated.
/// 1. Own properties even if invisible or not getter-setters.
/// 2. If DisplayObject, magic properties
/// 3. Visible own getter-setter properties of all __proto__ objects
@@ -714,6 +679,13 @@
string_table::key nsname, bool ifFound)
{
+ bool tfVarFound = false;
+ if (displayObject()) {
+ MovieClip* mc = dynamic_cast<MovieClip*>(this);
+ if (mc) tfVarFound = mc->setTextFieldVariables(key, val, nsname);
+ // We still need to set the member.
+ }
+
const ObjectURI uri(key, nsname);
PrototypeRecursor<Exists> pr(this, uri);
@@ -724,7 +696,7 @@
// even if invisible.
if (!prop) {
- if (_displayObject) {
+ if (displayObject()) {
if (setDisplayObjectProperty(*this, key, val)) return true;
// TODO: should we execute triggers?
}
@@ -762,6 +734,10 @@
return true;
}
+ // Return true if we found a textfield variable, even if it was not
+ // an own property.
+ if (tfVarFound) return true;
+
// Else, add new property...
if (ifFound) return false;
@@ -1004,7 +980,8 @@
// See actionscript.all/Inheritance.as for a way to trigger this
IF_VERBOSE_ASCODING_ERRORS(
- if ( obj ) log_aserror(_("Circular inheritance chain detected during
isPrototypeOf call"));
+ if (obj) log_aserror(_("Circular inheritance chain detected "
+ "during isPrototypeOf call"));
);
return false;
@@ -1072,7 +1049,7 @@
PropsCopier copier(*this);
// TODO: check if non-visible properties should be also copied !
- o.visitPropertyValues(copier);
+ o.visitProperties<Exists>(copier);
}
void
@@ -1273,28 +1250,25 @@
}
void
-as_object::getURLEncodedVars(std::string& data)
+getURLEncodedVars(as_object& o, std::string& data)
{
- SortedPropertyList props;
- enumerateProperties(props);
+ PropertyList::SortedPropertyList props;
+ o.enumerateProperties(props);
std::string del;
data.clear();
- for (SortedPropertyList::const_iterator i=props.begin(),
- e=props.end(); i!=e; ++i)
- {
- std::string name = i->first;
- std::string value = i->second;
- if ( ! name.empty() && name[0] == '$' ) continue; // see bug #22006
- URL::encode(value);
-
- data += del + name + "=" + value;
-
- del = "&";
-
+ for (PropertyList::SortedPropertyList::const_iterator i=props.begin(),
+ e=props.end(); i!=e; ++i) {
+ std::string name = i->first;
+ std::string value = i->second;
+ if (!name.empty() && name[0] == '$') continue; // see bug #22006
+ URL::encode(value);
+
+ data += del + name + "=" + value;
+
+ del = "&";
}
-
}
bool
@@ -1392,24 +1366,11 @@
}
}
-void
-as_object::visitPropertyValues(AbstractPropertyVisitor& visitor) const
-{
- _members.visitValues(visitor, *this);
-}
-
-void
-as_object::visitNonHiddenPropertyValues(AbstractPropertyVisitor& visitor) const
-{
- _members.visitNonHiddenValues(visitor, *this);
-}
-
-bool
-isNativeType(as_object* obj, DisplayObject*& relay)
-{
- if (!obj || !obj->displayObject()) return false;
- relay = static_cast<DisplayObject*>(obj);
- return true;
+DisplayObject*
+getDisplayObject(as_object* obj)
+{
+ if (!obj || !obj->displayObject()) return 0;
+ return &static_cast<DisplayObject&>(*obj);
}
/// Get the VM from an as_object
=== modified file 'libcore/as_object.h'
--- a/libcore/as_object.h 2009-10-14 08:47:08 +0000
+++ b/libcore/as_object.h 2009-10-16 14:17:00 +0000
@@ -62,7 +62,9 @@
/// An abstract property visitor
class AbstractPropertyVisitor {
public:
- virtual void accept(string_table::key key, const as_value& val)=0;
+
+ /// This function should return false if no further visits are needed.
+ virtual bool accept(string_table::key key, const as_value& val) = 0;
virtual ~AbstractPropertyVisitor() {}
};
@@ -160,12 +162,7 @@
/// Base-class for ActionScript script-defined objects.
/// This would likely be ActionScript's 'Object' class.
///
-class as_object :
-#ifdef GNASH_USE_GC
- public GcResource
-#else
- public ref_counted
-#endif
+class as_object : public GcResource
{
friend class asClass;
friend class Machine;
@@ -195,23 +192,12 @@
/// Construct an ActionScript object based on the given prototype.
explicit as_object(boost::intrusive_ptr<as_object> proto);
- /// Copy an as_object.
- //
- /// This is used by Array_as, but almost certainly shouldn't be. Please
- /// don't use this function.
- explicit as_object(const as_object& other);
-
/// The most common flags for built-in properties.
//
/// Most API properties, including classes and objects, have these flags.
static const int DefaultFlags = PropFlags::dontDelete |
PropFlags::dontEnum;
- /// Is any non-hidden property in this object ?
- bool hasNonHiddenProperties() const {
- return _members.hasNonHiddenProperties();
- }
-
/// Find a property scanning the inheritance chain
///
/// @param name
@@ -223,7 +209,7 @@
/// @param owner
/// If not null, this is set to the object which contained the property.
///
- /// @returns a Propery if found, NULL if not found
+ /// @returns a Property if found, NULL if not found
/// or not visible in current VM version
///
Property* findProperty(string_table::key name, string_table::key nsname,
@@ -732,7 +718,7 @@
/// - (true, false) : property protected from deletion
/// - (true, true) : property successfully deleted
///
- virtual std::pair<bool,bool> delProperty(string_table::key name,
+ std::pair<bool,bool> delProperty(string_table::key name,
string_table::key nsname = 0);
/// Get this object's own named property, if existing.
@@ -770,7 +756,7 @@
/// @return
/// true if the object has the property, false otherwise.
///
- virtual bool hasOwnProperty(string_table::key name,
+ bool hasOwnProperty(string_table::key name,
string_table::key nsname = 0);
/// Get a property from this object (or a prototype) by ordering index.
@@ -914,19 +900,6 @@
///
void enumerateProperties(SortedPropertyList& to) const;
- /// Get url-encoded variables
- //
- /// This method will be used for loadVariables and loadMovie
- /// calls, to encode variables for sending over a network.
- /// Variables starting with a dollar sign will be skipped,
- /// as non-enumerable ones.
- ///
- /// @param data
- /// Output parameter, will be set to the url-encoded
- /// variables string, w/out any leading delimiter.
- ///
- void getURLEncodedVars(std::string& data);
-
/// Visit the properties of this object by key/as_value pairs
//
/// The method will invoke the given visitor method
@@ -939,22 +912,10 @@
/// reference as first argument and a const as_value reference
/// as second argument.
///
- virtual void visitPropertyValues(AbstractPropertyVisitor& visitor) const;
-
- /// Visit non-hidden properties of this object by key/as_value pairs
- //
- /// The method will invoke the given visitor method
- /// passing it two arguments: key of the property and
- /// value of it.
- ///
- /// @param visitor
- /// The visitor function. Will be invoked for each property
- /// of this object with a string_table::key
- /// reference as first argument and a const as_value reference
- /// as second argument.
- ///
- virtual void visitNonHiddenPropertyValues(AbstractPropertyVisitor& visitor)
- const;
+ template<typename T>
+ void visitProperties(AbstractPropertyVisitor& visitor) const {
+ _members.visitValues<T>(visitor, *this);
+ }
/// \brief
/// Add a getter/setter property, if no member already has
@@ -982,17 +943,13 @@
/// of the class this object is an instance of.
///
/// NOTE: can return NULL (and it is expected to do for Object.prototype)
- ///
as_object* get_prototype() const;
/// Set this object's '__proto__' member
//
- /// There is no point to make this function
- /// protected or private, as a call to the
- /// public: set_member("__proto__", anyting)
- /// will do just the same
- ///
- void set_prototype(const as_value& proto, int flags = DefaultFlags);
+ /// This does more or less what set_member("__proto__") does, but without
+ /// the lookup process.
+ void set_prototype(const as_value& proto);
/// Set the as_object's Relay object.
//
@@ -1099,10 +1056,18 @@
/// Mark properties and triggers list as reachable (for the GC)
void markAsObjectReachable() const;
+
#endif // GNASH_USE_GC
private:
+ /// Do not allow copies.
+ as_object(const as_object& other);
+
+ /// Don't allow implicit assignment.
+ as_object& operator=(const as_object&);
+
+ /// A utility class for processing this as_object's inheritance chain
template<typename T> class PrototypeRecursor;
/// DisplayObjects have properties not in the AS inheritance chain
@@ -1120,12 +1085,9 @@
/// The VM containing this object.
VM& _vm;
- /// Properties of this objects
+ /// Properties of this as_object
PropertyList _members;
- /// Don't allow implicit copy.
- as_object& operator=(const as_object&);
-
/// \brief
/// Find an existing property for update, only scanning the
/// inheritance chain for getter/setters or statics.
@@ -1150,6 +1112,50 @@
TriggerContainer _trigs;
};
+/// Function objects for visiting properties.
+class IsVisible
+{
+public:
+ IsVisible(int version) : _version(version) {}
+ bool operator()(const Property& prop) const {
+ return prop.visible(_version);
+ }
+private:
+ const int _version;
+};
+
+class Exists
+{
+public:
+ Exists() {}
+ bool operator()(const Property&) const {
+ return true;
+ }
+};
+
+class IsEnumerable
+{
+public:
+ IsEnumerable() {}
+ bool operator()(const Property& p) const {
+ return !p.getFlags().get_dont_enum();
+ }
+};
+
+/// Get url-encoded variables
+//
+/// This method will be used for loadVariables and loadMovie
+/// calls, to encode variables for sending over a network.
+/// Variables starting with a dollar sign will be skipped,
+/// as non-enumerable ones.
+//
+/// @param o The object whose properties should be encoded.
+/// @param data Output parameter, will be set to the url-encoded
+/// variables string without any leading delimiter.
+void getURLEncodedVars(as_object& o, std::string& data);
+
+
+/// Comparator for ObjectURI so it can serve as a key in stdlib containers.
inline bool
operator<(const ObjectURI& a, const ObjectURI& b)
{
@@ -1219,11 +1225,12 @@
return relay;
}
-/// An overload of isNativeType for DisplayObjects
+
+/// Return the DisplayObject part of an as_object
//
-/// This uses the DisplayObject flag.
-bool
-isNativeType(as_object* obj, DisplayObject*& relay);
+/// @param obj The object whose DisplayObject part should be returned
+/// @return The DisplayObject if the object is one, otherwise 0.
+DisplayObject* getDisplayObject(as_object* obj);
/// Ensure that the object is of a particular native type.
//
=== modified file 'libcore/as_value.cpp'
--- a/libcore/as_value.cpp 2009-10-14 14:26:23 +0000
+++ b/libcore/as_value.cpp 2009-10-16 14:17:00 +0000
@@ -166,7 +166,7 @@
_st(vm.getStringTable())
{}
- void accept(string_table::key key, const as_value& val)
+ bool accept(string_table::key key, const as_value& val)
{
// Test conducted with AMFPHP:
@@ -182,7 +182,7 @@
log_debug(" skip serialization of specially-named property %s",
_st.value(key));
#endif
- return;
+ return true;
}
amf::AMF amf;
@@ -224,6 +224,7 @@
if (el) {
_obj.addProperty(el);
}
+ return true;
}
private:
@@ -255,15 +256,15 @@
bool success() const { return !_error; }
- void accept(string_table::key key, const as_value& val)
+ bool accept(string_table::key key, const as_value& val)
{
- if ( _error ) return;
+ if ( _error ) return true;
// Tested with SharedObject and AMFPHP
if ( val.is_function() )
{
log_debug("AMF0: skip serialization of FUNCTION property");
- return;
+ return true;
}
// Test conducted with AMFPHP:
@@ -279,7 +280,7 @@
log_debug(" skip serialization of specially-named property %s",
_st.value(key));
#endif
- return;
+ return true;
}
// write property name
@@ -290,11 +291,11 @@
boost::uint16_t namelen = name.size();
_buf.appendNetworkShort(namelen);
_buf.append(name.c_str(), namelen);
- if ( ! val.writeAMF0(_buf, _offsetTable, _vm, _allowStrict) )
- {
+ if (!val.writeAMF0(_buf, _offsetTable, _vm, _allowStrict)) {
log_error("Problems serializing an object's member");
- _error=true;
+ _error = true;
}
+ return true;
}
private:
@@ -764,7 +765,7 @@
{
el->makeObject();
PropsSerializer props(*el, vm);
- ptr->visitPropertyValues(props);
+ ptr->visitProperties<Exists>(props);
break;
}
case AS_FUNCTION:
@@ -2279,27 +2280,34 @@
Array_as* ary = dynamic_cast<Array_as*>(obj);
if (ary) {
- const size_t len = ary->size();
- if (allowStrict && ary->isStrict()) {
+ string_table& st = vm.getStringTable();
+ const size_t len = arrayLength(*ary);
+ if (allowStrict) {
+ IsStrictArray s(st);
+ // Check if any non-hidden properties are non-numeric.
+ ary->visitProperties<IsEnumerable>(s);
+ if (s.strict()) {
+
#ifdef GNASH_DEBUG_AMF_SERIALIZE
- log_debug(_("writeAMF0: serializing array of %d "
- "elements as STRICT_ARRAY (index %d)"),
- len, idx);
+ log_debug(_("writeAMF0: serializing array of %d "
+ "elements as STRICT_ARRAY (index %d)"),
+ len, idx);
#endif
- buf.appendByte(amf::Element::STRICT_ARRAY_AMF0);
- buf.appendNetworkLong(len);
+ buf.appendByte(amf::Element::STRICT_ARRAY_AMF0);
+ buf.appendNetworkLong(len);
- as_value elem;
- for (size_t i = 0; i < len; ++i) {
- elem = ary->at(i);
- if (!elem.writeAMF0(buf, offsetTable, vm,
- allowStrict)) {
- log_error("Problems serializing strict array "
- "member %d=%s", i, elem);
- return false;
+ as_value elem;
+ for (size_t i = 0; i < len; ++i) {
+ elem = ary->getMember(arrayKey(st, i));
+ if (!elem.writeAMF0(buf, offsetTable, vm,
+ allowStrict)) {
+ log_error("Problems serializing strict
array "
+ "member %d=%s", i, elem);
+ return false;
+ }
}
+ return true;
}
- return true;
}
// A normal array.
@@ -2307,7 +2315,7 @@
log_debug(_("writeAMF0: serializing array of %d "
"elements as ECMA_ARRAY (index %d) "
"[allowStrict:%d, isStrict:%d]"),
- len, idx, allowStrict, ary->isStrict());
+ len, idx, allowStrict, isStrict);
#endif
buf.appendByte(amf::Element::ECMA_ARRAY_AMF0);
buf.appendNetworkLong(len);
@@ -2322,7 +2330,7 @@
}
PropsBufSerializer props(buf, vm, offsetTable, allowStrict);
- obj->visitNonHiddenPropertyValues(props);
+ obj->visitProperties<IsEnumerable>(props);
if (!props.success()) {
log_error("Could not serialize object");
return false;
=== modified file 'libcore/asobj/Array_as.cpp'
--- a/libcore/asobj/Array_as.cpp 2009-10-15 13:25:00 +0000
+++ b/libcore/asobj/Array_as.cpp 2009-10-16 14:17:00 +0000
@@ -91,6 +91,7 @@
as_value array_splice(const fn_call& fn);
string_table::key getKey(const fn_call& fn, size_t i);
+ int isIndex(const std::string& name);
/// Implementation of foreachArray that takes a start and end range.
template<typename T> void foreachArray(as_object& array, int start,
@@ -108,6 +109,10 @@
void pushIndices(as_object& o, const std::vector<indexed_as_value>& index);
+ /// Set the length property of an object only if it is a genuine array.
+ void setArrayLength(as_object& o, const int size);
+
+ void resizeArray(as_object& o, const int size);
}
/// Function objects for foreachArray()
@@ -647,17 +652,17 @@
class as_value_multiprop
{
public:
- typedef std::deque<as_cmp_fn> Comps;
+ typedef std::vector<as_cmp_fn> Comps;
Comps& _cmps;
- typedef std::deque<string_table::key> Props;
+ typedef std::vector<string_table::key> Props;
Props& _prps;
const as_object& _obj;
// Note: all as_cmp_fns in *cmps must implement strict weak ordering
- as_value_multiprop(std::deque<string_table::key>& prps,
- std::deque<as_cmp_fn>& cmps, const as_object& o)
+ as_value_multiprop(std::vector<string_table::key>& prps,
+ std::vector<as_cmp_fn>& cmps, const as_object& o)
:
_cmps(cmps),
_prps(prps),
@@ -669,7 +674,7 @@
{
if ( _cmps.empty() ) return false;
- std::deque<as_cmp_fn>::iterator cmp = _cmps.begin();
+ std::vector<as_cmp_fn>::iterator cmp = _cmps.begin();
// why do we cast ao/bo to objects here ?
boost::intrusive_ptr<as_object> ao = a.to_object(*getGlobal(_obj));
@@ -696,8 +701,8 @@
class as_value_multiprop_eq : public as_value_multiprop
{
public:
- as_value_multiprop_eq(std::deque<string_table::key>& prps,
- std::deque<as_cmp_fn>& cmps, const as_object& o)
+ as_value_multiprop_eq(std::vector<string_table::key>& prps,
+ std::vector<as_cmp_fn>& cmps, const as_object& o)
:
as_value_multiprop(prps, cmps, o),
_obj(o)
@@ -741,39 +746,77 @@
return flgs;
}
-// Convenience function to process and extract flags from an as_value array
-// of flags (as passed to sortOn when sorting on multiple properties)
-std::deque<boost::uint8_t>
-get_multi_flags(Array_as::const_iterator itBegin,
- Array_as::const_iterator itEnd, bool* uniq, bool* index)
+
+class GetKeys
{
- Array_as::const_iterator it = itBegin;
- std::deque<boost::uint8_t> flgs;
-
- // extract SORT_UNIQUE and SORT_RETURN_INDEX from first flag
- if (it != itEnd)
- {
- boost::uint8_t flag = static_cast<boost::uint8_t>((*it++).to_number());
- flag = flag_preprocess(flag, uniq, index);
- flgs.push_back(flag);
+public:
+ GetKeys(std::vector<string_table::key>& v, string_table& st, int version)
+ :
+ _v(v),
+ _st(st),
+ _version(version)
+ {}
+ void operator()(const as_value& val) {
+ _v.push_back(_st.find(val.to_string_versioned(_version)));
}
+private:
+ std::vector<string_table::key>& _v;
+ string_table& _st;
+ const int _version;
+};
- while (it != itEnd)
- {
- boost::uint8_t flag = static_cast<boost::uint8_t>((*it++).to_number());
+/// Functor to extract flags from an array-like object.
+//
+/// I don't know how accurate this code is. It was copied from the previous
+/// implementation but without using Array_as.
+class GetMultiFlags
+{
+public:
+ GetMultiFlags(std::vector<boost::uint8_t>& v)
+ :
+ _v(v),
+ _i(0),
+ _uniq(false),
+ _index(false)
+ {}
+ void operator()(const as_value& val) {
+ // extract SORT_UNIQUE and SORT_RETURN_INDEX from first flag
+ if (!_i) {
+ boost::uint8_t flag = static_cast<boost::uint8_t>(val.to_number());
+ flag = flag_preprocess(flag, &_uniq, &_index);
+ _v.push_back(flag);
+ ++_i;
+ return;
+ }
+ boost::uint8_t flag = static_cast<boost::uint8_t>(val.to_number());
flag &= ~(SORT_RETURN_INDEX);
flag &= ~(SORT_UNIQUE);
- flgs.push_back(flag);
+ _v.push_back(flag);
+ ++_i;
}
- return flgs;
+ bool unique() const { return _uniq; }
+ bool index() const { return _index; }
+
+private:
+ std::vector<boost::uint8_t>& _v;
+ size_t _i;
+ bool _uniq;
+ bool _index;
+};
+
}
+bool
+IsStrictArray::accept(string_table::key key, const as_value& /*val*/)
+{
+ if (isIndex(_st.value(key)) >= 0) return true;
+ _strict = false;
+ return false;
}
Array_as::Array_as()
:
- as_object(getArrayInterface()), // pass Array inheritance
- elements(0)
+ as_object(getArrayInterface())
{
init_member(NSV::PROP_LENGTH, 0.0);
}
@@ -783,147 +826,36 @@
{
}
-Array_as::const_iterator
-Array_as::begin()
-{
- return elements.begin();
-}
-
-Array_as::const_iterator
-Array_as::end()
-{
- return elements.end();
-}
-
-int
-Array_as::index_requested(string_table::key name)
-{
- const std::string& nameString = getStringTable(*this).value(name);
-
- // Anything not in [0-9] makes this an invalid index
- if ( nameString.find_first_not_of("0123456789") != std::string::npos )
- {
- return -1;
- }
-
- // TODO: do we need all this noise ? atol(3) should do !
-
- as_value temp;
- temp.set_string(nameString);
- double value = temp.to_number();
-
- // if we were sent a string that can't convert like "asdf", it returns as
NaN. -1 means invalid index
- if (!isFinite(value)) return -1;
-
- return int(value);
-}
-
unsigned int
Array_as::size() const
{
- return elements.size();
+ return arrayLength(const_cast<Array_as&>(*this));
}
as_value
Array_as::at(unsigned int index) const
{
- if ( index > elements.size()-1 ) return as_value();
- else return elements[index];
-}
-
-/* virtual public, overriding as_object::get_member */
-bool
-Array_as::get_member(string_table::key name, as_value *val,
- string_table::key nsname)
-{
- // an index has been requested
- int index = index_requested(name);
-
- if ( index >= 0 ) // a valid index was requested
- {
- size_t i = index;
- const_iterator it = elements.find(i);
- if ( it != elements.end() && it.index() == i )
- {
- *val = *it;
- return true;
- }
- }
-
- return as_object::get_member(name, val, nsname);
-}
-
-bool
-Array_as::hasOwnProperty(string_table::key name, string_table::key nsname)
-{
- // an index has been requested
- int index = index_requested(name);
-
- if ( index >= 0 ) // a valid index was requested
- {
- size_t i = index;
- const_iterator it = elements.find(i);
- if ( it != elements.end() && it.index() == i )
- {
- return true;
- }
- }
-
- return as_object::hasOwnProperty(name, nsname);
-}
-
-std::pair<bool,bool>
-Array_as::delProperty(string_table::key name, string_table::key nsname)
-{
- // an index has been requested
- int index = index_requested(name);
-
- if ( index >= 0 ) // a valid index was requested
- {
- size_t i = index;
- const_iterator it = elements.find(i);
- if ( it != elements.end() && it.index() == i )
- {
- elements.erase_element(i);
- return std::make_pair(true, true);
- }
- }
-
- return as_object::delProperty(name, nsname);
-}
-
-void
-Array_as::resize(unsigned int newsize)
-{
- elements.resize(newsize);
+ 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)
+Array_as::set_member(string_table::key name, const as_value& val,
+ string_table::key nsname, bool ifFound)
{
- int index = index_requested(name);
-
- // if we were sent a valid array index and not a normal member
- if (index >= 0)
- {
- if (size_t(index) >= elements.size())
- {
- // if we're setting index (x), the vector
- // must be size (x+1)
- elements.resize(index+1);
- }
-
- as_object::set_member(NSV::PROP_LENGTH, elements.size());
- // set the appropriate index and return
- elements[index] = val;
- return true;
- }
if (name == NSV::PROP_LENGTH) {
- elements.resize(std::max(val.to_int(), 0));
- // Don't return before as_object has set the value!
+ resizeArray(*this, val.to_int());
+ }
+ 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);
+ }
+ }
}
return as_object::set_member(name,val, nsname, ifFound);
@@ -982,74 +914,6 @@
where.init_member(getName(uri), cl, flags, getNamespace(uri));
}
-void
-Array_as::enumerateNonProperties(as_environment& env) const
-{
- std::stringstream ss;
- for (const_iterator it = elements.begin(),
- itEnd = elements.end(); it != itEnd; ++it)
- {
- int idx = it.index();
- // enumerated values need to be strings, not numbers
- ss.str(""); ss << idx;
- env.push(as_value(ss.str()));
- }
-}
-
-#ifdef GNASH_USE_GC
-void
-Array_as::markReachableResources() const
-{
- for (const_iterator i=elements.begin(), e=elements.end(); i!=e; ++i)
- {
- (*i).setReachable();
- }
- markAsObjectReachable();
-}
-#endif // GNASH_USE_GC
-
-void
-Array_as::visitPropertyValues(AbstractPropertyVisitor& visitor) const
-{
- std::stringstream ss;
- string_table& st = getStringTable(*this);
- for (const_iterator i=elements.begin(), ie=elements.end(); i!=ie; ++i)
- {
- int idx = i.index();
- ss.str(""); ss << idx;
- string_table::key k = st.find(ss.str());
- visitor.accept(k, *i);
- }
-
- // visit proper properties
- as_object::visitPropertyValues(visitor);
-}
-
-void
-Array_as::visitNonHiddenPropertyValues(AbstractPropertyVisitor& visitor) const
-{
- std::stringstream ss;
- string_table& st = getStringTable(*this);
- for (const_iterator i=elements.begin(), ie=elements.end(); i!=ie; ++i)
- {
- // TODO: skip hidden ones
- int idx = i.index();
- ss.str(""); ss << idx;
- string_table::key k = st.find(ss.str());
- visitor.accept(k, *i);
- }
-
- // visit proper properties
- as_object::visitNonHiddenPropertyValues(visitor);
-}
-
-bool
-Array_as::isStrict() const
-{
- if ( hasNonHiddenProperties() ) return false;
- return true;
-}
-
// Used by foreachArray, declared in Array_as.h
string_table::key
arrayKey(string_table& st, size_t i)
@@ -1260,8 +1124,10 @@
int version = getSWFVersion(fn);
string_table& st = getStringTable(fn);
+ if (fn.nargs == 0) return as_value();
+
// cases: sortOn("prop) and sortOn("prop", Array.FLAG)
- if (fn.nargs > 0 && fn.arg(0).is_string())
+ if (fn.arg(0).is_string())
{
string_table::key propField =
st.find(fn.arg(0).to_string_versioned(version));
@@ -1290,66 +1156,62 @@
return as_value(array);
}
+#if 1
// case: sortOn(["prop1", "prop2"] ...)
- if (fn.nargs > 0 && fn.arg(0).is_object() )
+ if (fn.arg(0).is_object())
{
- boost::intrusive_ptr<Array_as> props =
- ensureType<Array_as>(fn.arg(0).to_object(*getGlobal(fn)));
- std::deque<string_table::key> prp;
- unsigned int optnum = props->size();
- std::deque<as_cmp_fn> cmp;
- std::deque<as_cmp_fn> eq;
+ as_object* props = fn.arg(0).to_object(*getGlobal(fn));
+ assert(props);
- for (Array_as::const_iterator it = props->begin();
- it != props->end(); ++it)
- {
- string_table::key s = st.find((*it).to_string_versioned(version));
- prp.push_back(s);
- }
+ std::vector<string_table::key> prp;
+ GetKeys gk(prp, st, version);
+ foreachArray(*props, gk);
+
+ std::vector<as_cmp_fn> cmp;
+ std::vector<as_cmp_fn> eq;
+
+ // Will be the same as arrayLength(*props);
+ const size_t optnum = prp.size();
// case: sortOn(["prop1", "prop2"])
- if (fn.nargs == 1)
- {
+ if (fn.nargs == 1) {
// assign each cmp function to the standard cmp fn
as_cmp_fn c = get_basic_cmp(0, version);
cmp.assign(optnum, c);
}
// case: sortOn(["prop1", "prop2"], [Array.FLAG1, Array.FLAG2])
- else if ( fn.arg(1).is_object() )
- {
- boost::intrusive_ptr<Array_as> farray =
- ensureType<Array_as>(fn.arg(1).to_object(*getGlobal(fn)));
- if (farray->size() == optnum)
- {
- Array_as::const_iterator
- fBegin = farray->begin(),
- fEnd = farray->end();
-
- std::deque<boost::uint8_t> flgs =
- get_multi_flags(fBegin, fEnd,
- &do_unique, &do_index);
-
- std::deque<boost::uint8_t>::const_iterator it =
+ else if (fn.arg(1).is_object()) {
+
+ as_object* farray = fn.arg(1).to_object(*getGlobal(fn));
+
+ if (arrayLength(*farray) == optnum) {
+
+ std::vector<boost::uint8_t> flgs;
+ GetMultiFlags mf(flgs);
+ foreachArray(*farray, mf);
+ do_unique = mf.unique();
+ do_index = mf.index();
+
+ std::vector<boost::uint8_t>::const_iterator it =
flgs.begin();
- while (it != flgs.end())
+ while (it != flgs.end()) {
cmp.push_back(get_basic_cmp(*it++, version));
+ }
- if (do_unique)
- {
+ if (do_unique) {
it = flgs.begin();
while (it != flgs.end())
eq.push_back(get_basic_eq(*it++, version));
}
}
- else
- {
+ else {
as_cmp_fn c = get_basic_cmp(0, version);
cmp.assign(optnum, c);
}
}
// case: sortOn(["prop1", "prop2"], Array.FLAG)
- else if ( fn.arg(1).is_number() )
+ else if (fn.arg(1).is_number())
{
boost::uint8_t flags =
static_cast<boost::uint8_t>(fn.arg(1).to_number());
@@ -1358,13 +1220,11 @@
cmp.assign(optnum, c);
- if (do_unique)
- {
+ if (do_unique) {
as_cmp_fn e = get_basic_eq(flags, version);
eq.assign(optnum, e);
}
}
-
as_value_multiprop avc(prp, cmp, *getGlobal(fn));
if (do_unique)
@@ -1378,11 +1238,10 @@
return as_value(array);
}
+#endif
IF_VERBOSE_ASCODING_ERRORS(
- log_aserror(_("SortOn called with invalid arguments."));
+ log_aserror(_("SortOn called with invalid arguments."));
)
- if (fn.nargs == 0 )
- return as_value();
return as_value(array);
}
@@ -1399,12 +1258,11 @@
const size_t size = arrayLength(*array);
- for (size_t i = 0; i < fn.nargs; ++i) {
+ for (size_t i = 0; i < shift; ++i) {
array->set_member(getKey(fn, size + i), fn.arg(i));
}
-
- // TODO: this is wrong, but Gnash relies on it.
- array->set_member(NSV::PROP_LENGTH, size + shift);
+
+ log_debug("size: %s, shift :%s", size, shift);
return as_value(size + shift);
}
@@ -1437,8 +1295,7 @@
array->set_member(getKey(fn, index), fn.arg(index));
}
- // TODO: this is wrong, but Gnash relies on it.
- array->set_member(NSV::PROP_LENGTH, size + shift);
+ setArrayLength(*array, size + shift);
return as_value(size + shift);
}
@@ -1457,8 +1314,7 @@
as_value ret = array->getMember(ind);
array->delProperty(ind);
- // TODO: this is wrong, but Gnash relies on it.
- array->set_member(NSV::PROP_LENGTH, size - 1);
+ setArrayLength(*array, size - 1);
return ret;
}
@@ -1482,8 +1338,7 @@
array->set_member(currentkey, array->getMember(nextkey));
}
- // TODO: this is wrong, but Gnash relies on it.
- array->set_member(NSV::PROP_LENGTH, size - 1);
+ setArrayLength(*array, size - 1);
return ret;
}
@@ -1705,6 +1560,44 @@
foreachArray(array, pv);
}
+void
+resizeArray(as_object& o, const int size)
+{
+ // Only positive indices are deleted.
+ size_t realSize = std::max(size, 0);
+
+ const size_t currentSize = arrayLength(o);
+ if (realSize < currentSize) {
+ string_table& st = getStringTable(o);
+ for (size_t i = realSize; i < currentSize; ++i) {
+ o.delProperty(arrayKey(st, i));
+ }
+ }
+}
+
+void
+setArrayLength(as_object& o, 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);
+}
+
+int
+isIndex(const std::string& nameString)
+{
+ try {
+ return boost::lexical_cast<int>(nameString);
+ }
+ catch (boost::bad_lexical_cast& e) {
+ return -1;
+ }
+}
+
} // anonymous namespace
} // end of gnash namespace
=== modified file 'libcore/asobj/Array_as.h'
--- a/libcore/asobj/Array_as.h 2009-10-15 13:25:00 +0000
+++ b/libcore/asobj/Array_as.h 2009-10-16 14:17:00 +0000
@@ -26,8 +26,6 @@
#include <deque>
#include <vector>
#include <memory> // for auto_ptr
-#include <boost/numeric/ublas/vector_sparse.hpp>
-
#include <string>
// Forward declarations
@@ -38,93 +36,62 @@
namespace gnash {
+/// Get the length of an object as though it were an array
+//
+/// It may well be an array, but this also works on normal objects with a
+/// length property
+//
+/// @param array The object whose array length is needed.
+/// @return The array length of the object or 0 if no length is
+/// found.
size_t arrayLength(as_object& array);
+
+/// Convert an integral value into an array key
+//
+/// NB this function adds a string value to the string_table for each separate
+/// integral value. It's the way the string_table works.
+//
+/// @param i The integral value to find
+/// @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
+/// are strict arrays; any users of this functor should check that first.
+class IsStrictArray : public AbstractPropertyVisitor
+{
+public:
+ IsStrictArray(string_table& st) : _strict(true), _st(st) {}
+ virtual bool accept(string_table::key key, const as_value& val);
+
+ bool strict() const {
+ return _strict;
+ }
+private:
+ bool _strict;
+ string_table& _st;
+};
+
/// The Array ActionScript object
class Array_as : public as_object
{
- /// Other classes shouldn't care about this, but should rather use
- /// the public iterator / const_iterator members.
- typedef boost::numeric::ublas::mapped_vector<as_value> ArrayContainer;
-
public:
- typedef ArrayContainer::const_iterator const_iterator;
- typedef ArrayContainer::iterator iterator;
-
- // see dox in as_object.h
- virtual void visitPropertyValues(AbstractPropertyVisitor& visitor)
const;
-
- // see dox in as_object.h
- virtual void visitNonHiddenPropertyValues(AbstractPropertyVisitor&
visitor) const;
-
-
Array_as();
~Array_as();
- /// Return true if this is a strict array
- //
- /// Strict arrays are those whose enumerable
- /// properties are only valid positive integer.
- /// Telling strict apart from non-strict is needed
- /// for AMF encoding in remoting.
- ///
- bool isStrict() const;
-
- Array_as::const_iterator begin();
-
- Array_as::const_iterator end();
-
as_value at(unsigned int index) const;
unsigned int size() const;
- void resize(unsigned int);
-
- /// Why is this overridden?
- virtual bool get_member(string_table::key name, as_value* val,
- string_table::key nsname = 0);
-
/// 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);
- /// Overridden to deal with indexed elements
- virtual std::pair<bool,bool> delProperty(string_table::key name,
string_table::key nsname = 0);
-
- /// Overridden to expose indexed elements
- virtual bool hasOwnProperty(string_table::key name, string_table::key
nsname = 0);
-
- /// Enumerate elements
- //
- /// See as_object::enumerateNonProperties(as_environment&) for more
info.
- ///
- virtual void enumerateNonProperties(as_environment&) const;
-
-protected:
-
-#ifdef GNASH_USE_GC
- /// Mark array-specific reachable resources and invoke
- /// the parent's class version (markAsObjectReachable)
- //
- /// array-specific reachable resources are:
- /// - The elements values (elements)
- ///
- virtual void markReachableResources() const;
-#endif // GNASH_USE_GC
-
-private:
-
- ArrayContainer elements;
-
- // this function is used internally by set_member and get_member
- // it takes a string that is the member name of the array and returns -1
- // if the string does not refer to an index, or an appropriate int if
the string does refer to an index
- int index_requested(string_table::key name);
-
};
template<typename T>
=== modified file 'libcore/asobj/Color_as.cpp'
--- a/libcore/asobj/Color_as.cpp 2009-10-14 08:47:08 +0000
+++ b/libcore/asobj/Color_as.cpp 2009-10-16 06:31:31 +0000
@@ -274,7 +274,8 @@
const as_value& target = obj->getMember(NSV::PROP_TARGET);
MovieClip* sp = target.to_sprite();
if (sp) return sp;
- DisplayObject* d = fn.env().find_target(target.to_string());
+ as_object* o = fn.env().find_target(target.to_string());
+ DisplayObject* d = getDisplayObject(o);
if (d) return d->to_movie();
return 0;
}
=== modified file 'libcore/asobj/flash/display/MovieClip_as.cpp'
--- a/libcore/asobj/flash/display/MovieClip_as.cpp 2009-10-14 08:47:08
+0000
+++ b/libcore/asobj/flash/display/MovieClip_as.cpp 2009-10-16 06:31:31
+0000
@@ -1012,9 +1012,8 @@
// This is just an optimization if we aren't going
// to send the data anyway. It might be wrong, though.
- if (method != MovieClip::METHOD_NONE)
- {
- movieclip->getURLEncodedVars(data);
+ if (method != MovieClip::METHOD_NONE) {
+ getURLEncodedVars(*movieclip, data);
}
mr.loadMovie(urlstr, target, data, method);
@@ -1240,7 +1239,7 @@
if (method != MovieClip::METHOD_NONE) {
// Get encoded vars.
- movieclip->getURLEncodedVars(vars);
+ getURLEncodedVars(*movieclip, vars);
}
movie_root& m = getRoot(fn);
@@ -1254,8 +1253,8 @@
as_value
movieclip_getSWFVersion(const fn_call& fn)
{
- DisplayObject* o;
- if (!isNativeType(fn.this_ptr, o)) return as_value(-1);
+ DisplayObject* o = getDisplayObject(fn.this_ptr);
+ if (!o) return as_value(-1);
return as_value(o->getDefinitionVersion());
}
=== modified file 'libcore/asobj/flash/net/SharedObject_as.cpp'
--- a/libcore/asobj/flash/net/SharedObject_as.cpp 2009-10-14 08:47:08
+0000
+++ b/libcore/asobj/flash/net/SharedObject_as.cpp 2009-10-16 14:17:00
+0000
@@ -104,7 +104,7 @@
_st(vm.getStringTable())
{};
- void accept(string_table::key key, const as_value& val)
+ bool accept(string_table::key key, const as_value& val)
{
AMF amf;
boost::shared_ptr<amf::Element> el;
@@ -137,6 +137,7 @@
if (el) {
_sol.addObj(el);
}
+ return true;
}
private:
@@ -165,14 +166,13 @@
bool success() const { return !_error; }
- virtual void accept(string_table::key key, const as_value& val)
+ virtual bool accept(string_table::key key, const as_value& val)
{
- if ( _error ) return;
+ assert(!_error);
- if ( val.is_function() )
- {
+ if ( val.is_function()) {
log_debug("SOL: skip serialization of FUNCTION property");
- return;
+ return true;
}
// Test conducted with AMFPHP:
@@ -188,7 +188,7 @@
log_debug(" skip serialization of specially-named property %s",
_st.value(key));
#endif
- return;
+ return true;
}
// write property name
@@ -200,14 +200,18 @@
_buf.appendNetworkShort(namelen);
_buf.append(name.c_str(), namelen);
// Strict array are never encoded in SharedObject
- if ( ! val.writeAMF0(_buf, _offsetTable, _vm, false) )
+ if (!val.writeAMF0(_buf, _offsetTable, _vm, false))
{
log_error("Problems serializing an object's member %s=%s",
name, val);
_error = true;
+
+ // Stop visiting....
+ return false;
}
-
- _buf.appendByte(0); // SOL-specific
+ // SOL-specific
+ _buf.appendByte(0);
+ return true;
}
private:
@@ -373,9 +377,8 @@
std::map<as_object*, size_t> offsetTable;
SOLPropsBufSerializer props(buf, vm, offsetTable);
- _data->visitPropertyValues(props);
- if ( ! props.success() )
- {
+ _data->visitProperties<Exists>(props);
+ if (!props.success()) {
log_error("Could not serialize object");
return false;
}
=== modified file 'libcore/vm/ASHandlers.cpp'
--- a/libcore/vm/ASHandlers.cpp 2009-10-15 09:00:29 +0000
+++ b/libcore/vm/ASHandlers.cpp 2009-10-16 07:09:56 +0000
@@ -2207,12 +2207,11 @@
// is the target to load the resource into).
//
DisplayObject* curtgt = env.get_target();
- if ( ! curtgt )
- {
+ if (!curtgt) {
log_error(_("CommonGetUrl: current target is undefined"));
return;
}
- curtgt->getURLEncodedVars(varsToSend);
+ getURLEncodedVars(*curtgt, varsToSend);
}
@@ -2874,23 +2873,20 @@
void
SWFHandlers::ActionTargetPath(ActionExec& thread)
{
-
as_environment& env = thread.env;
- boost::intrusive_ptr<MovieClip> sp = env.top(0).to_sprite();
- if ( sp )
- {
+ DisplayObject* sp = env.top(0).toDisplayObject();
+ if (sp) {
env.top(0).set_string(sp->getTarget());
- }
- else
- {
- IF_VERBOSE_ASCODING_ERRORS(
- log_aserror(_("Argument to TargetPath(%s) doesn't cast to a
MovieClip"),
- env.top(0));
- );
- env.top(0).set_undefined();
- }
+ return;
+ }
+
+ IF_VERBOSE_ASCODING_ERRORS(
+ log_aserror(_("Argument to TargetPath(%s) doesn't cast "
+ "to a DisplayObject"), env.top(0));
+ );
+ env.top(0).set_undefined();
}
// Push a each object's member value on the stack
@@ -3008,7 +3004,6 @@
SWFHandlers::ActionDup(ActionExec& thread)
{
as_environment& env = thread.env;
-
env.push(env.top(0));
}
@@ -3016,10 +3011,7 @@
SWFHandlers::ActionSwap(ActionExec& thread)
{
as_environment& env = thread.env;
-
- as_value temp = env.top(1);
- env.top(1) = env.top(0);
- env.top(0) = temp;
+ std::swap(env.top(1), env.top(0));
}
void
@@ -3031,7 +3023,8 @@
as_value member_name = env.top(0);
as_value target = env.top(1);
- boost::intrusive_ptr<as_object> obj =
convertToObject(*getGlobal(thread.env), target);
+ boost::intrusive_ptr<as_object> obj =
+ convertToObject(*getGlobal(thread.env), target);
if (!obj)
{
IF_VERBOSE_ASCODING_ERRORS(
@@ -3080,18 +3073,15 @@
const std::string& member_name = env.top(1).to_string();
const as_value& member_value = env.top(0);
- if ( member_name.empty() )
- {
+ if (member_name.empty()) {
IF_VERBOSE_ASCODING_ERRORS (
// Invalid object, can't set.
- log_aserror(_("ActionSetMember: %s.%s=%s: member name evaluates to
invalid (empty) string"),
- env.top(2),
- env.top(1),
- env.top(0));
+ log_aserror(_("ActionSetMember: %s.%s=%s: member name "
+ "evaluates to invalid (empty) string"),
+ env.top(2), env.top(1), env.top(0));
);
}
- else if (obj)
- {
+ else if (obj) {
thread.setObjectMember(*(obj.get()), member_name, member_value);
IF_VERBOSE_ACTION (
@@ -3103,14 +3093,13 @@
}
else
{
- // Malformed SWF ? (don't think this is possible to do with
ActionScript syntax)
+ // Malformed SWF ? (don't think this is possible to do with
+ // ActionScript syntax)
// FIXME, should this be log_swferror?
IF_VERBOSE_ASCODING_ERRORS (
// Invalid object, can't set.
log_aserror(_("-- set_member %s.%s=%s on invalid object!"),
- env.top(2),
- member_name,
- member_value);
+ env.top(2), member_name, member_value);
);
}
@@ -3121,14 +3110,14 @@
SWFHandlers::ActionIncrement(ActionExec& thread)
{
as_environment& env = thread.env;
- env.top(0).set_double(env.top(0).to_number()+1);
+ env.top(0).set_double(env.top(0).to_number() + 1);
}
void
SWFHandlers::ActionDecrement(ActionExec& thread)
{
as_environment& env = thread.env;
- env.top(0).set_double(env.top(0).to_number()-1);
+ env.top(0).set_double(env.top(0).to_number() - 1);
}
void
=== modified file 'testsuite/actionscript.all/array.as'
--- a/testsuite/actionscript.all/array.as 2009-10-15 12:28:05 +0000
+++ b/testsuite/actionscript.all/array.as 2009-10-16 14:18:01 +0000
@@ -770,10 +770,10 @@
c[10] = 'ten';
check_equals(c.length, 11);
ASSetPropFlags(c, "2", 7, 0); // protect from deletion
-xcheck( ! delete c[2] ); // gnash doesn't store prop flags here..
-xcheck_equals(c[2], 30); // so won't respect delete-protection
+check( ! delete c[2] ); // gnash doesn't store prop flags here..
+check_equals(c[2], 30); // so won't respect delete-protection
c.length = 2;
-xcheck_equals(c[2], 30); // was protected !
+check_equals(c[2], 30); // was protected !
check_equals(typeof(c[10]), 'undefined'); // was not protected..
c.length = 11;
check_equals(typeof(c[10]), 'undefined'); // and won't come back
@@ -1357,18 +1357,18 @@
getCalls=0; setCalls=0;
a[1] = 1;
check_equals(getCalls, 0);
-xcheck_equals(setCalls, 1);
+check_equals(setCalls, 1);
ret = a.addProperty('2', get, set);
check_equals(ret, true);
getCalls=0; setCalls=0;
junk = a[2];
-xcheck_equals(getCalls, 1);
+check_equals(getCalls, 1);
check_equals(setCalls, 0);
getCalls=0; setCalls=0;
a[2] = 2;
check_equals(getCalls, 0);
-xcheck_equals(setCalls, 1);
+check_equals(setCalls, 1);
check_equals(a.length, 3);
ret = a.addProperty('3', get, set);
@@ -1378,7 +1378,7 @@
getCalls=0; setCalls=0;
a.push(2);
check_equals(getCalls, 0);
-check_equals(setCalls, 0);
+xcheck_equals(setCalls, 0);
#endif // OUTPUT_VERSION > 5
@@ -1394,7 +1394,7 @@
f = a.shift();
check_equals(a.length, 1);
check_equals(f, 'zero');
-xcheck_equals(a[0], 'zero'); // could not delete for override
+check_equals(a[0], 'zero'); // could not delete for override
check_equals(typeof(a[1]), 'undefined');
#if OUTPUT_VERSION > 5
check(!a.hasOwnProperty(1));
@@ -1409,10 +1409,10 @@
check_equals(a.length, 1);
check_equals(f, 'zero');
check_equals(a[0], 'one'); // could replace
-xcheck_equals(a[1], 'one'); // couldn't delete
+check_equals(a[1], 'one'); // couldn't delete
#if OUTPUT_VERSION > 5
check(a.hasOwnProperty(0));
- xcheck(a.hasOwnProperty(1));
+ check(a.hasOwnProperty(1));
#endif
//--------------------------------------------------------
@@ -1425,10 +1425,10 @@
ASSetPropFlags(a, "0", 4, 0); // protect 0 from override
check_equals(a.length, 2);
a[0] = 'overridden';
-xcheck_equals(a[0], 'zero'); // was protected..
+check_equals(a[0], 'zero'); // was protected..
f = a.shift();
check_equals(a.length, 1);
-xcheck_equals(f, 'zero');
+check_equals(f, 'zero');
check_equals(a[0], 'one'); // 0 was replaced anyway, didn't care about
protection
check_equals(typeof(a[1]), 'undefined');
a[0] = 'overridden';
@@ -1443,12 +1443,12 @@
a[2] = 'two';
ASSetPropFlags(a, "1", 4, 0); // protect 1 from override
a[1] = 'overridden';
-xcheck_equals(a[1], 'one'); // was protected
+check_equals(a[1], 'one'); // was protected
check_equals(a.length, 3);
f = a.shift();
check_equals(a.length, 2);
check_equals(f, 'zero');
-xcheck_equals(a[0], 'one'); // 0 was replaced anyway, didn't care about
protection
+check_equals(a[0], 'one'); // 0 was replaced anyway, didn't care about
protection
check_equals(a[1], 'two');
check_equals(typeof(a[2]), 'undefined');
a[1] = 'overridden';
@@ -1492,7 +1492,7 @@
o.shift();
// Properties are readded from 0 to 5.
check_equals(traceProps(o), "4,3,2,1,0,shift,length,7,6,5,");
-xcheck_equals(o.length, 6);
+check_equals(o.length, 6);
o = fakeArray();
o.unshift = Array.prototype.unshift;
@@ -1503,7 +1503,7 @@
o.unshift("new");
// Properties are readded in reverse order.
check_equals(traceProps(o), "0,1,2,3,4,5,6,unshift,length,7,")
-xcheck_equals(o.length, 6);
+check_equals(o.length, 6);
o = fakeArray();
@@ -1516,7 +1516,7 @@
check_equals(val, "five");
// Length is not decremented, property 5 is deleted.
check_equals(traceProps(o), "pop,length,7,6,4,3,2,1,");
-xcheck_equals(o.length, 6);
+check_equals(o.length, 6);
o = fakeArray();
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Gnash-commit] /srv/bzr/gnash/trunk r11567: Make more as_object functions non-virtual. Generally clean up and reduce the,
Benjamin Wolsey <=