[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gnash-commit] /srv/bzr/gnash/trunk r11405: Clean up and make object con
From: |
Benjamin Wolsey |
Subject: |
[Gnash-commit] /srv/bzr/gnash/trunk r11405: Clean up and make object conversion more consistent (and correct); |
Date: |
Tue, 11 Aug 2009 13:45:26 +0200 |
User-agent: |
Bazaar (1.16.1) |
------------------------------------------------------------
revno: 11405 [merge]
committer: Benjamin Wolsey <address@hidden>
branch nick: trunk
timestamp: Tue 2009-08-11 13:45:26 +0200
message:
Clean up and make object conversion more consistent (and correct);
importantly, this removes the need to access prototype code from outside
various files.
Add tests for those kind of conversions.
Fix a bug in XML's and LoadVars's sendAndLoad method.
Newly-added swfdec tests pass.
modified:
libbase/URL.cpp
libcore/as_function.cpp
libcore/asobj/Boolean_as.cpp
libcore/asobj/Boolean_as.h
libcore/asobj/Globals.cpp
libcore/asobj/LoadableObject.cpp
libcore/asobj/Number_as.cpp
libcore/asobj/Number_as.h
libcore/asobj/Object.cpp
libcore/asobj/String_as.cpp
libcore/asobj/String_as.h
libcore/asobj/flash/ui/Mouse_as.cpp
libcore/vm/ASHandlers.cpp
testsuite/actionscript.all/Object.as
testsuite/swfdec/PASSING
=== modified file 'libbase/URL.cpp'
--- a/libbase/URL.cpp 2009-05-04 20:07:52 +0000
+++ b/libbase/URL.cpp 2009-08-11 11:13:30 +0000
@@ -294,18 +294,18 @@
URL::str() const
{
std::string ret = _proto + "://" + _host;
- if ( _port != "" )
- {
+
+ if (!_port.empty()) {
ret += ":" + _port;
}
- ret += _path;
- if ( _querystring != "" )
- {
+ ret += _path;
+
+ if (!_querystring.empty()) {
ret += "?" + _querystring;
}
- if ( _anchor != "" )
- {
+
+ if (!_anchor.empty()) {
ret += "#" + _anchor;
}
return ret;
@@ -346,14 +346,14 @@
// extract the parameters from the URL
- size_t qmpos = _path.find("?");
+ std::string::size_type qmpos = _path.find("?");
if (qmpos == std::string::npos)
{
// no query string
return;
}
- _querystring = _path.substr(qmpos+1);
+ _querystring = _path.substr(qmpos + 1);
// update _path
_path.erase(qmpos);
=== modified file 'libcore/as_function.cpp'
--- a/libcore/as_function.cpp 2009-07-16 10:52:17 +0000
+++ b/libcore/as_function.cpp 2009-08-11 09:16:26 +0000
@@ -174,6 +174,11 @@
// reasonable, but anything else shouldn't be caught here.
log_debug("Native function called as constructor threw
exception: "
"%s", ex.what());
+
+ // If a constructor throws an exception, throw it back to the
+ // caller. This is the only way to signal that a constructor
+ // did not return anything.
+ throw;
}
if (ret.is_object()) newobj = ret.to_object(*getGlobal(env));
@@ -182,7 +187,9 @@
newobj = new as_object();
}
- assert(newobj); // we assume builtin functions do return
objects !!
+ // There should always be an object by this stage. Failed constructors
+ // are handled in the catch.
+ assert(newobj);
// Add a __constructor__ member to the new object, but only for
SWF6 up
// (to be checked). NOTE that we assume the builtin constructors
=== modified file 'libcore/asobj/Boolean_as.cpp'
--- a/libcore/asobj/Boolean_as.cpp 2009-07-29 05:59:24 +0000
+++ b/libcore/asobj/Boolean_as.cpp 2009-08-11 09:16:57 +0000
@@ -79,21 +79,6 @@
}
-as_object*
-init_boolean_instance(Global_as& g, bool val)
-{
- boost::intrusive_ptr<as_object> cl = getBooleanClass(g);
- as_function* ctor = cl->to_function();
- if (!ctor) return 0;
-
- as_environment env(getVM(g));
-
- std::auto_ptr< std::vector<as_value> > args ( new std::vector<as_value> );
- args->push_back(val);
- return ctor->constructInstance(env, args).get();
-}
-
-
namespace {
as_object*
=== modified file 'libcore/asobj/Boolean_as.h'
--- a/libcore/asobj/Boolean_as.h 2009-07-16 08:30:06 +0000
+++ b/libcore/asobj/Boolean_as.h 2009-08-11 09:16:57 +0000
@@ -29,9 +29,6 @@
/// Initialize the global Boolean class
void boolean_class_init(as_object& global, const ObjectURI& uri);
-
-/// Return a Boolean instance (in case the core lib needs it)
-as_object* init_boolean_instance(Global_as& g, bool val);
} // end of gnash namespace
=== modified file 'libcore/asobj/Globals.cpp'
--- a/libcore/asobj/Globals.cpp 2009-08-07 08:43:01 +0000
+++ b/libcore/asobj/Globals.cpp 2009-08-11 09:15:29 +0000
@@ -147,6 +147,8 @@
as_value global_setInterval(const fn_call& fn);
void registerNatives(as_object& global);
+ template<typename T> as_object* constructObject(Global_as& gl, const T&
arg,
+ string_table::key className);
}
AVM2Global::AVM2Global(Machine& /*machine*/, VM& vm)
@@ -213,19 +215,26 @@
as_object*
AVM1Global::createString(const std::string& s)
{
- return init_string_instance(*this, s);
+ // This is not really correct. If there is no String class, to_object()
+ // returns an undefined value, not a null object. The behaviour is the
+ // same for versions 5 to 8.
+ return constructObject(*this, s, NSV::CLASS_STRING);
}
as_object*
AVM1Global::createNumber(double d)
{
- return init_number_instance(*this, d);
+ // This is not really correct. If there is no String class, to_object()
+ // returns an undefined value, not a null object. The behaviour is the
+ // same for versions 5 to 8.
+ return constructObject(*this, d, NSV::CLASS_NUMBER);
+
}
as_object*
AVM1Global::createBoolean(bool b)
{
- return init_boolean_instance(*this, b);
+ return constructObject(*this, b, NSV::CLASS_BOOLEAN);
}
as_object*
@@ -257,19 +266,21 @@
as_object*
AVM2Global::createString(const std::string& s)
{
- return init_string_instance(*this, s);
+ // What AVM2 does for createString is untested, so we do the same
+ // as AVM1 for now.
+ return constructObject(*this, s, NSV::CLASS_STRING);
}
as_object*
AVM2Global::createNumber(double d)
{
- return init_number_instance(*this, d);
+ return constructObject(*this, d, NSV::CLASS_NUMBER);
}
as_object*
AVM2Global::createBoolean(bool b)
{
- return init_boolean_instance(*this, b);
+ return constructObject(*this, b, NSV::CLASS_BOOLEAN);
}
void
@@ -1142,6 +1153,44 @@
}
+/// Construct an instance of the specified global class.
+//
+/// If the class is not present or is not a constructor function, this
+/// function throws an ActionTypeError.
+//
+/// TODO: consider whether ActionTypeError is an appropriate exception.
+/// TODO: test the other failure cases.
+template<typename T> as_object* constructObject(Global_as& gl, const T& arg,
+ string_table::key className)
+{
+ as_value clval;
+
+ // This is tested in actionscript.all/Object.as to return an
+ // undefined value. We throw the exception back to the VM, which pushes
+ // an undefined value onto the stack.
+ if (!gl.get_member(className, &clval) ) {
+ throw ActionTypeError();
+ }
+
+ // This is not properly tested.
+ if (!clval.is_function()) {
+ throw ActionTypeError();
+ }
+
+ as_function* ctor = clval.to_as_function();
+
+ // This is also not properly tested.
+ if (!ctor) throw ActionTypeError();
+
+ std::auto_ptr<std::vector<as_value> > args(new std::vector<as_value>);
+ args->push_back(arg);
+ as_environment env(getVM(gl));
+ as_object* ret = ctor->constructInstance(env, args).get();
+
+ return ret;
+
+}
+
void
registerNatives(as_object& global)
{
=== modified file 'libcore/asobj/LoadableObject.cpp'
--- a/libcore/asobj/LoadableObject.cpp 2009-07-16 08:53:33 +0000
+++ b/libcore/asobj/LoadableObject.cpp 2009-08-11 11:13:35 +0000
@@ -160,9 +160,19 @@
std::ostringstream data;
toString(data, true);
- std::string getURL = urlstr + "?" + data.str();
- log_debug("Using GET method for sendAndLoad: %s", getURL);
- str = ri.streamProvider().getStream(getURL);
+ const std::string& dataString = data.str();
+
+ // Any data must be added to the existing querystring.
+ if (!dataString.empty()) {
+
+ std::string existingQS = url.querystring();
+ if (!existingQS.empty()) existingQS += "&";
+
+ url.set_querystring(existingQS + data.str());
+ }
+
+ log_debug("Using GET method for sendAndLoad: %s", url.str());
+ str = ri.streamProvider().getStream(url.str());
}
log_security(_("Loading from url: '%s'"), url.str());
=== modified file 'libcore/asobj/Number_as.cpp'
--- a/libcore/asobj/Number_as.cpp 2009-07-29 06:12:35 +0000
+++ b/libcore/asobj/Number_as.cpp 2009-08-11 09:17:11 +0000
@@ -198,7 +198,8 @@
// extern (used by Global.cpp)
-void number_class_init(as_object& global, const ObjectURI& uri)
+void
+number_class_init(as_object& global, const ObjectURI& uri)
{
boost::intrusive_ptr<as_object> cl = getNumberClass(*getGlobal(global));
@@ -208,20 +209,4 @@
}
-as_object*
-init_number_instance(Global_as& g, double val)
-{
- boost::intrusive_ptr<as_object> cl = getNumberClass(g);
- as_function* ctor = cl->to_function();
- if (!ctor) return 0;
-
- as_environment env(getVM(g));
-
- std::auto_ptr< std::vector<as_value> > args ( new std::vector<as_value> );
- args->push_back(val);
-
- return ctor->constructInstance(env, args).get();
-}
-
-
} // namespace gnash
=== modified file 'libcore/asobj/Number_as.h'
--- a/libcore/asobj/Number_as.h 2009-07-16 08:30:06 +0000
+++ b/libcore/asobj/Number_as.h 2009-08-11 09:17:11 +0000
@@ -33,9 +33,6 @@
/// Initialize the global Number class
void number_class_init(as_object& global, const ObjectURI& uri);
-/// Return a Number instance
-as_object* init_number_instance(Global_as& g, double val);
-
}
#endif // GNASH_NUMBER_H
=== modified file 'libcore/asobj/Object.cpp'
--- a/libcore/asobj/Object.cpp 2009-08-07 09:53:58 +0000
+++ b/libcore/asobj/Object.cpp 2009-08-11 08:35:18 +0000
@@ -170,31 +170,24 @@
object_ctor(const fn_call& fn)
{
Global_as* gl = getGlobal(fn);
+ as_object* proto = getObjectInterface();
if (fn.nargs == 1) {
-
as_object* obj = fn.arg(0).to_object(*gl).get();
-
- /// If it's not an object, return a simple object, not null.
- if (!obj) return gl->createObject();
-
- return as_value(obj);
+ if (obj) return as_value(obj);
}
- if (fn.nargs) {
+ if (fn.nargs > 1) {
IF_VERBOSE_ASCODING_ERRORS(
log_aserror(_("Too many args to Object constructor"));
);
}
if (!fn.isInstantiation()) {
- return gl->createObject();;
+ return gl->createObject();
}
- as_object* proto = getObjectInterface();
- boost::intrusive_ptr<as_object> obj = gl->createObject(proto);
-
- return as_value(obj.get());
+ return gl->createObject(proto);
}
=== modified file 'libcore/asobj/String_as.cpp'
--- a/libcore/asobj/String_as.cpp 2009-07-29 05:59:24 +0000
+++ b/libcore/asobj/String_as.cpp 2009-08-11 08:35:50 +0000
@@ -110,49 +110,8 @@
std::string _string;
};
-as_object*
-init_string_instance(Global_as& g, const std::string& val)
-{
- as_environment env(getVM(g));
-
- int swfVersion = getSWFVersion(g);
-
- boost::intrusive_ptr<as_function> ctor;
-
- if ( swfVersion < 6 ) {
- as_object* sc = getStringConstructor(g);
- if (sc) ctor = sc->to_function();
- }
- else {
- as_value clval;
-
- if (!g.get_member(NSV::CLASS_STRING, &clval) ) {
- log_debug("UNTESTED: String instantiation requested but
"
- "_global doesn't contain a 'String' symbol. Returning "
- "the NULL object.");
- return ctor.get();
- }
- else if (!clval.is_function()) {
- log_debug("UNTESTED: String instantiation requested but
"
- "_global.String is not a function (%s). Returning "
- "the NULL object.", clval);
- return ctor.get();
- }
- else {
- ctor = clval.to_as_function();
- }
- }
-
- if (!ctor.get()) return ctor.get();
-
- std::auto_ptr< std::vector<as_value> > args ( new std::vector<as_value>
);
- args->push_back(val);
- boost::intrusive_ptr<as_object> ret = ctor->constructInstance(env,
args);
-
- return ret.get();
-}
-
-void registerStringNative(as_object& global)
+void
+registerStringNative(as_object& global)
{
VM& vm = getVM(global);
vm.registerNative(as_object::tostring_method, 251, 1);
=== modified file 'libcore/asobj/String_as.h'
--- a/libcore/asobj/String_as.h 2009-07-16 08:30:06 +0000
+++ b/libcore/asobj/String_as.h 2009-08-11 08:35:50 +0000
@@ -31,15 +31,6 @@
// Initialize the global String class
void string_class_init(as_object& global, const ObjectURI& uri);
-/// Return a String instance (possibibly NULL!)
-//
-/// This function will use the native String constructor in SWF5, but
-/// any function registered by user as the _global.String for SWF6 and higher.
-/// In the second case, not finding a proper constructor might result in
-/// returning the NULL object.
-///
-as_object* init_string_instance(Global_as& g, const std::string& val);
-
void registerStringNative(as_object& global);
}
=== modified file 'libcore/asobj/flash/ui/Mouse_as.cpp'
--- a/libcore/asobj/flash/ui/Mouse_as.cpp 2009-07-28 11:58:27 +0000
+++ b/libcore/asobj/flash/ui/Mouse_as.cpp 2009-08-11 10:29:44 +0000
@@ -94,10 +94,7 @@
as_value
mouse_hide(const fn_call& fn)
{
- boost::intrusive_ptr<as_object> obj = ensureType<as_object>(fn.this_ptr);
-
movie_root& m = getRoot(fn);
-
const int success = (m.callInterface("Mouse.hide") == "true") ? 1 : 0;
// returns 1 if mouse was visible before call.
@@ -110,10 +107,7 @@
as_value
mouse_show(const fn_call& fn)
{
- boost::intrusive_ptr<as_object> obj=ensureType<as_object>(fn.this_ptr);
-
movie_root& m = getRoot(fn);
-
const int success = (m.callInterface("Mouse.show") == "true") ? 1 : 0;
// returns 1 if Mouse was visible before call.
=== modified file 'libcore/vm/ASHandlers.cpp'
--- a/libcore/vm/ASHandlers.cpp 2009-07-30 13:11:28 +0000
+++ b/libcore/vm/ASHandlers.cpp 2009-08-11 10:29:24 +0000
@@ -76,24 +76,15 @@
namespace gnash {
+namespace {
+
+ as_object* construct_object(as_function* ctor_as_func, as_environment& env,
+ unsigned int nargs);
+ as_object* convertToObject(Global_as& gl, const as_value& val);
+}
+
namespace SWF { // gnash::SWF
-//
-// Utility: construct an object using given constructor.
-// This is used by both ActionNew and ActionNewMethod and
-// hides differences between builtin and actionscript-defined
-// constructors.
-//
-static boost::intrusive_ptr<as_object>
-construct_object(as_function* ctor_as_func,
- as_environment& env, unsigned int nargs)
-{
- assert(ctor_as_func);
- std::auto_ptr< std::vector<as_value> > args (new std::vector<as_value> );
- args->reserve(nargs);
- for (unsigned int i=0; i<nargs; ++i) args->push_back(env.pop());
- return ctor_as_func->constructInstance(env, args);
-}
static void unsupported_action_handler(ActionExec& thread)
@@ -1411,7 +1402,7 @@
// Get the "instance"
boost::intrusive_ptr<as_object> instance =
- env.top(0).to_object(*getGlobal(thread.env));
+ convertToObject(*getGlobal(thread.env), env.top(0));
// Get the "super" function
as_function* super = env.top(1).to_as_function();
@@ -1454,10 +1445,8 @@
// TODO: This doesn't work quite right, yet.
as_environment& env = thread.env;
-
-
as_value objval = env.pop();
- as_object *obj = objval.to_object(*getGlobal(thread.env)).get();
+ as_object *obj = convertToObject(*getGlobal(thread.env), objval);
int count = static_cast<int>(env.pop().to_number());
as_value a(1);
@@ -1478,7 +1467,7 @@
);
return;
}
- obj = protoval.to_object(*getGlobal(thread.env)).get();
+ obj = convertToObject(*getGlobal(thread.env), protoval);
if (!obj)
{
IF_VERBOSE_ASCODING_ERRORS(
@@ -1500,7 +1489,7 @@
{
as_value ctorval = env.pop();
- as_object* ctor = ctorval.to_object(*getGlobal(thread.env)).get();
+ as_object* ctor = convertToObject(*getGlobal(thread.env), ctorval);
if ( ! ctor )
{
IF_VERBOSE_ASCODING_ERRORS(
@@ -1515,7 +1504,7 @@
);
continue;
}
- as_object *inter = protoval.to_object(*getGlobal(thread.env)).get();
+ as_object *inter = convertToObject(*getGlobal(thread.env), protoval);
if ( ! inter )
{
IF_VERBOSE_ASCODING_ERRORS(
@@ -2638,11 +2627,11 @@
}
else {
as_value target = thread.getVariable(path);
- obj = target.to_object(*getGlobal(thread.env));
+ obj = convertToObject(*getGlobal(thread.env), target);
propertyname = var;
}
}
- else obj = env.top(1).to_object(*getGlobal(thread.env));
+ else obj = convertToObject(*getGlobal(thread.env), env.top(1));
if (!obj)
{
@@ -2684,7 +2673,7 @@
// Otherwise see if it's an object and delete it.
as_value target = thread.getVariable(path);
- boost::intrusive_ptr<as_object> obj =
target.to_object(*getGlobal(thread.env));
+ boost::intrusive_ptr<as_object> obj =
convertToObject(*getGlobal(thread.env), target);
if (!obj)
{
@@ -2744,7 +2733,7 @@
log_error(_("ActionCallFunction: function name %s evaluated to "
"non-function value %s"), funcname, function);
// Calling super ?
- boost::intrusive_ptr<as_object> obj =
function.to_object(*getGlobal(thread.env));
+ boost::intrusive_ptr<as_object> obj =
convertToObject(*getGlobal(thread.env), function);
this_ptr = thread.getThisPointer();
if (!obj->get_member(NSV::PROP_CONSTRUCTOR, &function) )
{
@@ -2862,22 +2851,22 @@
return;
}
- boost::intrusive_ptr<as_object> newobj =
construct_object(constructor.get(),
- env, nargs);
-
+ // It is possible for constructors to fail, for instance if a
+ // conversion to object calls a built-in constructor that has been
+ // deleted. BitmapData also fails to construct anything under
+ // some circumstances.
+ try {
+ as_object* newobj = construct_object(constructor.get(), env, nargs);
#ifdef USE_DEBUGGER
-#ifndef GNASH_USE_GC
- // WARNING: new_obj.to_object(*getGlobal(thread.env)) can return a newly
allocated
- // thing into the intrusive_ptr, so the debugger
- // will be left with a deleted object !!
- // Rob: we don't want to use void pointers here..
- newobj->add_ref(); // this will leak, but at least debugger won't end up
- // with a dangling reference...
-#endif //ndef GNASH_USE_GC
- debugger.addSymbol(newobj.get(), classname);
+ debugger.addSymbol(newobj, classname);
#endif
-
- env.push(as_value(newobj));
+ env.push(newobj);
+ return;
+ }
+ catch (GnashException& ) {
+ env.push(as_value());
+ return;
+ }
}
@@ -2913,7 +2902,7 @@
// Call the array constructor, to create an empty array.
as_value result = array_new(fn_call(NULL, env));
- boost::intrusive_ptr<as_object> ao =
result.to_object(*getGlobal(thread.env));
+ boost::intrusive_ptr<as_object> ao =
convertToObject(*getGlobal(thread.env), result);
assert(ao);
// Fill the elements with the initial values from the stack.
@@ -3020,7 +3009,7 @@
env.top(0).set_undefined();
- const boost::intrusive_ptr<as_object> obj =
variable.to_object(*getGlobal(thread.env));
+ const boost::intrusive_ptr<as_object> obj =
convertToObject(*getGlobal(thread.env), variable);
if ( !obj || !variable.is_object() )
{
IF_VERBOSE_ASCODING_ERRORS(
@@ -3235,7 +3224,7 @@
as_value member_name = env.top(0);
as_value target = env.top(1);
- boost::intrusive_ptr<as_object> obj =
target.to_object(*getGlobal(thread.env));
+ boost::intrusive_ptr<as_object> obj =
convertToObject(*getGlobal(thread.env), target);
if (!obj)
{
IF_VERBOSE_ASCODING_ERRORS(
@@ -3280,7 +3269,7 @@
as_environment& env = thread.env;
- boost::intrusive_ptr<as_object> obj =
env.top(2).to_object(*getGlobal(thread.env));
+ boost::intrusive_ptr<as_object> obj =
convertToObject(*getGlobal(thread.env), env.top(2));
const std::string& member_name = env.top(1).to_string();
const as_value& member_value = env.top(0);
@@ -3371,7 +3360,7 @@
bool hasMethodName = ((!method_name.is_undefined()) &&
(!method_string.empty()) );
- boost::intrusive_ptr<as_object> obj =
obj_value.to_object(*getGlobal(thread.env));
+ boost::intrusive_ptr<as_object> obj =
convertToObject(*getGlobal(thread.env), obj_value);
if (!obj) {
// SWF integrity check
IF_VERBOSE_ASCODING_ERRORS(
@@ -3501,7 +3490,7 @@
nargs = available_args;
}
- boost::intrusive_ptr<as_object> obj =
obj_val.to_object(*getGlobal(thread.env));
+ boost::intrusive_ptr<as_object> obj =
convertToObject(*getGlobal(thread.env), obj_val);
if (!obj) {
// SWF integrity check
// FIXME, should this be log_swferror? Or log_aserror?
@@ -3543,10 +3532,19 @@
}
// Construct the object
- boost::intrusive_ptr<as_object> new_obj = construct_object(method.get(),
- env, nargs);
-
- env.push(as_value(new_obj));
+ // It is possible for constructors to fail, for instance if a
+ // conversion to object calls a built-in constructor that has been
+ // deleted. BitmapData also fails to construct anything under
+ // some circumstances.
+ try {
+ as_object* newobj = construct_object(method.get(), env, nargs);
+ env.push(newobj);
+ return;
+ }
+ catch (GnashException& ) {
+ env.push(as_value());
+ return;
+ }
}
@@ -3557,10 +3555,11 @@
as_environment& env = thread.env;
// Get the "super" function
- as_object* super = env.top(0).to_object(*getGlobal(thread.env)).get();
+ as_object* super = convertToObject(*getGlobal(thread.env), env.top(0));
// Get the "instance" (but avoid implicit conversion of primitive values!)
- as_object* instance = env.top(1).is_object() ?
env.top(1).to_object(*getGlobal(thread.env)).get() : NULL;
+ as_object* instance = env.top(1).is_object() ?
+ convertToObject(*getGlobal(thread.env), env.top(1)) : NULL;
// Invalid args!
if (!super || ! instance) {
@@ -3593,7 +3592,7 @@
// as we copied that as_value.
env.top(0).set_undefined();
- const boost::intrusive_ptr<as_object> obj =
obj_val.to_object(*getGlobal(thread.env));
+ const boost::intrusive_ptr<as_object> obj =
convertToObject(*getGlobal(thread.env), obj_val);
if ( !obj || !obj_val.is_object() )
{
IF_VERBOSE_ASCODING_ERRORS(
@@ -3866,11 +3865,11 @@
env.push(function_value);
}
#ifdef USE_DEBUGGER
- // WARNING: function_value.to_object(*getGlobal(thread.env)) can return a
newly allocated
+ // WARNING: convertToObject(*getGlobal(thread.env), function_value) can
return a newly allocated
// thing into the intrusive_ptr, so the debugger
// will be left with a deleted object !!
// Rob: we don't want to use void pointers here..
- boost::intrusive_ptr<as_object> o =
function_value.to_object(*getGlobal(thread.env));
+ boost::intrusive_ptr<as_object> o =
convertToObject(*getGlobal(thread.env), function_value);
#ifndef GNASH_USE_GC
o->add_ref(); // this will leak, but at least debugger won't end up
// with a dangling reference...
@@ -3949,9 +3948,9 @@
assert(thread.atActionTag(SWF::ACTION_WITH));
#endif
-
- as_value with_obj_val = env.pop().to_object(*getGlobal(thread.env));
- boost::intrusive_ptr<as_object> with_obj =
with_obj_val.to_object(*getGlobal(thread.env));
+ as_value with_obj_val = convertToObject(*getGlobal(thread.env), env.pop());
+ boost::intrusive_ptr<as_object> with_obj =
+ convertToObject(*getGlobal(thread.env), with_obj_val);
++pc; // skip tag code
@@ -4067,11 +4066,11 @@
//env.set_member(name, function_value);
thread.setVariable(name, function_value);
#ifdef USE_DEBUGGER
- // WARNING: new_obj.to_object(*getGlobal(thread.env)) can return a
newly allocated
+ // WARNING: convertToObject(*getGlobal(thread.env), new_obj) can
return a newly allocated
// thing into the intrusive_ptr, so the debugger
// will be left with a deleted object !!
// Rob: we don't want to use void pointers here..
- boost::intrusive_ptr<as_object> o =
function_value.to_object(*getGlobal(thread.env));
+ boost::intrusive_ptr<as_object> o =
convertToObject(*getGlobal(thread.env), function_value);
#ifndef GNASH_USE_GC
o->add_ref(); // this will leak, but at least debugger won't end up
// with a dandling reference...
@@ -4146,4 +4145,38 @@
} // namespace gnash::SWF
+/// Helper functions.
+namespace {
+
+as_object*
+convertToObject(Global_as& gl, const as_value& val)
+{
+
+ try {
+ return val.to_object(gl).get();
+ }
+ catch (const GnashException& gl) {
+ return 0;
+ }
+
+}
+
+// Utility: construct an object using given constructor.
+// This is used by both ActionNew and ActionNewMethod and
+// hides differences between builtin and actionscript-defined
+// constructors.
+as_object*
+construct_object(as_function* ctor_as_func, as_environment& env,
+ unsigned int nargs)
+{
+ assert(ctor_as_func);
+ std::auto_ptr<std::vector<as_value> > args(new std::vector<as_value>);
+ args->reserve(nargs);
+ for (size_t i=0; i<nargs; ++i) args->push_back(env.pop());
+ return ctor_as_func->constructInstance(env, args).get();
+}
+
+}
+
+
} // namespace gnash
=== modified file 'testsuite/actionscript.all/Object.as'
--- a/testsuite/actionscript.all/Object.as 2009-02-25 22:33:03 +0000
+++ b/testsuite/actionscript.all/Object.as 2009-08-11 11:45:26 +0000
@@ -220,6 +220,23 @@
check_equals( obj3.test, 4 );
check (copy.__proto__.constructor == Object);
+o = new Object("hello");
+check_equals(o.toString(), "hello");
+check_equals(o.valueOf(), "hello");
+
+o = new Object(5);
+check_equals(o.toString(), "5");
+check_equals(o.valueOf(), 5);
+
+o = new Object(undefined);
+check_equals(o.toString(), "[object Object]");
+check_equals(typeof(o.valueOf()), "object");
+check_equals(o.valueOf(), o);
+
+o = new Object(null);
+check_equals(o.toString(), "[object Object]");
+check_equals(typeof(o.valueOf()), "object");
+check_equals(o.valueOf(), o);
//---------------------------------------------
// Test addProperty / hasOwnProperty (SWF6 up)
@@ -901,11 +918,42 @@
check_equals(resolveCalled, 3);
check_equals(result, "quibbleDibblePropertyWithASillyName");
+////////////////////////////////
+
+// Messing about here with global classes may ruin later tests, so don't add
+// them after this.
+
+s = "hi";
+n = 7;
+b = true;
+
+delete String;
+
+o = new Object(s);
+check_equals(typeof(o), "undefined");
+o = new Object(n);
+check_equals(typeof(o), "object");
+check_equals(o.toString(), "7");
+o = new Object(b);
+check_equals(typeof(o), "object");
+check_equals(o.toString(), "true");
+
+delete Number;
+o = new Object(n);
+check_equals(typeof(o), "undefined");
+o = new Object(b);
+check_equals(typeof(o), "object");
+check_equals(o.toString(), "true");
+
+delete Boolean;
+o = new Object(b);
+check_equals(typeof(o), "undefined");
+
#if OUTPUT_VERSION <= 5
-totals(97);
+totals(116);
#endif
#if OUTPUT_VERSION >= 6
-totals(285);
+totals(304);
#endif
=== modified file 'testsuite/swfdec/PASSING'
--- a/testsuite/swfdec/PASSING 2009-08-06 11:05:32 +0000
+++ b/testsuite/swfdec/PASSING 2009-08-11 11:45:26 +0000
@@ -309,6 +309,10 @@
crash-0.9.1-getvariable-shapes-6.swf:45e434a401447915500c275c238b8ac0
crash-0.9.1-getvariable-shapes-7.swf:49f7609f50e4099528b3477b7124834c
crash-0.9.1-getvariable-shapes-8.swf:9827e209d6bf155d49fcdb4e15cf0442
+crash-0.9.2-beginBitmapFill-5.swf:74a978aa8c54e52be6491d897b0fa501
+crash-0.9.2-beginBitmapFill-6.swf:58c7f18522fb4fef1a128ca9ca3e7397
+crash-0.9.2-beginBitmapFill-7.swf:9feed2ef6a0b3aa28a66e9ff32b39889
+crash-0.9.2-beginBitmapFill-8.swf:c5bc166548d2832ac84f68767930014b
createTextField-returnvalue-6.swf:876f64cb4349313be58d1b9de5ca2ff4
createTextField-returnvalue-7.swf:397473c78af05cbb9e7e394ec4ce1a07
createTextField-returnvalue-8.swf:398e15cdabb4c9f9bdb56ee5b07e5126
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Gnash-commit] /srv/bzr/gnash/trunk r11405: Clean up and make object conversion more consistent (and correct);,
Benjamin Wolsey <=