/* [<][>][^][v][top][bottom][index][help] */
//
// Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010,
// 2011 Free Software Foundation, Inc
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#ifndef GNASH_AS_OBJECT_H
#define GNASH_AS_OBJECT_H
#ifdef HAVE_CONFIG_H
#include "gnashconfig.h"
#endif
#include <map>
#include <vector>
#include <cmath>
#include <utility>
#include <set>
#include <sstream>
#include <boost/scoped_ptr.hpp>
#include <boost/noncopyable.hpp>
#include "string_table.h"
#include "GC.h" // for inheritance from GcResource (to complete)
#include "PropertyList.h"
#include "PropFlags.h"
#include "Relay.h"
#include "ObjectURI.h"
// Forward declarations
namespace gnash {
class as_function;
class MovieClip;
class DisplayObject;
class as_environment;
class VM;
class IOChannel;
class movie_root;
class RunResources;
class Global_as;
class as_value;
}
namespace gnash {
/// A trigger that can be associated with a property name
class Trigger
{
public:
Trigger(const std::string& propname, as_function& trig,
const as_value& customArg)
:
_propname(propname),
_func(&trig),
_customArg(customArg),
_executing(false),
_dead(false)
{}
/// Call the trigger
//
/// @param oldval
/// Old value being modified
///
/// @param newval
/// New value requested
///
/// @param this_obj
/// Object of which the property is being changed
///
as_value call(const as_value& oldval, const as_value& newval,
as_object& this_obj);
/// True if this Trigger has been disposed of.
bool dead() const { return _dead; }
void kill() {
_dead = true;
}
void setReachable() const;
private:
/// Name of the property
//
/// By storing a string_table::key we'd save CPU cycles
/// while adding/removing triggers and some memory
/// on each trigger, but at the cost of looking up
/// the string_table on every invocation of the watch...
///
std::string _propname;
/// The trigger function
as_function* _func;
/// A custom argument to pass to the trigger
/// after old and new value.
as_value _customArg;
/// Flag to protect from infinite loops
bool _executing;
/// Flag to check whether this trigger has been deleted.
//
/// As a trigger can be removed during execution, it shouldn't be
/// erased from the container straight away, so this flag prevents
/// any execution.
bool _dead;
};
/// The base class for all ActionScript objects
//
/// Everything in ActionScript is an object or convertible to an object. This
/// class is the base class for all object types and the implementation of the
/// ActionScript Object type itself. See asobj/Object.cpp for the ActionScript
/// Object interface.
//
/// An AS2 object has 3 principle tasks:
//
/// 1. to store a set of ActionScript properties and to control dynamic access
/// to them.
/// 2. to store native type information.
/// 3. to store 'watches' that report on changes to any member property.
//
/// A fourth but relatively minor task is to store a list of implemented
/// interfaces (see as_object::instanceOf()).
//
/// ActionScript has two different levels of Object typing:
//
/// Dynamic Typing
//
/// 1a. Native type information, stored in a Relay and inaccessible
/// to ActionScript.
/// 1b. Array type information. This is very similar (and possibly identical
/// to) Relays.
/// 2. Link to a DisplayObject.
//
/// Both these dynamic types can be changed independently at runtime using
/// native functions (often, but not always, constructor functions).
//
/// Static Typing
//
/// Functions (as_function), Super objects (as_super) and AS3 Class types
/// (as_class) have a static type, that is, they are not convertible to each
/// other once created.
class as_object : public GcResource, boost::noncopyable
{
public:
/// Construct an ActionScript object with no prototype associated.
//
/// @param global A reference to the Global object the new
/// object ultimately belongs to. The created object
/// uses the resources of the Global object.
explicit as_object(const Global_as& global);
/// The as_object dtor does nothing special.
virtual ~as_object() {}
/// Function dispatch
//
/// Various objects can be called, including functions and super objects.
/// A normal object has no call functionality, so the default
/// implementation throws an ActionTypeError.
virtual as_value call(const fn_call& fn);
/// Return the string representation for this object
//
/// This is dependent on the VM version and the type of object, function,
/// or class.
virtual std::string stringValue() const;
/// 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;
/// Find a property, scanning the inheritance chain
//
/// @param uri Property identifier.
/// @param owner If not null, this is set to the object which contained
/// an inherited property.
/// @returns A property if found and visible, NULL if not found or
/// not visible in current VM version
Property* findProperty(const ObjectURI& uri, as_object** owner = 0);
/// Return a reference to this as_object's global object.
VM& vm() const {
return _vm;
}
/// Dump all properties using log_debug
//
/// Note that it is very likely that this will result in changes to the
/// object, as accessing getter/setters or destructive properties can
/// modify properties.
//
/// Only use this function for temporary debugging!
void dump_members();
/// Set a member value
//
/// @param uri Property identifier.
/// @param val Value to assign to the named property.
/// @param ifFound If true, don't create a new member, but rather only
/// update an existing one.
/// @return true if the given member existed, false otherwise.
/// NOTE: the return doesn't tell if the member exists
/// after the call, as watch triggers might have deleted
/// it after setting.
virtual bool set_member(const ObjectURI& uri, const as_value& val,
bool ifFound = false);
/// Initialize a member value by string
//
/// This is just a wrapper around the other init_member method
/// used as a trampoline to avoid changing all classes to
/// use string_table::key directly.
//
/// @param name Name of the member.
/// @param val Value to assign to the member.
/// @param flags Flags for the new member. By default dontDelete
/// and dontEnum.
void init_member(const std::string& name, const as_value& val,
int flags = DefaultFlags);
/// Initialize a member value by key
//
/// This method has to be used by built-in classes initialization
/// (VM initialization in general) as will avoid to scan the
/// inheritance chain.
///
/// By default, members initialized by calling this function will
/// be protected from deletion and not shown in enumeration.
/// These flags can be explicitly set using the third argument.
//
/// @param uri Property identifier.
/// @param val Value to assign to the member.
///
/// @param flags Flags for the new member. By default dontDelete
/// and dontEnum.
void init_member(const ObjectURI& uri, const as_value& val,
int flags = DefaultFlags);
/// Initialize a getter/setter property by name
//
/// This is just a wrapper around the other init_property method
/// used as a trampoline to avoid changing all classes to
/// use string_table::key directly.
///
/// @param key
/// Name of the property.
/// Will be converted to lowercase if VM is initialized for SWF6 or lower.
///
/// @param getter
/// A function to invoke when this property value is requested.
/// add_ref will be called on the function.
///
/// @param setter
/// A function to invoke when setting this property's value.
/// add_ref will be called on the function.
///
/// @param flags
/// Flags for the new member. By default dontDelete and dontEnum.
/// See PropFlags::Flags.
void init_property(const std::string& key, as_function& getter,
as_function& setter, int flags = DefaultFlags);
/// Initialize a getter/setter property by name
//
/// This is just a wrapper around the other init_property method
/// used as a trampoline to avoid changing all classes to
/// use string_table::key directly.
///
/// @param key Name of the property. Will be converted to lowercase
/// if VM is initialized for SWF6 or lower.
/// @param getter A function to invoke when this property value is
/// requested.
/// @param setter A function to invoke when setting this property's
/// value.
/// @param flags Flags for the new member. By default dontDelete and
/// dontEnum. See PropFlags::Flags.
void init_property(const std::string& key, as_c_function_ptr getter,
as_c_function_ptr setter, int flags = DefaultFlags);
/// Initialize a getter/setter property by key
//
/// This method has to be used by built-in classes initialization
/// (VM initialization in general) as will avoid to scan the
/// inheritance chain.
//
/// @param uri Property identifier.
/// @param getter A function to invoke when this property value is
/// requested.
/// @param setter A function to invoke when this property value is
/// set.
/// @param flags Flags for the new member. By default dontEnum and
/// dontDelete.
void init_property(const ObjectURI& uri, as_function& getter,
as_function& setter, int flags = DefaultFlags);
/// Initialize a getter/setter property by key
//
/// This method has to be used by built-in classes initialization
/// (VM initialization in general) as will avoid to scan the
/// inheritance chain.
///
/// @param uri Property identifier.
/// @param getter A function to invoke when this property value is
/// requested.
/// @param setter A function to invoke when this property value is
/// set.
/// @param flags Flags for the new member. By default dontEnum and
/// dontDelete.
void init_property(const ObjectURI& uri, as_c_function_ptr getter,
as_c_function_ptr setter, int flags = DefaultFlags);
/// Initialize a destructive getter property
//
/// A destructive getter can be used as a place holder for the real
/// value of a property. As soon as getValue is invoked on the getter,
/// it destroys itself after setting its property to the return value of
/// getValue.
//
/// @param uri Property identifier.
/// @param getter A function to invoke when this property value is
/// requested.
/// @param flags Flags for the new member. By default dontEnum.
bool init_destructive_property(const ObjectURI& uri, as_function& getter,
int flags = PropFlags::dontEnum);
/// Initialize a destructive getter property
//
/// A destructive getter can be used as a place holder for the real
/// value of a property. As soon as getValue is invoked on the getter,
/// it destroys itself after setting its property to the return value of
/// getValue.
//
/// @param uri Property identifier.
/// @param getter A function to invoke when this property value is
/// requested.
/// @param flags Flags for the new member. By default dontEnum.
bool init_destructive_property(const ObjectURI& uri,
as_c_function_ptr getter, int flags = PropFlags::dontEnum);
/// Use this method for read-only properties.
//
/// This method achieves the same as the above init_property method.
/// Additionally, it sets the property as read-only so that a default
/// handler will be triggered when ActionScript attempts to set the
/// property.
//
/// The arguments are the same as the above init_property arguments,
/// although the setter argument is omitted.
//
/// @param key Property name id
/// @param getter The getter function
/// @param flags Property flags
void init_readonly_property(const std::string& key, as_function& getter,
int flags = DefaultFlags);
/// Use this method for read-only properties.
//
/// This method achieves the same as the above init_property method.
/// Additionally, it sets the property as read-only so that a default
/// handler will be triggered when ActionScript attempts to set the
/// property.
///
/// The arguments are the same as the above init_property arguments,
/// although the setter argument is omitted.
///
/// @param key Property name id
/// @param getter The getter function
/// @param flags Property flags
void init_readonly_property(const std::string& key,
as_c_function_ptr getter, int flags = DefaultFlags);
/// Add a watch trigger, overriding any other defined for same name.
//
/// @param uri property identifier
/// @param trig A function to invoke when this property value is
/// assigned to. The function will be called with old
/// val, new val and the custom value below. Its
/// return code will be used to set actual value
/// @param cust Custom value to always pass to the trigger as third arg
/// @return true if the trigger was successfully added, false
/// otherwise.
bool watch(const ObjectURI& uri, as_function& trig, const as_value& cust);
/// Remove a watch trigger.
//
/// @param uri Property identifier.
/// @return true if the trigger was successfully removed, false
/// otherwise (no such trigger exists).
bool unwatch(const ObjectURI& uri);
/// Get a property by name if it exists.
//
/// NOTE: accessing a getter/setter property may modify the object.
//
/// See getMember() for a property accessor that corresponds to
/// ActionScript behaviour.
//
/// @param uri Property identifier.
/// @param val Variable to assign an existing value to.
/// Will be untouched if no property with the given name
/// was found.
/// @return true if the named property was found, false otherwise.
virtual bool get_member(const ObjectURI& uri, as_value* val);
/// Get the super object of this object.
///
/// The super should be __proto__ if this is a prototype object
/// itself, or __proto__.__proto__ if this is not a prototype
/// object. This is only conceptual however, and may be more
/// convoluted to obtain the actual super.
virtual as_object* get_super(const ObjectURI& fname);
as_object* get_super();
/// Delete a property of this object, unless protected from deletion.
//
/// This function does *not* recurse in this object's prototype.
//
/// @param uri Property identifier.
/// @return a pair of boolean values expressing whether the property
/// was found (first) and whether it was deleted (second).
/// Of course a pair(false, true) would be invalid (deleted
/// a non-found property!). Valid returns are:
/// - (false, false) : property not found
/// - (true, false) : property protected from deletion
/// - (true, true) : property successfully deleted
std::pair<bool, bool> delProperty(const ObjectURI& uri);
/// Get this object's own named property, if existing.
//
/// This function does *not* recurse in this object's prototype.
//
/// @param uri Property identifier.
/// @return A Property pointer, or NULL if this object doesn't
/// contain the named property.
Property* getOwnProperty(const ObjectURI& uri);
/// Set member flags (probably used by ASSetPropFlags)
//
/// @param name Name of the property. Must be all lowercase
/// if the current VM is initialized for a target
/// up to SWF6.
/// @param setTrue The set of flags to set
/// @param setFalse The set of flags to clear
void set_member_flags(const ObjectURI& uri, int setTrue, int setFalse = 0);
/// Cast to a as_function, or return NULL
virtual as_function* to_function() { return 0; }
/// Return true if this is a 'super' object
virtual bool isSuper() const { return false; }
/// Add an interface to the list of interfaces.
//
/// This is used by the action "implements". This opcode is a compile-time
/// promise that a class will implement all the methods of an
/// otherwise unrelated interface class. The only use in AVM1 is to
/// allow instanceOf to return true when a class implements another
/// class.
//
/// @param ctor An as_object to specify as an interface implemented
/// by this object.
void addInterface(as_object* ctor);
/// Check whether this object is an instance of the given constructor
//
/// An object is an instance of a constructor if constructor.prototype is
/// found anywhere in the object's prototype chain (e.g. if
/// object.__proto__ == constructor.prototype).
//
/// It is also an instance of a constructor if the constructor is
/// listed in the object's interfaces (this is a compile-time promise
/// and has no runtime effects other than for instanceOf).
//
/// @param ctor The as_object to compare this object to. For more
/// ActionScript-like syntax it can be any object
/// or null.
/// @return true if this object is an instance of ctor. The return
/// is always false if ctor is null.
bool instanceOf(as_object* ctor);
/// Check whether this object is in another object's inheritance chain.
//
/// This is roughly the inverse of instanceOf().
//
/// @param instance The instance object to check for inheritance from
/// this object.
/// @return true if instance inherits from this object.
bool prototypeOf(as_object& instance);
/// Set property flags
//
/// @param props A comma-delimited list of property names as a string,
/// a NULL value. This is in fact a string, which should
/// be split on the ',' to an array then processed.
/// TODO: this would be much better as a free function.
//
/// @param set_false A mask of flags to set to false.
/// @param set_true A mask of flags to set to true.
void setPropFlags(const as_value& props, int set_false, int set_true);
/// Copy properties from the given object
//
/// NOTE: the __proto__ member will NOT be copied.
//
/// @param o The object to copy properties from.
void copyProperties(const as_object& o);
/// Drop all properties from this object
void clearProperties() {
_members.clear();
}
/// Visit the properties of this object by key/as_value pairs
//
/// The method will invoke the given visitor method with the identifier
/// and value of the property. Note that this access values, which may
/// change the object.
//
/// @param visitor The visitor function. Will be invoked for each property
/// of this object with an ObjectURI as first argument and
/// a const as_value as second argument.
template<typename T>
void visitProperties(PropertyVisitor& visitor) const {
_members.visitValues<T>(visitor);
}
/// Visit all visible property identifiers.
//
/// NB: this function does not access the property values, so callers
/// can be certain no values will be changed.
//
/// The enumeration recurses through the prototype chain. This
/// implementation will keep track of visited object to avoid infinite
/// loops in the prototype chain. NOTE: the MM player just chokes in
/// this case.
//
/// @param visitor The visitor function. Will be invoked for each property
/// of this object with an ObjectURI as the only argument.
void visitKeys(KeyVisitor& visitor) const;
/// Add a getter/setter property if no member already has that name.
//
/// @param key Property identifier.
/// @param getter A function to invoke when this property value
/// is requested.
/// @param setter A function to invoke when setting this property's
/// value. By passing null, the property will have no
/// setter. This is valid.
void add_property(const std::string& key, as_function& getter,
as_function* setter);
/// Return this object's __proto__ member.
//
/// The __proto__ member is the exported interface (prototype)
/// 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
//
/// 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.
//
/// This is a pointer to a native object that contains special type
/// characteristics. Setting the Relay object allows native functions
/// to get or set non-ActionScript properties.
//
/// This function should only be used in native functions such as
/// 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;
if (_relay) _relay->clean();
_relay.reset(p);
}
/// Access the as_object's Relay object.
//
/// The Relay object is a polymorphic object containing native type
/// characteristics. It is rarely useful to use this function directly.
/// Instead use the convenience functions ensure<>() and
/// isNativeType() to access the Relay object.
//
/// Relay objects are not available to ActionScript, so this object
/// should not be used in built-in functions (that is, functions
/// implemented in ActionScript).
Relay* relay() const {
return _relay.get();
}
/// Return true if this object should be treated as an array.
bool array() const {
return _array;
}
/// Set whether this object should be treated as an array.
void setArray(bool array = true) {
_array = array;
}
/// Return the DisplayObject associated with this object.
//
/// @return A DisplayObject if this is as_object is associated with
/// one, otherwise 0.
DisplayObject* displayObject() const {
return _displayObject;
}
/// Set the DisplayObject associated with this as_object.
void setDisplayObject(DisplayObject* d) {
_displayObject = d;
}
protected:
/// Construct an as_object associated with a VM.
//
/// This constructor is intended for subclasses. Although they could call
/// the public constructor that accepts a Global_as, this could imply
/// that that constructor can access members of the passed Global_as
/// other than getVM(), which might not be available because the Global_as
/// will not be fully constructed yet. While that is currently not the
/// case, using this constructor eliminates this potential initialization
/// order problem.
/// @param vm The VM to associate the newly created as_object with.
explicit as_object(VM& vm);
/// Mark all reachable resources, override from GcResource.
//
/// The default implementation marks all properties
///
/// If a derived class provides access to more GC-managed
/// resources, it should override this function and call
/// this function directly as the last step.
virtual void markReachableResources() const;
private:
/// Find an existing property for update
//
/// Scans the inheritance chain only for getter/setters or statics.
//
/// NOTE: updatable here doesn't mean the property isn't protected
/// from update but only that a set_member will NOT create a new
/// property (either completely new or as an override).
///
/// @returns a property if found, NULL if not found
/// or not visible in current VM version
///
Property* findUpdatableProperty(const ObjectURI& uri);
void executeTriggers(Property* prop, const ObjectURI& uri,
const as_value& val);
/// 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
//
/// These magic properties are invoked in get_member only if the
/// object is a DisplayObject
DisplayObject* _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
/// destructor is called.
boost::scoped_ptr<Relay> _relay;
/// The VM containing this object.
VM& _vm;
/// Properties of this as_object
PropertyList _members;
/// The constructors of the objects implemented by this as_object.
//
/// There is no need to use a complex container as the list of
/// interfaces is generally small and the opcode rarely used anyway.
std::vector<as_object*> _interfaces;
typedef std::map<ObjectURI, Trigger, ObjectURI::LessThan> TriggerContainer;
boost::scoped_ptr<TriggerContainer> _trigs;
};
/// Send a system event
//
/// This is used for broadcasting system events. The prototype search is
/// carried out, but there is no call to __resolve and triggers
/// are not processed.
//
/// The function is called with no arguments.
//
/// @param o The object to send the event to.
/// @param env The environment to use, generally provided by the calling
/// DisplayObject
/// @param name The name of the function to call.
void sendEvent(as_object& o, const as_environment& env, const ObjectURI& name);
/// Get a member of an object using AS lookup rules
//
/// This is a wrapper round as_object::get_member that returns undefined if
/// the member is not found.
//
/// Note: this is the only full lookup process available in ActionScript code.
//
//
/// @param uri Property identifier.
/// @param o The object whose member is required.
/// @return Value of the member (possibly undefined),
/// or undefined if not found. Use get_member if you
/// need to know whether it was found or not.
inline as_value
getMember(as_object& o, const ObjectURI& uri)
{
as_value ret;
o.get_member(uri, &ret);
return ret;
}
/// Get an own member of an object.
//
/// This is a wrapper round as_object::getOwnProperty that returns undefined if
/// the member is not found.
//
/// Note: this requires two steps in ActionScript (hasOwnProperty + lookup), so
/// is probably only for use in native functions.
//
/// @param uri Property identifier.
/// @param o The object whose own member is required.
/// @return Value of the member (possibly undefined),
/// or undefined if not found. Use get_member if you
/// need to know whether it was found or not.
inline as_value
getOwnProperty(as_object& o, const ObjectURI& uri)
{
Property* p = o.getOwnProperty(uri);
return p ? p->getValue(o) : as_value();
}
/// Function objects for visiting properties.
class IsVisible
{
public:
IsVisible(int version) : _version(version) {}
bool operator()(const Property& prop) const {
return visible(prop, _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().test<PropFlags::dontEnum>();
}
};
/// 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.
/// @return the url-encoded variables string without any leading
/// delimiter.
std::string getURLEncodedVars(as_object& o);
/// Resolve the given relative path component
//
/// Path components are only objects, if the given string
/// points to a non-object member, NULL is returned.
///
/// Main use if for getvariable and settarget resolution,
/// currently implemented in as_environment.
as_object* getPathElement(as_object& o, const ObjectURI& uri);
/// Extract the DisplayObject attached to an object
//
/// @return 0 if no DisplayObject is attached, or if it is not the
/// requested type
/// @param o The object to check.
template<typename T>
T*
get(as_object* o)
{
if (!o) return 0;
return dynamic_cast<T*>(o->displayObject());
}
/// Return true if this object has the named property
//
/// @param o The object whose property should be searched for.
/// @param uri Property identifier.
/// @return true if the object has the property, false otherwise.
inline bool
hasOwnProperty(as_object& o, const ObjectURI& uri)
{
return (o.getOwnProperty(uri));
}
as_object* getObjectWithPrototype(Global_as& gl, const ObjectURI& c);
/// Check whether the object is an instance of a known type.
//
/// This is used to check the type of certain objects when it can't be
/// done through ActionScript and properties. Examples include conversion
/// of Date and String objects.
//
/// @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
isNativeType(const as_object* obj, T*& relay)
{
if (!obj) return false;
relay = dynamic_cast<T*>(obj->relay());
return relay;
}
/// This is used to hold an intermediate copy of an as_object's properties.
//
/// AS enumerates in reverse order of creation because these values are
/// pushed to the stack. The first value to be popped is then the oldest
/// property.
typedef std::vector<std::pair<ObjectURI, as_value> > SortedPropertyList;
/// Enumerate all non-hidden properties to the passed container
//
/// NB: it is likely that this call will change the object, as accessing
/// property values may call getter-setters.
//
/// The enumeration recurses through the prototype chain. This implementation
/// will keep track of visited object to avoid infinite loops in the
/// prototype chain. NOTE: the Adobe player just chokes in this case.
//
/// Note that the last element of the returned container is the oldest
/// property, so iterate in reverse to mimic AS behaviour.
//
/// @param o The object whose properties should be enumerated.
/// @return A list of properties in reverse creation order.
SortedPropertyList enumerateProperties(as_object& o);
/// Get the VM from an as_object.
VM& getVM(const as_object& o);
/// Get the movie_root from an as_object.
movie_root& getRoot(const as_object& o);
/// Get the string_table from an as_object.
string_table& getStringTable(const as_object& o);
/// Get the RunResources from an as_object.
const RunResources& getRunResources(const as_object& o);
/// Get the executing VM version from an as_object.
int getSWFVersion(const as_object& o);
/// Get the Global object from an as_object.
Global_as& getGlobal(const as_object& o);
/// Return whether property matching is caseless
inline bool caseless(const as_object& o) {
return getSWFVersion(o) < 7;
}
} // namespace gnash
#endif // GNASH_AS_OBJECT_H