[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gnash-commit] /srv/bzr/gnash/trunk r11662: Fixes and cleanups to functi
From: |
Benjamin Wolsey |
Subject: |
[Gnash-commit] /srv/bzr/gnash/trunk r11662: Fixes and cleanups to function execution and construction. |
Date: |
Mon, 30 Nov 2009 17:49:34 +0100 |
User-agent: |
Bazaar (1.16.1) |
------------------------------------------------------------
revno: 11662 [merge]
committer: Benjamin Wolsey <address@hidden>
branch nick: trunk
timestamp: Mon 2009-11-30 17:49:34 +0100
message:
Fixes and cleanups to function execution and construction.
added:
testsuite/misc-swfmill.all/trace-as2/arguments.trace
testsuite/misc-swfmill.all/trace-as2/arguments.xml
testsuite/misc-swfmill.all/trace-as2/this.trace
testsuite/misc-swfmill.all/trace-as2/this.xml
modified:
libcore/MovieClip.cpp
libcore/TextField.cpp
libcore/as_environment.cpp
libcore/as_environment.h
libcore/as_function.cpp
libcore/as_function.h
libcore/as_value.cpp
libcore/asobj/Color_as.cpp
libcore/asobj/Date_as.cpp
libcore/asobj/Globals.cpp
libcore/asobj/Object.cpp
libcore/asobj/String_as.cpp
libcore/asobj/flash/display/BitmapData_as.cpp
libcore/asobj/flash/display/MovieClip_as.cpp
libcore/asobj/flash/filters/BitmapFilter_as.cpp
libcore/asobj/flash/geom/Matrix_as.cpp
libcore/asobj/flash/geom/Point_as.cpp
libcore/asobj/flash/geom/Rectangle_as.cpp
libcore/asobj/flash/geom/Transform_as.cpp
libcore/asobj/flash/net/SharedObject_as.cpp
libcore/asobj/flash/net/XMLSocket_as.cpp
libcore/asobj/flash/ui/ContextMenuItem_as.cpp
libcore/asobj/flash/ui/ContextMenu_as.cpp
libcore/asobj/flash/ui/Mouse_as.cpp
libcore/asobj/flash/xml/XMLDocument_as.cpp
libcore/builtin_function.h
libcore/swf_function.cpp
libcore/swf_function.h
libcore/vm/ASHandlers.cpp
libcore/vm/ActionExec.cpp
libcore/vm/CallStack.cpp
libcore/vm/CallStack.h
libcore/vm/Machine.cpp
testsuite/misc-swfmill.all/trace-as2/Makefile.am
testsuite/misc-swfmill.all/trace-as2/PASSING
testsuite/misc-swfmill.all/trace-as2/super.xml
=== modified file 'libcore/MovieClip.cpp'
--- a/libcore/MovieClip.cpp 2009-11-29 09:24:30 +0000
+++ b/libcore/MovieClip.cpp 2009-11-30 13:09:55 +0000
@@ -991,17 +991,16 @@
// and stop at that frame.
setPlayState(PLAYSTATE_STOP);
- if ( target_frame_number > _def->get_frame_count() - 1)
- {
+ if (target_frame_number > _def->get_frame_count() - 1) {
+
target_frame_number = _def->get_frame_count() - 1;
- if ( ! _def->ensure_frame_loaded(target_frame_number+1) )
- {
+ if (!_def->ensure_frame_loaded(target_frame_number + 1)) {
log_error(_("Target frame of a gotoFrame(%d) was never loaded,"
"although frame count in header (%d) said we "
"should have found it"),
target_frame_number+1, _def->get_frame_count());
- return; // ... I guess, or not ?
+ return;
}
// Just set _currentframe and return.
@@ -1011,25 +1010,23 @@
return;
}
- if (target_frame_number == _currentFrame)
- {
+ if (target_frame_number == _currentFrame) {
// don't push actions
return;
}
// Unless the target frame is the next one, stop playback of soundstream
- if (target_frame_number != _currentFrame+1 )
- {
+ if (target_frame_number != _currentFrame + 1) {
stopStreamSound();
}
- size_t loaded_frames = get_loaded_frames();
+ const size_t loaded_frames = get_loaded_frames();
+
// target_frame_number is 0-based, get_loaded_frames() is 1-based
// so in order to goto_frame(3) loaded_frames must be at least 4
// if goto_frame(4) is called, and loaded_frames is 4 we're jumping
// forward
- if ( target_frame_number >= loaded_frames )
- {
+ if (target_frame_number >= loaded_frames) {
IF_VERBOSE_ASCODING_ERRORS(
log_aserror(_("GotoFrame(%d) targets a yet "
"to be loaded frame (%d) loaded). "
@@ -1039,13 +1036,12 @@
loaded_frames);
);
- if ( ! _def->ensure_frame_loaded(target_frame_number+1) )
- {
+ if (!_def->ensure_frame_loaded(target_frame_number + 1)) {
log_error(_("Target frame of a gotoFrame(%d) was never loaded, "
"although frame count in header (%d) said we should"
" have found it"),
- target_frame_number+1, _def->get_frame_count());
- return; // ... I guess, or not ?
+ target_frame_number + 1, _def->get_frame_count());
+ return;
}
}
@@ -1054,8 +1050,8 @@
// Construct the DisplayList of the target frame
//
- if (target_frame_number < _currentFrame)
- {
+ if (target_frame_number < _currentFrame) {
+
// Go backward to a previous frame
// NOTE: just in case we're being called by code in a called frame
// we'll backup and resume the _callingFrameActions flag
@@ -1068,13 +1064,11 @@
assert(_currentFrame == target_frame_number);
_callingFrameActions = callingFrameActionsBackup;
}
- else
- // Go forward to a later frame
- {
+ else {
+ // Go forward to a later frame
// We'd immediately return if target_frame_number == _currentFrame
assert(target_frame_number > _currentFrame);
- while (++_currentFrame < target_frame_number)
- {
+ while (++_currentFrame < target_frame_number) {
//for (size_t f = _currentFrame+1; f<target_frame_number; ++f)
// Second argument requests that only "DisplayList" tags
// are executed. This means NO actions will be
@@ -1084,7 +1078,6 @@
}
assert(_currentFrame == target_frame_number);
-
// Now execute target frame tags (queuing actions)
// NOTE: just in case we're being called by code in a called frame
// we'll backup and resume the _callingFrameActions flag
@@ -1107,17 +1100,16 @@
if (!_def) return false;
size_t target_frame;
- if (_def->get_labeled_frame(label, target_frame))
- {
+ if (_def->get_labeled_frame(label, target_frame)) {
goto_frame(target_frame);
return true;
}
- IF_VERBOSE_MALFORMED_SWF(
+ IF_VERBOSE_MALFORMED_SWF(
log_swferror(_("MovieClip::goto_labeled_frame('%s') "
"unknown label"), label);
- );
- return false;
+ );
+ return false;
}
void
@@ -1867,98 +1859,42 @@
void
MovieClip::constructAsScriptObject()
{
-#ifdef GNASH_DEBUG
- log_debug(_("constructAsScriptObject called for movieclip %s"),
- getTarget());
-#endif
-
- if (!isAS3(getVM(*getObject(this))) && !get_parent()) {
- getObject(this)->init_member("$version",
getVM(*getObject(this)).getPlayerVersion(), 0);
- }
-
- bool eventHandlersInvoked = false;
-
- do {
-
- if ( _name.empty() )
- {
- // instance name will be needed for properly setting up
- // a reference to 'this' object for ActionScript actions.
- // If the instance doesn't have a name, it will NOT be
- // an ActionScript referenceable object so we don't have
- // anything more to do.
- break;
- }
-
- const sprite_definition* def =
- dynamic_cast<const sprite_definition*>(_def.get());
-
- // We won't "construct" top-level movies
- if (!def) break;
-
- as_function* ctor = def->getRegisteredClass();
-#ifdef GNASH_DEBUG
- log_debug(_("Attached movieclips %s registered class is %p"),
- getTarget(), (void*)ctor);
-#endif
-
- // TODO: builtin constructors are different from user-defined ones
- // we should likely change that. See also vm/ASHandlers.cpp
- // (construct_object)
- if ( ctor && ! ctor->isBuiltin() )
- {
- // Set the new prototype *after* the constructor was called
- as_value proto = ctor->getMember(NSV::PROP_PROTOTYPE);
- getObject(this)->set_prototype(proto);
-
- // Call event handlers *after* setting up the __proto__
- // but *before* calling the registered class constructor
- notifyEvent(event_id::CONSTRUCT);
- eventHandlersInvoked = true;
-
- int swfversion = getSWFVersion(*getObject(this));
-
- // Set the '__constructor__' and 'constructor' members, as well
- // as calling the actual constructor.
- //
- // TODO: this would be best done by an
- // as_function::constructInstance() method. We have one but it
- // returns a new object rather then initializing a given object.
- // We just need to add another one...
- if ( swfversion > 5 )
- {
-
- const int flags = PropFlags::dontEnum;
-
- getObject(this)->set_member(NSV::PROP_uuCONSTRUCTORuu, ctor);
- getObject(this)->set_member_flags(NSV::PROP_uuCONSTRUCTORuu,
flags);
- if ( swfversion == 6 )
- {
- getObject(this)->set_member(NSV::PROP_CONSTRUCTOR, ctor);
- getObject(this)->set_member_flags(NSV::PROP_CONSTRUCTOR,
flags);
- }
-
- // Provide a 'super' reference..
- // Super is computed from the object we're constructing,
- // It will work as long as we did set its __proto__
- // and __constructor__ properties already.
- as_object* super = getObject(this)->get_super();
-
- as_environment& env = get_environment();
- fn_call call(getObject(this), env);
- call.super = super;
-
- // we don't use the constructor return (should we?)
- ctor->call(call);
- }
- }
-
- } while (0);
-
- /// Invoke event handlers if not done yet
- if ( ! eventHandlersInvoked )
- {
- notifyEvent(event_id::CONSTRUCT);
+ as_object* mc = getObject(this);
+
+ // A MovieClip should always have an associated object.
+ assert(mc);
+
+ if (!isAS3(getVM(*mc)) && !get_parent()) {
+ mc->init_member("$version", getVM(*mc).getPlayerVersion(), 0);
+ }
+
+ const sprite_definition* def =
+ dynamic_cast<const sprite_definition*>(_def.get());
+
+ // We won't "construct" top-level movies
+ as_function* ctor = def ? def->getRegisteredClass() : 0;
+
+#ifdef GNASH_DEBUG
+ log_debug(_("Attached movieclips %s registered class is %p"),
+ getTarget(), (void*)ctor);
+#endif
+
+ // Set this MovieClip object to be an instance of the class.
+ if (ctor) {
+ Property* proto = ctor->getOwnProperty(NSV::PROP_PROTOTYPE);
+ if (proto) mc->set_prototype(proto->getValue(*ctor));
+ }
+
+ // Send the construct event. This must be done after the __proto__
+ // member is set. It is always done.
+ notifyEvent(event_id::CONSTRUCT);
+
+ if (ctor) {
+ const int swfversion = getSWFVersion(*mc);
+ if (swfversion > 5) {
+ fn_call::Args args;
+ ctor->construct(*mc, get_environment(), args);
+ }
}
}
=== modified file 'libcore/TextField.cpp'
--- a/libcore/TextField.cpp 2009-11-18 11:51:35 +0000
+++ b/libcore/TextField.cpp 2009-11-30 11:12:37 +0000
@@ -134,7 +134,7 @@
if (!ctor) return 0;
fn_call::Args args;
as_environment env(getVM(gl));
- return ctor->constructInstance(env, args);
+ return constructInstance(*ctor, env, args);
}
@@ -3289,7 +3289,7 @@
if (!ctor) return as_value();
fn_call::Args args;
- as_object* textformat = ctor->constructInstance(fn.env(), args);
+ as_object* textformat = constructInstance(*ctor, fn.env(), args);
TextFormat_as* tf;
if (!isNativeType(textformat, tf)) {
=== modified file 'libcore/as_environment.cpp'
--- a/libcore/as_environment.cpp 2009-11-13 09:02:34 +0000
+++ b/libcore/as_environment.cpp 2009-11-30 15:59:02 +0000
@@ -57,10 +57,10 @@
///
/// @return true if the variable was found, false otherwise
bool
-getLocal(as_object* locals, const std::string& name, as_value& ret)
+getLocal(as_object& locals, const std::string& name, as_value& ret)
{
- string_table& st = getStringTable(*locals);
- return locals->get_member(st.find(name), &ret);
+ string_table& st = getStringTable(locals);
+ return locals.get_member(st.find(name), &ret);
}
/// Delete a local variable
@@ -69,12 +69,30 @@
/// Name of the local variable
///
/// @return true if the variable was found and deleted, false otherwise
-///
-bool
-deleteLocal(as_object* locals, const std::string& varname)
-{
- string_table& st = getStringTable(*locals);
- return locals->delProperty(st.find(varname)).second;
+bool
+deleteLocal(as_object& locals, const std::string& varname)
+{
+ string_table& st = getStringTable(locals);
+ return locals.delProperty(st.find(varname)).second;
+}
+
+/// Set a variable of the given object, if it exists.
+//
+/// @param varname
+/// Name of the local variable
+///
+/// @param val
+/// Value to assign to the variable
+///
+/// @return true if the variable was found, false otherwise
+bool
+setLocal(as_object& locals, const std::string& varname, const as_value& val)
+{
+ string_table& st = getStringTable(locals);
+ Property* prop = locals.getOwnProperty(st.find(varname));
+ if (!prop) return false;
+ prop->setValue(locals, val);
+ return true;
}
as_object*
@@ -431,10 +449,10 @@
else
{
// Not in frame; create a new local var.
- assert( ! varname.empty() ); // null varnames are invalid!
- as_object* locals = _localFrames.back().locals;
+ assert(!varname.empty()); // null varnames are invalid!
+ as_object& locals = _localFrames.back().locals();
//locals.push_back(as_environment::frame_slot(varname, val));
- locals->set_member(varkey, val);
+ locals.set_member(varkey, val);
}
}
@@ -446,10 +464,10 @@
if ( ! findLocal(varname, tmp) )
{
// Not in frame; create a new local var.
- assert( ! _localFrames.empty() );
+ assert(!_localFrames.empty());
assert( ! varname.empty() ); // null varnames are invalid!
- as_object* locals = _localFrames.back().locals;
- locals->set_member(_vm.getStringTable().find(varname), as_value());
+ as_object& locals = _localFrames.back().locals();
+ locals.set_member(_vm.getStringTable().find(varname), as_value());
}
}
@@ -744,45 +762,28 @@
return _vm.getSWFVersion();
}
-static void
-dump(const as_environment::Registers& r, std::ostream& out)
-{
- for (size_t i=0; i<r.size(); ++i)
- {
- if (i) out << ", ";
- out << i << ':' << '"' << r[i] << '"';
- }
-}
-
void
as_environment::dump_local_registers(std::ostream& out) const
{
if ( _localFrames.empty() ) return;
out << "Local registers: ";
-#ifndef DUMP_LOCAL_REGISTERS_IN_ALL_CALL_FRAMES
- dump(_localFrames.back().registers, out);
-#else
for (CallStack::const_iterator it=_localFrames.begin(),
- itEnd=_localFrames.end();
- it != itEnd; ++it)
- {
- if ( it != _localFrames.begin() ) out << " | ";
- dump(it->registers, out);
+ itEnd=_localFrames.end(); it != itEnd; ++it) {
+ if (it != _localFrames.begin()) out << " | ";
+ out << *it;
}
-#endif
out << std::endl;
}
static void
-dump(const as_object* locals, std::ostream& out)
+dump(as_object& locals, std::ostream& out)
{
typedef std::map<std::string, as_value> PropMap;
PropMap props;
- const_cast<as_object*>(locals)->dump_members(props);
+ locals.dump_members(props);
int count = 0;
- for (PropMap::iterator i=props.begin(), e=props.end(); i!=e; ++i)
- {
+ for (PropMap::iterator i=props.begin(), e=props.end(); i!=e; ++i) {
if (count++) out << ", ";
// TODO: define output operator for as_value !
out << i->first << "==" << i->second;
@@ -795,17 +796,12 @@
{
if ( _localFrames.empty() ) return;
out << "Local variables: ";
-#ifndef DUMP_LOCAL_VARIABLES_IN_ALL_CALL_FRAMES
- dump(_localFrames.back().locals, out);
-#else
- for (CallStack::const_iterator it=_localFrames.begin(),
- itEnd=_localFrames.end();
- it != itEnd; ++it)
- {
+ for (CallStack::iterator it=_localFrames.begin(),
+ itEnd=_localFrames.end(); it != itEnd; ++it) {
+
if ( it != _localFrames.begin() ) out << " | ";
- dump(it->locals, out);
+ dump(it->locals(), out);
}
-#endif
out << std::endl;
}
@@ -818,7 +814,7 @@
ss << "Global registers: ";
int defined=0;
- for (unsigned int i=0; i<numGlobalRegisters; ++i)
+ for (unsigned int i = 0; i < numGlobalRegisters; ++i)
{
if ( m_global_register[i].is_undefined() ) continue;
@@ -836,9 +832,10 @@
{
if (_localFrames.empty()) return false;
- if (getLocal(_localFrames.back().locals, varname, ret)) {
+ as_object& locals = _localFrames.back().locals();
- if (retTarget) *retTarget = _localFrames.back().locals;
+ if (getLocal(locals, varname, ret)) {
+ if (retTarget) *retTarget = &locals;
return true;
}
@@ -849,28 +846,21 @@
as_environment::delLocal(const std::string& varname)
{
if (_localFrames.empty()) return false;
- return deleteLocal(_localFrames.back().locals, varname);
+ return deleteLocal(_localFrames.back().locals(), varname);
}
bool
as_environment::setLocal(const std::string& varname, const as_value& val)
{
if (_localFrames.empty()) return false;
- return setLocal(_localFrames.back().locals, varname, val);
-}
-bool
-as_environment::setLocal(as_object* locals, const std::string& varname,
- const as_value& val)
-{
- Property* prop =
locals->getOwnProperty(_vm.getStringTable().find(varname));
- if (!prop) return false;
- prop->setValue(*locals, val);
- return true;
+ // If this name is not qualified, the compiler fails to look beyond
+ // as_environment::setLocal.
+ return gnash::setLocal(_localFrames.back().locals(), varname, val);
}
void
-as_environment::pushCallFrame(as_function* func)
+as_environment::pushCallFrame(as_function& func)
{
// The stack size can be changed by the ScriptLimits
@@ -878,7 +868,7 @@
// TODO: override from gnashrc.
// A stack size of 0 is apparently legitimate.
- const boost::uint16_t recursionLimit = getRoot(*func).getRecursionLimit();
+ const boost::uint16_t recursionLimit = getRoot(func).getRecursionLimit();
// Don't proceed if local call frames would reach the recursion limit.
if (_localFrames.size() + 1 >= recursionLimit) {
@@ -890,7 +880,7 @@
throw ActionLimitException(ss.str());
}
- _localFrames.push_back(CallFrame(func));
+ _localFrames.push_back(CallFrame(&func));
}
@@ -904,15 +894,7 @@
void
as_environment::set_target(DisplayObject* target)
{
- //assert(target);
- if ( ! _original_target )
- {
- //assert(target); // we assume any as_environment creator sets a
target too I guess..
- // WRONG ASSUMPTION: ^^^^^^^^^ : as_value::to_primitive doesn't care
about setting a target here
-
- //log_debug("as_environment(%p)::set_target(%p): setting original
target to %s", this, target, target ? target->getTarget() : "<null>");
- _original_target = target;
- }
+ if (!_original_target) _original_target = target;
m_target = target;
}
@@ -922,8 +904,8 @@
assert(!varname.empty());
assert(!_localFrames.empty());
- as_object* locals = _localFrames.back().locals;
- locals->set_member(_vm.getStringTable().find(varname), val);
+ as_object& locals = _localFrames.back().locals();
+ locals.set_member(_vm.getStringTable().find(varname), val);
}
void
@@ -953,36 +935,43 @@
unsigned int
as_environment::setRegister(unsigned int regnum, const as_value& v)
{
- if (_localFrames.empty() || _localFrames.back().registers.empty()) {
- if ( regnum >= numGlobalRegisters ) return 0;
+ // If there is a call frame and it has registers, the value must be
+ // set there.
+ if (!_localFrames.empty()) {
+ CallFrame& fr = _localFrames.back();
+ if (fr.hasRegisters()) {
+ if (_localFrames.back().setRegister(regnum, v)) return 2;
+ return 0;
+ }
+ }
+
+ if (regnum < numGlobalRegisters) {
m_global_register[regnum] = v;
return 1;
}
- Registers& registers = _localFrames.back().registers;
- if (regnum < registers.size()) {
- registers[regnum] = v;
- return 2;
- }
-
return 0;
}
unsigned int
as_environment::getRegister(unsigned int regnum, as_value& v)
{
- if (_localFrames.empty() || _localFrames.back().registers.empty()) {
- if ( regnum >= numGlobalRegisters ) return 0;
+ // If there is a call frame and it has registers, the value must be
+ // sought there.
+ if (!_localFrames.empty()) {
+ const CallFrame& fr = _localFrames.back();
+ if (fr.hasRegisters()) {
+ if (fr.getRegister(regnum, v)) return 2;
+ return 0;
+ }
+ }
+
+ // Otherwise it can be in the global registers.
+ if (regnum < numGlobalRegisters) {
v = m_global_register[regnum];
return 1;
}
- Registers& registers = _localFrames.back().registers;
- if (regnum < registers.size()) {
- v = registers[regnum];
- return 2;
- }
-
return 0;
}
=== modified file 'libcore/as_environment.h'
--- a/libcore/as_environment.h 2009-11-13 08:18:42 +0000
+++ b/libcore/as_environment.h 2009-11-30 15:59:02 +0000
@@ -47,8 +47,6 @@
/// A stack of objects used for variables/members lookup
typedef std::vector<as_object*> ScopeStack;
- typedef std::vector<as_value> Registers;
-
as_environment(VM& vm);
VM& getVM() const { return _vm; }
@@ -219,7 +217,7 @@
///
void add_local_registers(unsigned int register_count) {
assert(!_localFrames.empty());
- return _localFrames.back().registers.resize(register_count);
+ return _localFrames.back().resizeRegisters(register_count);
}
/// Set value of a register (local or global).
@@ -275,22 +273,10 @@
///
unsigned int getRegister(unsigned int regnum, as_value& v);
- /// Return a reference to the Nth local register.
- //
- /// Local registers are only meaningful within a function2 context.
- ///
- as_value& local_register(boost::uint8_t n) {
- assert(!_localFrames.empty());
- return _localFrames.back().registers[n];
- }
-
/// Set the Nth local register to something
void set_local_register(boost::uint8_t n, as_value &val) {
if (! _localFrames.empty()) {
- Registers& registers = _localFrames.back().registers;
- if (n < registers.size()) {
- registers[n] = val;
- }
+ _localFrames.back().setRegister(n, val);
}
}
@@ -416,8 +402,9 @@
class FrameGuard
{
as_environment& _env;
+
public:
- FrameGuard(as_environment& env, as_function* func)
+ FrameGuard(as_environment& env, as_function& func)
:
_env(env)
{
@@ -474,7 +461,7 @@
/// @param func
/// The function being called
///
- void pushCallFrame(as_function* func);
+ void pushCallFrame(as_function& func);
/// Remove current call frame from the stack
//
@@ -545,18 +532,6 @@
///
bool setLocal(const std::string& varname, const as_value& val);
- /// Set a variable of the given object, if it exists.
- //
- /// @param varname
- /// Name of the local variable
- ///
- /// @param val
- /// Value to assign to the variable
- ///
- /// @return true if the variable was found, false otherwise
- ///
- bool setLocal(as_object* locals, const std::string& varname, const
as_value& val);
-
static as_value undefVal;
};
=== modified file 'libcore/as_function.cpp'
--- a/libcore/as_function.cpp 2009-11-29 09:24:30 +0000
+++ b/libcore/as_function.cpp 2009-11-30 12:06:32 +0000
@@ -30,6 +30,7 @@
#include "namedStrings.h"
#include "NativeFunction.h"
#include "Object.h"
+#include "DisplayObject.h"
#include <iostream>
@@ -90,40 +91,41 @@
}
as_object*
-as_function::constructInstance(const as_environment& env, fn_call::Args& args)
+constructInstance(as_function& ctor, const as_environment& env,
+ fn_call::Args& args)
{
-
-#ifndef GNASH_USE_GC
- assert(get_ref_count() > 0);
-#endif // GNASH_USE_GC
-
- int swfversion = getSWFVersion(env);
-
- Property* proto = getOwnProperty(NSV::PROP_PROTOTYPE);
-
+ Global_as& gl = getGlobal(ctor);
+
// Create an empty object, with a ref to the constructor's prototype.
// The function's prototype property always becomes the new object's
// __proto__ member, regardless of whether it is an object and regardless
// of its visibility.
- as_object* newobj = new as_object();
- if (proto) newobj->set_prototype(proto->getValue(*this));
+ as_object* newobj = new as_object(gl);
+ Property* proto = ctor.getOwnProperty(NSV::PROP_PROTOTYPE);
+ if (proto) newobj->set_prototype(proto->getValue(ctor));
+
+ return ctor.construct(*newobj, env, args);
+}
+
+as_object*
+as_function::construct(as_object& newobj, const as_environment& env,
+ fn_call::Args& args)
+{
+ const int swfversion = getSWFVersion(env);
+
+ // Add a __constructor__ member to the new object visible from version 6.
+ const int flags = PropFlags::dontEnum |
+ PropFlags::onlySWF6Up;
+
+ newobj.init_member(NSV::PROP_uuCONSTRUCTORuu, this, flags);
+
+ if (swfversion < 7) {
+ newobj.init_member(NSV::PROP_CONSTRUCTOR, this, PropFlags::dontEnum);
+ }
- // Add a __constructor__ member to the new object, but only for SWF6 up
- // (to be checked). NOTE that we assume the builtin constructors
- // won't set __constructor__ to some other value...
- int flags = PropFlags::dontEnum |
- PropFlags::onlySWF6Up;
-
- newobj->init_member(NSV::PROP_uuCONSTRUCTORuu, as_value(this), flags);
-
- if (swfversion < 7) {
- newobj->init_member(NSV::PROP_CONSTRUCTOR, as_value(this),
- PropFlags::dontEnum);
- }
-
// Don't set a super so that it will be constructed only if required
// by the function.
- fn_call fn(newobj, env, args, 0, true);
+ fn_call fn(&newobj, env, args, 0, true);
as_value ret;
try {
@@ -149,19 +151,20 @@
// 'this' pointer. Others return a new object. This is to handle those
// cases.
if (isBuiltin() && ret.is_object()) {
- newobj = ret.to_object(getGlobal(env));
+ as_object* fakeobj = ret.to_object(getGlobal(env));
- newobj->init_member(NSV::PROP_uuCONSTRUCTORuu, as_value(this),
+ fakeobj->init_member(NSV::PROP_uuCONSTRUCTORuu, as_value(this),
flags);
// Also for SWF5+ only?
if (swfversion < 7) {
- newobj->init_member(NSV::PROP_CONSTRUCTOR, as_value(this),
+ fakeobj->init_member(NSV::PROP_CONSTRUCTOR, as_value(this),
PropFlags::dontEnum);
}
+ return fakeobj;
}
- return newobj;
+ return &newobj;
}
@@ -334,24 +337,15 @@
}
else {
new_fn_call.this_ptr = this_ptr;
- as_object* proto = this_ptr->get_prototype();
- if (proto) {
- // Note: do not override fn_call::super by creating a super
- // object, as it may not be needed. Doing so can have a very
- // detrimental effect on memory usage!
- // Normal supers will be created when needed in the function
- // call.
+ // Note: do not override fn_call::super by creating a super
+ // object, as it may not be needed. Doing so can have a very
+ // detrimental effect on memory usage!
+ // Normal supers will be created when needed in the function
+ // call.
- // TODO: it seems pointless to copy the old fn_call and
- // then change almost everything...
- new_fn_call.super = 0;
- }
- else {
- // TODO: check this !
- log_debug("No prototype in 'this' pointer "
- "passed to Function.call");
- new_fn_call.super = function_obj->get_super();
- }
+ // TODO: it seems pointless to copy the old fn_call and
+ // then change almost everything...
+ new_fn_call.super = 0;
}
new_fn_call.drop_bottom();
}
=== modified file 'libcore/as_function.h'
--- a/libcore/as_function.h 2009-11-29 09:27:07 +0000
+++ b/libcore/as_function.h 2009-11-30 12:32:56 +0000
@@ -67,27 +67,33 @@
// Avoid RTTI
as_function* to_function() { return this; }
- /// Function dispatch.
- //
+ /// Function dispatch. //
/// Override from as_object, although as_objects cannot generally
/// be called.
virtual as_value call(const fn_call& fn) = 0;
- /// Construct an instance of this class
- //
- /// Post-conditions:
- /// - The returned object is an instance of this class.
- /// See as_object::instanceOf
- ///
- /// @param env
- /// The environment to use for stack, local variables,
- /// registers and scope chain.
- ///
- /// @param args
- /// Arguments for the constructor invocation
- ///
- as_object* constructInstance(const as_environment& env,
- fn_call::Args& args);
+ /// Run this function as a constructor on an object
+ //
+ /// This function assigns various constructor properties and runs the
+ /// constructor.
+ //
+ /// NB: This function does not make the object an 'instance of' the
+ /// constructor, i.e. it does not assign a __proto__ property. For
+ /// ActionScript compatibility, callers should ensure this is already
+ /// done.
+ //
+ /// @param newobj The object to construct. This will be used as the
+ /// 'this' object in the constructor.
+ /// @param env The environment to use for stack, local variables,
+ /// registers and scope chain.
+ /// @param args Arguments for the constructor invocation
+ /// @return The constructed object. TODO: return void; currently
+ /// there is a hack to cope with some remaining bogus
+ /// constructors (Microphone and Camera), which
+ /// necessitates returning a different object from the
+ /// passed 'this' pointer.
+ as_object* construct(as_object& newobj, const as_environment& env,
+ fn_call::Args& args);
/// Return true if this is a built-in class.
virtual bool isBuiltin() { return false; }
@@ -105,6 +111,21 @@
};
+
+/// Construct a new object from the given constructor
+//
+/// This function takes care of creating the new object and assigning the
+/// __proto__ property. The construct() function is then called with the
+/// new object as its 'this' object.
+//
+/// @param ctor The constructor to run.
+/// @param env The environment to use for the function call.
+/// @param arg The arguments to pass to the constructor function.
+/// @return A newly-created object constructed by the specified
+/// function.
+as_object* constructInstance(as_function& ctor, const as_environment& env,
+ fn_call::Args& args);
+
/// Initialize the global Function constructor
void function_class_init(as_object& global, const ObjectURI& uri);
void registerFunctionNative(as_object& global);
=== modified file 'libcore/as_value.cpp'
--- a/libcore/as_value.cpp 2009-11-27 10:30:36 +0000
+++ b/libcore/as_value.cpp 2009-11-30 11:12:37 +0000
@@ -2186,7 +2186,7 @@
if (ctor) {
fn_call::Args args;
args += dub;
- ret.set_as_object(ctor->constructInstance(as_environment(vm),
+ ret.set_as_object(constructInstance(*ctor, as_environment(vm),
args));
}
=== modified file 'libcore/asobj/Color_as.cpp'
--- a/libcore/asobj/Color_as.cpp 2009-11-18 11:51:35 +0000
+++ b/libcore/asobj/Color_as.cpp 2009-11-30 10:31:53 +0000
@@ -103,9 +103,9 @@
as_value
color_getrgb(const fn_call& fn)
{
- boost::intrusive_ptr<as_object> obj = ensure<ThisIs<as_object> >(fn);
+ as_object* obj = ensure<ValidThis>(fn);
- MovieClip* sp = getTarget(obj.get(), fn);
+ MovieClip* sp = getTarget(obj, fn);
if (!sp) return as_value();
const cxform& trans = sp->get_user_cxform();
@@ -122,9 +122,9 @@
as_value
color_gettransform(const fn_call& fn)
{
- boost::intrusive_ptr<as_object> obj = ensure<ThisIs<as_object> >(fn);
+ as_object* obj = ensure<ValidThis>(fn);
- MovieClip* sp = getTarget(obj.get(), fn);
+ MovieClip* sp = getTarget(obj, fn);
if (!sp) return as_value();
const cxform& cx = sp->get_user_cxform();
@@ -150,7 +150,7 @@
as_value
color_setrgb(const fn_call& fn)
{
- boost::intrusive_ptr<as_object> obj = ensure<ThisIs<as_object> >(fn);
+ as_object* obj = ensure<ValidThis>(fn);
if (!fn.nargs) {
IF_VERBOSE_ASCODING_ERRORS(
@@ -159,7 +159,7 @@
return as_value();
}
- MovieClip* sp = getTarget(obj.get(), fn);
+ MovieClip* sp = getTarget(obj, fn);
if (!sp) return as_value();
boost::int32_t color = fn.arg(0).to_int();
@@ -183,7 +183,7 @@
as_value
color_settransform(const fn_call& fn)
{
- boost::intrusive_ptr<as_object> obj = ensure<ThisIs<as_object> >(fn);
+ as_object* obj = ensure<ValidThis>(fn);
if (!fn.nargs) {
IF_VERBOSE_ASCODING_ERRORS(
@@ -192,7 +192,7 @@
return as_value();
}
- boost::intrusive_ptr<as_object> trans =
fn.arg(0).to_object(getGlobal(fn));
+ as_object* trans = fn.arg(0).to_object(getGlobal(fn));
if (!trans) {
IF_VERBOSE_ASCODING_ERRORS(
@@ -203,7 +203,7 @@
return as_value();
}
- MovieClip* sp = getTarget(obj.get(), fn);
+ MovieClip* sp = getTarget(obj, fn);
if (!sp) return as_value();
string_table& st = getStringTable(*obj);
=== modified file 'libcore/asobj/Date_as.cpp'
--- a/libcore/asobj/Date_as.cpp 2009-11-18 11:51:35 +0000
+++ b/libcore/asobj/Date_as.cpp 2009-11-30 11:12:37 +0000
@@ -419,7 +419,7 @@
as_function* ctor = gl.getMember(NSV::CLASS_DATE).to_function();
if (!ctor) return as_value();
fn_call::Args args;
- return ctor->constructInstance(fn.env(), args);
+ return constructInstance(*ctor, fn.env(), args);
}
// Reject all date specifications containing Infinities and NaNs.
=== modified file 'libcore/asobj/Globals.cpp'
--- a/libcore/asobj/Globals.cpp 2009-11-30 07:43:29 +0000
+++ b/libcore/asobj/Globals.cpp 2009-11-30 16:49:34 +0000
@@ -1268,7 +1268,7 @@
as_function* ctor = gl.getMember(NSV::CLASS_ERROR).to_function();
if (ctor) {
fn_call::Args args;
- as_object* proto = ctor->constructInstance(fn.env(), args);
+ as_object* proto = constructInstance(*ctor, fn.env(), args);
// Not really sure what the point of this is.
gl.createClass(local_errorConstructor, proto);
@@ -1488,7 +1488,7 @@
args += arg;
as_environment env(getVM(gl));
- as_object* ret = ctor->constructInstance(env, args);
+ as_object* ret = constructInstance(*ctor, env, args);
return ret;
=== modified file 'libcore/asobj/Object.cpp'
--- a/libcore/asobj/Object.cpp 2009-11-29 08:57:58 +0000
+++ b/libcore/asobj/Object.cpp 2009-11-30 13:44:18 +0000
@@ -63,16 +63,16 @@
{
VM& vm = getVM(global);
- vm.registerNative(object_watch, 101, 0);
- vm.registerNative(object_unwatch, 101, 1);
- vm.registerNative(object_addproperty, 101, 2);
- vm.registerNative(object_valueOf, 101, 3);
- vm.registerNative(object_toString, 101, 4);
- vm.registerNative(object_hasOwnProperty, 101, 5);
- vm.registerNative(object_isPrototypeOf, 101, 6);
- vm.registerNative(object_isPropertyEnumerable, 101, 7);
- vm.registerNative(object_registerClass, 101, 8);
- vm.registerNative(object_ctor, 101, 9);
+ vm.registerNative(object_watch, 101, 0);
+ vm.registerNative(object_unwatch, 101, 1);
+ vm.registerNative(object_addproperty, 101, 2);
+ vm.registerNative(object_valueOf, 101, 3);
+ vm.registerNative(object_toString, 101, 4);
+ vm.registerNative(object_hasOwnProperty, 101, 5);
+ vm.registerNative(object_isPrototypeOf, 101, 6);
+ vm.registerNative(object_isPropertyEnumerable, 101, 7);
+ vm.registerNative(object_registerClass, 101, 8);
+ vm.registerNative(object_ctor, 101, 9);
}
// extern (used by Global.cpp)
@@ -83,8 +83,13 @@
assert(proto);
attachObjectInterface(*proto);
- Global_as& gl = getGlobal(where);
- as_object* cl = gl.createClass(object_ctor, proto);
+ // Object is a native constructor.
+ VM& vm = getVM(where);
+ as_object* cl = vm.getNative(101, 9);
+ cl->init_member(NSV::PROP_PROTOTYPE, proto);
+ proto->init_member(NSV::PROP_CONSTRUCTOR, cl);
+
+ attachObjectInterface(*proto);
// The as_function ctor takes care of initializing these, but they
// are different for the Object class.
@@ -93,13 +98,12 @@
cl->set_member_flags(NSV::PROP_CONSTRUCTOR, readOnly);
cl->set_member_flags(NSV::PROP_PROTOTYPE, readOnly);
- VM& vm = getVM(where);
const int readOnlyFlags = as_object::DefaultFlags | PropFlags::readOnly;
cl->init_member("registerClass", vm.getNative(101, 8), readOnlyFlags);
-
- // Register _global.Object (should only be visible in SWF5 up)
- int flags = PropFlags::dontEnum;
- where.init_member(getName(uri), cl, flags, getNamespace(uri));
+
+ // Register _global.Object (should only be visible in SWF5 up)
+ int flags = PropFlags::dontEnum;
+ where.init_member(getName(uri), cl, flags, getNamespace(uri));
}
@@ -109,25 +113,25 @@
void
attachObjectInterface(as_object& o)
{
- VM& vm = getVM(o);
+ VM& vm = getVM(o);
- // We register natives despite swf version,
+ // We register natives despite swf version,
Global_as& gl = getGlobal(o);
- o.init_member("valueOf", vm.getNative(101, 3));
- o.init_member("toString", vm.getNative(101, 4));
- o.init_member("toLocaleString",
gl.createFunction(object_toLocaleString));
+ o.init_member("valueOf", vm.getNative(101, 3));
+ o.init_member("toString", vm.getNative(101, 4));
+ o.init_member("toLocaleString", gl.createFunction(object_toLocaleString));
- int swf6flags = PropFlags::dontEnum |
+ int swf6flags = PropFlags::dontEnum |
PropFlags::dontDelete |
PropFlags::onlySWF6Up;
- o.init_member("addProperty", vm.getNative(101, 2), swf6flags);
- o.init_member("hasOwnProperty", vm.getNative(101, 5), swf6flags);
- o.init_member("isPropertyEnumerable", vm.getNative(101, 7), swf6flags);
- o.init_member("isPrototypeOf", vm.getNative(101, 6), swf6flags);
- o.init_member("watch", vm.getNative(101, 0), swf6flags);
- o.init_member("unwatch", vm.getNative(101, 1), swf6flags);
+ o.init_member("addProperty", vm.getNative(101, 2), swf6flags);
+ o.init_member("hasOwnProperty", vm.getNative(101, 5), swf6flags);
+ o.init_member("isPropertyEnumerable", vm.getNative(101, 7), swf6flags);
+ o.init_member("isPrototypeOf", vm.getNative(101, 6), swf6flags);
+ o.init_member("watch", vm.getNative(101, 0), swf6flags);
+ o.init_member("unwatch", vm.getNative(101, 1), swf6flags);
}
@@ -136,16 +140,16 @@
{
Global_as& gl = getGlobal(fn);
- if (fn.nargs == 1) {
+ if (fn.nargs == 1) {
as_object* obj = fn.arg(0).to_object(gl);
if (obj) return as_value(obj);
- }
+ }
- if (fn.nargs > 1) {
- IF_VERBOSE_ASCODING_ERRORS(
- log_aserror(_("Too many args to Object constructor"));
- );
- }
+ if (fn.nargs > 1) {
+ IF_VERBOSE_ASCODING_ERRORS(
+ log_aserror(_("Too many args to Object constructor"));
+ );
+ }
if (!fn.isInstantiation()) {
return new as_object();
@@ -160,7 +164,7 @@
as_value
object_toString(const fn_call& fn)
{
- as_object* obj = fn.this_ptr;
+ as_object* obj = ensure<ValidThis>(fn);
if (obj && obj->to_function()) {
return as_value("[type Function]");
@@ -171,7 +175,7 @@
as_value
object_valueOf(const fn_call& fn)
{
- return fn.this_ptr;
+ return fn.this_ptr;
}
@@ -180,252 +184,241 @@
as_value
object_addproperty(const fn_call& fn)
{
- assert(fn.this_ptr);
- boost::intrusive_ptr<as_object> obj = fn.this_ptr;
+ as_object* obj = ensure<ValidThis>(fn);
/// Extra arguments are just ignored.
- if ( fn.nargs < 3 )
- {
- IF_VERBOSE_ASCODING_ERRORS(
- std::stringstream ss;
- fn.dump_args(ss);
- log_aserror(_("Invalid call to Object.addProperty(%s) - "
- "expected 3 arguments (<name>, <getter>, <setter>)"),
- ss.str());
- );
-
- // if we've been given more args then needed there's
- // no need to abort here
- if ( fn.nargs < 3 )
- {
- return as_value(false);
- }
- }
-
- const std::string& propname = fn.arg(0).to_string();
- if (propname.empty())
- {
- IF_VERBOSE_ASCODING_ERRORS(
- log_aserror(_("Invalid call to Object.addProperty() - "
- "empty property name"));
- );
- return as_value(false);
- }
-
- as_function* getter = fn.arg(1).to_function();
- if (!getter)
- {
- IF_VERBOSE_ASCODING_ERRORS(
- log_aserror(_("Invalid call to Object.addProperty() - "
- "getter is not an AS function"));
- );
- return as_value(false);
- }
-
- as_function* setter = NULL;
- const as_value& setterval = fn.arg(2);
- if (!setterval.is_null())
- {
- setter = setterval.to_function();
- if (!setter)
- {
- IF_VERBOSE_ASCODING_ERRORS(
- log_aserror(_("Invalid call to Object.addProperty() - "
- "setter is not null and not an AS function
(%s)"),
- setterval);
- );
- return as_value(false);
- }
- }
-
- // Now that we checked everything, let's call the as_object
- // interface for getter/setter properties :)
- obj->add_property(propname, *getter, setter);
-
- return as_value(true);
+ if ( fn.nargs < 3 )
+ {
+ IF_VERBOSE_ASCODING_ERRORS(
+ std::stringstream ss;
+ fn.dump_args(ss);
+ log_aserror(_("Invalid call to Object.addProperty(%s) - "
+ "expected 3 arguments (<name>, <getter>, <setter>)"),
+ ss.str());
+ );
+
+ // if we've been given more args then needed there's
+ // no need to abort here
+ if ( fn.nargs < 3 )
+ {
+ return as_value(false);
+ }
+ }
+
+ const std::string& propname = fn.arg(0).to_string();
+ if (propname.empty())
+ {
+ IF_VERBOSE_ASCODING_ERRORS(
+ log_aserror(_("Invalid call to Object.addProperty() - "
+ "empty property name"));
+ );
+ return as_value(false);
+ }
+
+ as_function* getter = fn.arg(1).to_function();
+ if (!getter)
+ {
+ IF_VERBOSE_ASCODING_ERRORS(
+ log_aserror(_("Invalid call to Object.addProperty() - "
+ "getter is not an AS function"));
+ );
+ return as_value(false);
+ }
+
+ as_function* setter = NULL;
+ const as_value& setterval = fn.arg(2);
+ if (!setterval.is_null())
+ {
+ setter = setterval.to_function();
+ if (!setter)
+ {
+ IF_VERBOSE_ASCODING_ERRORS(
+ log_aserror(_("Invalid call to Object.addProperty() - "
+ "setter is not null and not an AS function (%s)"),
+ setterval);
+ );
+ return as_value(false);
+ }
+ }
+
+ // Now that we checked everything, let's call the as_object
+ // interface for getter/setter properties :)
+ obj->add_property(propname, *getter, setter);
+
+ return as_value(true);
}
as_value
object_registerClass(const fn_call& fn)
{
- assert(fn.this_ptr);
-
- if ( fn.nargs != 2 )
- {
- IF_VERBOSE_ASCODING_ERRORS(
- std::stringstream ss;
- fn.dump_args(ss);
- log_aserror(_("Invalid call to Object.registerClass(%s) - "
- "expected 2 arguments (<symbol>, <constructor>)"),
- ss.str());
- );
-
- // if we've been given more args then needed there's
- // no need to abort here
- if ( fn.nargs < 2 )
- {
- return as_value(false);
- }
- }
-
- const std::string& symbolid = fn.arg(0).to_string();
- if ( symbolid.empty() )
- {
- IF_VERBOSE_ASCODING_ERRORS(
- std::stringstream ss;
- fn.dump_args(ss);
- log_aserror(_("Invalid call to Object.registerClass(%s) - "
- "first argument (symbol id) evaluates to empty
string"), ss.str());
- );
- return as_value(false);
- }
-
- as_function* theclass = fn.arg(1).to_function();
- if ( ! theclass )
- {
- IF_VERBOSE_ASCODING_ERRORS(
- std::stringstream ss;
- fn.dump_args(ss);
- log_aserror(_("Invalid call to Object.registerClass(%s) - "
- "second argument (class) is not a function)"),
ss.str());
- );
- return as_value(false);
- }
-
- // Find the exported resource
-
- // Using definition of current target fixes the youtube beta case
- // https://savannah.gnu.org/bugs/index.php?23130
- DisplayObject* tgt = fn.env().get_target();
- if ( ! tgt ) {
- log_error("current environment has no target, wouldn't know
where to look for symbol required for registerClass");
- return as_value(false);
- }
- Movie* relRoot = tgt->get_root();
- assert(relRoot);
- const movie_definition* def = relRoot->definition();
-
- boost::intrusive_ptr<ExportableResource> exp_res =
- def->get_exported_resource(symbolid);
- if ( ! exp_res )
- {
- IF_VERBOSE_ASCODING_ERRORS(
- log_aserror(_("Object.registerClass(%s, %s): "
- "can't find exported symbol"),
- symbolid,
- typeid(theclass).name());
- );
- return as_value(false);
- }
-
- // Check that the exported resource is a sprite_definition
- // (we're looking for a MovieClip symbol)
-
- boost::intrusive_ptr<sprite_definition> exp_clipdef(
- dynamic_cast<sprite_definition*>(exp_res.get()));
-
-
- if ( ! exp_clipdef )
- {
- IF_VERBOSE_ASCODING_ERRORS(
- log_aserror(_("Object.registerClass(%s, %s): "
- "exported symbol is not a MovieClip symbol "
- "(sprite_definition), but a %s"),
- symbolid, typeName(theclass), typeName(exp_res));
- );
- return as_value(false);
- }
-
- exp_clipdef->registerClass(theclass);
- return as_value(true);
+
+ if (fn.nargs != 2) {
+ IF_VERBOSE_ASCODING_ERRORS(
+ std::stringstream ss;
+ fn.dump_args(ss);
+ log_aserror(_("Invalid call to Object.registerClass(%s) - "
+ "expected 2 arguments (<symbol>, <constructor>)"),
+ ss.str());
+ );
+
+ // if we've been given more args then needed there's
+ // no need to abort here
+ if (fn.nargs < 2) {
+ return as_value(false);
+ }
+ }
+
+ const std::string& symbolid = fn.arg(0).to_string();
+ if (symbolid.empty())
+ {
+ IF_VERBOSE_ASCODING_ERRORS(
+ std::stringstream ss;
+ fn.dump_args(ss);
+ log_aserror(_("Invalid call to Object.registerClass(%s) - "
+ "first argument (symbol id) evaluates to empty string"),
+ ss.str());
+ );
+ return as_value(false);
+ }
+
+ as_function* theclass = fn.arg(1).to_function();
+ if (!theclass) {
+ IF_VERBOSE_ASCODING_ERRORS(
+ std::stringstream ss;
+ fn.dump_args(ss);
+ log_aserror(_("Invalid call to Object.registerClass(%s) - "
+ "second argument (class) is not a function)"), ss.str());
+ );
+ return as_value(false);
+ }
+
+ // Find the exported resource
+
+ // Using definition of current target fixes the youtube beta case
+ // https://savannah.gnu.org/bugs/index.php?23130
+ DisplayObject* tgt = fn.env().get_target();
+ if (!tgt) {
+ log_error("current environment has no target, wouldn't know "
+ "where to look for symbol required for registerClass");
+ return as_value(false);
+ }
+
+ Movie* relRoot = tgt->get_root();
+ assert(relRoot);
+ const movie_definition* def = relRoot->definition();
+
+ ExportableResource* exp_res = def->get_exported_resource(symbolid).get();
+ if (!exp_res) {
+ IF_VERBOSE_ASCODING_ERRORS(
+ log_aserror(_("Object.registerClass(%s, %s): "
+ "can't find exported symbol"),
+ symbolid, typeName(theclass));
+ );
+ return as_value(false);
+ }
+
+ // Check that the exported resource is a sprite_definition
+ // (we're looking for a MovieClip symbol)
+
+ sprite_definition* exp_clipdef(
+ dynamic_cast<sprite_definition*>(exp_res));
+
+
+ if (!exp_clipdef) {
+ IF_VERBOSE_ASCODING_ERRORS(
+ log_aserror(_("Object.registerClass(%s, %s): "
+ "exported symbol is not a MovieClip symbol "
+ "(sprite_definition), but a %s"),
+ symbolid, typeName(theclass), typeName(exp_res));
+ );
+ return as_value(false);
+ }
+
+ exp_clipdef->registerClass(theclass);
+ return as_value(true);
}
as_value
object_hasOwnProperty(const fn_call& fn)
{
- boost::intrusive_ptr<as_object> obj = ensure<ThisIs<as_object> >(fn);
-
- //assert(fn.result->is_undefined());
- if ( fn.nargs < 1 )
- {
- IF_VERBOSE_ASCODING_ERRORS(
- log_aserror(_("Object.hasOwnProperty() requires one arg"));
- );
- return as_value(false);
- }
- const as_value& arg = fn.arg(0);
- const std::string& propname = arg.to_string();
- if ( arg.is_undefined() || propname.empty() )
- {
- IF_VERBOSE_ASCODING_ERRORS(
- log_aserror(_("Invalid call to Object.hasOwnProperty('%s')"),
arg);
- );
- return as_value(false);
- }
- //log_debug("%p.hasOwnProperty", fn.this_ptr);
- const bool found =
- fn.this_ptr->hasOwnProperty(getStringTable(fn).find(propname));
+ as_object* obj = ensure<ValidThis>(fn);
+
+ if ( fn.nargs < 1 )
+ {
+ IF_VERBOSE_ASCODING_ERRORS(
+ log_aserror(_("Object.hasOwnProperty() requires one arg"));
+ );
+ return as_value(false);
+ }
+ const as_value& arg = fn.arg(0);
+ const std::string& propname = arg.to_string();
+ if (arg.is_undefined() || propname.empty())
+ {
+ IF_VERBOSE_ASCODING_ERRORS(
+ log_aserror(_("Invalid call to Object.hasOwnProperty('%s')"), arg);
+ );
+ return as_value(false);
+ }
+
+ const bool found = obj->hasOwnProperty(getStringTable(fn).find(propname));
return as_value(found);
}
as_value
object_isPropertyEnumerable(const fn_call& fn)
{
- boost::intrusive_ptr<as_object> obj = ensure<ThisIs<as_object> >(fn);
-
- //assert(fn.result->is_undefined());
- if ( fn.nargs < 1 )
- {
- IF_VERBOSE_ASCODING_ERRORS(
- log_aserror(_("Object.isPropertyEnumerable() requires one
arg"));
- );
- return as_value();
- }
- const as_value& arg = fn.arg(0);
- const std::string& propname = arg.to_string();
- if ( arg.is_undefined() || propname.empty() )
- {
- IF_VERBOSE_ASCODING_ERRORS(
- log_aserror(_("Invalid call to
Object.isPropertyEnumerable('%s')"), arg);
- );
- return as_value();
- }
-
- Property* prop =
- fn.this_ptr->getOwnProperty(getStringTable(fn).find(propname));
- if ( ! prop )
- {
- return as_value(false);
- }
-
- return as_value( ! prop->getFlags().get_dont_enum() );
+ as_object* obj = ensure<ValidThis>(fn);
+
+ if (fn.nargs < 1) {
+ IF_VERBOSE_ASCODING_ERRORS(
+ log_aserror(_("Object.isPropertyEnumerable() requires one arg"));
+ );
+ return as_value();
+ }
+ const as_value& arg = fn.arg(0);
+ const std::string& propname = arg.to_string();
+ if (arg.is_undefined() || propname.empty()) {
+ IF_VERBOSE_ASCODING_ERRORS(
+ log_aserror(_("Invalid call to Object.isPropertyEnumerable('%s')"),
+ arg);
+ );
+ return as_value();
+ }
+
+ Property* prop = obj->getOwnProperty(getStringTable(fn).find(propname));
+
+ if (!prop) {
+ return as_value(false);
+ }
+
+ return as_value(!prop->getFlags().get_dont_enum());
}
as_value
object_isPrototypeOf(const fn_call& fn)
{
- //assert(fn.result->is_undefined());
- if ( fn.nargs < 1 )
- {
- IF_VERBOSE_ASCODING_ERRORS(
- log_aserror(_("Object.isPrototypeOf() requires one arg"));
- );
- return as_value(false);
- }
-
- boost::intrusive_ptr<as_object> obj =
fn.arg(0).to_object(getGlobal(fn));
- if ( ! obj )
- {
- IF_VERBOSE_ASCODING_ERRORS(
- log_aserror(_("First arg to Object.isPrototypeOf(%s) is not an
object"), fn.arg(0));
- );
- return as_value(false);
- }
-
- return as_value(fn.this_ptr->prototypeOf(*obj));
+ as_object* obj = ensure<ValidThis>(fn);
+
+ if (fn.nargs < 1) {
+ IF_VERBOSE_ASCODING_ERRORS(
+ log_aserror(_("Object.isPrototypeOf() requires one arg"));
+ );
+ return as_value(false);
+ }
+
+ as_object* arg = fn.arg(0).to_object(getGlobal(fn));
+ if (!arg) {
+ IF_VERBOSE_ASCODING_ERRORS(
+ log_aserror(_("First arg to Object.isPrototypeOf(%s) is "
+ "not an object"), fn.arg(0));
+ );
+ return as_value(false);
+ }
+
+ return as_value(obj->prototypeOf(*arg));
}
@@ -433,62 +426,62 @@
as_value
object_watch(const fn_call& fn)
{
- as_object* obj = fn.this_ptr;
-
- if ( fn.nargs < 2 )
- {
- IF_VERBOSE_ASCODING_ERRORS(
- std::stringstream ss; fn.dump_args(ss);
- log_aserror(_("Object.watch(%s): missing arguments"));
- );
- return as_value(false);
- }
-
- const as_value& propval = fn.arg(0);
- const as_value& funcval = fn.arg(1);
-
- if ( ! funcval.is_function() )
- {
- IF_VERBOSE_ASCODING_ERRORS(
- std::stringstream ss; fn.dump_args(ss);
- log_aserror(_("Object.watch(%s): second argument is not a
function"));
- );
- return as_value(false);
- }
-
- string_table& st = getStringTable(fn);
-
- std::string propname = propval.to_string();
- string_table::key propkey = st.find(propname);
- as_function* trig = funcval.to_function();
- as_value cust; if ( fn.nargs > 2 ) cust = fn.arg(2);
-
- return as_value(obj->watch(propkey, *trig, cust));
+ as_object* obj = ensure<ValidThis>(fn);
+
+ if ( fn.nargs < 2 )
+ {
+ IF_VERBOSE_ASCODING_ERRORS(
+ std::stringstream ss; fn.dump_args(ss);
+ log_aserror(_("Object.watch(%s): missing arguments"));
+ );
+ return as_value(false);
+ }
+
+ const as_value& propval = fn.arg(0);
+ const as_value& funcval = fn.arg(1);
+
+ if ( ! funcval.is_function() )
+ {
+ IF_VERBOSE_ASCODING_ERRORS(
+ std::stringstream ss; fn.dump_args(ss);
+ log_aserror(_("Object.watch(%s): second argument is not a function"));
+ );
+ return as_value(false);
+ }
+
+ string_table& st = getStringTable(fn);
+
+ std::string propname = propval.to_string();
+ string_table::key propkey = st.find(propname);
+ as_function* trig = funcval.to_function();
+ as_value cust; if ( fn.nargs > 2 ) cust = fn.arg(2);
+
+ return as_value(obj->watch(propkey, *trig, cust));
}
as_value
object_unwatch(const fn_call& fn)
{
- as_object* obj = fn.this_ptr;
-
- if ( fn.nargs < 1 )
- {
- IF_VERBOSE_ASCODING_ERRORS(
- std::stringstream ss; fn.dump_args(ss);
- log_aserror(_("Object.unwatch(%s): missing argument"));
- );
- return as_value(false);
- }
-
- const as_value& propval = fn.arg(0);
-
- string_table& st = getStringTable(fn);
-
- std::string propname = propval.to_string();
- string_table::key propkey = st.find(propname);
-
- return as_value(obj->unwatch(propkey));
+ as_object* obj = ensure<ValidThis>(fn);
+
+ if ( fn.nargs < 1 )
+ {
+ IF_VERBOSE_ASCODING_ERRORS(
+ std::stringstream ss; fn.dump_args(ss);
+ log_aserror(_("Object.unwatch(%s): missing argument"));
+ );
+ return as_value(false);
+ }
+
+ const as_value& propval = fn.arg(0);
+
+ string_table& st = getStringTable(fn);
+
+ std::string propname = propval.to_string();
+ string_table::key propkey = st.find(propname);
+
+ return as_value(obj->unwatch(propkey));
}
@@ -496,7 +489,7 @@
object_toLocaleString(const fn_call& fn)
{
as_object* obj = ensure<ValidThis>(fn);
- return callMethod(obj, NSV::PROP_TO_STRING);
+ return callMethod(obj, NSV::PROP_TO_STRING);
}
} // anonymous namespace
=== modified file 'libcore/asobj/String_as.cpp'
--- a/libcore/asobj/String_as.cpp 2009-11-18 11:51:35 +0000
+++ b/libcore/asobj/String_as.cpp 2009-11-30 10:19:02 +0000
@@ -156,7 +156,6 @@
as_value
string_concat(const fn_call& fn)
{
- boost::intrusive_ptr<as_object> obj = ensure<ThisIs<as_object> >(fn);
as_value val(fn.this_ptr);
std::string str;
@@ -174,7 +173,6 @@
as_value
string_slice(const fn_call& fn)
{
- boost::intrusive_ptr<as_object> obj = ensure<ThisIs<as_object> >(fn);
as_value val(fn.this_ptr);
std::string str;
@@ -230,7 +228,6 @@
as_value
string_split(const fn_call& fn)
{
- boost::intrusive_ptr<as_object> obj = ensure<ThisIs<as_object> >(fn);
as_value val(fn.this_ptr);
std::string str;
@@ -346,7 +343,6 @@
as_value
string_lastIndexOf(const fn_call& fn)
{
- boost::intrusive_ptr<as_object> obj = ensure<ThisIs<as_object> >(fn);
as_value val(fn.this_ptr);
std::string str;
@@ -383,7 +379,6 @@
as_value
string_substr(const fn_call& fn)
{
- boost::intrusive_ptr<as_object> obj = ensure<ThisIs<as_object> >(fn);
as_value val(fn.this_ptr);
std::string str;
@@ -422,7 +417,6 @@
as_value
string_substring(const fn_call& fn)
{
- boost::intrusive_ptr<as_object> obj = ensure<ThisIs<as_object> >(fn);
as_value val(fn.this_ptr);
std::string str;
@@ -475,7 +469,6 @@
as_value
string_indexOf(const fn_call& fn)
{
- boost::intrusive_ptr<as_object> obj = ensure<ThisIs<as_object> >(fn);
as_value val(fn.this_ptr);
/// Do not return before this, because the toString method should always
@@ -567,7 +560,6 @@
as_value
string_charCodeAt(const fn_call& fn)
{
- boost::intrusive_ptr<as_object> obj = ensure<ThisIs<as_object> >(fn);
as_value val(fn.this_ptr);
std::string str;
@@ -604,7 +596,6 @@
as_value
string_charAt(const fn_call& fn)
{
- boost::intrusive_ptr<as_object> obj = ensure<ThisIs<as_object> >(fn);
as_value val(fn.this_ptr);
std::string str;
@@ -639,7 +630,6 @@
as_value
string_toUpperCase(const fn_call& fn)
{
- boost::intrusive_ptr<as_object> obj = ensure<ThisIs<as_object> >(fn);
as_value val(fn.this_ptr);
std::string str;
@@ -677,7 +667,6 @@
as_value
string_toLowerCase(const fn_call& fn)
{
- boost::intrusive_ptr<as_object> obj = ensure<ThisIs<as_object> >(fn);
as_value val(fn.this_ptr);
std::string str;
@@ -714,7 +703,6 @@
as_value
string_oldToLower(const fn_call& fn)
{
- boost::intrusive_ptr<as_object> obj = ensure<ThisIs<as_object> >(fn);
as_value val(fn.this_ptr);
// This should use the C locale; extended DisplayObjects are
@@ -727,7 +715,6 @@
as_value
string_oldToUpper(const fn_call& fn)
{
- boost::intrusive_ptr<as_object> obj = ensure<ThisIs<as_object> >(fn);
as_value val(fn.this_ptr);
// This should use the C locale; extended DisplayObjects are
=== modified file 'libcore/asobj/flash/display/BitmapData_as.cpp'
--- a/libcore/asobj/flash/display/BitmapData_as.cpp 2009-11-18 11:51:35
+0000
+++ b/libcore/asobj/flash/display/BitmapData_as.cpp 2009-11-30 11:12:37
+0000
@@ -594,7 +594,7 @@
args += 0.0, 0.0, ptr->getWidth(), ptr->getHeight();
boost::intrusive_ptr<as_object> newRect =
- rectCtor->constructInstance(fn.env(), args);
+ constructInstance(*rectCtor, fn.env(), args);
return as_value(newRect.get());
}
=== modified file 'libcore/asobj/flash/display/MovieClip_as.cpp'
--- a/libcore/asobj/flash/display/MovieClip_as.cpp 2009-11-18 12:32:41
+0000
+++ b/libcore/asobj/flash/display/MovieClip_as.cpp 2009-11-30 11:12:37
+0000
@@ -1239,7 +1239,7 @@
args += getObject(movieclip);
boost::intrusive_ptr<as_object> ts =
- tsCtor->constructInstance(fn.env(), args);
+ constructInstance(*tsCtor, fn.env(), args);
return as_value(ts.get());
}
@@ -2330,7 +2330,7 @@
args += getObject(ptr);
boost::intrusive_ptr<as_object> newTrans =
- transCtor->constructInstance(fn.env(), args);
+ constructInstance(*transCtor, fn.env(), args);
return as_value(newTrans.get());
}
=== modified file 'libcore/asobj/flash/filters/BitmapFilter_as.cpp'
--- a/libcore/asobj/flash/filters/BitmapFilter_as.cpp 2009-11-18 11:51:35
+0000
+++ b/libcore/asobj/flash/filters/BitmapFilter_as.cpp 2009-11-30 11:12:37
+0000
@@ -85,7 +85,7 @@
if (constructor) {
fn_call::Args args;
VM& vm = getVM(where);
- proto = constructor->constructInstance(as_environment(vm), args);
+ proto = constructInstance(*constructor, as_environment(vm), args);
}
else proto = 0;
=== modified file 'libcore/asobj/flash/geom/Matrix_as.cpp'
--- a/libcore/asobj/flash/geom/Matrix_as.cpp 2009-11-18 11:51:35 +0000
+++ b/libcore/asobj/flash/geom/Matrix_as.cpp 2009-11-30 11:12:37 +0000
@@ -130,10 +130,10 @@
as_object*
instanceOfMatrix(const fn_call& fn)
{
- boost::intrusive_ptr<as_object> obj = ensure<ThisIs<as_object> >(fn);
+ as_object* obj = ensure<ValidThis>(fn);
as_function* ctor = getClassConstructor(fn, "flash.geom.Matrix");
- if (obj->instanceOf(ctor)) return obj.get();
+ if (obj->instanceOf(ctor)) return obj;
return 0;
}
@@ -143,7 +143,7 @@
{
// It doesn't matter whether it is a matrix or not; a new Matrix
// is created using any Matrix properties the object may have.
- boost::intrusive_ptr<as_object> ptr = ensure<ThisIs<as_object> >(fn);
+ as_object* ptr = ensure<ValidThis>(fn);
as_value a, b, c, d, tx, ty;
ptr->get_member(NSV::PROP_A, &a);
@@ -163,7 +163,7 @@
return as_value();
}
- as_object* o = ctor->constructInstance(fn.env(), args);
+ as_object* o = constructInstance(*ctor, fn.env(), args);
return as_value(o);
}
@@ -173,7 +173,7 @@
matrix_concat(const fn_call& fn)
{
// Doesn't have to be a Matrix.
- boost::intrusive_ptr<as_object> ptr = ensure<ThisIs<as_object> >(fn);
+ as_object* ptr = ensure<ValidThis>(fn);
if (fn.nargs < 1)
{
@@ -241,7 +241,7 @@
matrix_createBox(const fn_call& fn)
{
// Doesn't have to be a Matrix
- boost::intrusive_ptr<as_object> ptr = ensure<ThisIs<as_object> >(fn);
+ as_object* ptr = ensure<ValidThis>(fn);
if (fn.nargs < 2)
{
@@ -374,7 +374,7 @@
matrix_deltaTransformPoint(const fn_call& fn)
{
// Doesn't have to be a Matrix
- boost::intrusive_ptr<as_object> ptr = ensure<ThisIs<as_object> >(fn);
+ as_object* ptr = ensure<ValidThis>(fn);
if (fn.nargs < 1)
{
@@ -406,7 +406,7 @@
as_object* obj = arg.to_object(getGlobal(fn));
assert(obj);
- const PointType& point = transformPoint(obj, ptr.get());
+ const PointType& point = transformPoint(obj, ptr);
// Construct a Point and set its properties.
as_value pointClass(fn.env().find_object("flash.geom.Point"));
@@ -421,7 +421,7 @@
fn_call::Args args;
args += point(0), point(1);
- as_value ret = pointCtor->constructInstance(fn.env(), args);
+ as_value ret = constructInstance(*pointCtor, fn.env(), args);
return as_value(ret);
}
@@ -437,7 +437,7 @@
matrix_identity(const fn_call& fn)
{
// Doesn't have to be a Matrix
- boost::intrusive_ptr<as_object> ptr = ensure<ThisIs<as_object> >(fn);
+ as_object* ptr = ensure<ValidThis>(fn);
ptr->set_member(NSV::PROP_A, 1.0);
ptr->set_member(NSV::PROP_B, 0.0);
@@ -461,7 +461,7 @@
{
// Doesn't have to be a Matrix
- boost::intrusive_ptr<as_object> ptr = ensure<ThisIs<as_object> >(fn);
+ as_object* ptr = ensure<ValidThis>(fn);
MatrixType currentMatrix;
@@ -651,7 +651,7 @@
matrix_toString(const fn_call& fn)
{
// Doesn't have to be a Matrix
- boost::intrusive_ptr<as_object> ptr = ensure<ThisIs<as_object> >(fn);
+ as_object* ptr = ensure<ValidThis>(fn);
as_value a, b, c, d, tx, ty;
@@ -680,7 +680,7 @@
matrix_transformPoint(const fn_call& fn)
{
// Doesn't have to be a Matrix
- boost::intrusive_ptr<as_object> ptr = ensure<ThisIs<as_object> >(fn);
+ as_object* ptr = ensure<ValidThis>(fn);
if (fn.nargs < 1)
{
@@ -722,7 +722,7 @@
ptr->get_member(NSV::PROP_TX, &tx);
ptr->get_member(NSV::PROP_TY, &ty);
- const PointType& point = transformPoint(obj, ptr.get());
+ const PointType& point = transformPoint(obj, ptr);
// Construct a Point and set its properties.
as_value pointClass(fn.env().find_object("flash.geom.Point"));
@@ -737,7 +737,7 @@
fn_call::Args args;
args += point(0) + tx.to_number(), point(1) + ty.to_number();
- as_value ret = pointCtor->constructInstance(fn.env(), args);
+ as_value ret = constructInstance(*pointCtor, fn.env(), args);
return as_value(ret);
}
@@ -746,7 +746,7 @@
matrix_translate(const fn_call& fn)
{
// Doesn't have to be a Matrix
- boost::intrusive_ptr<as_object> ptr = ensure<ThisIs<as_object> >(fn);
+ as_object* ptr = ensure<ValidThis>(fn);
if (fn.nargs < 2)
{
@@ -863,7 +863,7 @@
as_value
matrix_ctor(const fn_call& fn)
{
- boost::intrusive_ptr<as_object> obj = ensure<ThisIs<as_object> >(fn);
+ as_object* obj = ensure<ValidThis>(fn);
as_value a, b, c, d, tx, ty;
=== modified file 'libcore/asobj/flash/geom/Point_as.cpp'
--- a/libcore/asobj/flash/geom/Point_as.cpp 2009-11-18 11:51:35 +0000
+++ b/libcore/asobj/flash/geom/Point_as.cpp 2009-11-30 11:12:37 +0000
@@ -71,7 +71,7 @@
fn_call::Args args;
args += x, y;
- return ctor->constructInstance(fn.env(), args);
+ return constructInstance(*ctor, fn.env(), args);
}
void
@@ -103,7 +103,7 @@
as_value
point_add(const fn_call& fn)
{
- boost::intrusive_ptr<as_object> ptr = ensure<ThisIs<as_object> >(fn);
+ as_object* ptr = ensure<ValidThis>(fn);
as_value x, y;
ptr->get_member(NSV::PROP_X, &x);
@@ -166,7 +166,7 @@
as_value
point_clone(const fn_call& fn)
{
- boost::intrusive_ptr<as_object> ptr = ensure<ThisIs<as_object> >(fn);
+ as_object* ptr = ensure<ValidThis>(fn);
as_value x, y;
ptr->get_member(NSV::PROP_X, &x);
@@ -178,7 +178,7 @@
as_value
point_equals(const fn_call& fn)
{
- boost::intrusive_ptr<as_object> ptr = ensure<ThisIs<as_object> >(fn);
+ as_object* ptr = ensure<ValidThis>(fn);
if ( ! fn.nargs )
{
@@ -224,7 +224,7 @@
as_value
point_normalize(const fn_call& fn)
{
- boost::intrusive_ptr<as_object> ptr = ensure<ThisIs<as_object> >(fn);
+ as_object* ptr = ensure<ValidThis>(fn);
as_value argval;
@@ -278,7 +278,7 @@
as_value
point_offset(const fn_call& fn)
{
- boost::intrusive_ptr<as_object> ptr = ensure<ThisIs<as_object> >(fn);
+ as_object* ptr = ensure<ValidThis>(fn);
as_value x, y;
ptr->get_member(NSV::PROP_X, &x);
=== modified file 'libcore/asobj/flash/geom/Rectangle_as.cpp'
--- a/libcore/asobj/flash/geom/Rectangle_as.cpp 2009-11-18 11:51:35 +0000
+++ b/libcore/asobj/flash/geom/Rectangle_as.cpp 2009-11-30 11:12:37 +0000
@@ -138,7 +138,7 @@
fn_call::Args args;
args += x, y, w, h;
- return ctor->constructInstance(fn.env(), args);
+ return constructInstance(*ctor, fn.env(), args);
}
as_value
@@ -430,7 +430,7 @@
fn_call::Args args;
args += x, y;
- as_value ret = pointCtor->constructInstance(fn.env(), args);
+ as_value ret = constructInstance(*pointCtor, fn.env(), args);
return ret;
}
@@ -524,7 +524,7 @@
fn_call::Args args;
args += w, h;
- ret = pointCtor->constructInstance(fn.env(), args);
+ ret = constructInstance(*pointCtor, fn.env(), args);
}
else // setter
{
@@ -589,7 +589,7 @@
fn_call::Args args;
args += x, y;
- ret = pointCtor->constructInstance(fn.env(), args);
+ ret = constructInstance(*pointCtor, fn.env(), args);
}
else // setter
=== modified file 'libcore/asobj/flash/geom/Transform_as.cpp'
--- a/libcore/asobj/flash/geom/Transform_as.cpp 2009-11-18 11:51:35 +0000
+++ b/libcore/asobj/flash/geom/Transform_as.cpp 2009-11-30 11:12:37 +0000
@@ -145,7 +145,7 @@
c.rb, c.gb, c.bb, c.ab;
as_object* colorTransformObj =
- colorTransformCtor->constructInstance(fn.env(), args);
+ constructInstance(*colorTransformCtor, fn.env(), args);
return as_value(colorTransformObj);
}
@@ -231,7 +231,7 @@
c.rb, c.gb, c.bb, c.ab;
as_object* colorTransformObj =
- colorTransformCtor->constructInstance(fn.env(), args);
+ constructInstance(*colorTransformCtor, fn.env(), args);
return as_value(colorTransformObj);
}
@@ -270,7 +270,7 @@
twipsToPixels(m.tx),
twipsToPixels(m.ty);
- as_object* matrixObj = matrixCtor->constructInstance(fn.env(), args);
+ as_object* matrixObj = constructInstance(*matrixCtor, fn.env(), args);
return as_value(matrixObj);
}
@@ -314,7 +314,7 @@
twipsToPixels(m.tx),
twipsToPixels(m.ty);
- as_object* matrixObj = matrixCtor->constructInstance(fn.env(), args);
+ as_object* matrixObj = constructInstance(*matrixCtor, fn.env(), args);
return as_value(matrixObj);
}
=== modified file 'libcore/asobj/flash/net/SharedObject_as.cpp'
--- a/libcore/asobj/flash/net/SharedObject_as.cpp 2009-11-27 11:41:17
+0000
+++ b/libcore/asobj/flash/net/SharedObject_as.cpp 2009-11-30 11:12:37
+0000
@@ -1303,7 +1303,7 @@
if (!ctor) return 0;
as_environment env(getVM(gl));
fn_call::Args args;
- as_object* o = ctor->constructInstance(env, args);
+ as_object* o = constructInstance(*ctor, env, args);
std::auto_ptr<SharedObject_as> sh(new SharedObject_as(*o));
o->setRelay(sh.release());
=== modified file 'libcore/asobj/flash/net/XMLSocket_as.cpp'
--- a/libcore/asobj/flash/net/XMLSocket_as.cpp 2009-11-18 11:51:35 +0000
+++ b/libcore/asobj/flash/net/XMLSocket_as.cpp 2009-11-30 11:12:37 +0000
@@ -547,7 +547,7 @@
as_value xml;
if (ctor) {
- xml = ctor->constructInstance(fn.env(), args);
+ xml = constructInstance(*ctor, fn.env(), args);
}
// The built-in function calls:
=== modified file 'libcore/asobj/flash/ui/ContextMenuItem_as.cpp'
--- a/libcore/asobj/flash/ui/ContextMenuItem_as.cpp 2009-11-18 11:51:35
+0000
+++ b/libcore/asobj/flash/ui/ContextMenuItem_as.cpp 2009-11-30 11:12:37
+0000
@@ -62,7 +62,7 @@
as_value
contextmenuitem_copy(const fn_call& fn)
{
- boost::intrusive_ptr<as_object> ptr = ensure<ThisIs<as_object> >(fn);
+ as_object* ptr = ensure<ValidThis>(fn);
Global_as& gl = getGlobal(fn);
string_table& st = getStringTable(fn);
@@ -79,7 +79,7 @@
ptr->getMember(NSV::PROP_ENABLED),
ptr->getMember(st.find("visible"));
- return ctor->constructInstance(fn.env(), args);
+ return constructInstance(*ctor, fn.env(), args);
}
=== modified file 'libcore/asobj/flash/ui/ContextMenu_as.cpp'
--- a/libcore/asobj/flash/ui/ContextMenu_as.cpp 2009-11-18 11:51:35 +0000
+++ b/libcore/asobj/flash/ui/ContextMenu_as.cpp 2009-11-30 11:12:37 +0000
@@ -108,7 +108,7 @@
as_value
contextmenu_hideBuiltInItems(const fn_call& fn)
{
- boost::intrusive_ptr<as_object> ptr = ensure<ThisIs<as_object> >(fn);
+ as_object* ptr = ensure<ValidThis>(fn);
string_table& st = getStringTable(fn);
Global_as& gl = getGlobal(fn);
@@ -122,7 +122,7 @@
as_value
contextmenu_copy(const fn_call& fn)
{
- boost::intrusive_ptr<as_object> ptr = ensure<ThisIs<as_object> >(fn);
+ as_object* ptr = ensure<ValidThis>(fn);
Global_as& gl = getGlobal(fn);
@@ -132,7 +132,7 @@
}
fn_call::Args args;
- as_object* o = ctor->constructInstance(fn.env(), args);
+ as_object* o = constructInstance(*ctor, fn.env(), args);
if (!o) return as_value();
@@ -158,7 +158,7 @@
as_function* arrayctor = getClassConstructor(fn, "Array");
if (arrayctor) {
fn_call::Args args;
- as_object* arr = arrayctor->constructInstance(fn.env(), args);
+ as_object* arr = constructInstance(*arrayctor, fn.env(), args);
if (arr) {
as_object* customs;
if (customItems.is_object() &&
=== modified file 'libcore/asobj/flash/ui/Mouse_as.cpp'
--- a/libcore/asobj/flash/ui/Mouse_as.cpp 2009-11-18 11:51:35 +0000
+++ b/libcore/asobj/flash/ui/Mouse_as.cpp 2009-11-30 13:14:56 +0000
@@ -77,6 +77,10 @@
// Mouse is always initialized as an AsBroadcaster, even for
// SWF5.
AsBroadcaster::initialize(o);
+
+ Global_as& gl = getGlobal(o);
+ as_object* null = 0;
+ callMethod(&gl, NSV::PROP_AS_SET_PROP_FLAGS, &o, null, 7);
}
/// Returns whether the mouse was visible before the call.
=== modified file 'libcore/asobj/flash/xml/XMLDocument_as.cpp'
--- a/libcore/asobj/flash/xml/XMLDocument_as.cpp 2009-11-27 12:59:50
+0000
+++ b/libcore/asobj/flash/xml/XMLDocument_as.cpp 2009-11-30 11:12:37
+0000
@@ -687,7 +687,7 @@
fn_call::Args args;
args += 1, "";
as_object* proto =
- ctor->constructInstance(as_environment(getVM(where)), args);
+ constructInstance(*ctor, as_environment(getVM(where)), args);
attachXMLInterface(*proto);
cl->init_member(NSV::PROP_PROTOTYPE, proto);
}
=== modified file 'libcore/builtin_function.h'
--- a/libcore/builtin_function.h 2009-11-23 07:42:51 +0000
+++ b/libcore/builtin_function.h 2009-11-30 15:59:02 +0000
@@ -50,7 +50,6 @@
/// @param func
/// The C function to call when this as_function is invoked.
/// For classes, the function pointer is the constructor.
- ///
builtin_function(Global_as& gl, ASFunction func)
:
as_function(gl),
@@ -61,20 +60,8 @@
/// Invoke this function or this Class constructor
virtual as_value call(const fn_call& fn)
{
- // Real native functions don't put self on the CallStack
- // (they never end up in an arguments.caller).
- // This is, for example, the case for Array.sort when
- // calling a custom comparator.
- // Unfortunately gnash implements all builtin as natives
- // while the proprietary player doesn't (for example
- // MovieClip.meth does end up in arguments.caller).
- //
- // A possible short-term solution to this could be
- // specifying for a builtin_function whether or not
- // it should be considered 'native'.
- // If not 'native', we'd push a CallFrame on stack...
as_environment env = fn.env();
- as_environment::FrameGuard guard(env, this);
+ as_environment::FrameGuard guard(env, *this);
assert(_func);
return _func(fn);
=== modified file 'libcore/swf_function.cpp'
--- a/libcore/swf_function.cpp 2009-11-29 09:27:07 +0000
+++ b/libcore/swf_function.cpp 2009-11-30 15:59:02 +0000
@@ -34,18 +34,12 @@
namespace {
- /// Return an 'arguments' object.
+ /// Add properties to an 'arguments' object.
//
/// The 'arguments' variable is an array with an additional
/// 'callee' member, set to the function being called.
- ///
- /// NOTE: the callee as_object will be stored in an as_value, thus
- /// getting wrapped into an intrusive_ptr. Make sure you have
- /// a reference on it!
- ///
- ///
- as_object* getArguments(swf_function& callee, const fn_call& fn,
- as_object* caller);
+ as_object* getArguments(swf_function& callee, as_object& args,
+ const fn_call& fn, as_object* caller);
}
swf_function::swf_function(const action_buffer& ab, as_environment& env,
@@ -53,15 +47,15 @@
:
as_function(getGlobal(env)),
m_action_buffer(ab),
- m_env(env),
+ _env(env),
_scopeStack(scopeStack),
- m_start_pc(start),
- m_length(0),
- m_is_function2(false),
- m_local_register_count(0),
- m_function2_flags(0)
+ _startPC(start),
+ _length(0),
+ _isFunction2(false),
+ _registerCount(0),
+ _function2Flags(0)
{
- assert( m_start_pc < m_action_buffer.size() );
+ assert( _startPC < m_action_buffer.size() );
// We're stuck initializing our own prototype at the moment.
as_object* proto = getGlobal(env).createObject();
@@ -109,19 +103,19 @@
swf_function::call(const fn_call& fn)
{
// Extract caller before pushing ourself on the call stack
- as_object* caller = 0;
VM& vm = getVM(fn);
CallStack& cs = vm.getCallStack();
- if ( ! cs.empty() ) caller = cs.back().func;
+
+ as_object* caller = cs.empty() ? 0 : &cs.back().function();
// Set up local stack frame, for parameters and locals.
- as_environment::FrameGuard guard(m_env, this);
+ as_environment::FrameGuard guard(_env, *this);
- DisplayObject* target = m_env.get_target();
- DisplayObject* orig_target = m_env.get_original_target();
+ DisplayObject* target = _env.get_target();
+ DisplayObject* orig_target = _env.get_original_target();
// Some features are version-dependant.
- const int swfversion = vm.getSWFVersion();
+ const int swfversion = getSWFVersion(fn);
if (swfversion < 6) {
// In SWF5, when 'this' is a DisplayObject it becomes
@@ -144,128 +138,138 @@
/// the one set now (rather then the really original one)
/// TODO: test scope when calling functions defined in another timeline
/// (target, in particular).
- ///
- TargetGuard targetGuard(m_env, target, orig_target);
-
- if (!m_is_function2)
- {
+ TargetGuard targetGuard(_env, target, orig_target);
+
+ if (!_isFunction2) {
+
// Conventional function.
// Push the arguments onto the local frame.
- for (size_t i=0, n=m_args.size(); i<n; ++i)
+ for (size_t i=0, n=_args.size(); i<n; ++i)
{
- assert(m_args[i].m_register == 0);
+ assert(_args[i].reg == 0);
if (i < fn.nargs) {
- m_env.add_local(m_args[i].m_name, fn.arg(i));
+ _env.add_local(_args[i].name, fn.arg(i));
}
else {
// Still declare named arguments, even if
// they are not passed from caller
// See bug #22203
- m_env.declare_local(m_args[i].m_name);
+ _env.declare_local(_args[i].name);
}
}
// Add 'this'
- m_env.set_local("this", fn.this_ptr ? fn.this_ptr : as_value());
+ _env.set_local("this", fn.this_ptr ? fn.this_ptr : as_value());
as_object* super = fn.super ? fn.super :
fn.this_ptr ? fn.this_ptr->get_super() : 0;
// Add 'super' (SWF6+ only)
if (super && swfversion > 5) {
- m_env.set_local("super", super);
+ _env.set_local("super", super);
}
// Add 'arguments'
- m_env.set_local("arguments", getArguments(*this, fn, caller));
+ as_object* args = getGlobal(fn).createArray();
+ _env.set_local("arguments", getArguments(*this, *args, fn,
caller));
}
else
{
// function2: most args go in registers; any others get pushed.
// Create local registers.
- m_env.add_local_registers(m_local_register_count);
+ _env.add_local_registers(_registerCount);
// Handle the implicit args.
// @@ why start at 1 ? Note that starting at 0 makes
// intro.swf movie fail to play correctly.
- unsigned int current_reg = 1;
- if ((m_function2_flags & PRELOAD_THIS) &&
- !(m_function2_flags & SUPPRESS_THIS)) {
- // preload 'this' into a register.
- // TODO: check whether it should be undefined or null if this_ptr
- // is null.
- m_env.setRegister(current_reg, fn.this_ptr);
- ++current_reg;
- }
-
- if (!(m_function2_flags & SUPPRESS_THIS)) {
- // Put 'this' in a local var.
- m_env.add_local("this", fn.this_ptr ? fn.this_ptr :
as_value());
- }
-
- // Init arguments array, if it's going to be needed.
- as_object* arg_array = 0;
-
- if ((m_function2_flags & PRELOAD_ARGUMENTS) ||
- !(m_function2_flags & SUPPRESS_ARGUMENTS)) {
- arg_array = getArguments(*this, fn, caller);
- }
-
- if (m_function2_flags & PRELOAD_ARGUMENTS) {
- // preload 'arguments' into a register.
- m_env.setRegister(current_reg, as_value(arg_array));
- current_reg++;
- }
-
- if (!(m_function2_flags & SUPPRESS_ARGUMENTS)) {
- // Put 'arguments' in a local var.
- m_env.add_local("arguments", arg_array);
- }
+ size_t current_reg(1);
+
+ // If this is not suppressed it is either placed in a register
+ // or set as a local variable, but not both.
+ if (!(_function2Flags & SUPPRESS_THIS)) {
+ if (_function2Flags & PRELOAD_THIS) {
+ // preload 'this' into a register.
+ // TODO: check whether it should be undefined or null
+ // if this_ptr is null.
+ _env.setRegister(current_reg, fn.this_ptr);
+ ++current_reg;
+ }
+ else {
+ // Put 'this' in a local var.
+ _env.add_local("this", fn.this_ptr ? fn.this_ptr : as_value());
+ }
+ }
+
+ // This works slightly differently from 'super' and 'this'. The
+ // arguments are only ever either placed in the register or a
+ // local variable, but if both preload and suppress arguments flags
+ // are set, an empty array is still placed to the register.
+ // This seems like a bug in the reference player.
+ if (!(_function2Flags & SUPPRESS_ARGUMENTS) ||
+ (_function2Flags & PRELOAD_ARGUMENTS)) {
+
+ as_object* args = getGlobal(fn).createArray();
+
+ if (!(_function2Flags & SUPPRESS_ARGUMENTS)) {
+ getArguments(*this, *args, fn, caller);
+ }
+
+ if (_function2Flags & PRELOAD_ARGUMENTS) {
+ // preload 'arguments' into a register.
+ _env.setRegister(current_reg, args);
+ ++current_reg;
+ }
+ else {
+ // Put 'arguments' in a local var.
+ _env.add_local("arguments", args);
+ }
+
+ }
// If super is not suppressed it is either placed in a register
// or set as a local variable, but not both.
- if (swfversion > 5 && !(m_function2_flags & SUPPRESS_SUPER)) {
+ if (swfversion > 5 && !(_function2Flags & SUPPRESS_SUPER)) {
// Put 'super' in a register (SWF6+ only).
// TOCHECK: should we still set it if not available ?
as_object* super = fn.super ? fn.super :
fn.this_ptr ? fn.this_ptr->get_super() : 0;
- if (super && (m_function2_flags & PRELOAD_SUPER)) {
- m_env.setRegister(current_reg, super);
+ if (super && (_function2Flags & PRELOAD_SUPER)) {
+ _env.setRegister(current_reg, super);
current_reg++;
}
else if (super) {
- m_env.add_local("super", super);
+ _env.add_local("super", super);
}
}
- if (m_function2_flags & PRELOAD_ROOT) {
+ if (_function2Flags & PRELOAD_ROOT) {
// Put '_root' (if any) in a register.
- DisplayObject* tgtch = m_env.get_target();
+ DisplayObject* tgtch = _env.get_target();
if (tgtch) {
// NOTE: _lockroot will be handled by
getAsRoot()
as_object* r = getObject(tgtch->getAsRoot());
- m_env.setRegister(current_reg, r);
+ _env.setRegister(current_reg, r);
++current_reg;
}
}
- if (m_function2_flags & PRELOAD_PARENT) {
- DisplayObject* tgtch = m_env.get_target();
+ if (_function2Flags & PRELOAD_PARENT) {
+ DisplayObject* tgtch = _env.get_target();
if (tgtch) {
as_object* parent = getObject(tgtch->get_parent());
- m_env.setRegister(current_reg, parent);
+ _env.setRegister(current_reg, parent);
++current_reg;
}
}
- if (m_function2_flags & PRELOAD_GLOBAL) {
+ if (_function2Flags & PRELOAD_GLOBAL) {
// Put '_global' in a register.
as_object* global = vm.getGlobal();
- m_env.setRegister(current_reg, global);
+ _env.setRegister(current_reg, global);
++current_reg;
}
@@ -273,25 +277,25 @@
// This must be done after implicit ones,
// as the explicit override the implicits:
// see swfdec/definefunction2-override
- for (size_t i = 0, n = m_args.size(); i < n; ++i) {
+ for (size_t i = 0, n = _args.size(); i < n; ++i) {
// not a register, declare as local
- if (!m_args[i].m_register) {
+ if (!_args[i].reg) {
if (i < fn.nargs) {
// Conventional arg passing: create a
local var.
- m_env.add_local(m_args[i].m_name,
fn.arg(i));
+ _env.add_local(_args[i].name,
fn.arg(i));
}
else {
// Still declare named arguments, even
if
// they are not passed from caller
// See bug #22203
- m_env.declare_local(m_args[i].m_name);
+ _env.declare_local(_args[i].name);
}
}
else {
if (i < fn.nargs) {
// Pass argument into a register.
- const int reg = m_args[i].m_register;
- m_env.setRegister(reg, fn.arg(i));
+ const int reg = _args[i].reg;
+ _env.setRegister(reg, fn.arg(i));
}
// If no argument was passed, no need to setup a register
// I guess.
@@ -299,42 +303,28 @@
}
}
- as_value result;
-
// Execute the actions.
// Do this in a try block to proper drop the pushed call frame
// in case of problems (most interesting action limits)
try
{
- ActionExec exec(*this, m_env, &result, fn.this_ptr);
+ as_value result;
+ ActionExec exec(*this, _env, &result, fn.this_ptr);
exec();
+ return result;
}
catch (ActionLimitException& ale) // expected and sane
{
- //log_debug("ActionLimitException got from swf_function
execution: %s", ale.what());
- throw;
- }
- catch (std::exception& ex) // unexpected but we can tell what it is
- {
- log_debug("Unexpected exception from swf_function execution:
%s",
- ex.what());
- throw;
- }
- catch (...) // unexpected, unknown, but why not cleaning up...
- {
- log_debug("Unknown exception got from swf_function execution");
- throw;
- }
-
- return result;
+ throw;
+ }
}
void
swf_function::set_length(int len)
{
assert(len >= 0);
- assert(m_start_pc+len <= m_action_buffer.size());
- m_length = len;
+ assert(_startPC+len <= m_action_buffer.size());
+ _length = len;
}
#ifdef GNASH_USE_GC
@@ -348,7 +338,7 @@
(*i)->setReachable();
}
- m_env.markReachableResources();
+ _env.markReachableResources();
// Invoke parent class marker
markAsObjectReachable();
@@ -357,21 +347,18 @@
namespace {
-as_object*
-getArguments(swf_function& callee, const fn_call& fn,
+as_object*
+getArguments(swf_function& callee, as_object& args, const fn_call& fn,
as_object* caller)
{
- as_object* arguments = getGlobal(fn).createArray();
for (size_t i = 0; i < fn.nargs; ++i) {
- callMethod(arguments, NSV::PROP_PUSH, fn.arg(i));
+ callMethod(&args, NSV::PROP_PUSH, fn.arg(i));
}
- arguments->init_member(NSV::PROP_CALLEE, &callee);
-
- arguments->init_member(NSV::PROP_CALLER, caller);
-
- return arguments;
+ args.init_member(NSV::PROP_CALLEE, &callee);
+ args.init_member(NSV::PROP_CALLER, caller);
+ return &args;
}
=== modified file 'libcore/swf_function.h'
--- a/libcore/swf_function.h 2009-11-29 09:27:07 +0000
+++ b/libcore/swf_function.h 2009-11-30 09:19:50 +0000
@@ -76,7 +76,7 @@
//
/// TODO: check this.
/// See:
- ///
http://sswf.sourceforge.net/SWFalexref.html#action_declare_function2
+ /// http://www.m2osw.com/swf_alexref.html#action_declare_function2
/// Looks like flags would look swapped
PRELOAD_GLOBAL = 256 // 0x100
@@ -103,37 +103,35 @@
size_t getStartPC() const
{
- return m_start_pc;
+ return _startPC;
}
size_t getLength() const
{
- return m_length;
+ return _length;
}
bool isFunction2() const
{
- return m_is_function2;
+ return _isFunction2;
}
- void set_is_function2() { m_is_function2 = true; }
+ void set_is_function2() { _isFunction2 = true; }
void set_local_register_count(boost::uint8_t ct) {
- assert(m_is_function2);
- m_local_register_count = ct;
+ assert(_isFunction2);
+ _registerCount = ct;
}
void set_function2_flags(boost::uint16_t flags) {
- assert(m_is_function2);
- m_function2_flags = flags;
+ assert(_isFunction2);
+ _function2Flags = flags;
}
void add_arg(int arg_register, const char* name)
{
- assert(arg_register == 0 || m_is_function2 == true);
- m_args.resize(m_args.size() + 1);
- m_args.back().m_register = arg_register;
- m_args.back().m_name = PROPNAME(name);
+ assert(arg_register == 0 || _isFunction2 == true);
+ _args.push_back(Argument(arg_register, name));
}
void set_length(int len);
@@ -156,7 +154,7 @@
const action_buffer& m_action_buffer;
/// @@ might need some kind of ref count here, but beware cycles
- as_environment& m_env;
+ as_environment& _env;
/// Scope stack on function definition.
ScopeStack _scopeStack;
@@ -164,28 +162,31 @@
/// \brief
/// Offset within the action_buffer where
/// start of the function is found.
- size_t m_start_pc;
+ size_t _startPC;
/// Length of the function within the action_buffer
//
/// This is currently expressed in bytes as the
- /// action_buffer is just a blog of memory corresponding
+ /// action_buffer is just a blocḱ of memory corresponding
/// to a DoAction block
- size_t m_length;
+ size_t _length;
- struct arg_spec
+ struct Argument
{
- int m_register;
- std::string m_name;
+ Argument(int r, const std::string& n) : reg(r), name(n) {}
+ int reg;
+ std::string name;
};
- std::vector<arg_spec> m_args;
- bool m_is_function2;
- boost::uint8_t m_local_register_count;
+
+ std::vector<Argument> _args;
+ bool _isFunction2;
+ boost::uint8_t _registerCount;
/// used by function2 to control implicit arg register assignments
//
- /// See
http://sswf.sourceforge.net/SWFalexref.html#action_declare_function2
- boost::uint16_t m_function2_flags;
+ /// See
+ /// http://sswf.sourceforge.net/SWFalexref.html#action_declare_function2
+ boost::uint16_t _function2Flags;
};
=== modified file 'libcore/vm/ASHandlers.cpp'
--- a/libcore/vm/ASHandlers.cpp 2009-11-29 09:07:59 +0000
+++ b/libcore/vm/ASHandlers.cpp 2009-11-30 15:59:02 +0000
@@ -518,14 +518,17 @@
assert(thread.atActionTag(SWF::ACTION_GOTOFRAME));
#endif
- size_t frame = code.read_int16(thread.getCurrentPC()+3);
+ size_t frame = code.read_int16(thread.getCurrentPC() + 3);
DisplayObject* tgtch = env.get_target();
MovieClip* tgt = tgtch ? tgtch->to_movie() : 0;
// frame number within this tag is hard-coded and 0-based
- if ( tgt ) tgt->goto_frame(frame);
- else log_debug(_("ActionGotoFrame: as_environment target is null or not a
sprite"));
+ if (tgt) tgt->goto_frame(frame);
+ else {
+ log_debug(_("ActionGotoFrame: as_environment target is null "
+ "or not a sprite"));
+ }
}
void
@@ -1982,14 +1985,14 @@
{
unsigned int reg = code[3 + i];
++i;
- as_value v;
- if ( ! env.getRegister(reg, v) )
- {
- IF_VERBOSE_MALFORMED_SWF(
- log_swferror(_("Invalid register %d in ActionPush"),
reg);
- );
- }
- env.push(v);
+ as_value v;
+ if (!env.getRegister(reg, v)) {
+ IF_VERBOSE_MALFORMED_SWF(
+ log_swferror(_("Invalid register %d in ActionPush"),
+ reg);
+ );
+ }
+ env.push(v);
break;
}
@@ -3684,36 +3687,44 @@
const action_buffer& code = thread.code;
- unsigned int reg = code[thread.getCurrentPC() + 3];
+ const size_t reg = code[thread.getCurrentPC() + 3];
// Save top of stack in specified register.
- int ret = env.setRegister(reg, env.top(0));
- if ( ! ret )
- {
- IF_VERBOSE_MALFORMED_SWF(
- log_swferror(_("Invalid register %d in ActionSetRegister"), reg);
- );
- }
- else if ( ret == 1 )
- {
- IF_VERBOSE_ACTION (
- log_action(_("-------------- global register[%d] = '%s'"),
- reg, env.top(0));
- );
- }
- else
- {
- IF_VERBOSE_ACTION (
- log_action(_("-------------- local register[%d] = '%s'"),
- reg, env.top(0));
- );
+ const int ret = env.setRegister(reg, env.top(0));
+
+ switch (ret) {
+ default:
+ case 0:
+ {
+ IF_VERBOSE_MALFORMED_SWF(
+ log_swferror(_("Invalid register %d in ActionSetRegister"),
+ reg);
+ );
+ break;
+ }
+ case 1:
+ {
+ IF_VERBOSE_ACTION (
+ log_action(_("-------------- global register[%d] = '%s'"),
+ reg, env.top(0));
+ );
+ break;
+ }
+ case 2:
+ {
+ IF_VERBOSE_ACTION (
+ log_action(_("-------------- local register[%d] = '%s'"),
+ reg, env.top(0));
+ );
+ break;
+ }
}
}
const char*
SWFHandlers::action_name(ActionType x) const
{
- if ( static_cast<size_t>(x) > get_handlers().size() )
+ if (static_cast<size_t>(x) > get_handlers().size())
{
log_error(_("at SWFHandlers::action_name(%d) call time, "
"_handlers size is %d"),
@@ -3757,7 +3768,7 @@
for (size_t i = 0; i < nargs; ++i) {
args += env.pop();
}
- return ctor_as_func->constructInstance(env, args);
+ return constructInstance(*ctor_as_func, env, args);
}
// Common code for GetUrl and GetUrl2. See:
=== modified file 'libcore/vm/ActionExec.cpp'
--- a/libcore/vm/ActionExec.cpp 2009-11-13 08:18:42 +0000
+++ b/libcore/vm/ActionExec.cpp 2009-11-30 15:59:02 +0000
@@ -41,7 +41,7 @@
#ifndef DEBUG_STACK
-// temporarly disabled as will produce lots of output with -v
+// temporarily disabled as will produce lots of output with -v
// we'd need another switch maybe, as -va does also produce
// too much information for my tastes. I really want just
// to see how stack changes while executing actions...
@@ -52,7 +52,7 @@
# define STACK_DUMP_LIMIT 32
// Define to get debugging messages for try / catch
-//#define GNASH_DEBUG_TRY 1
+#define GNASH_DEBUG_TRY 1
#endif
@@ -64,11 +64,11 @@
static Debugger& debugger = Debugger::getDefaultInstance();
#endif
-ActionExec::ActionExec(const swf_function& func, as_environment& newEnv,
as_value* nRetVal, as_object* this_ptr)
+ActionExec::ActionExec(const swf_function& func, as_environment& newEnv,
+ as_value* nRetVal, as_object* this_ptr)
:
_withStack(),
_scopeStack(func.getScopeStack()),
- // See comment in header
_withStackLimit(7),
_func(&func),
_this_ptr(this_ptr),
@@ -81,7 +81,7 @@
_abortOnUnload(false),
pc(func.getStartPC()),
next_pc(pc),
- stop_pc(pc+func.getLength()),
+ stop_pc(pc + func.getLength()),
code(func.getActionBuffer()),
env(newEnv),
retval(nRetVal)
@@ -105,25 +105,23 @@
// set local var: i=[number:0]
// push 'i' getvariable
// get var: i=[undefined]
- //
- if ( code.getDefinitionVersion() > 5 )
- //if ( env.get_version() > 5 )
- {
- // We assume that the swf_function () operator already initialized its
environment
- // so that it's activation object is now in the top element of the
CallFrame stack
- //
+ if (code.getDefinitionVersion() > 5) {
+ // We assume that the swf_function () operator already initialized
+ // its environment so that its activation object is now in the
+ // top element of the CallFrame stack
CallFrame& topFrame = newEnv.topCallFrame();
- assert(topFrame.func == &func);
- _scopeStack.push_back(topFrame.locals);
+ assert(&topFrame.function() == &func);
+ _scopeStack.push_back(&topFrame.locals());
}
}
-ActionExec::ActionExec(const action_buffer& abuf, as_environment& newEnv, bool
abortOnUnloaded)
+ActionExec::ActionExec(const action_buffer& abuf, as_environment& newEnv,
+ bool abortOnUnloaded)
:
_withStack(),
_scopeStack(), // TODO: initialize the scope stack somehow
_withStackLimit(7),
- _func(NULL),
+ _func(0),
_initialStackSize(0),
_initialCallStackDepth(0),
_originalTarget(0),
@@ -138,25 +136,24 @@
env(newEnv),
retval(0)
{
- //GNASH_REPORT_FUNCTION;
-
/// See comment in header
// TODO: stack limit dependent on function version or VM version ?
- if ( env.get_version() > 5 ) {
+ if (env.get_version() > 5) {
_withStackLimit = 15;
}
}
void
-ActionExec::operator() ()
+ActionExec::operator()()
{
VM& vm = getVM(env);
// Do not execute if scripts are disabled
- if ( vm.getRoot().scriptsDisabled() ) return;
+ if (vm.getRoot().scriptsDisabled()) return;
_origExecSWFVersion = vm.getSWFVersion();
- int codeVersion = code.getDefinitionVersion();
+
+ const int codeVersion = code.getDefinitionVersion();
vm.setSWFVersion(codeVersion);
static const SWF::SWFHandlers& ash = SWF::SWFHandlers::instance();
@@ -184,8 +181,6 @@
// TODO: specify in the .gnashrc !!
static const size_t maxBranchCount = 65536; // what's enough ?
- //WallClockTimer timer;
-
// stop_pc: set to the code boundary at which we should check
// for exceptions. If there is no exception in a TryBlock, it
// is set to the end of that block; all the code (including catch
@@ -200,18 +195,19 @@
size_t branchCount = 0;
try {
- while (1) // We might not stop at stop_pc, if we are trying.
- {
- if (pc >= stop_pc)
- {
+ log_debug("Try list size: %s", _tryList.size());
+
+ // We might not stop at stop_pc, if we are trying.
+ while (1) {
+
+ if (pc >= stop_pc) {
// No try blocks
if (_tryList.empty()) {
// Check for any uncaught exceptions.
- if (env.stack_size() && env.top(0).is_exception())
- {
+ if (env.stack_size() && env.top(0).is_exception()) {
log_debug ("Exception on stack, no handlers left.");
- // Stop execution (for how long?) if an exception
+ // Stop execution if an exception
// is still on the stack and there is nothing
// left to catch it.
throw ActionScriptException();
@@ -222,7 +218,7 @@
// If we are in a try block, check to see if we have thrown.
TryBlock& t = _tryList.back();
- if (! processExceptions(t)) break;
+ if (!processExceptions(t)) break;
continue;
}
@@ -248,28 +244,26 @@
// Set default next_pc offset, control flow action handlers
// will be able to reset it.
- if ((action_id & 0x80) == 0)
- {
+ if ((action_id & 0x80) == 0) {
// action with no extra data
next_pc = pc+1;
}
- else
- {
+ else {
// action with extra data
- boost::uint16_t length = boost::uint16_t(code.read_int16(pc +
1));
+ // Note this converts from int to uint!
+ boost::uint16_t length(code.read_int16(pc + 1));
+
next_pc = pc + length + 3;
- if ( next_pc > stop_pc )
- {
+ if (next_pc > stop_pc) {
IF_VERBOSE_MALFORMED_SWF(
log_swferror(_("Length %u (%d) of action tag"
" id %u at pc %d"
" overflows actions buffer size %d"),
- length, static_cast<int>(length),
- static_cast<unsigned>(action_id), pc,
- stop_pc);
+ length, static_cast<int>(length),
+ static_cast<unsigned>(action_id), pc,
+ stop_pc);
);
- //throw ActionException(ss.str());
// no way to recover from this actually...
// Give this action handler a chance anyway.
// Maybe it will be able to do something about
@@ -279,30 +273,28 @@
}
// Do we still need this ?
- if ( action_id == SWF::ACTION_END )
- {
+ if (action_id == SWF::ACTION_END) {
break;
}
ash.execute(static_cast<SWF::ActionType>(action_id), *this);
-#if 1 // See bugs: #20974, #21069, #20996.
-
-#if 0
- // curveball.swf and feed.swf break with this
- DisplayObject* guardedChar = env.get_original_target(); // watch
out : _originalTarget is not necessarely the same
-#else
- // curveball.swf and feed.swf suggest that it is the *current*
target,
- // not the *original* one that matters.
+ // Code round here has to do with bugs: #20974, #21069, #20996,
+ // but since there is so much disabled code it's not clear exactly
+ // what part.
+
+ // curveball.swf and feed.swf suggest that it is the
+ // *current* target, not the *original* one that matters.
DisplayObject* guardedChar = env.get_target();
-#endif
- if ( _abortOnUnload && guardedChar && guardedChar->unloaded() )
- // action_execution_order_test8.c shows that the opcode guard is
not SWF version based (TODO: automate it!)
- {
+ if (_abortOnUnload && guardedChar && guardedChar->unloaded()) {
+ // action_execution_order_test8.c shows that the opcode
+ // guard is not SWF version based (TODO: automate it!)
std::stringstream ss;
ss << "Target of action_buffer (" << guardedChar->getTarget()
- << " of type " << typeName(*guardedChar) << ") unloaded by
execution of opcode: " << std::endl;
+ << " of type " << typeName(*guardedChar) << ") unloaded "
+ "by execution of opcode: " << std::endl;
+
dumpActions(pc, next_pc, ss);
ss << "Discarding " << stop_pc-next_pc
<< " bytes of remaining opcodes: " << std::endl;
@@ -310,7 +302,6 @@
log_debug("%s", ss.str());
break;
}
-#endif
#ifdef USE_DEBUGGER
@@ -324,7 +315,8 @@
#if DEBUG_STACK
IF_VERBOSE_ACTION (
- log_action(_("After execution: PC %d, next PC %d, stack
follows"), pc, next_pc);
+ log_action(_("After execution: PC %d, next PC %d, "
+ "stack follows"), pc, next_pc);
std::stringstream ss;
env.dump_stack(ss, STACK_DUMP_LIMIT);
env.dump_global_registers(ss);
@@ -339,51 +331,33 @@
// Check for script limits hit.
// See: http://www.gnashdev.org/wiki/index.php/ScriptLimits
- //
-#if 0
- // TODO: only check on branch-back ? (would be less aggressive..)
- // WARNING: if the movie is stopped, the wall clock continues to
run !
- if ( timeLimit && timer.elapsed() > timeLimit )
- {
- throw ActionLimitException("Script exceeded time limit");
- }
-#else
- if ( pc <= oldPc )
- {
- if ( ++branchCount > maxBranchCount )
- {
+ if (pc <= oldPc) {
+ if (++branchCount > maxBranchCount) {
boost::format fmt(_("Loop iterations count exceeded "
"limit of %d. Last branch was from pc %d "
"to %d"));
fmt % maxBranchCount % oldPc % pc;
throw ActionLimitException(fmt.str());
}
- //log_debug("Branch count: %u", branchCount);
}
-#endif
-
}
-
}
- catch (ActionLimitException& ex)
- {
+ catch (ActionLimitException& ex) {
// Script execution should stop (for this frame only?)
// Here's were we should pop-up a window to prompt user about
// what to do next (abort or not ?)
- //log_error("Script aborted due to exceeded limit: %s - cleaning up
after run", ex.what());
cleanupAfterRun(true); // we expect inconsistencies here
throw;
}
- catch (ActionScriptException& ex)
- {
+ catch (ActionScriptException& ex) {
// An unhandled ActionScript exception was thrown.
cleanupAfterRun(true);
- // Forceably clear the stack.
- // - Fixes misc-mtasc.all/exception.swf
- // By commenting the line above, we get an XPASS in
- // - swfdec/catch-in-caller.swf
- env.drop(env.stack_size());
+ // Forceably clear the stack.
+ // - Fixes misc-mtasc.all/exception.swf
+ // By commenting the line above, we get an XPASS in
+ // - swfdec/catch-in-caller.swf
+ env.drop(env.stack_size());
return;
}
=== modified file 'libcore/vm/CallStack.cpp'
--- a/libcore/vm/CallStack.cpp 2009-08-27 06:21:01 +0000
+++ b/libcore/vm/CallStack.cpp 2009-11-30 15:59:02 +0000
@@ -14,19 +14,22 @@
// 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
-//
+
#include "CallStack.h"
#include "as_object.h"
#include "as_function.h"
#include "Global_as.h"
+#include <ostream>
+
namespace gnash {
-CallFrame::CallFrame(as_function* funcPtr)
- :
- locals(new as_object),
- func(funcPtr)
+CallFrame::CallFrame(as_function* f)
+ :
+ _locals(new as_object(getGlobal(*f))),
+ _func(f)
{
+ assert(_func);
}
/// Mark all reachable resources
@@ -36,13 +39,26 @@
void
CallFrame::markReachableResources() const
{
- if ( func ) func->setReachable();
- for (Registers::const_iterator i=registers.begin(), e=registers.end();
i!=e; ++i)
- {
- i->setReachable();
- }
- if (locals)
- locals->setReachable();
-}
-
+ // Func is always valid.
+ assert(_func);
+ _func->setReachable();
+
+ std::for_each(_registers.begin(), _registers.end(),
+ std::mem_fun_ref(&as_value::setReachable));
+
+ if (_locals) _locals->setReachable();
+}
+
+std::ostream&
+operator<<(std::ostream& o, const CallFrame& fr)
+{
+ CallFrame::Registers r = fr._registers;
+
+ for (size_t i = 0; i < r.size(); ++i) {
+ if (i) o << ", ";
+ o << i << ':' << '"' << r[i] << '"';
+ }
+ return o;
+
+}
} // namespace gnash
=== modified file 'libcore/vm/CallStack.h'
--- a/libcore/vm/CallStack.h 2009-02-25 22:33:03 +0000
+++ b/libcore/vm/CallStack.h 2009-11-30 15:59:02 +0000
@@ -19,6 +19,7 @@
#define GNASH_VM_CALL_STACK_H
#include <vector>
+
#include "as_value.h"
// Forward declarations
@@ -30,27 +31,61 @@
namespace gnash {
/// An element of a CallStack
-struct CallFrame
+class CallFrame
{
+public:
+
typedef std::vector<as_value> Registers;
-
- CallFrame(as_function* funcPtr);
+ CallFrame(as_function* func);
CallFrame(const CallFrame& other)
:
- locals(other.locals),
- registers(other.registers),
- func(other.func)
- {/**/}
+ _locals(other._locals),
+ _registers(other._registers),
+ _func(other._func)
+ {}
+
+ as_object& locals() {
+ return *_locals;
+ }
+
+ as_function& function() {
+ return *_func;
+ }
+
+ bool getRegister(size_t i, as_value& val) const {
+ if (i >= _registers.size()) return false;
+ val = _registers[i];
+ return true;
+ }
+
+ bool setRegister(size_t i, const as_value& val) {
+ if (i >= _registers.size()) return false;
+ _registers[i] = val;
+ return true;
+ }
+
+ void resizeRegisters(size_t i) {
+ _registers.resize(i);
+ }
+
+ bool hasRegisters() const {
+ return !_registers.empty();
+ }
+
+
+private:
+
+ friend std::ostream& operator<<(std::ostream&, const CallFrame&);
/// function use this
- as_object* locals;
+ as_object* _locals;
/// function2 also use this
- Registers registers;
+ Registers _registers;
- as_function* func;
+ as_function* _func;
/// Mark all reachable resources
//
@@ -61,6 +96,7 @@
typedef std::vector<CallFrame> CallStack;
+std::ostream& operator<<(std::ostream& o, const CallFrame& fr);
} // namespace gnash
=== modified file 'libcore/vm/Machine.cpp'
--- a/libcore/vm/Machine.cpp 2009-11-20 08:00:47 +0000
+++ b/libcore/vm/Machine.cpp 2009-11-30 11:12:37 +0000
@@ -1587,7 +1587,7 @@
if (ctor) {
boost::intrusive_ptr<as_object> newobj =
- ctor->constructInstance(env, args);
+ constructInstance(*ctor, env, args);
push_stack(as_value(newobj));
}
=== modified file 'testsuite/misc-swfmill.all/trace-as2/Makefile.am'
--- a/testsuite/misc-swfmill.all/trace-as2/Makefile.am 2009-11-25 15:11:59
+0000
+++ b/testsuite/misc-swfmill.all/trace-as2/Makefile.am 2009-11-30 07:53:30
+0000
@@ -25,10 +25,14 @@
TRACE_TESTS = \
super.xml \
+ this.xml \
+ arguments.xml \
$(NULL)
TRACE_TRACES = \
super.trace \
+ this.trace \
+ arguments.trace \
$(NULL)
EXTRA_DIST = \
=== modified file 'testsuite/misc-swfmill.all/trace-as2/PASSING'
--- a/testsuite/misc-swfmill.all/trace-as2/PASSING 2009-11-25 11:19:40
+0000
+++ b/testsuite/misc-swfmill.all/trace-as2/PASSING 2009-11-30 09:00:24
+0000
@@ -1,1 +1,3 @@
+arguments
super
+this
=== added file 'testsuite/misc-swfmill.all/trace-as2/arguments.trace'
--- a/testsuite/misc-swfmill.all/trace-as2/arguments.trace 1970-01-01
00:00:00 +0000
+++ b/testsuite/misc-swfmill.all/trace-as2/arguments.trace 2009-11-30
08:01:47 +0000
@@ -0,0 +1,8 @@
+6.5
+undefined
+undefined
+undefined
+6.5
+undefined
+
+6.5
=== added file 'testsuite/misc-swfmill.all/trace-as2/arguments.xml'
--- a/testsuite/misc-swfmill.all/trace-as2/arguments.xml 1970-01-01
00:00:00 +0000
+++ b/testsuite/misc-swfmill.all/trace-as2/arguments.xml 2009-11-30
08:01:47 +0000
@@ -0,0 +1,372 @@
+<?xml version="1.0"?>
+<swf version="7" compressed="1">
+
+<!-- Tests when and where super is preloaded -->
+<!-- The answer is:
+ If it's suppressed, it's not available at all.
+ If it's preloaded, it is only available in a register, not as
+ a local variable.
+-->
+
+ <Header framerate="12" frames="1">
+ <size>
+ <Rectangle left="0" right="12800" top="0" bottom="9600"/>
+ </size>
+ <tags>
+ <DoAction>
+ <actions>
+ <Dictionary>
+ <strings>
+ <String value="o"/>
+ <String value="ns"/>
+ <String value="arguments"/>
+ <String value="nr"/>
+ <String value="sss"/>
+ <String value="pss"/>
+ <String value="psr"/>
+ <String value="psss"/>
+ <String value="pssr"/>
+ <String value="__proto__"/>
+ <String value="oo"/>
+ </strings>
+ </Dictionary>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="0"/>
+ <StackInteger value="0"/>
+ </items>
+ </PushData>
+ <DeclareObject/>
+ <SetVariable/>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="0"/>
+ </items>
+ </PushData>
+ <GetVariable/>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="1"/>
+ </items>
+ </PushData>
+
+ <!-- Check arguments for a normal function -->
+ <DeclareFunction2 name="" argc="0" regc="2" preloadParent="0"
preloadRoot="0" suppressSuper="0" preloadSuper="0" suppressArguments="0"
preloadArguments="0" suppressThis="0" preloadThis="0" reserved="0"
preloadGlobal="0">
+ <args/>
+ <actions>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="2"/>
+ </items>
+ </PushData>
+ <GetVariable/>
+ <Return/>
+ </actions>
+ </DeclareFunction2>
+ <SetMember/>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="0"/>
+ </items>
+ </PushData>
+ <GetVariable/>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="3"/>
+ </items>
+ </PushData>
+
+ <!-- Check what's in register 1 for a normal function (nothing)-->
+ <DeclareFunction2 name="" argc="0" regc="2" preloadParent="0"
preloadRoot="0" suppressSuper="0" preloadSuper="0" suppressArguments="0"
preloadArguments="0" suppressThis="0" preloadThis="0" reserved="0"
preloadGlobal="0">
+ <args/>
+ <actions>
+ <PushData>
+ <items>
+ <StackRegister reg="1"/>
+ </items>
+ </PushData>
+ <Return/>
+ </actions>
+ </DeclareFunction2>
+ <SetMember/>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="0"/>
+ </items>
+ </PushData>
+ <GetVariable/>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="4"/>
+ </items>
+ </PushData>
+
+ <!-- Check what arguments is when it's suppressed-->
+ <DeclareFunction2 name="" argc="0" regc="2" preloadParent="0"
preloadRoot="0" suppressSuper="0" preloadSuper="0" suppressArguments="1"
preloadArguments="0" suppressThis="0" preloadThis="0" reserved="0"
preloadGlobal="0">
+ <args/>
+ <actions>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="2"/>
+ </items>
+ </PushData>
+ <GetVariable/>
+ <Return/>
+ </actions>
+ </DeclareFunction2>
+ <SetMember/>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="0"/>
+ </items>
+ </PushData>
+ <GetVariable/>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="5"/>
+ </items>
+ </PushData>
+
+ <!-- Check what arguments is when it's preloaded-->
+ <DeclareFunction2 name="" argc="0" regc="2" preloadParent="0"
preloadRoot="0" suppressSuper="0" preloadSuper="0" suppressArguments="0"
preloadArguments="1" suppressThis="0" preloadThis="0" reserved="0"
preloadGlobal="0">
+ <args/>
+ <actions>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="2"/>
+ </items>
+ </PushData>
+ <GetVariable/>
+ <Return/>
+ </actions>
+ </DeclareFunction2>
+ <SetMember/>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="0"/>
+ </items>
+ </PushData>
+ <GetVariable/>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="6"/>
+ </items>
+ </PushData>
+
+ <!-- Check what register 1 is when arguments is preloaded-->
+ <DeclareFunction2 name="" argc="0" regc="2" preloadParent="0"
preloadRoot="0" suppressSuper="0" preloadSuper="0" suppressArguments="0"
preloadArguments="1" suppressThis="0" preloadThis="0" reserved="0"
preloadGlobal="0">
+ <args/>
+ <actions>
+ <PushData>
+ <items>
+ <StackRegister reg="1"/>
+ </items>
+ </PushData>
+ <Return/>
+ </actions>
+ </DeclareFunction2>
+ <SetMember/>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="0"/>
+ </items>
+ </PushData>
+ <GetVariable/>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="7"/>
+ </items>
+ </PushData>
+
+ <!-- Check what arguments is when it's suppressed and preloaded-->
+ <DeclareFunction2 name="" argc="0" regc="2" preloadParent="0"
preloadRoot="0" suppressSuper="0" preloadSuper="0" suppressArguments="1"
preloadArguments="1" suppressThis="0" preloadThis="0" reserved="0"
preloadGlobal="0">
+ <args/>
+ <actions>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="2"/>
+ </items>
+ </PushData>
+ <GetVariable/>
+ <Return/>
+ </actions>
+ </DeclareFunction2>
+ <SetMember/>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="0"/>
+ </items>
+ </PushData>
+ <GetVariable/>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="8"/>
+ </items>
+ </PushData>
+
+ <!-- Check what register 1 is when arguments suppressed and
preloaded-->
+ <DeclareFunction2 name="" argc="0" regc="2" preloadParent="0"
preloadRoot="0" suppressSuper="0" preloadSuper="0" suppressArguments="1"
preloadArguments="1" suppressThis="0" preloadThis="0" reserved="0"
preloadGlobal="0">
+ <args/>
+ <actions>
+ <PushData>
+ <items>
+ <StackRegister reg="1"/>
+ </items>
+ </PushData>
+ <Return/>
+ </actions>
+ </DeclareFunction2>
+ <SetMember/>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="0"/>
+ </items>
+ </PushData>
+ <GetVariable/>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="9"/>
+ <StackInteger value="0"/>
+ </items>
+ </PushData>
+ <DeclareObject/>
+ <SetMember/>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="10"/>
+ <StackInteger value="0"/>
+ <StackDictionaryLookup index="0"/>
+ </items>
+ </PushData>
+ <New/>
+ <SetLocalVariable/>
+
+ <!-- Start function calls -->
+ <PushData>
+ <items>
+ <StackDouble value="6.5"/>
+ <StackInteger value="1"/>
+ <StackDictionaryLookup index="0"/>
+ </items>
+ </PushData>
+ <GetVariable/>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="1"/>
+ </items>
+ </PushData>
+ <CallMethod/>
+ <Trace/>
+ <PushData>
+ <items>
+ <StackDouble value="6.5"/>
+ <StackInteger value="1"/>
+ <StackDictionaryLookup index="0"/>
+ </items>
+ </PushData>
+ <GetVariable/>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="3"/>
+ </items>
+ </PushData>
+ <CallMethod/>
+ <Trace/>
+ <PushData>
+ <items>
+ <StackDouble value="6.5"/>
+ <StackInteger value="1"/>
+ <StackDictionaryLookup index="0"/>
+ </items>
+ </PushData>
+ <GetVariable/>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="4"/>
+ </items>
+ </PushData>
+ <CallMethod/>
+ <Trace/>
+ <PushData>
+ <items>
+ <StackDouble value="6.5"/>
+ <StackInteger value="1"/>
+ <StackDictionaryLookup index="0"/>
+ </items>
+ </PushData>
+ <GetVariable/>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="5"/>
+ </items>
+ </PushData>
+ <CallMethod/>
+ <Trace/>
+ <PushData>
+ <items>
+ <StackDouble value="6.5"/>
+ <StackInteger value="1"/>
+ <StackDictionaryLookup index="0"/>
+ </items>
+ </PushData>
+ <GetVariable/>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="6"/>
+ </items>
+ </PushData>
+ <CallMethod/>
+ <Trace/>
+ <PushData>
+ <items>
+ <StackDouble value="6.5"/>
+ <StackInteger value="1"/>
+ <StackDictionaryLookup index="0"/>
+ </items>
+ </PushData>
+ <GetVariable/>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="7"/>
+ </items>
+ </PushData>
+ <CallMethod/>
+ <Trace/>
+ <PushData>
+ <items>
+ <StackDouble value="6.5"/>
+ <StackInteger value="1"/>
+ <StackDictionaryLookup index="0"/>
+ </items>
+ </PushData>
+ <GetVariable/>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="8"/>
+ </items>
+ </PushData>
+ <CallMethod/>
+ <Trace/>
+ <PushData>
+ <items>
+ <StackDouble value="6.5"/>
+ <StackInteger value="1"/>
+ <StackDictionaryLookup index="0"/>
+ </items>
+ </PushData>
+ <GetVariable/>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="1"/>
+ </items>
+ </PushData>
+ <CallMethod/>
+ <Trace/>
+ <EndAction/>
+ </actions>
+ </DoAction>
+ <ShowFrame/>
+ <End/>
+ </tags>
+ </Header>
+</swf>
=== modified file 'testsuite/misc-swfmill.all/trace-as2/super.xml'
--- a/testsuite/misc-swfmill.all/trace-as2/super.xml 2009-11-25 11:19:40
+0000
+++ b/testsuite/misc-swfmill.all/trace-as2/super.xml 2009-11-30 07:37:35
+0000
@@ -27,7 +27,6 @@
<String value="psss"/>
<String value="pssr"/>
<String value="__proto__"/>
- <String value="oo"/>
</strings>
</Dictionary>
<PushData>
@@ -49,6 +48,8 @@
<StackDictionaryLookup index="1"/>
</items>
</PushData>
+
+ <!-- ns(): Check super for a normal function (nothing)-->
<DeclareFunction2 name="" argc="0" regc="2" preloadParent="0"
preloadRoot="0" suppressSuper="0" preloadSuper="0" suppressArguments="0"
preloadArguments="0" suppressThis="0" preloadThis="0" reserved="0"
preloadGlobal="0">
<args/>
<actions>
@@ -74,7 +75,8 @@
</items>
</PushData>
- <!-- Check what's in register 0 for a normal function (nothing)-->
+ <!-- nr(): Check what's in register 1 for a normal function
+ (nothing)-->
<DeclareFunction2 name="" argc="0" regc="2" preloadParent="0"
preloadRoot="0" suppressSuper="0" preloadSuper="0" suppressArguments="0"
preloadArguments="0" suppressThis="0" preloadThis="0" reserved="0"
preloadGlobal="0">
<args/>
<actions>
@@ -99,7 +101,7 @@
</items>
</PushData>
- <!-- Check what super is when it's suppressed-->
+ <!-- sss(): Check what super is when it's suppressed-->
<DeclareFunction2 name="" argc="0" regc="2" preloadParent="0"
preloadRoot="0" suppressSuper="1" preloadSuper="0" suppressArguments="0"
preloadArguments="0" suppressThis="0" preloadThis="0" reserved="0"
preloadGlobal="0">
<args/>
<actions>
@@ -125,7 +127,7 @@
</items>
</PushData>
- <!-- Check what super is when it's preloaded-->
+ <!-- pss(): Check what super is when it's preloaded-->
<DeclareFunction2 name="" argc="0" regc="2" preloadParent="0"
preloadRoot="0" suppressSuper="0" preloadSuper="1" suppressArguments="0"
preloadArguments="0" suppressThis="0" preloadThis="0" reserved="0"
preloadGlobal="0">
<args/>
<actions>
@@ -151,7 +153,7 @@
</items>
</PushData>
- <!-- Check what register 0 is when super is preloaded-->
+ <!-- psr(): Check what register 1 is when super is preloaded-->
<DeclareFunction2 name="" argc="0" regc="2" preloadParent="0"
preloadRoot="0" suppressSuper="0" preloadSuper="1" suppressArguments="0"
preloadArguments="0" suppressThis="0" preloadThis="0" reserved="0"
preloadGlobal="0">
<args/>
<actions>
@@ -176,7 +178,7 @@
</items>
</PushData>
- <!-- Check what super is when it's suppressed and preloaded-->
+ <!-- psss(): Check what super is when it's suppressed and
preloaded-->
<DeclareFunction2 name="" argc="0" regc="2" preloadParent="0"
preloadRoot="0" suppressSuper="1" preloadSuper="1" suppressArguments="0"
preloadArguments="0" suppressThis="0" preloadThis="0" reserved="0"
preloadGlobal="0">
<args/>
<actions>
@@ -202,7 +204,8 @@
</items>
</PushData>
- <!-- Check what super is when it's suppressed and preloaded-->
+ <!-- pssr(): Check what register 1 is when it's suppressed and
+ preloaded-->
<DeclareFunction2 name="" argc="0" regc="2" preloadParent="0"
preloadRoot="0" suppressSuper="1" preloadSuper="1" suppressArguments="0"
preloadArguments="0" suppressThis="0" preloadThis="0" reserved="0"
preloadGlobal="0">
<args/>
<actions>
@@ -229,15 +232,6 @@
</PushData>
<DeclareObject/>
<SetMember/>
- <PushData>
- <items>
- <StackDictionaryLookup index="10"/>
- <StackInteger value="0"/>
- <StackDictionaryLookup index="0"/>
- </items>
- </PushData>
- <New/>
- <SetLocalVariable/>
<!-- Start function calls -->
<PushData>
=== added file 'testsuite/misc-swfmill.all/trace-as2/this.trace'
--- a/testsuite/misc-swfmill.all/trace-as2/this.trace 1970-01-01 00:00:00
+0000
+++ b/testsuite/misc-swfmill.all/trace-as2/this.trace 2009-11-29 21:29:59
+0000
@@ -0,0 +1,8 @@
+[object Object]
+undefined
+_level0
+_level0
+[object Object]
+_level0
+undefined
+[object Object]
=== added file 'testsuite/misc-swfmill.all/trace-as2/this.xml'
--- a/testsuite/misc-swfmill.all/trace-as2/this.xml 1970-01-01 00:00:00
+0000
+++ b/testsuite/misc-swfmill.all/trace-as2/this.xml 2009-11-30 07:48:37
+0000
@@ -0,0 +1,355 @@
+<?xml version="1.0"?>
+<swf version="7" compressed="1">
+
+<!-- Tests when and where super is preloaded -->
+<!-- The answer is:
+ If it's suppressed, it's not available at all.
+ If it's preloaded, it is only available in a register, not as
+ a local variable.
+-->
+
+ <Header framerate="12" frames="1">
+ <size>
+ <Rectangle left="0" right="12800" top="0" bottom="9600"/>
+ </size>
+ <tags>
+ <DoAction>
+ <actions>
+ <Dictionary>
+ <strings>
+ <String value="o"/>
+ <String value="ns"/>
+ <String value="this"/>
+ <String value="nr"/>
+ <String value="sss"/>
+ <String value="pss"/>
+ <String value="psr"/>
+ <String value="psss"/>
+ <String value="pssr"/>
+ <String value="__proto__"/>
+ <String value="oo"/>
+ </strings>
+ </Dictionary>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="0"/>
+ <StackInteger value="0"/>
+ </items>
+ </PushData>
+ <DeclareObject/>
+ <SetVariable/>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="0"/>
+ </items>
+ </PushData>
+ <GetVariable/>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="1"/>
+ </items>
+ </PushData>
+
+ <!-- ns(): Check this for a normal function -->
+ <DeclareFunction2 name="" argc="0" regc="2" preloadParent="0"
preloadRoot="0" suppressSuper="0" preloadSuper="0" suppressArguments="0"
preloadArguments="0" suppressThis="0" preloadThis="0" reserved="0"
preloadGlobal="0">
+ <args/>
+ <actions>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="2"/>
+ </items>
+ </PushData>
+ <GetVariable/>
+ <Return/>
+ </actions>
+ </DeclareFunction2>
+ <SetMember/>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="0"/>
+ </items>
+ </PushData>
+ <GetVariable/>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="3"/>
+ </items>
+ </PushData>
+
+ <!-- nr(): Check what's in register 1 for a normal function
(nothing)-->
+ <DeclareFunction2 name="" argc="0" regc="2" preloadParent="0"
preloadRoot="0" suppressSuper="0" preloadSuper="0" suppressArguments="0"
preloadArguments="0" suppressThis="0" preloadThis="0" reserved="0"
preloadGlobal="0">
+ <args/>
+ <actions>
+ <PushData>
+ <items>
+ <StackRegister reg="1"/>
+ </items>
+ </PushData>
+ <Return/>
+ </actions>
+ </DeclareFunction2>
+ <SetMember/>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="0"/>
+ </items>
+ </PushData>
+ <GetVariable/>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="4"/>
+ </items>
+ </PushData>
+
+ <!-- sss(): Check what this is when it's suppressed-->
+ <DeclareFunction2 name="" argc="0" regc="2" preloadParent="0"
preloadRoot="0" suppressSuper="0" preloadSuper="0" suppressArguments="0"
preloadArguments="0" suppressThis="1" preloadThis="0" reserved="0"
preloadGlobal="0">
+ <args/>
+ <actions>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="2"/>
+ </items>
+ </PushData>
+ <GetVariable/>
+ <Return/>
+ </actions>
+ </DeclareFunction2>
+ <SetMember/>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="0"/>
+ </items>
+ </PushData>
+ <GetVariable/>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="5"/>
+ </items>
+ </PushData>
+
+ <!-- pss(): Check what this is when it's preloaded-->
+ <DeclareFunction2 name="" argc="0" regc="2" preloadParent="0"
preloadRoot="0" suppressSuper="0" preloadSuper="0" suppressArguments="0"
preloadArguments="0" suppressThis="0" preloadThis="1" reserved="0"
preloadGlobal="0">
+ <args/>
+ <actions>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="2"/>
+ </items>
+ </PushData>
+ <GetVariable/>
+ <Return/>
+ </actions>
+ </DeclareFunction2>
+ <SetMember/>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="0"/>
+ </items>
+ </PushData>
+ <GetVariable/>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="6"/>
+ </items>
+ </PushData>
+
+ <!-- psr(): Check what register 1 is when this is preloaded-->
+ <DeclareFunction2 name="" argc="0" regc="2" preloadParent="0"
preloadRoot="0" suppressSuper="0" preloadSuper="0" suppressArguments="0"
preloadArguments="0" suppressThis="0" preloadThis="1" reserved="0"
preloadGlobal="0">
+ <args/>
+ <actions>
+ <PushData>
+ <items>
+ <StackRegister reg="1"/>
+ </items>
+ </PushData>
+ <Return/>
+ </actions>
+ </DeclareFunction2>
+ <SetMember/>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="0"/>
+ </items>
+ </PushData>
+ <GetVariable/>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="7"/>
+ </items>
+ </PushData>
+
+ <!-- psss(): Check what this is when it's suppressed and preloaded-->
+ <DeclareFunction2 name="" argc="0" regc="2" preloadParent="0"
preloadRoot="0" suppressSuper="0" preloadSuper="0" suppressArguments="0"
preloadArguments="0" suppressThis="1" preloadThis="1" reserved="0"
preloadGlobal="0">
+ <args/>
+ <actions>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="2"/>
+ </items>
+ </PushData>
+ <GetVariable/>
+ <Return/>
+ </actions>
+ </DeclareFunction2>
+ <SetMember/>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="0"/>
+ </items>
+ </PushData>
+ <GetVariable/>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="8"/>
+ </items>
+ </PushData>
+
+ <!-- pssr(): Check what register 1 is when this suppressed and
preloaded-->
+ <DeclareFunction2 name="" argc="0" regc="2" preloadParent="0"
preloadRoot="0" suppressSuper="0" preloadSuper="0" suppressArguments="0"
preloadArguments="0" suppressThis="1" preloadThis="1" reserved="0"
preloadGlobal="0">
+ <args/>
+ <actions>
+ <PushData>
+ <items>
+ <StackRegister reg="1"/>
+ </items>
+ </PushData>
+ <Return/>
+ </actions>
+ </DeclareFunction2>
+ <SetMember/>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="0"/>
+ </items>
+ </PushData>
+ <GetVariable/>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="9"/>
+ <StackInteger value="0"/>
+ </items>
+ </PushData>
+ <DeclareObject/>
+ <SetMember/>
+
+ <!-- Start function calls -->
+ <PushData>
+ <items>
+ <StackInteger value="0"/>
+ <StackDictionaryLookup index="0"/>
+ </items>
+ </PushData>
+ <GetVariable/>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="1"/>
+ </items>
+ </PushData>
+ <CallMethod/>
+ <Trace/>
+ <PushData>
+ <items>
+ <StackInteger value="0"/>
+ <StackDictionaryLookup index="0"/>
+ </items>
+ </PushData>
+ <GetVariable/>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="3"/>
+ </items>
+ </PushData>
+ <CallMethod/>
+ <Trace/>
+ <PushData>
+ <items>
+ <StackInteger value="0"/>
+ <StackDictionaryLookup index="0"/>
+ </items>
+ </PushData>
+ <GetVariable/>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="4"/>
+ </items>
+ </PushData>
+ <CallMethod/>
+ <Trace/>
+ <PushData>
+ <items>
+ <StackInteger value="0"/>
+ <StackDictionaryLookup index="0"/>
+ </items>
+ </PushData>
+ <GetVariable/>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="5"/>
+ </items>
+ </PushData>
+ <CallMethod/>
+ <Trace/>
+ <PushData>
+ <items>
+ <StackInteger value="0"/>
+ <StackDictionaryLookup index="0"/>
+ </items>
+ </PushData>
+ <GetVariable/>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="6"/>
+ </items>
+ </PushData>
+ <CallMethod/>
+ <Trace/>
+ <PushData>
+ <items>
+ <StackInteger value="0"/>
+ <StackDictionaryLookup index="0"/>
+ </items>
+ </PushData>
+ <GetVariable/>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="7"/>
+ </items>
+ </PushData>
+ <CallMethod/>
+ <Trace/>
+ <PushData>
+ <items>
+ <StackInteger value="0"/>
+ <StackDictionaryLookup index="0"/>
+ </items>
+ </PushData>
+ <GetVariable/>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="8"/>
+ </items>
+ </PushData>
+ <CallMethod/>
+ <Trace/>
+ <PushData>
+ <items>
+ <StackInteger value="0"/>
+ <StackDictionaryLookup index="0"/>
+ </items>
+ </PushData>
+ <GetVariable/>
+ <PushData>
+ <items>
+ <StackDictionaryLookup index="1"/>
+ </items>
+ </PushData>
+ <CallMethod/>
+ <Trace/>
+ <EndAction/>
+ </actions>
+ </DoAction>
+ <ShowFrame/>
+ <End/>
+ </tags>
+ </Header>
+</swf>
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Gnash-commit] /srv/bzr/gnash/trunk r11662: Fixes and cleanups to function execution and construction.,
Benjamin Wolsey <=