[Top][All Lists]
[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 $?
- [Gnash-commit] /srv/bzr/gnash/trunk r10541: Numerous AS fixes for 26 new swfdec testsuite and some actionscript.all,
Benjamin Wolsey <=