gnash-commit
[Top][All Lists]
Advanced

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

[Gnash-commit] /srv/bzr/gnash/trunk r11649: Add call() to as_object inte


From: Benjamin Wolsey
Subject: [Gnash-commit] /srv/bzr/gnash/trunk r11649: Add call() to as_object interface, as this helps AS3 work.
Date: Mon, 23 Nov 2009 19:05:35 +0100
User-agent: Bazaar (1.16.1)

------------------------------------------------------------
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


reply via email to

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