[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Gnash-commit] /srv/bzr/gnash/trunk r11649: Add call() to as_object
From: |
strk |
Subject: |
Re: [Gnash-commit] /srv/bzr/gnash/trunk r11649: Add call() to as_object interface, as this helps AS3 work. |
Date: |
Tue, 24 Nov 2009 22:06:16 +0100 |
Tests in misc-swfmill.all fail for me:
FAIL: trace-test-runner: stack1
FAIL: trace-test-runner: super
should they be only run when avm2 is built ?
--strk;
On Mon, Nov 23, 2009 at 07:05:35PM +0100, Benjamin Wolsey wrote:
> ------------------------------------------------------------
> revno: 11649 [merge]
> committer: Benjamin Wolsey <address@hidden>
> branch nick: trunk
> timestamp: Mon 2009-11-23 19:05:35 +0100
> message:
> Add call() to as_object interface, as this helps AS3 work.
>
> Improve super handling, CallFunction and CallMethod, as they can also be
> implemented more correctly if as_super inherits from as_object.
>
> Allow undefined 'this' in function calls. This is fine for SWF-defined
> functions; built-in and native functions should always check before
> using the this pointer, but some may not. This would be a bug.
>
> Test and fix super creation in functions.
>
> Change the meaning of fn_call::super (see documentation!) to be an override
> only if the normal super is not used. Create super only when necessary,
> resulting in major memory saving under suitable circumstances.
> added:
> testsuite/misc-swfmill.all/super.trace
> testsuite/misc-swfmill.all/super.xml
> modified:
> libcore/ClassHierarchy.cpp
> libcore/MovieClip.cpp
> libcore/NativeFunction.h
> libcore/Property.cpp
> libcore/Timers.cpp
> libcore/abc/abc_function.cpp
> libcore/abc/abc_function.h
> libcore/as_function.cpp
> libcore/as_function.h
> libcore/as_object.cpp
> libcore/as_object.h
> libcore/as_value.cpp
> libcore/asobj/Global_as.h
> libcore/asobj/Object.cpp
> libcore/builtin_function.h
> libcore/swf_function.cpp
> libcore/swf_function.h
> libcore/vm/ASHandlers.cpp
> libcore/vm/fn_call.h
> testsuite/actionscript.all/getvariable.as
> testsuite/misc-swfmill.all/Makefile.am
> testsuite/misc-swfmill.all/PASSING
> testsuite/swfdec/PASSING
> === modified file 'libcore/ClassHierarchy.cpp'
> --- a/libcore/ClassHierarchy.cpp 2009-11-18 11:51:35 +0000
> +++ b/libcore/ClassHierarchy.cpp 2009-11-23 07:42:51 +0000
> @@ -75,7 +75,7 @@
> {
> }
>
> - virtual as_value operator()(const fn_call& fn)
> + virtual as_value call(const fn_call& fn)
> {
> string_table& st = getStringTable(fn);
> log_debug("Loading extension class %s", st.value(mDeclaration.name));
> @@ -134,7 +134,7 @@
> {
> }
>
> - virtual as_value operator()(const fn_call& fn)
> + virtual as_value call(const fn_call& fn)
> {
> string_table& st = getStringTable(fn);
> log_debug("Loading native class %s", st.value(mDeclaration.name));
>
> === modified file 'libcore/MovieClip.cpp'
> --- a/libcore/MovieClip.cpp 2009-11-20 11:36:15 +0000
> +++ b/libcore/MovieClip.cpp 2009-11-23 07:42:51 +0000
> @@ -1949,7 +1949,7 @@
> call.super = super;
>
> // we don't use the constructor return (should we?)
> - (*ctor)(call);
> + ctor->call(call);
> }
> }
>
>
> === modified file 'libcore/NativeFunction.h'
> --- a/libcore/NativeFunction.h 2009-08-18 08:00:20 +0000
> +++ b/libcore/NativeFunction.h 2009-11-23 07:42:51 +0000
> @@ -56,7 +56,7 @@
> }
>
> /// Invoke this function
> - virtual as_value operator()(const fn_call& fn)
> + virtual as_value call(const fn_call& fn)
> {
> assert(_func);
> return _func(fn);
>
> === modified file 'libcore/Property.cpp'
> --- a/libcore/Property.cpp 2009-08-20 06:55:15 +0000
> +++ b/libcore/Property.cpp 2009-11-23 07:42:51 +0000
> @@ -125,7 +125,7 @@
> return underlyingValue;
> }
>
> - if ( mGetter ) return (*mGetter)(fn);
> + if (mGetter) return mGetter->call(fn);
> else return as_value(); // should we return underlyingValue here ?
> }
>
> @@ -139,7 +139,7 @@
> return;
> }
>
> - (*mSetter)(fn);
> + mSetter->call(fn);
> }
>
> as_value
>
> === modified file 'libcore/Timers.cpp'
> --- a/libcore/Timers.cpp 2009-11-16 11:21:48 +0000
> +++ b/libcore/Timers.cpp 2009-11-23 14:22:25 +0000
> @@ -100,37 +100,13 @@
> Timer::execute()
> {
>
> - as_value timer_method;
> -
> // If _function is not 0, _methodName should be 0 anyway, but the
> // ternary operator is there for clarity.
> as_object* super = _object->get_super(_function ? 0 : _methodName);
> VM& vm = getVM(*_object);
>
> - if (_function) {
> - timer_method.set_as_function(_function);
> - }
> - else {
> - as_value tmp;
> - if (!_object->get_member(_methodName, &tmp)) {
> - IF_VERBOSE_ASCODING_ERRORS(
> - log_aserror("object %p has no member named %s (interval method)",
> - _object, _methodName);
> - );
> - return;
> - }
> -
> - as_function* f = tmp.to_function();
> -
> - if (!f) {
> - IF_VERBOSE_ASCODING_ERRORS(
> - log_aserror("member %s of object %p (interval method) is not "
> - "a function (%s)", _methodName, (void*)_object, tmp);
> - );
> - return;
> - }
> - timer_method.set_as_function(f);
> - }
> + as_value timer_method = _function ? _function :
> + _object->getMember(_methodName);
>
> as_environment env(vm);
>
>
> === modified file 'libcore/abc/abc_function.cpp'
> --- a/libcore/abc/abc_function.cpp 2009-11-16 14:42:56 +0000
> +++ b/libcore/abc/abc_function.cpp 2009-11-23 07:42:51 +0000
> @@ -34,7 +34,7 @@
>
> // Dispatch.
> as_value
> -abc_function::operator()(const fn_call& fn)
> +abc_function::call(const fn_call& fn)
> {
>
> log_abc("Calling an abc_function id=%u.", _methodInfo->methodID());
>
> === modified file 'libcore/abc/abc_function.h'
> --- a/libcore/abc/abc_function.h 2009-11-16 14:42:56 +0000
> +++ b/libcore/abc/abc_function.h 2009-11-23 07:42:51 +0000
> @@ -43,7 +43,7 @@
> public:
> abc_function(Method* methodInfo, Machine* machine);
>
> - as_value operator()(const fn_call& fn);
> + as_value call(const fn_call& fn);
>
> CodeStream* getCodeStream() const {
> return _methodInfo->getBody();
>
> === modified file 'libcore/as_function.cpp'
> --- a/libcore/as_function.cpp 2009-11-18 12:00:44 +0000
> +++ b/libcore/as_function.cpp 2009-11-23 17:14:01 +0000
> @@ -79,10 +79,13 @@
> }
>
> void
> -as_function::extends(as_function& superclass)
> +as_function::extends(as_object& superclass)
> {
> as_object* newproto = new as_object();
> - newproto->set_prototype(superclass.getPrototype().get());
> + as_object* p =
> + superclass.getMember(NSV::PROP_PROTOTYPE).to_object(
> + *VM::get().getGlobal());
> + newproto->set_prototype(p);
>
> if (getSWFVersion(superclass) > 5) {
> const int flags = PropFlags::dontEnum;
> @@ -154,7 +157,9 @@
> PropFlags::dontEnum);
> }
>
> - fn_call fn(newobj, env, args, newobj->get_super(), true);
> + // 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);
> as_value ret;
>
> try {
> @@ -271,8 +276,7 @@
> function_apply(const fn_call& fn)
> {
>
> - // Get function body
> - as_function* function_obj = ensure<ThisIs<as_function> >(fn);
> + as_object* function_obj = ensure<ValidThis>(fn);
>
> // Copy new function call from old one, we'll modify
> // the copy only if needed
> @@ -294,7 +298,13 @@
> if (!obj) obj = new as_object;
>
> new_fn_call.this_ptr = obj;
> - new_fn_call.super = obj->get_super();
> +
> + // 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.
> + new_fn_call.super = 0;
>
> // Check for second argument ('arguments' array)
> if (fn.nargs > 1)
> @@ -329,8 +339,7 @@
> function_call(const fn_call& fn)
> {
>
> - // Get function body
> - as_function* function_obj = ensure<ThisIs<as_function> >(fn);
> + as_object* function_obj = ensure<ValidThis>(fn);
>
> // Copy new function call from old one, we'll modify
> // the copy only if needed
> @@ -364,7 +373,15 @@
> new_fn_call.this_ptr = this_ptr;
> as_object* proto = this_ptr->get_prototype();
> if (proto) {
> - new_fn_call.super = this_ptr->get_super();
> + // 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 !
> @@ -377,7 +394,7 @@
> }
>
> // Call the function
> - return (*function_obj)(new_fn_call);
> + return function_obj->call(new_fn_call);
>
> }
>
>
> === modified file 'libcore/as_function.h'
> --- a/libcore/as_function.h 2009-11-18 09:33:28 +0000
> +++ b/libcore/as_function.h 2009-11-23 08:58:01 +0000
> @@ -67,11 +67,11 @@
> // Avoid RTTI
> as_function* to_function() { return this; }
>
> - /// Dispatch.
> - virtual as_value operator()(const fn_call& fn) = 0;
> -
> - /// Alias for operator()
> - as_value call(const fn_call& fn) { return operator()(fn); }
> + /// 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
> //
> @@ -94,7 +94,7 @@
> boost::intrusive_ptr<as_object> getPrototype();
>
> /// Make this function a subclass of the given as_function
> - void extends(as_function& superclass);
> + void extends(as_object& superclass);
>
> /// Return true if this is a built-in class.
> virtual bool isBuiltin() { return false; }
>
> === modified file 'libcore/as_object.cpp'
> --- a/libcore/as_object.cpp 2009-11-20 15:13:16 +0000
> +++ b/libcore/as_object.cpp 2009-11-23 18:05:35 +0000
> @@ -124,13 +124,13 @@
> /// to change this in the future to implement what ECMA-262 refers to
> /// as the [[Call]] property of objects.
> ///
> -class as_super : public as_function
> +class as_super : public as_object
> {
> public:
>
> as_super(Global_as& gl, as_object* super)
> :
> - as_function(gl),
> + as_object(gl),
> _super(super)
> {
> set_prototype(prototype());
> @@ -151,7 +151,7 @@
> }
>
> /// Dispatch.
> - virtual as_value operator()(const fn_call& fn)
> + virtual as_value call(const fn_call& fn)
> {
>
> // TODO: this is a hack to make sure objects are constructed, not
> @@ -173,7 +173,7 @@
> virtual void markReachableResources() const
> {
> if (_super) _super->setReachable();
> - markAsFunctionReachable();
> + markAsObjectReachable();
> }
>
> private:
> @@ -261,7 +261,6 @@
> } // end of anonymous namespace
>
>
> -
> const int as_object::DefaultFlags;
>
> as_object::as_object(Global_as& gl)
> @@ -284,6 +283,11 @@
> {
> }
>
> +as_value
> +as_object::call(const fn_call& /*fn*/) {
> + throw ActionTypeError();
> +}
> +
> std::pair<bool,bool>
> as_object::delProperty(string_table::key name, string_table::key nsname)
> {
>
> === modified file 'libcore/as_object.h'
> --- a/libcore/as_object.h 2009-11-20 15:13:16 +0000
> +++ b/libcore/as_object.h 2009-11-23 18:05:35 +0000
> @@ -184,6 +184,13 @@
> /// Construct an ActionScript object with no prototype associated.
> as_object();
>
> + /// Function dispatch
> + //
> + /// Various objects can be called, including functions and super objects.
> + /// A normal object has no call functionality, so the default
> + /// implementation throws an ActionTypeError.
> + virtual as_value call(const fn_call& fn);
> +
> /// The most common flags for built-in properties.
> //
> /// Most API properties, including classes and objects, have these flags.
>
> === modified file 'libcore/as_value.cpp'
> --- a/libcore/as_value.cpp 2009-11-18 11:51:35 +0000
> +++ b/libcore/as_value.cpp 2009-11-23 09:04:08 +0000
> @@ -1269,8 +1269,7 @@
> return "null";
>
> case as_value::AS_FUNCTION:
> - if ( getFun()->isSuper() ) return "object";
> - else return "function";
> + return "function";
>
> default:
> if (is_exception())
>
> === modified file 'libcore/asobj/Global_as.h'
> --- a/libcore/asobj/Global_as.h 2009-11-18 11:51:35 +0000
> +++ b/libcore/asobj/Global_as.h 2009-11-23 08:58:01 +0000
> @@ -187,7 +187,7 @@
>
> /// Call an as_value on an as_object.
> //
> -/// The call will fail harmlessly if the as_value is not a function.
> +/// The call will fail harmlessly if the as_value is not callable.
> inline DSOEXPORT as_value
> invoke(const as_value& method, const as_environment& env, as_object*
> this_ptr,
> fn_call::Args& args, as_object* super = 0,
> @@ -200,9 +200,9 @@
> call.callerDef = callerDef;
>
> try {
> - if (as_function* func = method.to_function()) {
> + if (as_object* func = method.to_object(getGlobal(env))) {
> // Call function.
> - val = (*func)(call);
> + val = func->call(call);
> }
> else {
> IF_VERBOSE_ASCODING_ERRORS(
>
> === modified file 'libcore/asobj/Object.cpp'
> --- a/libcore/asobj/Object.cpp 2009-11-18 11:43:03 +0000
> +++ b/libcore/asobj/Object.cpp 2009-11-23 09:04:08 +0000
> @@ -188,7 +188,7 @@
> {
> as_object* obj = fn.this_ptr;
>
> - if (obj && obj->to_function() && !obj->isSuper()) {
> + if (obj && obj->to_function()) {
> return as_value("[type Function]");
> }
> return as_value("[object Object]");
>
> === modified file 'libcore/builtin_function.h'
> --- a/libcore/builtin_function.h 2009-10-15 14:40:38 +0000
> +++ b/libcore/builtin_function.h 2009-11-23 07:42:51 +0000
> @@ -59,7 +59,7 @@
> }
>
> /// Invoke this function or this Class constructor
> - virtual as_value operator()(const fn_call& fn)
> + 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).
>
> === modified file 'libcore/swf_function.cpp'
> --- a/libcore/swf_function.cpp 2009-11-18 11:34:54 +0000
> +++ b/libcore/swf_function.cpp 2009-11-23 16:46:42 +0000
> @@ -106,7 +106,7 @@
>
> // Dispatch.
> as_value
> -swf_function::operator()(const fn_call& fn)
> +swf_function::call(const fn_call& fn)
> {
> // Extract caller before pushing ourself on the call stack
> as_object* caller = 0;
> @@ -122,11 +122,8 @@
>
> // Some features are version-dependant.
> const int swfversion = vm.getSWFVersion();
> - as_object *super = NULL;
> - if (swfversion > 5) {
> - super = fn.super;
> - }
> - else {
> +
> + if (swfversion < 6) {
> // In SWF5, when 'this' is a DisplayObject it becomes
> // the target for this function call.
> // See actionscript.all/setProperty.as
> @@ -170,12 +167,14 @@
> }
>
> // Add 'this'
> - assert(fn.this_ptr);
> - m_env.set_local("this", fn.this_ptr);
> + m_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", as_value(super));
> + m_env.set_local("super", super);
> }
>
> // Add 'arguments'
> @@ -195,13 +194,15 @@
> if ((m_function2_flags & PRELOAD_THIS) &&
> !(m_function2_flags & SUPPRESS_THIS)) {
> // preload 'this' into a register.
> - m_env.setRegister(current_reg, as_value(fn.this_ptr));
> - current_reg++;
> + // 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", as_value(fn.this_ptr));
> + m_env.add_local("this", fn.this_ptr ? fn.this_ptr :
> as_value());
> }
>
> // Init arguments array, if it's going to be needed.
> @@ -220,23 +221,24 @@
>
> if (!(m_function2_flags & SUPPRESS_ARGUMENTS)) {
> // Put 'arguments' in a local var.
> - m_env.add_local("arguments", as_value(arg_array));
> + m_env.add_local("arguments", arg_array);
> }
>
> - if ((m_function2_flags & PRELOAD_SUPER) && swfversion > 5) {
> - // Put 'super' in a register (SWF6+ only).
> - // TOCHECK: should we still set it if not available ?
> - if ( super ) {
> - m_env.setRegister(current_reg, as_value(super));
> + // 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)) {
> +
> + // 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);
> current_reg++;
> }
> - }
> -
> - if (!(m_function2_flags & SUPPRESS_SUPER)) {
> - if (super && swfversion > 5) {
> - // TOCHECK: should we still set it if unavailable ?
> - // Put 'super' in a local var (SWF6+ only)
> - m_env.add_local("super", as_value(super));
> + else if (super) {
> + m_env.add_local("super", super);
> }
> }
>
> @@ -246,7 +248,7 @@
> if (tgtch) {
> // NOTE: _lockroot will be handled by
> getAsRoot()
> as_object* r = getObject(tgtch->getAsRoot());
> - m_env.setRegister(current_reg, as_value(r));
> + m_env.setRegister(current_reg, r);
> ++current_reg;
> }
> }
> @@ -263,7 +265,7 @@
> if (m_function2_flags & PRELOAD_GLOBAL) {
> // Put '_global' in a register.
> as_object* global = vm.getGlobal();
> - m_env.setRegister(current_reg, as_value(global));
> + m_env.setRegister(current_reg, global);
> ++current_reg;
> }
>
>
> === modified file 'libcore/swf_function.h'
> --- a/libcore/swf_function.h 2009-11-13 08:19:10 +0000
> +++ b/libcore/swf_function.h 2009-11-23 07:42:51 +0000
> @@ -139,7 +139,7 @@
> void set_length(int len);
>
> /// Dispatch.
> - as_value operator()(const fn_call& fn);
> + virtual as_value call(const fn_call& fn);
>
> #ifdef GNASH_USE_GC
> /// Mark reachable resources. Override from as_function.
>
> === modified file 'libcore/vm/ASHandlers.cpp'
> --- a/libcore/vm/ASHandlers.cpp 2009-11-20 14:54:19 +0000
> +++ b/libcore/vm/ASHandlers.cpp 2009-11-23 18:05:35 +0000
> @@ -1326,7 +1326,7 @@
> as_object* instance = convertToObject(getGlobal(thread.env), env.top(0));
>
> // Get the "super" function
> - as_function* super = env.top(1).to_function();
> + as_object* super = convertToObject(getGlobal(thread.env), env.top(1));
>
> // Invalid args!
> if (!super || ! instance)
> @@ -2432,47 +2432,38 @@
> // In all cases, even undefined, the specified number of arguments
> // is dropped from the stack.
> const std::string& funcname = env.pop().to_string();
> - as_object* this_ptr = thread.getThisPointer();
> - as_object* super = NULL;
> -
> +
> + as_object* super(0);
> +
> + as_object* this_ptr;
> as_value function = thread.getVariable(funcname, &this_ptr);
>
> if (!function.is_object()) {
> + // In this case the call to invoke() will fail. We won't return
> + // because we still need to handle the stack, and the attempt to
> + // convert the value to an object may have effects in AS (haven't
> + // checked).
> IF_VERBOSE_ASCODING_ERRORS (
> - log_aserror(_("ActionCallFunction: %s is not an object"), funcname);
> + log_aserror(_("ActionCallFunction: %s is not an object"),
> + funcname);
> )
> }
> else if (!function.is_function()) {
> - log_error(_("ActionCallFunction: function name %s evaluated to "
> - "non-function value %s"), funcname, function);
> - // Calling super ?
> - as_object* obj = convertToObject(getGlobal(thread.env), function);
> - this_ptr = thread.getThisPointer();
> - if (!obj->get_member(NSV::PROP_CONSTRUCTOR, &function) )
> - {
> - IF_VERBOSE_ASCODING_ERRORS (
> - log_aserror(_("Object doesn't have a constructor"));
> - )
> - }
> - }
> - else if ( function.to_function()->isSuper() )
> - {
> - this_ptr = thread.getThisPointer();
> -
> - // the new 'super' will be computed from the old one
> - as_function* oldSuper = function.to_function();
> - super = oldSuper->get_super();
> + as_object* obj = function.to_object(getGlobal(thread.env));
> + super = obj->get_super();
> + this_ptr = thread.getThisPointer();
> }
>
> // Get number of args, modifying it if not enough values are on the
> stack.
> - unsigned nargs = unsigned(env.pop().to_number());
> - unsigned available_args = env.stack_size();
> - if ( available_args < nargs )
> - {
> + // TODO: this may cause undefined behaviour if the number on the stack
> + // is too large. Fix it.
> + size_t nargs = static_cast<size_t>(env.pop().to_number());
> + const size_t available_args = env.stack_size();
> + if (available_args < nargs) {
> IF_VERBOSE_MALFORMED_SWF(
> - log_swferror(_("Attempt to call a function with %u arguments "
> - "while only %u are available on the stack."),
> - nargs, available_args);
> + log_swferror(_("Attempt to call a function with %u arguments "
> + "while only %u are available on the stack."),
> + nargs, available_args);
> );
> nargs = available_args;
> }
> @@ -2493,8 +2484,7 @@
> env.push(result);
>
> // If the function threw an exception, do so here.
> - if (result.is_exception())
> - {
> + if (result.is_exception()) {
> thread.skipRemainingBuffer();
> }
>
> @@ -2553,12 +2543,11 @@
> unsigned nargs = unsigned(env.pop().to_number());
>
> as_value constructorval = thread.getVariable(classname);
> - boost::intrusive_ptr<as_function> constructor =
> constructorval.to_function();
> - if ( ! constructor )
> - {
> + as_function* constructor = constructorval.to_function();
> + if (!constructor) {
> IF_VERBOSE_ASCODING_ERRORS(
> - log_aserror(_("ActionNew: "
> - "'%s' is not a constructor"), classname);
> + log_aserror(_("ActionNew: "
> + "'%s' is not a constructor"), classname);
> );
> env.drop(nargs);
> env.push(as_value()); // should we push an object anyway ?
> @@ -2570,7 +2559,7 @@
> // deleted. BitmapData also fails to construct anything under
> // some circumstances.
> try {
> - as_object* newobj = construct_object(constructor.get(), env, nargs);
> + as_object* newobj = construct_object(constructor, env, nargs);
> #ifdef USE_DEBUGGER
> debugger.addSymbol(newobj, classname);
> #endif
> @@ -2923,6 +2912,27 @@
> env.top(0).set_double(env.top(0).to_number() - 1);
> }
>
> +
> +/// Call a method of an object
> +//
> +/// Stack: method, object, argc, arg0 ... argn
> +//
> +/// The standard use of this opcode is:
> +/// 1. First stack value converted to a string (method name).
> +/// 2. Second stack value converted to an object (this pointer).
> +/// 3. Arg count and arguments parsed.
> +/// 4. The method name must be a property of the object and is called with
> +/// the object as its 'this'.
> +//
> +/// But it can also be used in a different way under some circumstances.
> +//
> +/// 1. If the method name is defined and not empty, the object value must
> +/// be an object and the method name must be a property of the object
> +/// (may be inherited). Otherwise the call fails and returns undefined.
> +/// 2. If the method name is undefined or empty, the second stack value is
> +/// called, and call's 'this' pointer is undefined.
> +//
> +/// In both usages the arguments are passed.
> void
> SWFHandlers::ActionCallMethod(ActionExec& thread)
> {
> @@ -2931,101 +2941,61 @@
> // Get name function of the method
> as_value method_name = env.pop();
>
> + std::string method_string = method_name.to_string();
> +
> // Get an object
> as_value obj_value = env.pop();
>
> // Get number of args, modifying it if not enough values are on the
> stack.
> - unsigned nargs = unsigned(env.pop().to_number());
> - unsigned available_args = env.stack_size();
> - if (available_args < nargs)
> - {
> + size_t nargs = static_cast<size_t>(env.pop().to_number());
> + const size_t available_args = env.stack_size();
> + if (available_args < nargs) {
> IF_VERBOSE_MALFORMED_SWF(
> - log_swferror(_("Attempt to call a method with %u arguments "
> - "while only %u are available on the stack."),
> - nargs, available_args);
> + log_swferror(_("Attempt to call a method with %u arguments "
> + "while only %u are available on the stack."),
> + nargs, available_args);
> );
> nargs = available_args;
> }
>
> -
> IF_VERBOSE_ACTION (
> log_action(_(" method name: %s"), method_name);
> log_action(_(" method object/func: %s"), obj_value);
> log_action(_(" method nargs: %d"), nargs);
> );
>
> - std::string method_string = method_name.to_string();
> -
> - bool hasMethodName = ((!method_name.is_undefined()) &&
> - (!method_string.empty()) );
> -
> as_object* obj = convertToObject(getGlobal(thread.env), obj_value);
> if (!obj) {
> - // SWF integrity check
> + // If this value is not an object, it can neither have any members
> + // nor be called as a function, so neither opcode usage is possible.
> IF_VERBOSE_ASCODING_ERRORS(
> - log_aserror(_("ActionCallMethod invoked with "
> - "non-object object/func (%s)"), obj_value);
> + log_aserror(_("ActionCallMethod invoked with "
> + "non-object object/func (%s)"), obj_value);
> );
> env.drop(nargs);
> env.push(as_value());
> return;
> }
>
> - as_object* this_ptr = obj;
> -
> - if (obj->isSuper()) {
> - if (thread.isFunction()) this_ptr = thread.getThisPointer();
> - }
> -
> + const bool noMeth = (method_name.is_undefined() ||
> method_string.empty());
> +
> + // The method to call
> + as_value method;
> +
> + // The object to be the 'this' pointer during the call.
> + as_object* this_ptr(0);
> string_table& st = getStringTable(env);
> - as_object* super =
> - obj->get_super(hasMethodName ? st.find(method_string) : 0);
> -
> - as_value method_val;
> -
> - if (!hasMethodName) {
> - // We'll be calling the super constructor here
> - method_val = obj_value;
> -
> - if (!method_val.is_function())
> - {
> -
> - log_debug(_("Function object given to ActionCallMethod"
> - " is not a function (%s), will try to use"
> - " its 'constructor' member (but should instead "
> - "invoke its [[Call]] method"), obj_value);
> -
> - // TODO: all this crap should go into an
> - // as_object::getConstructor instead
> - as_value ctor;
> - if (!obj->get_member(NSV::PROP_CONSTRUCTOR, &ctor) )
> - {
> - IF_VERBOSE_ASCODING_ERRORS(
> - log_aserror(_("ActionCallMethod: object has no "
> - "constructor"));
> - );
> - env.drop(nargs);
> - env.push(as_value());
> - return;
> - }
> - if (!ctor.is_function())
> - {
> - IF_VERBOSE_ASCODING_ERRORS(
> - log_aserror(_("ActionCallMethod: object constructor "
> - "is not a function"));
> - );
> - env.drop(nargs);
> - env.push(as_value());
> - return;
> - }
> - method_val = ctor;
> - }
> + as_object* super = obj->get_super(noMeth ? 0 : st.find(method_string));
> +
> + // If the method name is undefined or evaluates to an empty string,
> + // the first argument is used as the method name and the 'this' pointer
> + // is undefined. We can signify this by leaving the 'this' pointer as
> + // null.a
> + if (noMeth) {
> + method = obj_value;
> }
> - else
> - {
> -
> - if ( ! thread.getObjectMember(*obj, method_string, method_val) )
> - {
> + else {
> + if (!thread.getObjectMember(*obj, method_string, method)) {
> IF_VERBOSE_ASCODING_ERRORS(
> log_aserror(_("ActionCallMethod: "
> "Can't find method %s of object %s"),
> @@ -3033,22 +3003,29 @@
> obj_value);
> );
> env.drop(nargs);
> - env.push(as_value()); // should we push an object anyway ?
> + env.push(as_value());
> return;
> }
> + else {
> + this_ptr = obj;
> + }
> + }
> +
> + // If we are calling a method of a super object, the 'this' pointer
> + // for the call is always the this pointer of the function that called
> + // super().
> + if (obj->isSuper()) {
> + if (thread.isFunction()) this_ptr = thread.getThisPointer();
> }
>
> #ifdef USE_DEBUGGER
> -// log_debug (_("FIXME: method name is: %s"), method_namexxx);
> -// // IT IS NOT GUARANTEE WE DO HAVE A METHOD NAME HERE !
> - if ( ! method_name.is_undefined() )
> - {
> + if (! method_name.is_undefined()) {
> debugger.callStackPush(method_name.to_string());
> debugger.matchBreakPoint(method_name.to_string(), true);
> }
> - else
> - {
> - LOG_ONCE( log_unimpl(_("FIXME: debugger doesn't deal with anonymous
> function calls")) );
> + else {
> + LOG_ONCE( log_unimpl(_("FIXME: debugger doesn't deal with "
> + "anonymous function calls")) );
> }
> #endif
>
> @@ -3057,7 +3034,7 @@
> args += env.pop();
> }
>
> - as_value result = invoke(method_val, env, this_ptr,
> + as_value result = invoke(method, env, this_ptr,
> args, super, &(thread.code.getMovieDefinition()));
>
> env.push(result);
> @@ -3122,7 +3099,7 @@
> }
> }
>
> - boost::intrusive_ptr<as_function> method = method_val.to_function();
> + as_function* method = method_val.to_function();
> if (!method) {
> IF_VERBOSE_MALFORMED_SWF(
> log_swferror(_("ActionNewMethod: method name is undefined "
> @@ -3139,7 +3116,7 @@
> // deleted. BitmapData also fails to construct anything under
> // some circumstances.
> try {
> - as_object* newobj = construct_object(method.get(), env, nargs);
> + as_object* newobj = construct_object(method, env, nargs);
> env.push(newobj);
> return;
> }
> @@ -3334,21 +3311,17 @@
>
> as_environment& env = thread.env;
>
> - as_function* super = env.top(0).to_function();
> + as_object* super = env.top(0).to_object(getGlobal(thread.env));
> as_function* sub = env.top(1).to_function();
>
> - if ( ! super || ! sub )
> - {
> - IF_VERBOSE_ASCODING_ERRORS
> - (
> - if ( ! super )
> - {
> - log_aserror(_("ActionExtends: Super is not an as_function
> (%s)"),
> + if (!super ||!sub) {
> + IF_VERBOSE_ASCODING_ERRORS(
> + if (!super) {
> + log_aserror(_("ActionExtends: Super is not an object (%s)"),
> env.top(0));
> }
> - if ( ! sub )
> - {
> - log_aserror(_("ActionExtends: Sub is not an as_function
> (%s)"),
> + if (!sub) {
> + log_aserror(_("ActionExtends: Sub is not a function (%s)"),
> env.top(1));
> }
> );
>
> === modified file 'libcore/vm/fn_call.h'
> --- a/libcore/vm/fn_call.h 2009-11-16 10:40:56 +0000
> +++ b/libcore/vm/fn_call.h 2009-11-23 16:45:19 +0000
> @@ -109,13 +109,61 @@
> class fn_call
> {
> public:
> +
> typedef FunctionArgs<as_value> Args;
>
> + /// Construct a fn_call
> + //
> + /// @param isNew Pass true if this is a constructing fn_call,
> + /// i.e. if it is called as a result of 'new'.
> + /// @param super Pass an overridden super value to the function
> + /// call. If this is 0, the super reference will be
> + /// calculated from the this pointer (if that is not
> + /// null) whenever a function requires it.
> + fn_call(as_object* this_in, const as_environment& env_in,
> + Args& args, as_object* sup = 0, bool isNew = false)
> + :
> + this_ptr(this_in),
> + super(sup),
> + nargs(args.size()),
> + callerDef(0),
> + _new(isNew),
> + _env(env_in)
> + {
> + args.swap(_args);
> + }
> +
> + fn_call(as_object* this_in, const as_environment& env_in)
> + :
> + this_ptr(this_in),
> + super(0),
> + nargs(0),
> + callerDef(0),
> + _new(false),
> + _env(env_in)
> + {
> + }
> +
> + /// Copy constructor
> + fn_call(const fn_call& fn)
> + :
> + this_ptr(fn.this_ptr),
> + super(fn.super),
> + nargs(fn.nargs),
> + callerDef(fn.callerDef),
> + _new(false),
> + _env(fn._env),
> + _args(fn._args)
> + {
> + }
> +
> /// The as_object (or a pointer derived thereof) on which this call
> /// is taking place.
> as_object* this_ptr;
>
> /// The "super" object in this function call context
> + //
> + /// If this is 0, the super may be constructed from the this pointer.
> as_object* super;
>
> /// Number of arguments to this ActionScript function call.
> @@ -124,68 +172,6 @@
> /// Definition containing caller code. 0 if spontaneous (system event).
> const movie_definition* callerDef;
>
> - fn_call(const fn_call& fn)
> - :
> - this_ptr(fn.this_ptr),
> - super(fn.super),
> - nargs(fn.nargs),
> - callerDef(fn.callerDef),
> - _new(false),
> - _env(fn._env),
> - _args(fn._args)
> - {
> - }
> -
> - fn_call(const fn_call& fn, as_object* this_in, as_object* sup = 0)
> - :
> - this_ptr(this_in),
> - super(sup),
> - nargs(fn.nargs),
> - callerDef(fn.callerDef),
> - _new(false),
> - _env(fn._env),
> - _args(fn._args)
> - {
> - }
> -
> - fn_call(as_object* this_in, const as_environment& env_in,
> - int nargs_in, size_t first_in, as_object* sup = 0)
> - :
> - this_ptr(this_in),
> - super(sup),
> - nargs(nargs_in),
> - callerDef(0),
> - _new(false),
> - _env(env_in)
> - {
> - assert(first_in + 1 == env_in.stack_size());
> - readArgs(env_in, first_in, nargs);
> - }
> -
> - fn_call(as_object* this_in, const as_environment& env_in,
> - Args& args, as_object* sup = 0, bool isNew = false)
> - :
> - this_ptr(this_in),
> - super(sup),
> - nargs(args.size()),
> - callerDef(0),
> - _new(isNew),
> - _env(env_in)
> - {
> - args.swap(_args);
> - }
> -
> - fn_call(as_object* this_in, const as_environment& env_in)
> - :
> - this_ptr(this_in),
> - super(0),
> - nargs(0),
> - callerDef(0),
> - _new(false),
> - _env(env_in)
> - {
> - }
> -
> /// Return the VM this fn_call is running from
> VM& getVM() const
> {
> @@ -195,12 +181,6 @@
> /// Return true if this call is an object instantiation
> bool isInstantiation() const
> {
> - // Currently the as_function::constructInstance
> - // will set 'this_ptr' to NULL when calling a builtin
> - // function, so we use this info to find out.
> - // For the future, we might use an explicit flag instead
> - // as I belive there are some cases in which 'this' is
> - // undefined even in a normal function call.
> return _new;
> }
>
> @@ -268,14 +248,6 @@
> /// The actual arguments
> Args::container_type _args;
>
> - void readArgs(const as_environment& env, int first_in, size_t nargs)
> - {
> - _args.clear();
> - for (size_t i = 0; i < nargs; ++i) {
> - _args.push_back(env.bottom(first_in - i));
> - }
> - }
> -
> };
>
>
>
> === modified file 'testsuite/actionscript.all/getvariable.as'
> --- a/testsuite/actionscript.all/getvariable.as 2009-02-25 22:33:03
> +0000
> +++ b/testsuite/actionscript.all/getvariable.as 2009-11-23 10:33:10
> +0000
> @@ -687,9 +687,9 @@
> //-----------------------------------------------------------------------
>
> #if OUTPUT_VERSION < 6
> - xcheck_totals(52); // gnash runs +2 tests ?!
> + check_totals(52); // gnash runs +2 tests ?!
> #else
> - xcheck_totals(57); // gnash runs +2 tests ?!
> + check_totals(57); // gnash runs +2 tests ?!
> #endif
>
> #else // ndef MING_SUPPORT_ASM
>
> === modified file 'testsuite/misc-swfmill.all/Makefile.am'
> --- a/testsuite/misc-swfmill.all/Makefile.am 2009-07-07 07:52:53 +0000
> +++ b/testsuite/misc-swfmill.all/Makefile.am 2009-11-23 16:44:15 +0000
> @@ -40,6 +40,15 @@
> $(NULL)
>
> # XML tests that rely on comparing trace output.
> +
> +TRACE_AS2_TESTS = \
> + super.xml \
> + $(NULL)
> +
> +TRACE_AS2_TRACES = \
> + super.trace \
> + $(NULL)
> +
> TRACE_AS3_TESTS = \
> scope1.xml \
> stack1.xml \
> @@ -52,7 +61,9 @@
>
> EXTRA_DIST = $(SC_AS2_XMLTESTS) \
> $(SC_AS3_XMLTESTS) \
> - $(TRACE_AS3_TESTS) \
> + $(TRACE_AS2_TESTS) \
> + $(TRACE_AS2_TRACES) \
> + $(TRACE_AS3_TESTS) \
> $(TRACE_AS3_TRACES) \
> gen-swfmill-trace-runner.sh \
> $(NULL)
> @@ -70,20 +81,26 @@
> -I$(top_srcdir)/testsuite \
> $(NULL)
>
> +TRACE_TESTS = $(TRACE_AS2_TESTS)
> +TRACES = $(TRACE_AS2_TRACES)
> SC_XMLTESTS_OUT = $(SC_AS2_XMLTESTS:.xml=.swf)
> -TRACE_XMLTESTS_OUT =
> +
>
> if ENABLE_AVM2
> if SWFMILL_AS3_SUPPORT
> +TRACE_TESTS += $(TRACE_AS3_TESTS)
> +TRACES += $(TRACE_AS3_TRACES)
> SC_XMLTESTS_OUT += $(SC_AS3_XMLTESTS:.xml=.swf)
> -TRACE_XMLTESTS_OUT += $(TRACE_AS3_TESTS:.xml=.swf)
> -endif
> -endif
> +endif
> +endif
> +
> +TRACE_XMLTESTS_OUT = $(TRACE_TESTS:.xml=.swf)
>
> # Dependencies for all self-contained SWF tests
> $(SC_XMLTESTS_OUT) :
>
> check_SCRIPTS = \
> + trace-test-runner \
> mixed-bytecode-as2-runner \
> jump_after_end-runner \
> jump_to_prev_block-runner \
> @@ -98,7 +115,6 @@
> if SWFMILL_AS3_SUPPORT
> check_SCRIPTS += \
> mixed-bytecode-as3-runner \
> - trace-test-runner \
> $(NULL)
> endif
> endif
>
> === modified file 'testsuite/misc-swfmill.all/PASSING'
> --- a/testsuite/misc-swfmill.all/PASSING 2009-06-29 11:43:07 +0000
> +++ b/testsuite/misc-swfmill.all/PASSING 2009-11-23 16:44:15 +0000
> @@ -1,1 +1,2 @@
> stack1
> +super
>
> === added file 'testsuite/misc-swfmill.all/super.trace'
> --- a/testsuite/misc-swfmill.all/super.trace 1970-01-01 00:00:00 +0000
> +++ b/testsuite/misc-swfmill.all/super.trace 2009-11-23 16:44:15 +0000
> @@ -0,0 +1,8 @@
> +[object Object]
> +undefined
> +undefined
> +undefined
> +[object Object]
> +undefined
> +undefined
> +[object Object]
>
> === added file 'testsuite/misc-swfmill.all/super.xml'
> --- a/testsuite/misc-swfmill.all/super.xml 1970-01-01 00:00:00 +0000
> +++ b/testsuite/misc-swfmill.all/super.xml 2009-11-23 16:44:15 +0000
> @@ -0,0 +1,362 @@
> +<?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="super"/>
> + <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>
> + <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 0 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 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>
> + <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 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>
> + <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 0 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>
> + <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 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>
> + <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 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>
> + <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>
> + <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>
>
> === modified file 'testsuite/swfdec/PASSING'
> --- a/testsuite/swfdec/PASSING 2009-11-11 23:18:13 +0000
> +++ b/testsuite/swfdec/PASSING 2009-11-23 17:22:36 +0000
> @@ -175,6 +175,10 @@
> button-properties-8.swf:794f9c47e03aa3b0c75eeff87ba8a140
> call-arguments-5.swf:422c391a2abd3e864eb8ed8a1e05ad31
> callfunction-stack.swf:21d0c957f4caf0eb0ccd0dcadaf17500
> +callmethod-undefined-this-5.swf:affed3be009b851c05f72b8429f13b2d
> +callmethod-undefined-this-6.swf:c1695e653464da8c9b58b3e08c0d3325
> +callmethod-undefined-this-7.swf:6d2bd3cde681a7283013ebc7d9118cf7
> +callmethod-undefined-this-8.swf:467f925f9d959e71b8bcd14bb9222b16
> camera-properties-5.swf:495e39b641f89aa49a927cf0a8413028
> camera-properties-6.swf:3eb69243268f61cb8e130b661b6eac1a
> camera-properties-7.swf:ec270af18a3930560841e04ae4c8d952
>
> _______________________________________________
> Gnash-commit mailing list
> address@hidden
> http://lists.gnu.org/mailman/listinfo/gnash-commit
--
Free GIS & Flash consultant/developer () ASCII Ribbon Campaign
http://foo.keybit.net/~strk/services.html /\ Keep it simple!