gnash-commit
[Top][All Lists]
Advanced

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

[Gnash-commit] /srv/bzr/gnash/trunk r10541: Numerous AS fixes for 26 new


From: Benjamin Wolsey
Subject: [Gnash-commit] /srv/bzr/gnash/trunk r10541: Numerous AS fixes for 26 new swfdec testsuite and some actionscript.all
Date: Tue, 13 Jan 2009 14:35:10 +0100
User-agent: Bazaar (1.5)

------------------------------------------------------------
revno: 10541
committer: Benjamin Wolsey <address@hidden>
branch nick: trunk
timestamp: Tue 2009-01-13 14:35:10 +0100
message:
  Numerous AS fixes for 26 new swfdec testsuite and some actionscript.all
  passes.
modified:
  libcore/MovieClip.cpp
  libcore/MovieClip.h
  libcore/as_environment.cpp
  libcore/as_function.cpp
  libcore/as_object.cpp
  libcore/as_value.cpp
  libcore/as_value.h
  libcore/asobj/Array_as.cpp
  libcore/asobj/Date_as.cpp
  libcore/asobj/Error_as.cpp
  libcore/asobj/Global.cpp
  libcore/asobj/LoadVars_as.cpp
  libcore/asobj/LoadVars_as.h
  libcore/asobj/LoadableObject.cpp
  libcore/asobj/NetStream_as.cpp
  libcore/asobj/Number_as.cpp
  libcore/asobj/Object.cpp
  libcore/asobj/String_as.cpp
  libcore/movie_root.cpp
  libcore/vm/ASHandlers.cpp
  testsuite/actionscript.all/Date.as
  testsuite/actionscript.all/Error.as
  testsuite/actionscript.all/Number.as
  testsuite/swfdec/PASSING
  testsuite/swfdec/swfdec_gnash_tester
    ------------------------------------------------------------
    revno: 10538.1.1
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Sat 2009-01-10 13:29:31 +0100
    message:
      Add a couple more tests in Number.as (all passing).
    modified:
      libcore/vm/ASHandlers.cpp
      testsuite/actionscript.all/Number.as
    ------------------------------------------------------------
    revno: 10538.1.2
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Sat 2009-01-10 16:14:35 +0100
    message:
      Move number conversion into separate functions so it can be used for
      parseInt too.
    modified:
      libcore/as_value.cpp
      libcore/as_value.h
    ------------------------------------------------------------
    revno: 10538.1.3
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Sat 2009-01-10 19:26:07 +0100
    message:
      Start using as_value::parseInt for Global.parseInt.
    modified:
      libcore/as_value.cpp
      libcore/as_value.h
      libcore/asobj/Global.cpp
    ------------------------------------------------------------
    revno: 10538.1.4
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Sat 2009-01-10 20:54:58 +0100
    message:
      Cleaned up but slightly unsafe version of parseInt.
    modified:
      libcore/asobj/Global.cpp
    ------------------------------------------------------------
    revno: 10538.1.5
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Sat 2009-01-10 21:19:13 +0100
    message:
      Clean it up and make safe.
    modified:
      libcore/asobj/Global.cpp
    ------------------------------------------------------------
    revno: 10538.1.6
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Sat 2009-01-10 21:29:06 +0100
    message:
      Use string size_type properly.
    modified:
      libcore/asobj/Global.cpp
    ------------------------------------------------------------
    revno: 10538.1.7
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Sat 2009-01-10 21:51:43 +0100
    message:
      More sensible name.
    modified:
      libcore/as_value.cpp
      libcore/as_value.h
      libcore/asobj/Global.cpp
    ------------------------------------------------------------
    revno: 10538.1.8
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Mon 2009-01-12 10:50:04 +0100
    message:
      Do doubleToString better in as_value. Move dox to header.
      
      Check Date.setTime() arguments better, so that swfdec test passes.
    modified:
      libcore/as_value.cpp
      libcore/as_value.h
      libcore/asobj/Date_as.cpp
      libcore/asobj/Number_as.cpp
    ------------------------------------------------------------
    revno: 10538.1.9
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Mon 2009-01-12 13:03:12 +0100
    message:
      Make leap years calculation more readable and do what it's supposed to.
      
      Handle setYear arguments properly.
      
      Passes in actionscript.all, and 8 more swfdec passes.
    modified:
      libcore/asobj/Date_as.cpp
      testsuite/actionscript.all/Date.as
      testsuite/swfdec/PASSING
    ------------------------------------------------------------
    revno: 10538.1.10
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Mon 2009-01-12 14:51:00 +0100
    message:
      Prefer valueOf over toString for all objects when comparing as_values 
where
      this is an object. Fixes ActionNewEquals for dates in SWF6+, and some
      swfdec testcases.
    modified:
      libcore/as_object.cpp
      libcore/as_value.cpp
      libcore/asobj/Date_as.cpp
      libcore/asobj/Object.cpp
      libcore/vm/ASHandlers.cpp
      testsuite/swfdec/PASSING
    ------------------------------------------------------------
    revno: 10538.1.11
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Mon 2009-01-12 15:37:36 +0100
    message:
      Split long lines.
    modified:
      libcore/vm/ASHandlers.cpp
    ------------------------------------------------------------
    revno: 10538.1.12
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Mon 2009-01-12 16:17:59 +0100
    message:
      Pass a const std::string& to add_empty_movieclip().
    modified:
      libcore/MovieClip.cpp
      libcore/MovieClip.h
    ------------------------------------------------------------
    revno: 10538.1.13
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Mon 2009-01-12 17:00:41 +0100
    message:
      Correct Error implementation. Passes in actionscript.all.
    modified:
      libcore/asobj/Error_as.cpp
      testsuite/actionscript.all/Error.as
    ------------------------------------------------------------
    revno: 10538.1.14
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Mon 2009-01-12 17:41:54 +0100
    message:
      Correct prop flags for "extends". SWF5 still fails, probably because of
      prop flags when looking up constructor and __proto__.
    modified:
      libcore/as_function.cpp
      testsuite/swfdec/PASSING
    ------------------------------------------------------------
    revno: 10538.1.15
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Mon 2009-01-12 22:12:01 +0100
    message:
      Modify sed script so it doesn't drop half the lines from
      function-apply-?.out.swf.
    modified:
      testsuite/swfdec/swfdec_gnash_tester
    ------------------------------------------------------------
    revno: 10538.1.16
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Mon 2009-01-12 22:13:27 +0100
    message:
      function-apply-5.swf passes now the whole trace is compared.
    modified:
      testsuite/swfdec/PASSING
    ------------------------------------------------------------
    revno: 10538.1.17
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Mon 2009-01-12 22:34:39 +0100
    message:
      Assign correct "this" in function apply() calls undefined or non-object
      first argument.
      
      The only remaining failure in function-apply is the fact that arrays can't
      be faked in Gnash.
    modified:
      libcore/as_function.cpp
    ------------------------------------------------------------
    revno: 10538.1.18
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Tue 2009-01-13 07:55:23 +0100
    message:
      Indentation.
    modified:
      libcore/as_environment.cpp
    ------------------------------------------------------------
    revno: 10538.1.19
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Tue 2009-01-13 08:05:59 +0100
    message:
      Line breaks.
    modified:
      libcore/movie_root.cpp
    ------------------------------------------------------------
    revno: 10538.1.20
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Tue 2009-01-13 08:51:21 +0100
    message:
      Register LoadVars.decode as an ASnative, move to LoadableObject, and drop
      type checking. Passes in swfdec testsuite.
    modified:
      libcore/asobj/LoadVars_as.cpp
      libcore/asobj/LoadVars_as.h
      libcore/asobj/LoadableObject.cpp
      testsuite/swfdec/PASSING
    ------------------------------------------------------------
    revno: 10538.1.21
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Tue 2009-01-13 09:22:29 +0100
    message:
      Cosmetic change.
    modified:
      libcore/asobj/String_as.cpp
    ------------------------------------------------------------
    revno: 10538.1.22
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Tue 2009-01-13 12:05:41 +0100
    message:
      Clean ups.
    modified:
      libcore/as_object.cpp
      libcore/asobj/Global.cpp
    ------------------------------------------------------------
    revno: 10538.1.23
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Tue 2009-01-13 13:09:21 +0100
    message:
      Break long lines, especially long comments appended to lines of code,
      which are annoying and horrible.
    modified:
      libcore/asobj/Array_as.cpp
      libcore/asobj/NetStream_as.cpp
    ------------------------------------------------------------
    revno: 10538.1.24
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Tue 2009-01-13 13:25:30 +0100
    message:
      Always start the NetStream advance timer, so that status notifications
      are always sent. Pass in swfdec testsuite.
    modified:
      libcore/asobj/NetStream_as.cpp
    ------------------------------------------------------------
    revno: 10538.1.25
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Tue 2009-01-13 13:56:25 +0100
    message:
      Add pass in swfdec.
    modified:
      testsuite/swfdec/PASSING
    ------------------------------------------------------------
    revno: 10538.1.26
    committer: Benjamin Wolsey <address@hidden>
    branch nick: work
    timestamp: Tue 2009-01-13 14:11:42 +0100
    message:
      Finish documentation.
    modified:
      libcore/as_value.h
=== modified file 'libcore/MovieClip.cpp'
--- a/libcore/MovieClip.cpp     2009-01-12 08:48:02 +0000
+++ b/libcore/MovieClip.cpp     2009-01-13 13:35:10 +0000
@@ -539,7 +539,7 @@
 }
 
 character*
-MovieClip::add_empty_movieclip(const char* name, int depth)
+MovieClip::add_empty_movieclip(const std::string& name, int depth)
 {
     // empty_movieclip_def will be deleted during deleting movieclip
     sprite_definition* empty_sprite_def =
@@ -2197,14 +2197,14 @@
     // See misc-ming.all/action_execution_order_test4.{c,swf}
     //
     assert(!_callingFrameActions); // or will not be queuing actions
-    if ( get_parent() == 0 )
+    if (!get_parent())
     {
 #ifdef GNASH_DEBUG
         log_debug(_("Executing tags of frame0 in movieclip %s"), getTarget());
 #endif
         execute_frame_tags(0, m_display_list, TAG_DLIST|TAG_ACTION);
 
-        if ( _vm.getSWFVersion() > 5 )
+        if (_vm.getSWFVersion() > 5)
         {
 #ifdef GNASH_DEBUG
             log_debug(_("Queuing ONLOAD event for movieclip %s"), getTarget());
@@ -2215,7 +2215,6 @@
     }
     else
     {
-
 #ifdef GNASH_DEBUG
         log_debug(_("Queuing ONLOAD event for movieclip %s"), getTarget());
 #endif
@@ -2241,15 +2240,14 @@
     {
         assert(!initObj);
 #ifdef GNASH_DEBUG
-        log_debug(_("Queuing INITIALIZE event for movieclip %s"), getTarget());
+        log_debug(_("Queuing INITIALIZE and CONSTRUCT events for movieclip 
%s"),
+                getTarget());
 #endif
         queueEvent(event_id::INITIALIZE, movie_root::apINIT);
 
-#ifdef GNASH_DEBUG
-        log_debug(_("Queuing CONSTRUCT event for movieclip %s"), getTarget());
-#endif
         std::auto_ptr<ExecutableCode> code ( new ConstructEvent(this) );
         _vm.getRoot().pushAction(code, movie_root::apCONSTRUCT);
+
     }
     else {
 
@@ -2261,10 +2259,6 @@
         }
 
         constructAsScriptObject(); 
-#ifdef GNASH_DEBUG
-        log_debug(_("Sprite %s is dynamic, sending "
-                "INITIALIZE and CONSTRUCT events immediately"), getTarget());
-#endif
 
         // Tested in testsuite/swfdec/duplicateMovieclip-events.c and
         // testsuite/swfdec/clone-sprite-events.c not to call on_event
@@ -3379,7 +3373,7 @@
     // Unlike other MovieClip methods, the depth argument of an empty movie 
clip
     // can be any number. All numbers are converted to an int32_t, and are 
valid
     // depths even when outside the usual bounds.
-    character* ch = 
movieclip->add_empty_movieclip(fn.arg(0).to_string().c_str(),
+    character* ch = movieclip->add_empty_movieclip(fn.arg(0).to_string(),
             fn.arg(1).to_int());
     return as_value(ch);
 }

=== modified file 'libcore/MovieClip.h'
--- a/libcore/MovieClip.h       2008-12-17 07:29:09 +0000
+++ b/libcore/MovieClip.h       2009-01-12 15:17:59 +0000
@@ -349,7 +349,7 @@
     ///
     character* get_character_at_depth(int depth);
 
-    character* add_empty_movieclip(const char* name, int depth);
+    character* add_empty_movieclip(const std::string& name, int depth);
 
     boost::intrusive_ptr<character> add_textfield(const std::string& name,
             int depth, int x, int y, float width, float height);

=== modified file 'libcore/as_environment.cpp'
--- a/libcore/as_environment.cpp        2009-01-07 15:23:27 +0000
+++ b/libcore/as_environment.cpp        2009-01-13 06:55:23 +0000
@@ -60,15 +60,16 @@
 as_environment::get_variable(const std::string& varname,
         const ScopeStack& scopeStack, as_object** retTarget) const
 {
-    // Path lookup rigamarole.
-    std::string path;
-    std::string var;
 
 #ifdef GNASH_DEBUG_GET_VARIABLE
     log_debug(_("get_variable(%s)"), varname);
 #endif
 
-    if ( parse_path(varname, path, var) )
+    // Path lookup rigamarole.
+    std::string path;
+    std::string var;
+
+    if (parse_path(varname, path, var))
     {
         // TODO: let find_target return generic as_objects, or use 'with' 
stack,
         //       see player2.swf or bug #18758 (strip.swf)
@@ -77,7 +78,7 @@
 
         if (target)
         {
-            as_value    val;
+            as_value val;
             target->get_member(_vm.getStringTable().find(var), &val);
             if ( retTarget ) *retTarget = target;
             return val;
@@ -553,22 +554,21 @@
 }
 
 as_object*
-as_environment::find_object(const std::string& path_in,
+as_environment::find_object(const std::string& path,
         const ScopeStack* scopeStack) const
 {
 #ifdef DEBUG_TARGET_FINDING 
-    log_debug(_("find_object(%s) called"), path_in);
+    log_debug(_("find_object(%s) called"), path);
 #endif
 
-    if (path_in.empty())
+    if (path.empty())
     {
 #ifdef DEBUG_TARGET_FINDING 
-    log_debug(_("Returning m_target (empty path)"));
+        log_debug(_("Returning m_target (empty path)"));
 #endif
-    return m_target; // or should we return the *original* path ?
+        return m_target; // or should we return the *original* path ?
     }
     
-    std::string path = PROPNAME(path_in);
     VM& vm = _vm;
     string_table& st = vm.getStringTable();
     int swfVersion = vm.getSWFVersion(); 
@@ -577,48 +577,50 @@
     env = m_target; 
 
     bool firstElementParsed = false;
-    bool dot_allowed=true;
+    bool dot_allowed = true;
 
     const char* p = path.c_str();
     if (*p == '/')
     {
-    // Absolute path.  Start at the (AS) root (handle _lockroot)
-    MovieClip* root = 0;
+        // Absolute path.  Start at the (AS) root (handle _lockroot)
+        MovieClip* root = 0;
         if ( m_target ) root = const_cast<MovieClip*>(m_target->getAsRoot());
         else {
             if ( _original_target )
             {
-                log_debug("current target is undefined on 
as_environment::find_object, we'll use original");
+                log_debug("current target is undefined on "
+                        "as_environment::find_object, we'll use original");
                 root = const_cast<MovieClip*>(_original_target->getAsRoot());
             }
             else
             {
-                log_debug("both current and original target are undefined on 
as_environment::find_object, we'll return 0");
+                log_debug("both current and original target are undefined "
+                        "on as_environment::find_object, we'll return 0");
                 return 0;
             }
         }
 
-    if ( ! *(++p) )
-    {
+        if ( ! *(++p) )
+        {
 #ifdef DEBUG_TARGET_FINDING 
-        log_debug(_("Path is '/', return the root (%p)"), (void*)root);
+            log_debug(_("Path is '/', return the root (%p)"), (void*)root);
 #endif
-        return root; // that's all folks.. 
-    }
+            return root; // that's all folks.. 
+        }
 
-    env = root;
+        env = root;
         firstElementParsed = true;
-    dot_allowed = false;
+        dot_allowed = false;
 
 #ifdef DEBUG_TARGET_FINDING 
-    log_debug(_("Absolute path, start at the root (%p)"), (void*)env);
+        log_debug(_("Absolute path, start at the root (%p)"), (void*)env);
 #endif
 
     }
 #ifdef DEBUG_TARGET_FINDING 
     else
     {
-    log_debug(_("Relative path, start at (%s)"), m_target->getTarget());
+        log_debug(_("Relative path, start at (%s)"), m_target->getTarget());
     }
 #endif
     
@@ -627,143 +629,145 @@
     std::string subpart;
     while (1)
     {
-    while ( *p == ':' ) ++p;
+        while ( *p == ':' ) ++p;
 
-    // No more components to scan
-    if ( ! *p )
-    {
+        // No more components to scan
+        if ( ! *p )
+        {
 #ifdef DEBUG_TARGET_FINDING 
-        log_debug(_("Path is %s, returning whatever we were up to"), path);
+            log_debug(_("Path is %s, returning whatever we were up to"), path);
 #endif
-        return env;
-    }
-
-
-    const char* next_slash = next_slash_or_dot(p);
-    subpart = p;
-    if (next_slash == p)
-    {
+            return env;
+        }
+
+
+        const char* next_slash = next_slash_or_dot(p);
+        subpart = p;
+        if (next_slash == p)
+        {
             IF_VERBOSE_ASCODING_ERRORS(
-        log_aserror(_("invalid path '%s' (p=next_slash=%s)"), path, 
next_slash);
-        );
-        return NULL;
-    }
-    else if (next_slash)
-    {
-        if ( *next_slash == '.' )
-        {
-            if ( ! dot_allowed )
-            {
-                IF_VERBOSE_ASCODING_ERRORS(
-                log_aserror(_("invalid path '%s' (dot not allowed after having 
seen a slash)"), path);
-                );
-                return NULL;
-            }
-        }
-        else if ( *next_slash == '/' )
-        {
-            dot_allowed = false;
-        }
-
-        // Cut off the slash and everything after it.
-        subpart.resize(next_slash - p);
-    }
-    
-    assert(subpart[0] != ':');
-
-    // No more components to scan
-    if ( subpart.empty() )
-    {
-#ifdef DEBUG_TARGET_FINDING 
-        log_debug(_("No more subparts, env is %p"), (void*)env);
-#endif
-        break;
-    }
-
-    string_table::key subpartKey = st.find(subpart);
-
-    if ( ! firstElementParsed )
-    {
-        as_object* element = NULL;
-
-        do {
-
-            // Try scope stack
-            if ( scopeStack )
-            {
-                for (size_t i = scopeStack->size(); i > 0; --i)
-                {
-                    // const_cast needed due to non-const 
as_object::get_member 
-                    as_object* obj = 
const_cast<as_object*>((*scopeStack)[i-1].get());
-                    element = obj->get_path_element(subpartKey);
-                    if ( element ) break;
-                }
-                if ( element ) break;
-            }
-
-            // Try current target  (if any)
-            assert(env == m_target);
-            if ( env )
-            {
-                element = env->get_path_element(subpartKey);
-                if ( element ) break;
-            }
-            // else if ( _original_target) // TODO: try orig target too ?
-
-            // Looking for _global ?
-            as_object* global = _vm.getGlobal();
-            if ( swfVersion > 5 && subpartKey == NSV::PROP_uGLOBAL )
-            {
-                element = global;
-                break;
-            }
-
-            // Try globals
-            element = global->get_path_element(subpartKey);
-            //if ( element ) break;
-
-        } while (0);
-
-        if ( ! element ) 
-        {
-#ifdef DEBUG_TARGET_FINDING 
-            log_debug("subpart %s of path %s not found in any "
-            "scope stack element", subpart, path);
-#endif
-            return NULL;
-        }
-
-        env = element;
-        firstElementParsed = true;
-    }
-    else
-    {
-
-        assert(env);
-
-#ifdef DEBUG_TARGET_FINDING 
-        log_debug(_("Invoking get_path_element(%s) on object "
-                "%p (%s)"), subpart, (void *)env, env->get_text_value());
-#endif
-
-        as_object* element = env->get_path_element(subpartKey);
-        if ( ! element )
-        {
-#ifdef DEBUG_TARGET_FINDING 
-            log_debug(_("Path element %s not found in "
-                        "object %p"), subpart, (void *)env);
-#endif
-            return NULL;
-        }
-        env = element;
-    }
-
-    if (next_slash == NULL)
-    {
-        break;
-    }
-    
-    p = next_slash + 1;
+                log_aserror(_("invalid path '%s' (p=next_slash=%s)"),
+                path, next_slash);
+            );
+            return NULL;
+        }
+        else if (next_slash)
+        {
+            if ( *next_slash == '.' )
+            {
+                if ( ! dot_allowed )
+                {
+                    IF_VERBOSE_ASCODING_ERRORS(
+                    log_aserror(_("invalid path '%s' (dot not allowed "
+                            "after having seen a slash)"), path);
+                    );
+                    return NULL;
+                }
+            }
+            else if ( *next_slash == '/' )
+            {
+                dot_allowed = false;
+            }
+
+            // Cut off the slash and everything after it.
+            subpart.resize(next_slash - p);
+        }
+        
+        assert(subpart[0] != ':');
+
+        // No more components to scan
+        if ( subpart.empty() )
+        {
+#ifdef DEBUG_TARGET_FINDING 
+            log_debug(_("No more subparts, env is %p"), (void*)env);
+#endif
+            break;
+        }
+
+        string_table::key subpartKey = st.find(subpart);
+
+        if ( ! firstElementParsed )
+        {
+            as_object* element = NULL;
+
+            do {
+
+                // Try scope stack
+                if ( scopeStack )
+                {
+                    for (size_t i = scopeStack->size(); i > 0; --i)
+                    {
+                        // const_cast needed due to non-const 
+                        // as_object::get_member 
+                        as_object* obj = 
+                            const_cast<as_object*>((*scopeStack)[i-1].get());
+                        
+                        element = obj->get_path_element(subpartKey);
+                        if ( element ) break;
+                    }
+                    if ( element ) break;
+                }
+
+                // Try current target  (if any)
+                assert(env == m_target);
+                if ( env )
+                {
+                    element = env->get_path_element(subpartKey);
+                    if ( element ) break;
+                }
+                // else if ( _original_target) // TODO: try orig target too ?
+
+                // Looking for _global ?
+                as_object* global = _vm.getGlobal();
+                if ( swfVersion > 5 && subpartKey == NSV::PROP_uGLOBAL )
+                {
+                    element = global;
+                    break;
+                }
+
+                // Try globals
+                element = global->get_path_element(subpartKey);
+                //if ( element ) break;
+
+            } while (0);
+
+            if ( ! element ) 
+            {
+#ifdef DEBUG_TARGET_FINDING 
+                log_debug("subpart %s of path %s not found in any "
+                "scope stack element", subpart, path);
+#endif
+                return NULL;
+            }
+
+            env = element;
+            firstElementParsed = true;
+        }
+        else
+        {
+
+            assert(env);
+
+#ifdef DEBUG_TARGET_FINDING 
+            log_debug(_("Invoking get_path_element(%s) on object "
+                    "%p (%s)"), subpart, (void *)env, env->get_text_value());
+#endif
+
+            as_object* element = env->get_path_element(subpartKey);
+            if ( ! element )
+            {
+#ifdef DEBUG_TARGET_FINDING 
+                log_debug(_("Path element %s not found in "
+                            "object %p"), subpart, (void *)env);
+#endif
+                return NULL;
+            }
+            env = element;
+        }
+
+        if (next_slash == NULL) break;
+        
+        p = next_slash + 1;
     }
     return env;
 }

=== modified file 'libcore/as_function.cpp'
--- a/libcore/as_function.cpp   2009-01-08 08:36:56 +0000
+++ b/libcore/as_function.cpp   2009-01-12 21:34:39 +0000
@@ -140,10 +140,10 @@
        as_object* newproto = new as_object(superclass.getPrototype().get());
        newproto->init_member(NSV::PROP_uuPROTOuu, 
superclass.getPrototype().get());
 
-       if ( VM::get().getSWFVersion() > 5 )
-       {
-               newproto->init_member(NSV::PROP_uuCONSTRUCTORuu, &superclass); 
-       }
+    if (VM::get().getSWFVersion() > 5) {
+        const int flags = as_prop_flags::dontEnum;
+        newproto->init_member(NSV::PROP_uuCONSTRUCTORuu, &superclass, flags); 
+    }
 
        init_member(NSV::PROP_PROTOTYPE, as_value(newproto));
 }
@@ -183,10 +183,13 @@
 void
 function_class_init(as_object& global)
 {
-       boost::intrusive_ptr<builtin_function> 
func=as_function::getFunctionConstructor();
+       boost::intrusive_ptr<builtin_function> func = 
+        as_function::getFunctionConstructor();
 
        // Register _global.Function, only visible for SWF6 up
-       int swf6flags = 
as_prop_flags::dontEnum|as_prop_flags::dontDelete|as_prop_flags::onlySWF6Up;
+       int swf6flags = as_prop_flags::dontEnum | 
+                    as_prop_flags::dontDelete | 
+                    as_prop_flags::onlySWF6Up;
        global.init_member("Function", func.get(), swf6flags);
 
 }
@@ -194,7 +197,6 @@
 as_value
 function_apply(const fn_call& fn)
 {
-       //int pushed=0; // new values we push on the stack
 
        // Get function body 
        boost::intrusive_ptr<as_function> function_obj =
@@ -210,20 +212,19 @@
                IF_VERBOSE_ASCODING_ERRORS(
                log_aserror (_("Function.apply() called with no args"));
                );
+        new_fn_call.this_ptr = new as_object;
        }
        else
        {
                // Get the object to use as 'this' reference
-               new_fn_call.this_ptr = fn.arg(0).to_object();
-               if (!new_fn_call.this_ptr )
-               {
-                       // ... or recycle this function's call 'this' pointer
-                       // (most likely the Function instance)
-                       new_fn_call.this_ptr = fn.this_ptr;
-               }
-
+               as_object* obj = fn.arg(0).to_object().get();
+
+        if (!obj) obj = new as_object; 
+
+        new_fn_call.this_ptr = obj;
+
+               // Check for second argument ('arguments' array)
                if ( fn.nargs > 1 )
-               // we have an 'arguments' array
                {
                        IF_VERBOSE_ASCODING_ERRORS(
                                if ( fn.nargs > 2 )
@@ -248,7 +249,7 @@
                                goto call_it;
                        }
 
-                       boost::intrusive_ptr<Array_as> arg_array = \
+                       boost::intrusive_ptr<Array_as> arg_array = 
                                        
boost::dynamic_pointer_cast<Array_as>(arg1);
 
                        if ( ! arg_array )
@@ -258,23 +259,18 @@
                                                " is of type %s, with value %s"
                                                " (expected array)"
                                                " - considering as call with no 
args"),
-                                               fn.arg(1).typeOf(),
-                                               fn.arg(1).to_string().c_str());
+                                               fn.arg(1).typeOf(), 
fn.arg(1).to_string());
                                );
                                goto call_it;
                        }
 
                        unsigned int nelems = arg_array->size();
 
-                       //log_debug(_("Function.apply(this_ref, array[%d])"), 
nelems);
                        for (unsigned int i=0; i<nelems; ++i)
                        {
                                new_fn_call.pushArg(arg_array->at(i));
-                               //pushed++;
                        }
 
-                       //new_fn_call.set_offset(fn.env().get_top_index());
-                       //new_fn_call.nargs=nelems;
                }
        }
 
@@ -283,10 +279,7 @@
        // Call the function 
        as_value rv = function_obj->call(new_fn_call);
 
-       // Drop additional values we pushed on the stack 
-       //fn.env().drop(pushed);
-
-        return rv;
+    return rv;
 }
 
 as_value

=== modified file 'libcore/as_object.cpp'
--- a/libcore/as_object.cpp     2008-12-28 09:40:28 +0000
+++ b/libcore/as_object.cpp     2009-01-13 11:05:41 +0000
@@ -457,7 +457,8 @@
        if (key == NSV::PROP_uuPROTOuu && !nsname)
        {
                Property* prop = _members.getProperty(key, nsname);
-               // TODO: add ignoreVisibility parameter to allow using 
__proto__ even when not visible ?
+               // TODO: add ignoreVisibility parameter to allow using 
+        // __proto__ even when not visible ?
                if (prop && prop->isVisible(swfVersion))
                {
                        if (owner != NULL)
@@ -541,12 +542,11 @@
 void
 as_object::set_prototype(boost::intrusive_ptr<as_object> proto, int flags)
 {
-       static string_table::key key = NSV::PROP_uuPROTOuu;
-
        // TODO: check what happens if __proto__ is set as a user-defined 
     // getter/setter
        // TODO: check triggers !!
-       _members.setValue(key, as_value(proto.get()), *this, 0, flags);
+       _members.setValue(NSV::PROP_uuPROTOuu, as_value(proto.get()), *this, 0,
+            flags);
 }
 
 void
@@ -967,21 +967,9 @@
                return;
        }
 
-       // Evan: it seems that if set_true == 0 and set_false == 0,
-       // this function acts as if the parameters were (object, null, 0x1, 0)
-#if 0 // bullshit, see actionscript.all/Global.as
-       if (set_false == 0 && set_true == 0)
-       {
-           props_val.set_null();
-           set_false = 0;
-           set_true = 0x1;
-       }
-#endif
-
        if (props_val.is_null())
        {
                // Take all the members of the object
-               //std::pair<size_t, size_t> result = 
                _members.setFlagsAll(set_true, set_false);
 
                // Are we sure we need to descend to __proto__ ?
@@ -1071,7 +1059,6 @@
        :
        _members(),
        _vm(VM::get())
-       //, m_prototype(NULL)
 {
 }
 
@@ -1079,7 +1066,6 @@
        :
        _members(),
        _vm(VM::get())
-       //, m_prototype(proto)
 {
        init_member(NSV::PROP_uuPROTOuu, as_value(proto));
 }
@@ -1088,9 +1074,7 @@
        :
        _members(),
        _vm(VM::get())
-       //, m_prototype(proto)
 {
-       //set_prototype(proto);
        init_member(NSV::PROP_uuPROTOuu, as_value(proto));
 }
 
@@ -1145,30 +1129,15 @@
 boost::intrusive_ptr<as_object>
 as_object::get_prototype()
 {
-#if 0
-       as_value val;
-       if ( ! get_member(NSV::PROP_uuPROTOuu, &val) )
-       {
-               //log_debug("Object %p has no __proto__ member");
-               return NULL;
-       }
-       //log_debug("%p.__proto__ is %s", val);
-       return val.to_object().get();
-#else
-       static string_table::key key = NSV::PROP_uuPROTOuu;
-
        int swfVersion = _vm.getSWFVersion();
 
-       boost::intrusive_ptr<as_object> nullRet = NULL;
-
-       Property* prop = _members.getProperty(key);
-       if ( ! prop ) return nullRet;
-       if ( ! prop->isVisible(swfVersion) ) return nullRet;
+       Property* prop = _members.getProperty(NSV::PROP_uuPROTOuu);
+       if ( ! prop ) return 0;
+       if ( ! prop->isVisible(swfVersion) ) return 0;
 
        as_value tmp = prop->getValue(*this);
 
        return tmp.to_object();
-#endif
 }
 
 bool
@@ -1190,19 +1159,17 @@
 {
        as_value ret;
        get_member(name, &ret, nsname);
-       //get_member(PROPNAME(name), &ret);
        return ret;
 }
 
 as_value
 as_object::callMethod(string_table::key methodName)
 {
-       as_value ret;
        as_value method;
 
        if (! get_member(methodName, &method))
        {
-               return ret;
+               return as_value();
        }
 
        as_environment env(_vm);
@@ -1213,12 +1180,11 @@
 as_value
 as_object::callMethod(string_table::key methodName, const as_value& arg0)
 {
-       as_value ret;
        as_value method;
 
        if (!get_member(methodName, &method))
        {
-               return ret;
+               return as_value();
        }
 
        as_environment env(_vm);
@@ -1226,21 +1192,18 @@
        std::auto_ptr< std::vector<as_value> > args ( new std::vector<as_value> 
);
        args->push_back(arg0);
 
-       ret = call_method(method, &env, this, args);
-
-       return ret;
+       return call_method(method, &env, this, args);
 }
 
 as_value
-as_object::callMethod(string_table::key methodName,
-       const as_value& arg0, const as_value& arg1)
+as_object::callMethod(string_table::key methodName, const as_value& arg0,
+        const as_value& arg1)
 {
-       as_value ret;
        as_value method;
 
        if (! get_member(methodName, &method))
        {
-               return ret;
+               return as_value();
        }
 
        as_environment env(_vm);
@@ -1249,9 +1212,7 @@
        args->push_back(arg0);
        args->push_back(arg1);
 
-       ret = call_method(method, &env, this, args);
-
-       return ret;
+       return call_method(method, &env, this, args);
 }
 
 as_value
@@ -1279,16 +1240,14 @@
 }
 
 as_value
-as_object::callMethod(string_table::key methodName,
-       const as_value& arg0, const as_value& arg1,
-       const as_value& arg2, const as_value& arg3)
+as_object::callMethod(string_table::key methodName, const as_value& arg0,
+        const as_value& arg1, const as_value& arg2, const as_value& arg3)
 {
-       as_value ret;
        as_value method;
 
        if (! get_member(methodName, &method))
        {
-               return ret;
+               return as_value();
        }
 
        as_environment env(_vm);
@@ -1299,9 +1258,8 @@
        args->push_back(arg2);
        args->push_back(arg3);
 
-       ret = call_method(method, &env, this, args);
+       return call_method(method, &env, this, args);
 
-       return ret;
 }
 
 as_object*
@@ -1366,7 +1324,8 @@
        TriggerContainer::iterator it = _trigs.find(k);
        if ( it == _trigs.end() )
        {
-               return _trigs.insert(std::make_pair(k, Trigger(propname, trig, 
cust))).second;
+               return _trigs.insert(
+                std::make_pair(k, Trigger(propname, trig, cust))).second;
        }
        it->second = Trigger(propname, trig, cust);
        return true;
@@ -1378,13 +1337,15 @@
        TriggerContainer::iterator trigIter = _trigs.find(std::make_pair(key, 
ns));
        if ( trigIter == _trigs.end() )
        {
-               log_debug("No watch for property %s", 
getVM().getStringTable().value(key));
+               log_debug("No watch for property %s",
+                getVM().getStringTable().value(key));
                return false;
        }
        Property* prop = _members.getProperty(key, ns);
        if ( prop && prop->isGetterSetter() )
        {
-               log_debug("Watch on %s not removed (is a getter-setter)", 
getVM().getStringTable().value(key));
+               log_debug("Watch on %s not removed (is a getter-setter)",
+                getVM().getStringTable().value(key));
                return false;
        }
        _trigs.erase(trigIter);
@@ -1422,7 +1383,7 @@
        try {
                as_environment env(VM::get()); // TODO: get VM in some other 
way 
 
-               std::auto_ptr< std::vector<as_value> > args ( new 
std::vector<as_value> );
+               std::auto_ptr<std::vector<as_value> > args (new 
std::vector<as_value>);
                args->push_back(_propname);
                args->push_back(oldval);
                args->push_back(newval);
@@ -1437,7 +1398,7 @@
                return ret;
 
        }
-       catch (...)
+       catch (GnashException&)
        {
                _executing = false;
                throw;

=== modified file 'libcore/as_value.cpp'
--- a/libcore/as_value.cpp      2009-01-09 21:10:24 +0000
+++ b/libcore/as_value.cpp      2009-01-12 13:51:00 +0000
@@ -39,6 +39,7 @@
 #include "Array_as.h"
 #include "Date_as.h" // for Date type (readAMF0)
 #include "SimpleBuffer.h"
+#include "StringPredicates.h"
 
 #include <cmath> // std::fmod
 #include <boost/algorithm/string/case_conv.hpp>
@@ -64,9 +65,10 @@
 // Define this macto to make AMF writing verbose
 //#define GNASH_DEBUG_AMF_SERIALIZE
 
+namespace gnash {
+
 namespace {
 
-
 struct invalidHexDigit {};
 boost::uint8_t parseHex(char c)
 {
@@ -92,12 +94,63 @@
        }
 }
 
-} // end of namespace
-
-
-namespace gnash {
-
-namespace { 
+/// Truncates a double to a 32-bit unsigned int.
+//
+/// In fact, it is a 32-bit unsigned int with an additional sign, cast
+/// to an unsigned int. Not sure what the sense is, but that's how it works:
+//
+/// 0xffffffff is interpreted as -1, -0xffffffff as 1.
+boost::int32_t
+truncateToInt(double d)
+{
+    if (d < 0)
+    {   
+           return - static_cast<boost::uint32_t>(std::fmod(-d, 4294967296.0));
+    }
+       
+    return static_cast<boost::uint32_t>(std::fmod(d, 4294967296.0));
+}
+
+enum Base
+{
+    BASE_OCT,
+    BASE_HEX
+};
+
+
+/// Converts a string to a uint32_t cast to an int32_t.
+//
+/// @param whole    When true, any string that isn't wholly valid is rejected.
+/// @param base     The base (8 or 16) to use.
+/// @param s        The string to parse.
+/// @return         The converted number.
+boost::int32_t
+parsePositiveInt(const std::string& s, Base base, bool whole = true)
+{
+
+    std::istringstream is(s);
+    boost::uint32_t target;
+
+    switch (base)
+    {
+        case BASE_OCT:
+            is >> std::oct;
+            break;
+        case BASE_HEX:
+            is >> std::hex;
+            break;
+    }
+
+    char c;
+
+    // If the cast fails, or if the whole string must be convertible and
+    // some characters are left, throw an exception.
+    if (!(is >> target) || (whole && is.get(c))) {
+        throw boost::bad_lexical_cast();
+    }
+
+    return target;
+}
 
 // This class is used to iterate through all the properties of an AS object,
 // so we can change them to children of an AMF0 element.
@@ -318,7 +371,6 @@
                case AS_FUNCTION:
                case OBJECT:
                {
-                       //as_object* obj = m_type == OBJECT ? getObj().get() : 
getFun().get();
                        try
                        {
                                as_value ret = to_primitive(STRING);
@@ -638,47 +690,63 @@
        return *this;
 }
 
+
+bool
+as_value::parseNonDecimalInt(const std::string& s, double& d, bool whole)
+{
+    const std::string::size_type slen = s.length();
+
+    // "0#" would still be octal, but has the same value as a decimal.
+    if (slen < 3) return false;
+
+    bool negative = false;
+
+    if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X'))
+    {
+        // The only legitimate place for a '-' is after 0x. If it's a
+        // '+' we don't care, as it won't disturb the conversion.
+        std::string::size_type start = 2;
+        if (s[2] == '-') {
+            negative = true;
+            ++start;
+        }
+        d = parsePositiveInt(s.substr(start), BASE_HEX, whole);
+        if (negative) d = -d;
+        return true;
+    }
+    else if ((s[0] == '0' || ((s[0] == '-' || s[0] == '+') && s[1] == '0')) &&
+            s.find_first_not_of("01234567", 1) == std::string::npos)
+    {
+        std::string::size_type start = 0;
+        if (s[0] == '-') {
+            negative = true;
+            ++start;
+        }
+        d = parsePositiveInt(s.substr(start), BASE_OCT, whole);
+        if (negative) d = -d;
+        return true;
+    }
+
+    return false;
+
+}
+
 double
 as_value::to_number() const
 {
 
-    int swfversion = VM::get().getSWFVersion();
+    const int swfversion = VM::get().getSWFVersion();
 
     switch (m_type)
     {
         case STRING:
         {
-            std::string s = getStr();
+            const std::string& s = getStr();
             if ( s.empty() ) {
-                return static_cast<double>( swfversion >= 5 ? NaN : 0.0 );
-            }
-
-            if ( swfversion > 5 )
-            {
-                size_t slen = s.length();
-                if ( slen > 2 ) // "0#" would still be octal, but has the same 
value of the decimal equivalent
-                {
-                    if ( s[0] == '0' && (s[1] == 'x' || s[1] == 'X') )
-                    {
-                        // base 16
-                        const char* cs = s.c_str();
-                        char* end;
-                        boost::int32_t i = strtol (cs+2, &end, 16); // 
truncation to 32bit is intentional
-                        double d = (double)i;
-                        if ( *end == '\0' ) return d;
-                    }
-                    else if ( (s[0] == '0' || ((s[0] == '-' || s[0] == '+') && 
s[1] == '0'))
-                         && s.find_first_not_of("01234567", 1) == 
std::string::npos )
-                    {
-                            // base 8
-                            const char* cs = s.c_str();
-                            char* end;
-                            double d = (double)strtol (cs, &end, 8); // 
include sign
-                            if ( *end == '\0' ) return d;
-                    }
-                }
-            }
-            else if (swfversion <= 4)
+                return swfversion >= 5 ? NaN : 0.0;
+            }
+            
+            if (swfversion <= 4)
             {
                 // For SWF4, any valid number before non-numerical
                 // characters is returned, including exponent, positive
@@ -689,30 +757,38 @@
                 return d;
             }
 
-            // @@ Moock says the rule here is: if the
-            // string is a valid float literal, then it
-            // gets converted; otherwise it is set to NaN.
-            // Valid for SWF5 and above.
-            //
-            // boost::lexical_cast is remarkably inflexible and 
-            // fails for anything that has non-numerical characters.
-            // Fortunately, actionscript is equally inflexible.
-            try 
-            { 
-                
-                const char* p = s.c_str();
-                // skip blanks
-                while (*p && isspace(*p)) ++p;
-                double d = boost::lexical_cast<double>(p);
-                return d;
-            } 
-            catch (boost::bad_lexical_cast &) 
-            // There is no standard textual representation of infinity in the
-            // C++ standard, so boost throws a bad_lexical_cast for 'inf',
-            // just like for any other non-numerical text. This is correct
-            // behaviour.
-            {
-               return static_cast<double>(NaN);
+            try {
+
+                if (swfversion > 5)
+                {
+                    double d;
+                    // Will throw if invalid.
+                    if (parseNonDecimalInt(s, d)) return d;
+                }
+
+                // @@ Moock says the rule here is: if the
+                // string is a valid float literal, then it
+                // gets converted; otherwise it is set to NaN.
+                // Valid for SWF5 and above.
+                //
+                // boost::lexical_cast is remarkably inflexible and 
+                // fails for anything that has non-numerical characters.
+                // Fortunately, actionscript is equally inflexible.
+                std::string::size_type pos;
+                if ((pos = s.find_first_not_of(" \r\n\t")) 
+                        == std::string::npos) {
+                    return NaN;
+                }
+
+                return boost::lexical_cast<double>(s.substr(pos));
+ 
+            }
+            catch (boost::bad_lexical_cast&) {
+                // There is no standard textual representation of infinity
+                // in the C++ standard, so our conversion function an
+                // exception for 'inf', just like for any other
+                // non-numerical text. This is correct behaviour.
+                return NaN;
             }
         }
 
@@ -740,8 +816,6 @@
             // method".
             //
             // Arrays and Movieclips should return NaN.
-
-            //as_object* obj = m_type == OBJECT ? getObj().get() : 
getFun().get();
             try
             {
                 as_value ret = to_primitive(NUMBER);
@@ -750,33 +824,26 @@
             catch (ActionTypeError& e)
             {
 #if GNASH_DEBUG_CONVERSION_TO_PRIMITIVE
-                log_debug(_("to_primitive(%s, NUMBER) threw an ActionTypeError 
%s"),
-                        *this, e.what());
+                log_debug(_("to_primitive(%s, NUMBER) threw an "
+                            "ActionTypeError %s"), *this, e.what());
 #endif
-                if ( m_type == AS_FUNCTION && swfversion < 6 )
-                {
-                    return 0;
-                }
-                else
-                {
-                    return NaN;
-                }
+                if (m_type == AS_FUNCTION && swfversion < 6) return 0;
+                
+                return NaN;
             }
         }
 
         case MOVIECLIP:
-       {
+        {
             // This is tested, no valueOf is going
             // to be invoked for movieclips.
             return NaN; 
-       }
+        }
 
         default:
-            // Other object types should return NaN, but if we implement that,
-            // every GUI's movie canvas shrinks to size 0x0. No idea why.
-            return NaN; // 0.0;
+            // Other object types should return NaN.
+            return NaN;
     }
-    /* NOTREACHED */
 }
 
 std::auto_ptr<amf::Element>
@@ -829,18 +896,7 @@
 
        if ( ! utility::isFinite(d) ) return 0;
 
-       boost::int32_t i = 0;
-
-    if (d < 0)
-    {   
-           i = - static_cast<boost::uint32_t>(std::fmod(-d, 4294967296.0));
-    }
-    else
-    {
-           i = static_cast<boost::uint32_t>(std::fmod(d, 4294967296.0));
-    }
-    
-    return i;
+    return truncateToInt(d);
 }
 
 // Conversion to boolean for SWF7 and up
@@ -1177,8 +1233,8 @@
     //    return the result of the comparison x == ToNumber(y).
     if (m_type == NUMBER && v.m_type == STRING)
     {
-       double n = v.to_number();
-       if ( ! utility::isFinite(n) ) return false;
+        double n = v.to_number();
+        if ( ! utility::isFinite(n) ) return false;
         return equalsSameType(n);
     }
 
@@ -1186,9 +1242,9 @@
     //     return the result of the comparison ToNumber(x) == y.
     if (v.m_type == NUMBER && m_type == STRING)
     {
-       double n = to_number();
-       if ( ! utility::isFinite(n) ) return false;
-        return v.equalsSameType(n); 
+        double n = to_number();
+        if ( ! utility::isFinite(n) ) return false;
+            return v.equalsSameType(n); 
     }
 
     // 18. If Type(x) is Boolean, return the result of the comparison 
ToNumber(x) == y.
@@ -1205,7 +1261,8 @@
 
     // 20. If Type(x) is either String or Number and Type(y) is Object,
     //     return the result of the comparison x == ToPrimitive(y).
-    if ( (m_type == STRING || m_type == NUMBER ) && ( v.m_type == OBJECT || 
v.m_type == AS_FUNCTION ) )
+    if ( (m_type == STRING || m_type == NUMBER ) && 
+            (v.m_type == OBJECT || v.m_type == AS_FUNCTION ))
     {
         // convert this value to a primitive and recurse
        try
@@ -1231,29 +1288,33 @@
 
     // 21. If Type(x) is Object and Type(y) is either String or Number,
     //    return the result of the comparison ToPrimitive(x) == y.
-    if ( (v.m_type == STRING || v.m_type == NUMBER ) && ( m_type == OBJECT || 
m_type == AS_FUNCTION ) )
+    if ((v.m_type == STRING || v.m_type == NUMBER) && 
+            (m_type == OBJECT || m_type == AS_FUNCTION))
     {
         // convert this value to a primitive and recurse
         try
-       {
-               as_value v2 = to_primitive(); 
-               if ( strictly_equals(v2) ) return false;
-
-#ifdef GNASH_DEBUG_EQUALITY
-               log_debug(" 21: convertion to primitive : %s -> %s", *this, v2);
-#endif
-
-               return v2.equals(v);
-       }
-       catch (ActionTypeError& e)
-       {
-
-#ifdef GNASH_DEBUG_EQUALITY
-               log_debug(" %s.to_primitive() threw an ActionTypeError %s", 
*this, e.what());
-#endif
-
-               return false; // no valid conversion
-       }
+        {
+            // Date objects default to primitive type STRING from SWF6 up,
+            // but we always prefer valueOf to toString in this case.
+               as_value v2 = to_primitive(NUMBER); 
+            if ( strictly_equals(v2) ) return false;
+
+#ifdef GNASH_DEBUG_EQUALITY
+            log_debug(" 21: convertion to primitive : %s -> %s", *this, v2);
+#endif
+
+            return v2.equals(v);
+        }
+        catch (ActionTypeError& e)
+        {
+
+#ifdef GNASH_DEBUG_EQUALITY
+            log_debug(" %s.to_primitive() threw an ActionTypeError %s",
+                    *this, e.what());
+#endif
+
+            return false; // no valid conversion
+        }
 
     }
 
@@ -1528,151 +1589,107 @@
 }
 
 
-// Convert numeric value to string value, following ECMA-262 specification
+/// Examples:
+//
+/// e.g. for 9*.1234567890123456789:
+/// 9999.12345678901
+/// 99999.123456789
+/// 999999.123456789
+/// 9999999.12345679
+/// [...]
+/// 999999999999.123
+/// 9999999999999.12
+/// 99999999999999.1
+/// 999999999999999
+/// 1e+16
+/// 1e+17
+//
+/// For 1*.111111111111111111111111111111111111:
+/// 1111111111111.11
+/// 11111111111111.1
+/// 111111111111111
+/// 1.11111111111111e+15
+/// 1.11111111111111e+16
+//
+/// For 1.234567890123456789 * 10^-i:
+/// 1.23456789012346
+/// 0.123456789012346
+/// 0.0123456789012346
+/// 0.00123456789012346
+/// 0.000123456789012346
+/// 0.0000123456789012346
+/// 0.00000123456789012346
+/// 1.23456789012346e-6
+/// 1.23456789012346e-7
 std::string
 as_value::doubleToString(double val, int radix)
 {
-       // Printing formats:
-       //
-       // If _val > 1, Print up to 15 significant digits, then switch
-       // to scientific notation, rounding at the last place and
-       // omitting trailing zeroes.
-       // e.g. for 9*.1234567890123456789
-       // ...
-       // 9999.12345678901
-       // 99999.123456789
-       // 999999.123456789
-       // 9999999.12345679
-       // 99999999.1234568
-       // 999999999.123457
-       // 9999999999.12346
-       // 99999999999.1235
-       // 999999999999.123
-       // 9999999999999.12
-       // 99999999999999.1
-       // 999999999999999
-       // 1e+16
-       // 1e+17
-       // ...
-       // e.g. for 1*.111111111111111111111111111111111111
-       // ...
-       // 1111111111111.11
-       // 11111111111111.1
-       // 111111111111111
-       // 1.11111111111111e+15
-       // 1.11111111111111e+16
-       // ...
-       // For values < 1, print up to 4 leading zeroes after the
-       // decimal point, then switch to scientific notation with up
-       // to 15 significant digits, rounding with no trailing zeroes
-       // e.g. for 1.234567890123456789 * 10^-i:
-       // 1.23456789012346
-       // 0.123456789012346
-       // 0.0123456789012346
-       // 0.00123456789012346
-       // 0.000123456789012346
-       // 0.0000123456789012346
-       // 0.00000123456789012346
-       // 1.23456789012346e-6
-       // 1.23456789012346e-7
-       // ...
-       //
-       // If the value is negative, just add a '-' to the start; this
-       // does not affect the precision of the printed value.
-       //
-       // This almost corresponds to iomanip's std::setprecision(15)
-       // format, except that iomanip switches to scientific notation
-       // at e-05 not e-06, and always prints at least two digits for the 
exponent.
-
-       // The C implementation had problems with the following cases:
-       // 9.99999999999999[39-61] e{-2,-3}. Adobe prints these as
-       // 0.0999999999999999 and 0.00999999999999 while we print them
-       // as 0.1 and 0.01
-       // These values are at the limit of a double's precision,
-       // for example, in C,
-       // .99999999999999938 printfs as
-       // .99999999999999933387 and
-       // .99999999999999939 printfs as
-       // .99999999999999944489
-       // so this behaviour is probably too compiler-dependent to
-       // reproduce exactly.
-       //
-       // There may be some milage in comparing against
-       // 0.00009999999999999995 and
-       // 0.000009999999999999995 instead.
-       //
-       // The stringstream implementation seems to have no problems with them,
-       // but that may just be a better compiler.
-
        // Handle non-numeric values.
-       if (isNaN(val))
-       {
-               return "NaN";
-       }
-       else if (isInf(val))
-       {
-               return val < 0 ? "-Infinity" : "Infinity";
-       }
-       else if (val == 0.0 || val == -0.0)
-       {
-               return "0";
-       }
-
-       std::ostringstream ostr;
-       std::string str;
-
-       if ( radix == 10 )
+       if (isNaN(val)) return "NaN";
+       
+    if (isInf(val)) return val < 0 ? "-Infinity" : "Infinity";
+
+    if (val == 0.0 || val == -0.0) return "0"; 
+
+    std::ostringstream ostr;
+
+       if (radix == 10)
        {
                // ActionScript always expects dot as decimal point.
                ostr.imbue(std::locale::classic()); 
                
-               // force to decimal notation for this range (because the 
reference player does)
+               // force to decimal notation for this range (because the
+        // reference player does)
                if (std::abs(val) < 0.0001 && std::abs(val) >= 0.00001)
                {
                        // All nineteen digits (4 zeros + up to 15 significant 
digits)
                        ostr << std::fixed << std::setprecision(19) << val;
                        
-                       str = ostr.str();
+            std::string str = ostr.str();
                        
                        // Because 'fixed' also adds trailing zeros, remove 
them.
                        std::string::size_type pos = str.find_last_not_of('0');
                        if (pos != std::string::npos) {
                                str.erase(pos + 1);
                        }
-               }
-               else
-               {
-                       ostr << std::setprecision(15) << val;
-                       
-                       str = ostr.str();
-                       
-                       // Remove a leading zero from 2-digit exponent if any
-                       std::string::size_type pos = str.find("e", 0);
-
-                       if (pos != std::string::npos && str.at(pos + 2) == '0') 
{
-                               str.erase(pos + 2, 1);
-                       }
-               }
+            return str;
+               }
+
+        ostr << std::setprecision(15) << val;
+        
+        std::string str = ostr.str();
+        
+        // Remove a leading zero from 2-digit exponent if any
+        std::string::size_type pos = str.find("e", 0);
+
+        if (pos != std::string::npos && str.at(pos + 2) == '0') {
+            str.erase(pos + 2, 1);
+        }
 
         return str;
-
        }
 
     // Radix isn't 10
-
        bool negative = (val < 0);
-       if ( negative ) val = -val;
+       if (negative) val = -val;
 
        double left = std::floor(val);
-       if ( left < 1 ) return "0";
-       while ( left != 0 )
+       if (left < 1) return "0";
+
+    std::string str;
+    const std::string digits = "0123456789abcdefghijklmnopqrstuvwxyz";
+
+    // Construct the string backwards for speed, then reverse.
+    while (left)
        {
                double n = left;
                left = std::floor(left / radix);
                n -= (left * radix);
-               str.insert(0, 1, (n < 10 ? ((int)n+'0') : ((int)n+('a'-10))));
+               str.push_back(digits[static_cast<int>(n)]);
        }
-       if ( negative ) str.insert(0, 1, '-'); 
+       if (negative) str.push_back('-'); 
+
+    std::reverse(str.begin(), str.end());
 
        return str;
        

=== modified file 'libcore/as_value.h'
--- a/libcore/as_value.h        2009-01-03 15:01:27 +0000
+++ b/libcore/as_value.h        2009-01-13 13:11:42 +0000
@@ -218,11 +218,12 @@
        /// @param objRefs
        ///     A vector of already-parsed objects to properly interpret 
references.
        ///     Pass an empty vector on first call as it will be used 
internally.
-       ///     On return, the vector will be filled with pointers to every 
complex object
-       ///     parsed from the stream.
+       ///     On return, the vector will be filled with pointers to every
+    ///     complex object parsed from the stream.
     ///
        /// @param vm
-    ///     Virtual machine to use for initialization of the values 
(string_table)
+    ///     Virtual machine to use for initialization of the values
+    ///     (string_table)
        ///
        DSOEXPORT bool readAMF0(const boost::uint8_t*& b,
             const boost::uint8_t* const end, int inType,
@@ -249,10 +250,38 @@
 
        /// Convert numeric value to string value, following ECMA-262 
specification
        //
-       /// TODO: move here some of the good comments found in the function 
definition.
-       ///
+       // Printing formats:
+       //
+       // If _val > 1, Print up to 15 significant digits, then switch
+       // to scientific notation, rounding at the last place and
+       // omitting trailing zeroes.
+       // For values < 1, print up to 4 leading zeroes after the
+       // decimal point, then switch to scientific notation with up
+       // to 15 significant digits, rounding with no trailing zeroes
+       // If the value is negative, just add a '-' to the start; this
+       // does not affect the precision of the printed value.
+       //
+       // This almost corresponds to iomanip's std::setprecision(15)
+       // format, except that iomanip switches to scientific notation
+       // at e-05 not e-06, and always prints at least two digits for the 
exponent.
        static std::string doubleToString(double val, int radix=10);
 
+    /// Try to parse a string into a 32-bit signed int using base 8 or 16.  //
+    /// This function will throw a boost::bad_lexical_cast (or a derived
+    /// exception) if the passed string cannot be converted.
+    //
+    /// @param s      The string to parse
+    /// @param d      The 32-bit int represented as a double. This is only a
+    ///               valid number if the return value is true.
+    /// @param whole  If true, expect the whole string to be valid, i.e.
+    ///               throw if there are any invalid characters. If false,
+    ///               returns any valid number up to the first invalid
+    ///               character.
+    /// @return       True if the string was non-decimal and successfully
+    ///               parsed.
+    static bool parseNonDecimalInt(const std::string& s, double& d,
+            bool whole = true);
+
        /// Return the primitive type of this value, as a string.
        const char* typeOf() const;
 

=== modified file 'libcore/asobj/Array_as.cpp'
--- a/libcore/asobj/Array_as.cpp        2008-12-27 19:56:32 +0000
+++ b/libcore/asobj/Array_as.cpp        2009-01-13 12:09:21 +0000
@@ -365,7 +365,7 @@
         as_value cmp_method(&_comp);
         as_value ret(0.0);
 
-           std::auto_ptr< std::vector<as_value> > args ( new 
std::vector<as_value> );
+           std::auto_ptr<std::vector<as_value> > args (new 
std::vector<as_value>);
            args->push_back(b);
            args->push_back(a);
         ret = call_method(cmp_method, &_env, _object, args);
@@ -961,26 +961,34 @@
     
     const int version = array->getVM().getSWFVersion();
     
-    boost::uint8_t flags = 0;
-
-    if ( fn.nargs == 0 )
+    if (!fn.nargs)
     {
         array->sort(as_value_lt(version));
         return as_value(array.get());
     }
-    else if ( fn.nargs == 1 && fn.arg(0).is_number() )
+    
+    if (fn.arg(0).is_undefined()) return as_value();
+
+    boost::uint8_t flags = 0;
+
+    if ( fn.nargs == 1 && fn.arg(0).is_number() )
     {
         flags=static_cast<boost::uint8_t>(fn.arg(0).to_number());
     }
-    else if ( fn.arg(0).is_as_function() )
+    else if (fn.arg(0).is_as_function())
     {
+
         // Get comparison function
         as_function* as_func = fn.arg(0).to_as_function();
+
+        assert(as_func);
+
         bool (*icmp)(int);
     
-        if ( fn.nargs == 2 && fn.arg(1).is_number() )
+        if (fn.nargs == 2 && fn.arg(1).is_number()) {
             flags=static_cast<boost::uint8_t>(fn.arg(1).to_number());
-        
+        }
+
         if (flags & Array_as::fDescending) icmp = &int_lt_or_eq;
         else icmp = &int_gt;
 
@@ -989,13 +997,12 @@
         as_value_custom avc = 
             as_value_custom(*as_func, icmp, fn.this_ptr, env);
 
-        if ( (flags & Array_as::fReturnIndexedArray) )
+        if ((flags & Array_as::fReturnIndexedArray))
         {
             return as_value(array->sort_indexed(avc));
         }
-        //log_debug("Sorting %d-sized array with custom function", 
array->size());
+
         array->sort(avc);
-        //log_debug("After sorting, array is %d-sized", array->size());
         return as_value(array.get());
         // note: custom AS function sorting apparently ignores the 
         // UniqueSort flag which is why it is also ignored here
@@ -1005,7 +1012,6 @@
         IF_VERBOSE_ASCODING_ERRORS(
         log_aserror(_("Sort called with invalid arguments."));
         )
-        if ( fn.arg(0).is_undefined() ) return as_value();
         return as_value(array.get());
     }
     bool do_unique, do_index;

=== modified file 'libcore/asobj/Date_as.cpp'
--- a/libcore/asobj/Date_as.cpp 2009-01-03 15:01:27 +0000
+++ b/libcore/asobj/Date_as.cpp 2009-01-12 13:51:00 +0000
@@ -289,10 +289,10 @@
 }
 
 
-inline size_t
+inline boost::int32_t
 countLeapYears(boost::int32_t year)
 {
-    return (year - 70) / 4 - (year - 70) / 100 + (year - 70) / 400;
+    return year / 4 - year / 100 + year / 400;
 }
 
 
@@ -706,22 +706,39 @@
 //    =========    Functions to set dates in various ways    ========
 //
 
-/// \brief Date.setTime
+/// Date.setTime
+//
 /// sets a Date in milliseconds after January 1, 1970 00:00 UTC.
 /// The return value is the same as the parameter.
+//
+/// If no arguments are passed or the first argument is undefined, the time
+/// value is set to NaN.
+//
+/// Partial milliseconds are just ignored. The permissible range
+/// is +/- 8.64+e15 (magic numbers).
 as_value
 date_setTime(const fn_call& fn)
 {
     boost::intrusive_ptr<Date_as> date = ensureType<Date_as>(fn.this_ptr);
 
-    if (fn.nargs < 1) {
+    if (fn.nargs < 1 || fn.arg(0).is_undefined()) {
         IF_VERBOSE_ASCODING_ERRORS(
             log_aserror(_("Date.setTime needs one argument"));
-        )
+        );
+        date->setTimeValue(NaN);
     }
     else {
         // returns a double
-        date->setTimeValue(fn.arg(0).to_number());
+        const double magicMaxValue = 8.64e+15;
+        double d = fn.arg(0).to_number();
+
+        if (!utility::isFinite(d) || std::abs(d) > magicMaxValue) {
+            date->setTimeValue(NaN);
+        }
+        else {
+            // Knock off the decimal part.
+            date->setTimeValue(d < 0 ? std::ceil(d) : std::floor(d));
+        }
     }
 
     if (fn.nargs > 1) {
@@ -814,31 +831,36 @@
 as_value
 date_setfullyear(const fn_call& fn)
 {
-  boost::intrusive_ptr<Date_as> date = ensureType<Date_as>(fn.this_ptr);
-
-  if (fn.nargs < 1) {
-      IF_VERBOSE_ASCODING_ERRORS(
-    log_aserror(_("Date.setFullYear needs one argument"));
-      )
-      date->setTimeValue(NaN);
-  } else if (rogue_date_args(fn, 3) != 0.0) {
-      date->setTimeValue(NaN);
-  } else {
-      GnashTime gt;
-
-      dateToGnashTime(*date, gt, utc);
-      gt.year = fn.arg(0).to_int() - 1900;
-      if (fn.nargs >= 2)
-        gt.month = fn.arg(1).to_int();
-      if (fn.nargs >= 3)
-        gt.monthday = fn.arg(2).to_int();
-      if (fn.nargs > 3) {
+    boost::intrusive_ptr<Date_as> date = ensureType<Date_as>(fn.this_ptr);
+
+    if (fn.nargs < 1) {
         IF_VERBOSE_ASCODING_ERRORS(
-            log_aserror(_("Date.set%sFullYear was called with "
+            log_aserror(_("Date.setFullYear needs one argument"));
+        )
+        date->setTimeValue(NaN);
+    }
+    else if (rogue_date_args(fn, 3) != 0.0) {
+        date->setTimeValue(NaN);
+    }
+    else {
+        GnashTime gt;
+
+        dateToGnashTime(*date, gt, utc);
+        gt.year = fn.arg(0).to_int() - 1900;
+        switch (fn.nargs)
+        {
+            default:
+                IF_VERBOSE_ASCODING_ERRORS(
+                    log_aserror(_("Date.set%sFullYear was called with "
                         "more than three arguments"), utc ? "UTC" : "");
-        )
-      }
-      gnashTimeToDate(gt, *date, utc);
+                );
+    
+            case 3:
+                gt.monthday = fn.arg(2).to_int();
+            case 2:
+                gt.month = fn.arg(1).to_int();
+        }
+        gnashTimeToDate(gt, *date, utc);
   }
   return as_value(date->getTimeValue());
 }
@@ -878,8 +900,11 @@
         dateToGnashTime(*date, gt, false);
 
         // TODO: Should truncation be done before or after subtracting 1900?
-        truncateDouble(gt.year, fn.arg(0).to_number());
-        gt.year -= 1900;
+        
+        double year = fn.arg(0).to_number();
+        if (year < 0 || year > 100) year -= 1900;
+
+        truncateDouble(gt.year, year);
 
         if (fn.nargs >= 2) gt.month = fn.arg(1).to_int();
         if (fn.nargs >= 3) gt.monthday = fn.arg(2).to_int();
@@ -1356,22 +1381,24 @@
 
     // Any negative remainder rolls back to the previous year.
     if (t.month < 0) {
-        t.year--;
+        --t.year;
         t.month += 12;
     }
 
     // Now work out the years from 1970 in days.
-    boost::int32_t day = t.monthday;    
-
-    // This works but is a bit clunky.
-    if (t.year < 70) {
-        day = countLeapYears(t.year - 2) + ((t.year - 70) * 365);
-        // Adds an extra leap year for the year 0.
-        if (t.year <= 0) day++;
-    }
-    else {
-        day = countLeapYears(t.year + 1) + ((t.year - 70) * 365);
-    }
+
+    // Use a temporary 1970-based year for clarity.
+    const int32_t ouryear = t.year - 70;
+    
+    // Count the leap years between 1970-1-1 and the beginning of our year.
+    // 1970 - 1972: no leap years
+    // 1970 - 1968: one leap year
+    // Adding one less than the required year gives this behaviour.
+    boost::int32_t day = countLeapYears(ouryear + 1969) - countLeapYears(1970);
+    day += ouryear * 365;
+
+    /// The year 0 was a leap year, but countLeapYears won't calculate it.
+    if (ouryear <= -1970) --day;
     
     // Add days for each month. Month must be 0 - 11;
     for (int i = 0; i < t.month; i++)
@@ -1384,7 +1411,7 @@
     day += t.monthday - 1;
 
     /// Work out the timestamp
-    double ret = static_cast<double>(day) * 86400000.0;
+    double ret = day * 86400000.0;
     ret += t.hour * 3600000.0;
     ret += t.minute * 60000.0;
     ret += t.second * 1000.0;

=== modified file 'libcore/asobj/Error_as.cpp'
--- a/libcore/asobj/Error_as.cpp        2008-12-22 14:57:10 +0000
+++ b/libcore/asobj/Error_as.cpp        2009-01-12 16:00:41 +0000
@@ -35,38 +35,14 @@
 
 namespace gnash {
 
-static as_value Error_toString(const fn_call& fn);
-static as_value Error_message_getset(const fn_call& fn);
-static as_value Error_name_getset(const fn_call& fn);
-
-
-as_value Error_ctor(const fn_call& fn);
-
-static void
-attachErrorInterface(as_object& o)
-{
-    o.init_member("toString", new builtin_function(Error_toString));
-    o.init_property("message", Error_message_getset, Error_message_getset);
-    o.init_property("name", Error_name_getset, Error_name_getset);
-}
-
-
-static as_object*
-getErrorInterface()
-{
-       static boost::intrusive_ptr<as_object> o;
-
-       if ( ! o )
-       {
-               o = new as_object(getObjectInterface());
-               VM::get().addStatic(o.get());
-
-               attachErrorInterface(*o);
-
-       }
-
-       return o.get();
-}
+namespace {
+    as_value error_toString(const fn_call& fn);
+    as_value error_ctor(const fn_call& fn);
+
+    as_object* getErrorInterface();
+    void attachErrorInterface(as_object& o);
+}
+
 
 class Error_as: public as_object
 {
@@ -75,79 +51,11 @@
 
        Error_as()
                :
-               as_object(getErrorInterface()),
-               _name("Error"),
-               _message("Error")
+               as_object(getErrorInterface())
        {}
 
-    void setName(const std::string& n) { _name = n; }
-    const std::string& getName() const { return _name; }
-
-    void setMessage(const std::string& m) { _message = m; }
-    const std::string& getMessage() const { return _message; }
-
-private:
-    std::string _name;
-    std::string _message;
 };
 
-static as_value
-Error_toString(const fn_call& fn)
-{
-       boost::intrusive_ptr<Error_as> ptr = ensureType<Error_as>(fn.this_ptr);
-       return as_value(ptr->getMessage());   
-}
-
-static as_value
-Error_message_getset(const fn_call& fn)
-{
-       boost::intrusive_ptr<Error_as> ptr = ensureType<Error_as>(fn.this_ptr);
-       if (fn.nargs == 0)
-       {
-           // Getter
-           return as_value(ptr->getMessage());
-       }
-       else
-       {
-           // Setter
-           ptr->setMessage(fn.arg(0).to_string());
-           return as_value();
-       }
-}
-
-static as_value
-Error_name_getset(const fn_call& fn)
-{
-       boost::intrusive_ptr<Error_as> ptr = ensureType<Error_as>(fn.this_ptr);
-       
-       if (fn.nargs == 0)
-       {
-           // Getter
-           return as_value(ptr->getName());
-       }
-       else
-       {
-           // Setter
-           ptr->setName(fn.arg(0).to_string());
-           return as_value();
-       }
-       
-}
-
-
-
-as_value
-Error_ctor(const fn_call& fn)
-{
-       boost::intrusive_ptr<Error_as> err = new Error_as;
-
-       if ( fn.nargs > 0)
-       {
-               err->setMessage(fn.arg(0).to_string());
-       }
-
-       return as_value(err.get()); // will keep alive
-}
 
 // extern 
 void Error_class_init(as_object& where)
@@ -155,10 +63,72 @@
        // This is going to be the Error "class"/"function"
        // in the 'where' package
        boost::intrusive_ptr<builtin_function> cl;
-       cl = new builtin_function(&Error_ctor, getErrorInterface());
+       cl = new builtin_function(&error_ctor, getErrorInterface());
 
        // Register _global.Error
        where.init_member("Error", cl.get());
 }
 
+
+namespace {
+
+as_object*
+getErrorInterface()
+{
+       static boost::intrusive_ptr<as_object> o;
+
+       if ( ! o )
+       {
+               o = new as_object(getObjectInterface());
+               VM::get().addStatic(o.get());
+
+               attachErrorInterface(*o);
+
+       }
+
+       return o.get();
+}
+
+
+void
+attachErrorInterface(as_object& o)
+{
+    int flags = 0;
+    o.init_member("toString", new builtin_function(error_toString), flags);
+    o.init_member("message", "Error", flags);
+    o.init_member("name", "Error", flags);
+}
+
+
+as_value
+error_toString(const fn_call& fn)
+{
+       boost::intrusive_ptr<Error_as> ptr = ensureType<Error_as>(fn.this_ptr);
+
+    string_table& st = ptr->getVM().getStringTable();
+    as_value message;
+    ptr->get_member(st.find("message"), &message);
+
+       return as_value(message);   
+}
+
+/// "e = new Error();" returns an Error, "e = Error"; returns undefined.
+as_value
+error_ctor(const fn_call& fn)
+{
+
+    if (!fn.isInstantiation()) return as_value();
+
+       boost::intrusive_ptr<Error_as> err = new Error_as;
+       
+    string_table& st = err->getVM().getStringTable();
+    if (fn.nargs > 0)
+       {
+               err->set_member(st.find("message"), fn.arg(0));
+       }
+
+       return as_value(err.get()); // will keep alive
+}
+
+}
 } // end of gnash namespace

=== modified file 'libcore/asobj/Global.cpp'
--- a/libcore/asobj/Global.cpp  2009-01-07 15:27:53 +0000
+++ b/libcore/asobj/Global.cpp  2009-01-13 11:05:41 +0000
@@ -348,8 +348,7 @@
 as_value
 as_global_parseint(const fn_call& fn)
 {
-    // assert(fn.nargs == 2 || fn.nargs == 1);
-    if (fn.nargs < 1) {
+    if (!fn.nargs) {
         IF_VERBOSE_ASCODING_ERRORS(
             log_aserror(_("%s needs at least one argument"), __FUNCTION__);
         )
@@ -362,114 +361,76 @@
         }
     )
 
-    const std::string digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
-
     const std::string& expr = fn.arg(0).to_string();
 
-    bool negative = false;
-    int base = 0;
-
-    std::string::const_iterator it = expr.begin();
-
-    // Try hexadecimal first
-    if (expr.substr(0, 2) == "0x" || expr.substr(0, 2) == "0X")
-    {
-        base = 16;
-        it += 2;
-        
-        if (*it == '-')
-        {
-            negative = true;
-            it++;
-        }
-        else if (*it == '+') 
-        {
-            it++;
-        }
-    }
-    // Either octal or decimal.
-    else if (*it == '0' || *it == '-' || *it == '+')
-    {
-
-        base = 8;
-
-        // Check for negative and move to the next digit
-        if (*it == '-')
-        {
-            negative = true;
-            it++;
-        }
-        else if (*it == '+') it++;
-        
-        if (*it != '0') base = 10;
-        
-        // Check for expectional case "-0x" or "+0x", which
-        // return NaN
-        else if (std::toupper(*(it + 1)) == 'X')
-        {
-            as_value rv;
-            rv.set_nan();
-            return rv;
-        }
-        
-        // Check from the current position for non-octal characters;
-        // it's decimal in that case.
-        else if (expr.find_first_not_of("01234567", it - expr.begin()) !=
-            std::string::npos)
-        {
-            base = 10;
-        }
-    }
-    // Everything else is decimal.
-    else
-    {
-        base = 10;
-        
-        // Skip leading whitespace
-        while(*it == ' ' || *it == '\n' || *it == '\t' || *it == '\r')
-        {
-            ++it;
-        }
-        if (*it == '-')
-        {
-            negative = true;
-            it++;
-        }
-        else if (*it == '+') it++;
-    }    
-
-    // After all that, a second argument specifies the base.
+    // A second argument specifies the base.
     // Parsing still starts after any positive/negative 
     // sign or hex identifier (parseInt("0x123", 8) gives
     // 83, not 0; parseInt(" 0x123", 8) is 0), which is
     // why we do this here.
+    size_t base;
     if (fn.nargs > 1)
     {
-        base = (fn.arg(1).to_int());
+        base = fn.arg(1).to_int();
     
         // Bases from 2 to 36 are valid, otherwise return NaN
-            if (base < 2 || base > 36)
-            {
-                as_value rv;
-                rv.set_nan();
-                return rv;
-            }
-          
+        if (base < 2 || base > 36) return as_value(NaN);
+    }
+    else
+    {
+        /// No radix specified, so try parsing as octal or hexadecimal
+        try {
+            double d;
+            if (as_value::parseNonDecimalInt(expr, d, false)) return d;
+        }
+        catch (boost::bad_lexical_cast&)
+        {
+            return as_value(NaN);
+        }
+
+        /// The number is not hex or octal, so we'll assume it's base-10.
+        base = 10;
+
+    }
+
+    std::string::const_iterator it = expr.begin();
+
+    // Check for expectional case "-0x" or "+0x", which
+    // return NaN
+    if ((expr.length() > 2) && (*it == '-' || *it == '+') &&
+            *(it + 1) == '0' && std::toupper(*(it + 2)) == 'X') {
+        return as_value(NaN);
+    }
+    
+    // Try hexadecimal first
+    if (expr.substr(0, 2) == "0x" || expr.substr(0, 2) == "0X") it += 2;
+    else {
+        // Skip leading whitespace
+        while(*it == ' ' || *it == '\n' || *it == '\t' || *it == '\r') {
+            ++it;
+        }
+        if (it == expr.end()) return as_value(NaN);
+    }    
+
+    bool negative = false;
+    if (*it == '-' || *it == '+')
+    {
+        if (*it == '-') negative = true;
+        
+        it++;
+        if (it == expr.end()) return as_value(NaN);
     }
     
     // Now we have the base, parse the digits. The iterator should
     // be pointing at the first digit.
     
+    const std::string digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
     // Check to see if the first digit is valid, otherwise 
     // return NaN.
-    int digit = digits.find(toupper(*it));
+    std::string::size_type digit = digits.find(toupper(*it));
 
-    if (digit >= base || digit < 0)
-    {
-        as_value rv;
-        rv.set_nan();
-        return rv;
-    }
+    if (digit >= base || digit == std::string::npos) return as_value(NaN);
 
     // The first digit was valid, so continue from the present position
     // until we reach the end of the string or an invalid character,
@@ -479,17 +440,14 @@
     ++it;
     
     while (it != expr.end() && (digit = digits.find(toupper(*it))) < base
-            && digit >= 0)
+            && digit != std::string::npos)
     {
         result = result * base + digit;
         ++it;
     }
 
-    if (negative)
-    result = -result;
-    
     // Now return the parsed string as an integer.
-    return as_value(result);
+    return negative ? as_value(-result) : as_value(result);
 }
 
 // ASSetPropFlags function
@@ -511,14 +469,8 @@
     IF_VERBOSE_ASCODING_ERRORS(
     if (fn.nargs > 4)
             log_aserror(_("%s has more than four arguments"), __FUNCTION__);
-#if 0 // it is perfectly legal to have 4 args in SWF5 it seems..
-    if (version == 5 && fn.nargs == 4)
-            log_aserror(_("%s has four arguments in a SWF version 5 movie"), 
__FUNCTION__);
-#endif
     )
     
-    // ASSetPropFlags(obj, props, n, allowFalse=false)
-
     // object
     boost::intrusive_ptr<as_object> obj = fn.arg(0).to_object();
     if ( ! obj )
@@ -535,14 +487,14 @@
 
     const as_value& props = fn.arg(1);
 
-    const int flagsMask = ( as_prop_flags::dontEnum |
-                            as_prop_flags::dontDelete |
-                            as_prop_flags::readOnly |
-                            as_prop_flags::onlySWF6Up |
-                            as_prop_flags::ignoreSWF6 |
-                            as_prop_flags::onlySWF7Up |
-                            as_prop_flags::onlySWF8Up |
-                            as_prop_flags::onlySWF9Up);
+    const int flagsMask = as_prop_flags::dontEnum |
+                          as_prop_flags::dontDelete |
+                          as_prop_flags::readOnly |
+                          as_prop_flags::onlySWF6Up |
+                          as_prop_flags::ignoreSWF6 |
+                          as_prop_flags::onlySWF7Up |
+                          as_prop_flags::onlySWF8Up |
+                          as_prop_flags::onlySWF9Up;
 
     // a number which represents three bitwise flags which
     // are used to determine whether the list of child names should be hidden,
@@ -554,9 +506,9 @@
     // except it sets the attributes to false. The
     // set_false bitmask is applied before set_true is applied
 
-    // ASSetPropFlags was exposed in Flash 5, however the fourth argument 
'set_false'
-    // was not required as it always defaulted to the value '~0'. 
-    const int setFalse = (fn.nargs < 4 ? 0 : int(fn.arg(3).to_number())) &
+    // ASSetPropFlags was exposed in Flash 5, however the fourth argument
+    // 'set_false' was not required as it always defaulted to the value '~0'. 
+    const int setFalse = (fn.nargs < 4 ? 0 : fn.arg(3).to_int()) &
         flagsMask;
 
     obj->setPropFlags(props, setFalse, setTrue);

=== modified file 'libcore/asobj/LoadVars_as.cpp'
--- a/libcore/asobj/LoadVars_as.cpp     2008-12-27 19:56:32 +0000
+++ b/libcore/asobj/LoadVars_as.cpp     2009-01-13 07:51:21 +0000
@@ -93,8 +93,6 @@
 
        static as_value getBytesTotal_method(const fn_call& fn);
 
-       static as_value decode_method(const fn_call& fn);
-
        static as_value onData_method(const fn_call& fn);
 
        static as_value onLoad_method(const fn_call& fn);
@@ -118,8 +116,7 @@
        {
         if (it != vars.begin()) o << "&";
         const std::string& val = it->second;
-        o << URL::encode(it->first) << "="
-                    << URL::encode(val);
+        o << URL::encode(it->first) << "=" << URL::encode(val);
        }
 
 }
@@ -140,7 +137,7 @@
 
        o.init_member("addRequestHeader", new builtin_function(
                    LoadableObject::loadableobject_addRequestHeader));
-       o.init_member("decode", new 
builtin_function(LoadVars_as::decode_method));
+       o.init_member("decode", vm.getNative(301, 3));
        o.init_member("getBytesLoaded", new builtin_function(
                    LoadVars_as::getBytesLoaded_method));
        o.init_member("getBytesTotal", new builtin_function(
@@ -167,29 +164,6 @@
 
 
 as_value
-LoadVars_as::decode_method(const fn_call& fn)
-{
-       boost::intrusive_ptr<LoadVars_as> ptr = 
ensureType<LoadVars_as>(fn.this_ptr);
-
-       if ( ! fn.nargs ) return as_value(false);
-
-       typedef std::map<std::string, std::string> ValuesMap;
-
-       ValuesMap vals;
-
-       URL::parse_querystring(fn.arg(0).to_string(), vals);
-
-       string_table& st = ptr->getVM().getStringTable();
-       for  (ValuesMap::const_iterator it=vals.begin(), itEnd=vals.end();
-                       it != itEnd; ++it)
-       {
-               ptr->set_member(st.find(it->first), 
as_value(it->second.c_str()));
-       }
-
-       return as_value(); 
-}
-
-as_value
 LoadVars_as::getBytesLoaded_method(const fn_call& fn)
 {
        boost::intrusive_ptr<LoadVars_as> ptr = 
ensureType<LoadVars_as>(fn.this_ptr);
@@ -199,14 +173,14 @@
 as_value
 LoadVars_as::getBytesTotal_method(const fn_call& fn)
 {
-       boost::intrusive_ptr<LoadVars_as> ptr = 
ensureType<LoadVars_as>(fn.this_ptr);
+       boost::intrusive_ptr<LoadVars_as> ptr =
+        ensureType<LoadVars_as>(fn.this_ptr);
        return as_value(ptr->getBytesTotal());
 }
 
 as_value
 LoadVars_as::onData_method(const fn_call& fn)
 {
-       //GNASH_REPORT_FUNCTION;
 
        as_object* thisPtr = fn.this_ptr.get();
        if ( ! thisPtr ) return as_value();

=== modified file 'libcore/asobj/LoadVars_as.h'
--- a/libcore/asobj/LoadVars_as.h       2008-09-16 17:45:34 +0000
+++ b/libcore/asobj/LoadVars_as.h       2009-01-13 07:51:21 +0000
@@ -26,9 +26,6 @@
 /// Initialize the global LoadVars class
 void loadvars_class_init(as_object& global);
 
-/// Return a LoadVars instance (in case the core lib needs it)
-//std::auto_ptr<as_object> init_loadvars_instance();
-  
 } // end of gnash namespace
 
 #endif

=== modified file 'libcore/asobj/LoadableObject.cpp'
--- a/libcore/asobj/LoadableObject.cpp  2009-01-07 12:19:14 +0000
+++ b/libcore/asobj/LoadableObject.cpp  2009-01-13 07:51:21 +0000
@@ -38,6 +38,7 @@
 namespace {
     as_value loadableobject_send(const fn_call& fn);
     as_value loadableobject_load(const fn_call& fn);
+    as_value loadableobject_decode(const fn_call& fn);
     as_value loadableobject_sendAndLoad(const fn_call& fn);
 }
 
@@ -323,6 +324,9 @@
     vm.registerNative(loadableobject_load, 301, 0);
     vm.registerNative(loadableobject_send, 301, 1);
     vm.registerNative(loadableobject_sendAndLoad, 301, 2);
+
+    /// This is only automatically used in LoadVars.
+    vm.registerNative(loadableobject_decode, 301, 3);
 }
 
 
@@ -443,6 +447,30 @@
 /// do not need to be public methods of the LoadableObject class.
 namespace {
 
+/// Decode method (ASnative 301, 3) can be applied to any as_object.
+as_value
+loadableobject_decode(const fn_call& fn)
+{
+       boost::intrusive_ptr<as_object> ptr = 
ensureType<as_object>(fn.this_ptr);
+
+       if (!fn.nargs) return as_value(false);
+
+       typedef std::map<std::string, std::string> ValuesMap;
+
+       ValuesMap vals;
+
+       URL::parse_querystring(fn.arg(0).to_string(), vals);
+
+       string_table& st = ptr->getVM().getStringTable();
+       for  (ValuesMap::const_iterator it=vals.begin(), itEnd=vals.end();
+                       it != itEnd; ++it)
+       {
+               ptr->set_member(st.find(it->first), as_value(it->second));
+       }
+
+       return as_value(); 
+}
+
 /// Returns true if the arguments are valid, otherwise false. The
 /// success of the connection is irrelevant.
 /// The second argument must be a loadable object (XML or LoadVars).

=== modified file 'libcore/asobj/NetStream_as.cpp'
--- a/libcore/asobj/NetStream_as.cpp    2009-01-03 16:34:08 +0000
+++ b/libcore/asobj/NetStream_as.cpp    2009-01-13 12:25:30 +0000
@@ -164,13 +164,16 @@
 void
 NetStream_as::processStatusNotifications()
 {
-    // TODO: check for System.onStatus too ! use a private getStatusHandler() 
method for this.
+    // TODO: check for System.onStatus too ! use a private
+    // getStatusHandler() method for this.
 
     StatusCode code;
     while (1)
     {
         code = popNextPendingStatusNotification();
-        if ( code == invalidStatus ) break; // no more pending notifications
+
+        // Nothing to do if no more valid notifications.
+        if (code == invalidStatus) return; 
 
         // Must be a new object every time.
         as_object* o = getStatusObject(code);
@@ -213,9 +216,9 @@
     if (m_newFrameReady) {
         m_newFrameReady = false;
         return true;
-    } else {
-        return false;
     }
+    
+    return false;
 }
 
 std::auto_ptr<GnashImage>
@@ -327,28 +330,27 @@
 NetStream_as::markReachableResources() const
 {
 
-    if ( _netCon ) _netCon->setReachable();
-
-    if ( m_statusHandler ) m_statusHandler->setReachable();
-
-    if ( _audioController ) _audioController->setReachable();
-
-    if ( _invalidatedVideoCharacter ) 
_invalidatedVideoCharacter->setReachable();
+    if (_netCon) _netCon->setReachable();
+
+    if (m_statusHandler) m_statusHandler->setReachable();
+
+    if (_audioController) _audioController->setReachable();
+
+    if (_invalidatedVideoCharacter) _invalidatedVideoCharacter->setReachable();
 
     // Invoke generic as_object marker
     markAsObjectReachable();
 }
 #endif // GNASH_USE_GC
 
-/*private static*/
 as_value
 NetStream_as::advanceWrapper(const fn_call& fn)
 {
-        boost::intrusive_ptr<NetStream_as> ptr =
-            ensureType<NetStream_as>(fn.this_ptr);
+    boost::intrusive_ptr<NetStream_as> ptr =
+        ensureType<NetStream_as>(fn.this_ptr);
 
-        ptr->advance();
-        return as_value();
+    ptr->advance();
+    return as_value();
 }
 
 void
@@ -368,7 +370,9 @@
     boost::intrusive_ptr<builtin_function> advanceCallback = 
         new builtin_function(&NetStream_as::advanceWrapper);
     std::auto_ptr<Timer> timer(new Timer);
-    unsigned long delayMS = 50; // TODO: base on media file FPS !!!
+
+    // TODO: base on media file FPS !!! 
+    unsigned long delayMS = 50;
     timer->setInterval(*advanceCallback, delayMS, this);
     _advanceTimer = getVM().getRoot().add_interval_timer(timer, true);
 }
@@ -385,7 +389,8 @@
 
 NetStream_as::~NetStream_as()
 {
-    close(); // close will also detach from sound handler
+    // close will also detach from sound handler
+    close();
 }
 
 
@@ -395,7 +400,9 @@
     switch ( mode )
     {
         case pauseModeToggle:
-            if ( _playHead.getState() == PlayHead::PLAY_PAUSED) 
unpausePlayback();
+            if (_playHead.getState() == PlayHead::PLAY_PAUSED) {
+                unpausePlayback();
+            }
             else pausePlayback();
             break;
         case pauseModePause:
@@ -471,13 +478,6 @@
 
     _inputStream = _netCon->getStream(url); 
 
-    if ( ! _inputStream.get() )
-    {
-        log_error( _("Gnash could not get stream '%s' from NetConnection"), 
url );
-        setStatus(streamNotFound);
-        return;
-    }
-
     // We need to start playback
     if (!startPlayback())
     {
@@ -494,16 +494,18 @@
 void
 NetStream_as::initVideoDecoder(const media::VideoInfo& info)
 {
-    assert ( _mediaHandler ); // caller should check this
-    assert ( !_videoInfoKnown ); // caller should check this
-    assert ( !_videoDecoder.get() ); // caller should check this
+    // Caller should check these:
+    assert ( _mediaHandler ); 
+    assert ( !_videoInfoKnown );
+    assert ( !_videoDecoder.get() );
 
     _videoInfoKnown = true; 
 
     try {
         _videoDecoder = _mediaHandler->createVideoDecoder(info);
-        assert ( _videoDecoder.get() ); // PARANOIA_LEVEL ?
-        log_debug("NetStream_as::initVideoDecoder: hot-plugging video 
consumer");
+        assert ( _videoDecoder.get() ); 
+        log_debug("NetStream_as::initVideoDecoder: hot-plugging "
+                "video consumer");
         _playHead.setVideoConsumerAvailable();
     }
     catch (MediaException& e) {
@@ -513,20 +515,21 @@
 }
 
 
-/* private */
 void
 NetStream_as::initAudioDecoder(const media::AudioInfo& info)
 {
-    assert ( _mediaHandler ); // caller should check this
-    assert ( !_audioInfoKnown ); // caller should check this
-    assert ( !_audioDecoder.get() ); // caller should check this
+    // Caller should check these
+    assert ( _mediaHandler ); 
+    assert ( !_audioInfoKnown ); 
+    assert ( !_audioDecoder.get() );
 
     _audioInfoKnown = true; 
 
     try {
         _audioDecoder = _mediaHandler->createAudioDecoder(info);
-        assert ( _audioDecoder.get() ); // PARANOIA_LEVE ?
-        log_debug("NetStream_as::initAudioDecoder: hot-plugging audio 
consumer");
+        assert ( _audioDecoder.get() );
+        log_debug("NetStream_as::initAudioDecoder: hot-plugging "
+                "audio consumer");
         _playHead.setAudioConsumerAvailable();
     }
     catch (MediaException& e) {
@@ -539,9 +542,20 @@
 bool
 NetStream_as::startPlayback()
 {
-    assert(_inputStream.get());
+
+    // Register advance callback. This must be registered in order for
+    // status notifications to be received (e.g. streamNotFound).
+    startAdvanceTimer();
+
+    if ( ! _inputStream.get() )
+    {
+        log_error(_("Gnash could not get stream '%s' from NetConnection"),
+                url);
+        setStatus(streamNotFound);
+        return false;
+    }
+
     assert(_inputStream->tell() == 0);
-
     inputPos = 0;
 
     if (!_mediaHandler)
@@ -556,7 +570,7 @@
     if ( ! m_parser.get() )
     {
         log_error(_("Unable to create parser for NetStream input"));
-        // not necessarely correct, the stream might have been found...
+        // not necessarily correct, the stream might have been found...
         setStatus(streamNotFound);
         return false;
     }
@@ -569,19 +583,18 @@
     // is when we have something to decode.
     // Postponing this will allow us NOT to block while probing
     // for stream contents.
-    //
 
     decodingStatus(DEC_BUFFERING);
-    _playbackClock->pause(); // NOTE: should be paused already
+
+    // NOTE: should be paused already 
+    _playbackClock->pause();
 
     _playHead.setState(PlayHead::PLAY_PLAYING);
 
-    // Register ::advance callback
-    startAdvanceTimer();
-
 #ifdef GNASH_DEBUG_STATUS
     log_debug("Setting playStart status");
-#endif // GNASH_DEBUG_STATUS
+#endif
+
     setStatus(playStart);
 
     return true;
@@ -591,7 +604,7 @@
 std::auto_ptr<GnashImage> 
 NetStream_as::getDecodedVideoFrame(boost::uint32_t ts)
 {
-    assert(_videoDecoder.get()); // caller should check this
+    assert(_videoDecoder.get()); 
 
     std::auto_ptr<GnashImage> video;
 
@@ -599,7 +612,7 @@
     if ( ! m_parser.get() )
     {
         log_error("getDecodedVideoFrame: no parser available");
-        return video; // no parser, no party
+        return video; 
     }
 
     boost::uint64_t nextTimestamp;
@@ -612,13 +625,15 @@
             "(nextVideoFrameTimestamp returned false, "
             "parsingComplete=%d)",
             ts, parsingComplete);
-#endif // GNASH_DEBUG_DECODING
+#endif 
 
         if ( parsingComplete )
         {
             decodingStatus(DEC_STOPPED);
 #ifdef GNASH_DEBUG_STATUS
-            log_debug("getDecodedVideoFrame setting playStop status (parsing 
complete and nextVideoFrameTimestamp() returned false)");
+            log_debug("getDecodedVideoFrame setting playStop status "
+                    "(parsing complete and nextVideoFrameTimestamp() "
+                    "returned false)");
 #endif
             setStatus(playStop);
         }
@@ -628,16 +643,17 @@
     if ( nextTimestamp > ts )
     {
 #ifdef GNASH_DEBUG_DECODING
-        log_debug("%p.getDecodedVideoFrame(%d): next video frame is in the 
future (%d)",
-            this, ts, nextTimestamp);
-#endif // GNASH_DEBUG_DECODING
-        return video; // next frame is in the future
+        log_debug("%p.getDecodedVideoFrame(%d): next video frame is in "
+                "the future (%d)", this, ts, nextTimestamp);
+#endif 
+        // next frame is in the future
+        return video; 
     }
 
     // Loop until a good frame is found
     while ( 1 )
     {
-            video = decodeNextVideoFrame();
+        video = decodeNextVideoFrame();
         if ( ! video.get() )
         {
             log_error("nextVideoFrameTimestamp returned true (%d), "
@@ -652,7 +668,7 @@
 #ifdef GNASH_DEBUG_DECODING
             log_debug("%p.getDecodedVideoFrame(%d): last video frame decoded "
                 "(should set playback status to STOP?)", this, ts);
-#endif // GNASH_DEBUG_DECODING
+#endif 
             break;
         }
         if ( nextTimestamp > ts )
@@ -663,8 +679,8 @@
                 "next video frame is in the future, "
                 "we'll return this one",
                 this, ts);
-#endif // GNASH_DEBUG_DECODING
-            break; // the one we decoded
+#endif 
+            break; 
         }
     }
 
@@ -679,7 +695,7 @@
     if ( ! m_parser.get() )
     {
         log_error("decodeNextVideoFrame: no parser available");
-        return video; // no parser, no party
+        return video; 
     }
 
     std::auto_ptr<media::EncodedVideoFrame> frame = 
m_parser->nextVideoFrame(); 
@@ -689,7 +705,7 @@
         log_debug("%p.decodeNextVideoFrame(): "
             "no more video frames in input",
             this);
-#endif // GNASH_DEBUG_DECODING
+#endif 
         return video;
     }
 
@@ -705,8 +721,10 @@
     }
 #endif
 
-    assert( _videoDecoder.get() ); // caller should check this
-    assert( ! _videoDecoder->peek() ); // everything we push, we'll pop too..
+    assert( _videoDecoder.get() ); 
+    
+    // everything we push, we'll pop too..
+    assert( ! _videoDecoder->peek() ); 
 
     _videoDecoder->push(*frame);
     video = _videoDecoder->pop();
@@ -731,15 +749,17 @@
         log_debug("%p.decodeNextAudioFrame: "
             "no more video frames in input",
             this);
-#endif // GNASH_DEBUG_DECODING
+#endif
         return 0;
     }
 
     // TODO: make the buffer cursored later ?
-    BufferedAudioStreamer::CursoredBuffer* raw = new 
BufferedAudioStreamer::CursoredBuffer();
+    BufferedAudioStreamer::CursoredBuffer* raw =
+        new BufferedAudioStreamer::CursoredBuffer();
     raw->m_data = _audioDecoder->decode(*frame, raw->m_size);
 
-    if ( _audioController ) // TODO: let the sound_handler do this .. sounds 
cleaner
+    // TODO: let the sound_handler do this .. sounds cleaner
+    if ( _audioController ) 
     {
         character* ch = _audioController->get();
         if ( ch )
@@ -750,7 +770,8 @@
                 // NOTE: adjust_volume assumes samples 
                 // are 16 bits in size, and signed.
                 // Size is still given in bytes..
-                adjust_volume(reinterpret_cast<boost::int16_t*>(raw->m_data), 
raw->m_size, vol);
+                adjust_volume(reinterpret_cast<boost::int16_t*>(raw->m_data),
+                        raw->m_size, vol);
             }
         }
     }
@@ -761,7 +782,7 @@
         "decoded to %d bytes",
         frame->dataSize,
         raw->m_size);
-#endif // GNASH_DEBUG_DECODING
+#endif 
 
     raw->m_ptr = raw->m_data;
 
@@ -800,12 +821,12 @@
     boost::uint32_t newpos = pos;
     if ( ! m_parser->seek(newpos) )
     {
-        //log_error("Seek to invalid time");
 #ifdef GNASH_DEBUG_STATUS
         log_debug("Setting invalidTime status");
 #endif
         setStatus(invalidTime);
-        _playbackClock->resume(); // we won't be *BUFFERING*, so resume now
+        // we won't be *BUFFERING*, so resume now
+        _playbackClock->resume(); 
         return;
     }
     log_debug("m_parser->seek(%d) returned %d", pos, newpos);
@@ -842,16 +863,17 @@
     // so this is to avoid that.
     boost::uint32_t parserTime = m_parser->getBufferLength();
     boost::uint32_t playHeadTime = time();
-    boost::uint32_t bufferLen = parserTime > playHeadTime ? 
parserTime-playHeadTime : 0;
+    boost::uint32_t bufferLen = 
+        parserTime > playHeadTime ? parserTime-playHeadTime : 0;
 #endif
 
     if ( _playHead.getState() == PlayHead::PLAY_PAUSED )
     {
 #ifdef GNASH_DEBUG_DECODING
-        log_debug("%p.refreshAudioBuffer: doing nothing as playhead is paused 
- "
-            "bufferLength=%d/%d",
-            this, bufferLength(), m_bufferTime);
-#endif // GNASH_DEBUG_DECODING
+        log_debug("%p.refreshAudioBuffer: doing nothing as playhead "
+                "is paused - bufferLength=%d/%d", this, bufferLength(),
+                m_bufferTime);
+#endif 
         return;
     }
 
@@ -862,7 +884,7 @@
             "as current position was already decoded - "
             "bufferLength=%d/%d",
             this, bufferLen, m_bufferTime);
-#endif // GNASH_DEBUG_DECODING
+#endif
         return;
     }
 
@@ -874,8 +896,9 @@
         this, curPos, _playHead.getState(), bufferLen, m_bufferTime);
 #endif // GNASH_DEBUG_DECODING
 
-    // TODO: here we should fetch all frames up to the one with timestamp >= 
curPos
-    //       and push them into the buffer to be consumed by audio_streamer
+    // TODO: here we should fetch all frames up to the one with
+    // timestamp >= curPos and push them into the buffer to be 
+    // consumed by audio_streamer
     pushDecodedAudioFrames(curPos);
 }
 
@@ -904,7 +927,6 @@
             // TODO: shouldn't we still flush any existing Audio frame
             //       in the encoded queue ?
 
-            // log_debug("pushDecodedAudioFrames: no decoder for audio in 
stream, nothing to do");
             return;
         }
 
@@ -912,10 +934,6 @@
         if ( ! audioInfo )
         {
             // case 3: no audio found yet
-
-            // assert(!parser.nextAudioFrameTimestamp); // if it was 
threadless...
-
-            // log_debug("pushDecodedAudioFrames: no audio in stream (yet), 
nothing to do");
             return;
         }
 
@@ -997,11 +1015,6 @@
         float swfFPS = 25; // TODO: get this host app (gnash -d affects this)
         double msecsPerAdvance = 10000/swfFPS;
 
-        //static const int outSampleSize = 2;     // <--- 2 is output sample 
size
-        //static const int outSampleFreq = 44100; // <--- 44100 is output 
audio frequency
-        //int samplesPerAdvance = 
(int)std::floor(secsPerAdvance*outSampleFreq); // round up
-        //unsigned int bufferLimit = outSampleSize*samplesPerAdvance;
-
         unsigned int bufferLimit = 20;
         unsigned int bufferSize = _audioStreamer._audioQueue.size();
         if ( bufferSize > bufferLimit )
@@ -1014,20 +1027,22 @@
             //
             // The alternative would be always decode on demand from the
             // audio consumer thread, but would introduce a lot of 
thread-safety
-            // issues: playhead would need protection, input would need 
protection.
+            // issues: playhead would need protection, input would need
+            // protection.
             //
 //#ifdef GNASH_DEBUG_DECODING
             log_debug("%p.pushDecodedAudioFrames(%d) : buffer overrun 
(%d/%d).",
                 this, ts, bufferSize, bufferLimit);
-//#endif // GNASH_DEBUG_DECODING
+//#endif 
 
             // we may want to pause the playbackClock here...
             _playbackClock->pause();
 
             return;
         }
-
-        lock.unlock(); // no need to keep the audio queue locked while 
decoding..
+        
+        // no need to keep the audio queue locked while decoding.
+        lock.unlock();
 
         bool parsingComplete = m_parser->parsingCompleted();
         if ( ! m_parser->nextAudioFrameTimestamp(nextTimestamp) )
@@ -1037,14 +1052,16 @@
                 "no more audio frames in input "
                 "(nextAudioFrameTimestamp returned false, parsingComplete=%d)",
                 this, ts, parsingComplete);
-#endif // GNASH_DEBUG_DECODING
+#endif 
 
             if ( parsingComplete )
             {
                 consumed = true;
                 decodingStatus(DEC_STOPPED);
 #ifdef GNASH_DEBUG_STATUS
-                log_debug("pushDecodedAudioFrames setting playStop status 
(parsing complete and nextAudioFrameTimestamp returned false)");
+                log_debug("pushDecodedAudioFrames setting playStop status "
+                        "(parsing complete and nextAudioFrameTimestamp "
+                        "returned false)");
 #endif
                 setStatus(playStop);
             }
@@ -1058,10 +1075,11 @@
             log_debug("%p.pushDecodedAudioFrames(%d): "
                 "next audio frame is in the future (%d)",
                 this, ts, nextTimestamp);
-#endif // GNASH_DEBUG_DECODING
+#endif 
             consumed = true;
 
-            if ( nextTimestamp > ts+msecsPerAdvance ) break; // next frame is 
in the future
+            // next frame is in the future
+            if (nextTimestamp > ts+msecsPerAdvance) break; 
         }
 
         BufferedAudioStreamer::CursoredBuffer* audio = decodeNextAudioFrame();
@@ -1078,7 +1096,8 @@
         {
             // Don't bother pushing an empty frame
             // to the audio queue...
-            log_debug("pushDecodedAudioFrames(%d): Decoded audio frame 
contains no samples");
+            log_debug("pushDecodedAudioFrames(%d): Decoded audio frame "
+                    "contains no samples");
             delete audio;
             continue;
         }
@@ -1086,15 +1105,16 @@
 #ifdef GNASH_DEBUG_DECODING
         // this one we might avoid :) -- a less intrusive logging could
         // be take note about how many things we're pushing over
-        log_debug("pushDecodedAudioFrames(%d) pushing %dth frame with 
timestamp %d", ts, _audioQueue.size()+1, nextTimestamp); 
+        log_debug("pushDecodedAudioFrames(%d) pushing %dth frame with "
+                "timestamp %d", ts, _audioQueue.size()+1, nextTimestamp); 
 #endif
 
         _audioStreamer.push(audio);
 
     }
 
-    // If we consumed audio of current position, feel free to advance if 
needed,
-    // resuming playbackClock too..
+    // If we consumed audio of current position, feel free to advance
+    // if needed, resuming playbackClock too...
     if ( consumed )
     {
         // resume the playback clock, assuming the
@@ -1104,7 +1124,7 @@
         // the audio data).
 #ifdef GNASH_DEBUG_DECODING
         log_debug("resuming playback clock on audio consume");
-#endif // GNASH_DEBUG_DECODING
+#endif 
         assert(decodingStatus()!=DEC_BUFFERING);
         _playbackClock->resume();
 
@@ -1140,7 +1160,6 @@
             // TODO: shouldn't we still flush any existing Video frame
             //       in the encoded queue ?
 
-            // log_debug("refreshVideoFrame: no decoder for video in stream, 
nothing to do");
             return;
         }
 
@@ -1148,10 +1167,6 @@
         if ( ! videoInfo )
         {
             // case 3: no video found yet
-
-            // assert(!parser.nextVideoFrameTimestamp); // if it was 
threadless...
-
-            // log_debug("refreshVideoFrame: no video in stream (yet), nothing 
to do");
             return;
         }
 
@@ -1166,7 +1181,6 @@
             // TODO: we should still flush any existing Video frame
             //       in the encoded queue...
             //       (or rely on next call)
-
             return; 
         }
 
@@ -1182,7 +1196,7 @@
         log_debug("%p.refreshVideoFrame: doing nothing as playhead is paused - 
"
             "bufferLength=%d, bufferTime=%d",
             this, bufferLen, m_bufferTime);
-#endif // GNASH_DEBUG_DECODING
+#endif 
         return;
     }
 
@@ -1201,9 +1215,10 @@
     boost::uint64_t curPos = _playHead.getPosition();
 
 #ifdef GNASH_DEBUG_DECODING
-    log_debug("%p.refreshVideoFrame: currentPosition=%d, playHeadState=%d, 
bufferLength=%d, bufferTime=%d",
-        this, curPos, _playHead.getState(), bufferLen, m_bufferTime);
-#endif // GNASH_DEBUG_DECODING
+    log_debug("%p.refreshVideoFrame: currentPosition=%d, playHeadState=%d, "
+            "bufferLength=%d, bufferTime=%d",
+            this, curPos, _playHead.getState(), bufferLen, m_bufferTime);
+#endif 
 
     // Get next decoded video frame from parser, will have the lowest timestamp
     std::auto_ptr<GnashImage> video = getDecodedVideoFrame(curPos);
@@ -1218,7 +1233,7 @@
                 "no more video frames to decode "
                 "(DEC_STOPPED, null from getDecodedVideoFrame)",
                 this);
-#endif // GNASH_DEBUG_DECODING
+#endif
         }
         else
         {
@@ -1227,7 +1242,7 @@
                 "last video frame was good enough "
                 "for current position",
                 this);
-#endif // GNASH_DEBUG_DECODING
+#endif 
             // There no video but decoder is still running
             // not much to do here except wait for next call
             //assert(decodingStatus() == DEC_BUFFERING);
@@ -1244,8 +1259,8 @@
             _invalidatedVideoCharacter->set_invalidated();
 
             // NOTE: setting the newFrameReady flag this is not needed anymore,
-            // we don't realy on newFrameReady() call anyore to invalidate the 
video character
-            //m_newFrameReady = true;
+            // we don't realy on newFrameReady() call anyore to invalidate
+            // the video character
         }
     }
 
@@ -1277,9 +1292,12 @@
     // pass them to a event handler
     processStatusNotifications();
 
-    // Nothing to do if we don't have a parser
-    // TODO: should we stopAdvanceTimer() ?
-    if ( ! m_parser.get() ) return;
+    // Nothing to do if we don't have a parser. Unregister the timer, as
+    // all status notifications should have been processed.
+    if ( ! m_parser.get() ) {
+        stopAdvanceTimer();
+        return;
+    }
 
     if ( decodingStatus() == DEC_STOPPED )
     {
@@ -1304,7 +1322,7 @@
             log_debug("%p.advance: buffer empty while decoding,"
                 " setting buffer to buffering and pausing playback clock",
                 this);
-#endif // GNASH_DEBUG_DECODING
+#endif 
 #ifdef GNASH_DEBUG_STATUS
             log_debug("Setting bufferEmpty status");
 #endif
@@ -1317,7 +1335,7 @@
 #ifdef GNASH_DEBUG_DECODING
             log_debug("%p.advance : bufferLength=%d, parsing completed",
                 this, bufferLen);
-#endif // GNASH_DEBUG_DECODING
+#endif
             // set playStop ? (will be done later for now)
         }
     }
@@ -1330,7 +1348,7 @@
             log_debug("%p.advance: buffering"
                 " - position=%d, buffer=%d/%d",
                 this, _playHead.getPosition(), bufferLen, m_bufferTime);
-#endif // GNASH_DEBUG_DECODING
+#endif
 
             // The very first video frame we want to provide
             // as soon as possible (if not paused),
@@ -1349,7 +1367,7 @@
         log_debug("%p.advance: buffer full (or parsing completed), "
                 "resuming playback clock - position=%d, buffer=%d/%d",
                 this, _playHead.getPosition(), bufferLen, m_bufferTime);
-#endif // GNASH_DEBUG_DECODING
+#endif
 
         setStatus(bufferFull);
         decodingStatus(DEC_DECODING);
@@ -1572,8 +1590,10 @@
         _audioQueue.push_back(audio);
         _audioQueueSize += audio->m_size;
     }
-    else // don't bother pushing audio to the queue, nobody would consume it...
+    else 
     {
+        // Don't bother pushing audio to the queue,
+        // as nobody would consume it...
         delete audio;
     }
 }
@@ -1582,7 +1602,8 @@
 BufferedAudioStreamer::cleanAudioQueue()
 {
     boost::mutex::scoped_lock lock(_audioQueueMutex);
-    for (AudioQueue::iterator i=_audioQueue.begin(), e=_audioQueue.end(); 
i!=e; ++i)
+    for (AudioQueue::iterator i=_audioQueue.begin(), e=_audioQueue.end();
+            i!=e; ++i)
     {
         delete *i;
     }
@@ -1642,7 +1663,9 @@
         mode = fn.arg(0).to_bool() ? NetStream_as::pauseModePause :
                                      NetStream_as::pauseModeUnPause;
     }
-    ns->pause(mode);    // toggle mode
+    
+    // Toggle pause mode
+    ns->pause(mode); 
     return as_value();
 }
 
@@ -1880,11 +1903,11 @@
 
     LOG_ONCE(log_unimpl("NetStream.liveDelay getter/setter"));
 
-    if ( fn.nargs == 0 ) // getter
+    if ( fn.nargs == 0 ) 
     {
         return as_value();
     }
-    else // setter
+    else 
     {
         return as_value();
     }

=== modified file 'libcore/asobj/Number_as.cpp'
--- a/libcore/asobj/Number_as.cpp       2008-10-30 16:46:00 +0000
+++ b/libcore/asobj/Number_as.cpp       2009-01-12 09:50:04 +0000
@@ -81,7 +81,7 @@
        boost::intrusive_ptr<Number_as> obj = 
ensureType<Number_as>(fn.this_ptr);
 
        double val = obj->get_numeric_value();
-       unsigned radix=10;
+       unsigned radix = 10;
 
        if ( fn.nargs ) 
        {

=== modified file 'libcore/asobj/Object.cpp'
--- a/libcore/asobj/Object.cpp  2008-12-09 09:04:55 +0000
+++ b/libcore/asobj/Object.cpp  2009-01-12 13:51:00 +0000
@@ -141,28 +141,30 @@
 {
        if ( fn.nargs == 1 ) // copy constructor
        {
-               // just copy the reference
+
+        as_object* obj = fn.arg(0).to_object().get();
+
+        /// If it's not an object, return an undefined object, not null.
+        if (!obj) return as_value(new as_object);
+
+        // just copy the reference
                //
                // WARNING: it is likely that fn.result and fn.arg(0)
                // are the same location... so we might skip
                // the set_as_object() call as a whole.
-               return as_value(fn.arg(0).to_object());
-       }
-
-       boost::intrusive_ptr<as_object> new_obj;
-       if ( fn.nargs == 0 )
-       {
-               new_obj = new as_object(getObjectInterface());
-       }
-       else
-       {
-               IF_VERBOSE_ASCODING_ERRORS (
-               log_aserror(_("Too many args to Object constructor"));
-               )
-               new_obj = new as_object(getObjectInterface());
-       }
-
-       return as_value(new_obj.get()); // will keep alive
+               return as_value(obj);
+       }
+
+       if (fn.nargs)
+       {
+               IF_VERBOSE_ASCODING_ERRORS(
+                   log_aserror(_("Too many args to Object constructor"));
+               );
+       }
+
+    boost::intrusive_ptr<as_object> obj = new as_object(getObjectInterface());
+
+       return as_value(obj.get()); 
 }
 
 

=== modified file 'libcore/asobj/String_as.cpp'
--- a/libcore/asobj/String_as.cpp       2009-01-09 21:33:17 +0000
+++ b/libcore/asobj/String_as.cpp       2009-01-13 08:22:29 +0000
@@ -859,8 +859,7 @@
 as_value
 string_toString(const fn_call& fn)
 {
-    boost::intrusive_ptr<String_as> obj 
-          = ensureType<String_as>(fn.this_ptr);
+    boost::intrusive_ptr<String_as> obj = ensureType<String_as>(fn.this_ptr);
     return as_value(obj->str());
 }
 

=== modified file 'libcore/movie_root.cpp'
--- a/libcore/movie_root.cpp    2009-01-08 07:05:33 +0000
+++ b/libcore/movie_root.cpp    2009-01-13 07:05:59 +0000
@@ -313,18 +313,23 @@
        int oldDepth = movie->get_depth();
 
 #ifdef GNASH_DEBUG_LEVELS_SWAPPING
-       log_debug("Before swapLevels (source depth %d, target depth %d) levels 
are: ", oldDepth, depth);
+       log_debug("Before swapLevels (source depth %d, target depth %d) "
+            "levels are: ", oldDepth, depth);
        for (Levels::const_iterator i=_movies.begin(), e=_movies.end(); i!=e; 
++i)
        {
-               log_debug(" %d: %p (%s @ depth %d)", i->first, 
(void*)(i->second.get()), i->second->getTarget(), i->second->get_depth());
+               log_debug(" %d: %p (%s @ depth %d)", i->first,
+                (void*)(i->second.get()), i->second->getTarget(),
+                i->second->get_depth());
        }
 #endif
 
        if ( oldDepth < character::staticDepthOffset ) // should include 
_level0 !
        {
                IF_VERBOSE_ASCODING_ERRORS(
-               log_aserror(_("%s.swapDepth(%d): movie has a depth (%d) below 
static depth zone (%d), won't swap its depth"),
-                       movie->getTarget(), depth, oldDepth, 
character::staticDepthOffset);
+               log_aserror(_("%s.swapDepth(%d): movie has a depth (%d) below "
+                "static depth zone (%d), won't swap its depth"),
+                movie->getTarget(), depth, oldDepth,
+                character::staticDepthOffset);
                );
                return;
        }
@@ -332,8 +337,10 @@
        if ( oldDepth >= 0 ) 
        {
                IF_VERBOSE_ASCODING_ERRORS(
-               log_aserror(_("%s.swapDepth(%d): movie has a depth (%d) below 
static depth zone (%d), won't swap its depth"),
-                       movie->getTarget(), depth, oldDepth, 
character::staticDepthOffset);
+               log_aserror(_("%s.swapDepth(%d): movie has a depth (%d) below "
+                "static depth zone (%d), won't swap its depth"),
+                movie->getTarget(), depth, oldDepth,
+                character::staticDepthOffset);
                );
                return;
        }
@@ -367,7 +374,9 @@
        log_debug("After swapLevels levels are: ");
        for (Levels::const_iterator i=_movies.begin(), e=_movies.end(); i!=e; 
++i)
        {
-               log_debug(" %d: %p (%s @ depth %d)", i->first, 
(void*)(i->second.get()), i->second->getTarget(), i->second->get_depth());
+               log_debug(" %d: %p (%s @ depth %d)", i->first, 
+                (void*)(i->second.get()), i->second->getTarget(),
+                i->second->get_depth());
        }
 #endif
        
@@ -386,7 +395,8 @@
        Levels::iterator it = _movies.find(depth);
        if ( it == _movies.end() )
        {
-               log_error("movie_root::dropLevel called against a movie not 
found in the levels container");
+               log_error("movie_root::dropLevel called against a movie not "
+                "found in the levels container");
                return;
        }
 

=== modified file 'libcore/vm/ASHandlers.cpp'
--- a/libcore/vm/ASHandlers.cpp 2009-01-09 13:50:44 +0000
+++ b/libcore/vm/ASHandlers.cpp 2009-01-12 14:37:36 +0000
@@ -2171,11 +2171,13 @@
         IF_VERBOSE_ACTION (
         if ( type == pushDict8 || type == pushDict16 )
         {
-            log_action(_("\t%d) type=%s (%d), value=%s"), count, 
pushType[type], id, env.top(0));
+            log_action(_("\t%d) type=%s (%d), value=%s"),
+                count, pushType[type], id, env.top(0));
         }
         else
         {
-            log_action(_("\t%d) type=%s, value=%s"), count, pushType[type], 
env.top(0));
+            log_action(_("\t%d) type=%s, value=%s"),
+                count, pushType[type], env.top(0));
         }
         ++count;
         );
@@ -3071,7 +3073,7 @@
                 v1, v2);
 #endif
 
-    if (v1.is_string() || v2.is_string() )
+    if (v1.is_string() || v2.is_string())
     {
         // NOTE: I've tested that we should change behaviour
         //       based on code definition version, not top-level
@@ -3176,20 +3178,20 @@
     if ( swfVersion <= 5 )
     {
         as_value op1 = env.top(0);
-    try { op1 = op1.to_primitive(); }
-    catch (ActionTypeError& e)
-    {
-        log_debug(_("to_primitive(%s) threw an ActionTypeError %s"),
-                op1, e.what());
-    }
+        try { op1 = op1.to_primitive(); }
+        catch (ActionTypeError& e)
+        {
+            log_debug(_("to_primitive(%s) threw an ActionTypeError %s"),
+                    op1, e.what());
+        }
 
         as_value op2 = env.top(1);
-    try { op2 = op2.to_primitive(); }
-    catch (ActionTypeError& e)
-    {
-        log_debug(_("to_primitive(%s) threw an ActionTypeError %s"),
-                op2, e.what());
-    }
+        try { op2 = op2.to_primitive(); }
+        catch (ActionTypeError& e)
+        {
+            log_debug(_("to_primitive(%s) threw an ActionTypeError %s"),
+                    op2, e.what());
+        }
 
         env.top(1).set_bool(op1.equals(op2));
     }

=== modified file 'testsuite/actionscript.all/Date.as'
--- a/testsuite/actionscript.all/Date.as        2009-01-09 08:37:20 +0000
+++ b/testsuite/actionscript.all/Date.as        2009-01-12 12:03:12 +0000
@@ -629,9 +629,9 @@
 d2 = new Date;
 check_equals(d1.toString(), d2.toString());
 
-xcheck_equals (Date.UTC(-1000, 20).valueOf(), -33713366400000);
-xcheck_equals (Date.UTC(-70, 0).toString(), "-4417977600000");
-xcheck_equals (Date.UTC(-70, 0).valueOf(), -4417977600000);
+check_equals (Date.UTC(-1000, 20).valueOf(), -33713366400000);
+check_equals (Date.UTC(-70, 0).toString(), "-4417977600000");
+check_equals (Date.UTC(-70, 0).valueOf(), -4417977600000);
 check_equals (Date.UTC(1969, 11).toString(), "-2678400000");
 check_equals (Date.UTC(1969, 11).valueOf(), -2678400000);
 check_equals (Date.UTC(1969, 12).toString(), "0");

=== modified file 'testsuite/actionscript.all/Error.as'
--- a/testsuite/actionscript.all/Error.as       2008-06-17 07:45:35 +0000
+++ b/testsuite/actionscript.all/Error.as       2009-01-12 16:00:41 +0000
@@ -31,8 +31,8 @@
 check(Error.prototype.hasOwnProperty("message"));
 #endif
 
-xcheck_equals(typeof(Error.prototype.message), "string");
-xcheck_equals(typeof(Error.prototype.name), "string");
+check_equals(typeof(Error.prototype.message), "string");
+check_equals(typeof(Error.prototype.name), "string");
 
 var errorObj = new Error;
 
@@ -62,18 +62,23 @@
 
 // Is there any sense in this?
 e = new Error(new Color);
-xcheck_equals(typeof(e.toString()), "object");
+check_equals(typeof(e.toString()), "object");
 check_equals(e.toString().toString(), "[object Object]");
 check_equals(e.name, "Error");
-xcheck_equals(typeof(e.message), "object");
+check_equals(typeof(e.message), "object");
 
 e.name = "ANewName";
 check_equals(e.name, "ANewName");
 e.message = "New message";
 check_equals(e.message, "New message");
 
+e = new Error;
+e.message = "stringo";
+check_equals(e.message, "stringo");
+check_equals(e.name, "Error");
+
 
 e = Error("NameOfSecondError");
-xcheck_equals(typeof(e), "undefined");
+check_equals(typeof(e), "undefined");
 
 totals();

=== modified file 'testsuite/actionscript.all/Number.as'
--- a/testsuite/actionscript.all/Number.as      2009-01-09 21:10:24 +0000
+++ b/testsuite/actionscript.all/Number.as      2009-01-10 12:29:31 +0000
@@ -610,6 +610,23 @@
 a=new Number(" 0x2");
 check(isNaN(a));
 
+a=Number("-0x2"); 
+check(isNaN(a));
+
+a=Number("0x-2"); 
+#if OUTPUT_VERSION < 6
+check(isNaN(a));
+#else
+check_equals(a, -2);
+#endif
+
+a=Number("0x-ffffffff"); 
+#if OUTPUT_VERSION < 6
+check(isNaN(a));
+#else
+check_equals(a, 1);
+#endif
+
 a=Number("077");
 #if OUTPUT_VERSION < 6
  check_equals(a, 77);
@@ -639,11 +656,11 @@
 // END OF TEST
 
 #if OUTPUT_VERSION < 6
- check_totals(227);
+ check_totals(230);
 #else
 #if OUTPUT_VERSION < 7
- check_totals(222);
+ check_totals(225);
 #else
- check_totals(220);
+ check_totals(223);
 #endif
 #endif

=== modified file 'testsuite/swfdec/PASSING'
--- a/testsuite/swfdec/PASSING  2009-01-09 21:45:28 +0000
+++ b/testsuite/swfdec/PASSING  2009-01-13 12:56:25 +0000
@@ -7,6 +7,9 @@
 add2-7.swf:60923badd220f89cb2d6a6e3380654b6
 add2-8.swf:593e048247f78abdb28dc1b69bf714d9
 add2-different-objects-5.swf:e35553c20f435d125b6e4905cbd1ad20
+add2-different-objects-6.swf:a4c3ced098c02e4659b553e6c981f68b
+add2-different-objects-7.swf:55b42c8a809762f4d35f33cd49d3e8b7
+add2-different-objects-8.swf:56083a88084b18813955ae90ca1d1117
 addProperty-5.swf:00e23fa4da0445805c0c4ea3f54a140d
 addProperty-6.swf:d35a3de35c9da995d03e0c2da1ea0dce
 addProperty-7.swf:6bb7593ed139daddaa7be97db33833fb
@@ -186,6 +189,9 @@
 constructor-madness-8.swf:5357273baf6b66f6af0223cb1d13b144
 constructor-prototype.swf:22505f0f8dd8440972a298110d697e3b
 constructor-relay-5.swf:2d1a814c37f55485d66624cb97c58e03
+conversion-functions-6.swf:29f141b5a2d03886c152342fdbea9b25
+conversion-functions-7.swf:8bc3951e61b7fefa82d24fb037929350
+conversion-functions-8.swf:4a68346aaa982e32b2882a49e34faa07
 convolution-filter-properties-5.swf:96e15de475e31c328e201c152ffd2f42
 convolution-filter-properties-5.swf:db6e2ddcbee195363a53c276bfc460d7
 countdown.swf:db94f8e7bb5a46cbf210c94a19fa068d
@@ -299,6 +305,13 @@
 dangling-print-6.swf:9c079b270d7ce76fbb1f0209a01de3c6
 dangling-print-7.swf:5338574e04b055fe168b443a5ca1da98
 dangling-print-8.swf:3a8af45c5348dd5da7417b75d7aef8c6
+date-set-multiple-5.swf:42e397f0380fd6e0ba4331e1cfe5cede
+date-set-multiple-6.swf:19e0539c29244563f8ac7ceadf2f561d
+date-set-multiple-7.swf:55ab4407ed40093961215c1e9d321a8f
+date-set-multiple-8.swf:e1710e922e76828005e39545f9517328
+date-set-time-6.swf:49754b2c54d66586f9d4398a5ce1d69d
+date-set-time-7.swf:a277c380a2c605c19d2b8853fffa7dbb
+date-set-time-8.swf:8eab1d0858e22404c28ba3f00597e250
 definefunction2-arguments-registers.swf:9cba221db1a793e345f727c9ec62a21b
 definefunction2-arguments.swf:054308da5bad0209a132f8d1be2f7240
 definefunction2-overwrite.swf:079d366e379196272b8b2327e068f336
@@ -386,6 +399,9 @@
 extends-constructors-6.swf:3e03e8d3b69a4617cd634340a05cc3b8
 extends-constructors-7.swf:bdd4d88deef41da109379e5dc0c130d6
 extends-constructors-8.swf:b812f8e472f897a73914d10101841b87
+extends-properties-6.swf:859cd7a6702e70280e37244a2604b362
+extends-properties-7.swf:f7d5b877c072428ee4381bf112d673ab
+extends-properties-8.swf:224438df996facd7d645d58a6fbf89e5
 extends-simple.swf:5e3daf1e64d50b0c9ef06f7ad99f2bda
 extends-super.swf:d6aa7d61f452c5ee3ff64876ad70263a
 externalinterface-escape-6.swf:a1e0bb4872f756050aa52aada9837599
@@ -428,6 +444,7 @@
 fscommand-8.swf:75832f55dd2be76d1c740f5b69e122f6
 function1.swf:56879c1d57617765e2ecf8c0a49047d8
 function2.swf:021842f44ba2c3e5c7c13786c7cc88ea
+function-apply-5.swf:4a8ae3ed3fe3e636c0aede2188dd9b92
 function-apply-crash-5.swf:cdaa243e5975d08e61781ad5632423f2
 function-apply-crash-6.swf:d37c7e90d823363dcc4052167fcbb754
 function-apply-crash-7.swf:28334f00875b4d137083a98c13fbab87
@@ -541,6 +558,10 @@
 loadobject-addrequestheader-8.swf:50ab764a31bff4a679a86e48d7000343
 loadvariables-5.swf:a24997be9ca59d8da2216f9527d0279a
 loadvars-5.swf:378a93e3fc7821a72f61332dcfa6cbf7
+loadvars-decode-return-5.swf:7d961f35feb3d46db0725e93c26bb90a
+loadvars-decode-return-6.swf:b087145545a09db783e43093e1ed6731
+loadvars-decode-return-7.swf:86b9a3bf16c7f8927a63b048b7886dbf
+loadvars-decode-return-8.swf:4a634352da2b0ab1a85746f566fe1fb3
 local-connection-properties-6.swf:396dc9cb0b3a2228c835f2ac284116b5
 local-connection-properties-7.swf:cea39463c752388d55e00442b6c24e35
 local-connection-properties-8.swf:8181bc0d301a99df5bc3e20766a35c83
@@ -653,6 +674,7 @@
 netstream-fscommand-7.swf:ec9312835ba2e8a7347252bcaef7db0b
 netstream-fscommand-8.swf:38f05e4f8d3a4e2faae0ef9e18e7754b
 netstream-onmetadata.swf:31c82598dc65e08e7ca07b38bb5f84e8
+netstream-onstatus-notfound.swf:a76b78d242368068b8368b41c45a4f7f
 newmethod-undefined-5.swf:e01bea2bb053c7448118759dacbcbe6b
 newmethod-undefined-6.swf:af4fc8db6114d8b4470b10a09b87e303
 newmethod-undefined-7.swf:7e226bdd682c6efeb3054b1f77fc9487
@@ -891,6 +913,9 @@
 round-direction-6.swf:2f7d7580490e0c4a3ddfb107849dc6d8
 round-direction-7.swf:66f77f46b6695bbb4d2a2e556ed737fa
 round-direction-8.swf:5e9afcedacd32a7438a21469f09cd853
+run_swfdec_testsuite_l running loadvars-decode-return-6.swf (expect pass: no)
+run_swfdec_testsuite_l running loadvars-decode-return-7.swf (expect pass: no)
+run_swfdec_testsuite_l running loadvars-decode-return-8.swf (expect pass: no)
 same-argument-name-5.swf:8a3048b2c4c143f3371caba918e3fa1b
 same-argument-name-6.swf:0814b0f0acc2abdc94f95972ec4db704
 same-argument-name-7.swf:a8db16910cb00b86ee7622e2d878ddc0

=== modified file 'testsuite/swfdec/swfdec_gnash_tester'
--- a/testsuite/swfdec/swfdec_gnash_tester      2008-04-25 09:26:32 +0000
+++ b/testsuite/swfdec/swfdec_gnash_tester      2009-01-12 21:12:01 +0000
@@ -32,6 +32,6 @@
        exit 2
 fi
 
-grep TRACE -A1 ${logout} | sed '/^--$/d; s/.*TRACE: //; /\n*[0-9][0-9]*\].*/d; 
s/^$//;' > $out
+grep TRACE -A1 ${logout} | sed '/^--$/d; s/.*TRACE: //; 
/\n*[0-9]:[0-9]*\].*/d; s/^$//;' > $out
 diff -u "$exp" "$out"
 exit $?


reply via email to

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