[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gnash-commit] /srv/bzr/gnash/trunk r11343: Fix a bug. Correct some prop
From: |
Benjamin Wolsey |
Subject: |
[Gnash-commit] /srv/bzr/gnash/trunk r11343: Fix a bug. Correct some properties for swfdec testsuite passes. |
Date: |
Thu, 30 Jul 2009 17:47:14 +0200 |
User-agent: |
Bazaar (1.13.1) |
------------------------------------------------------------
revno: 11343
committer: Benjamin Wolsey <address@hidden>
branch nick: trunk
timestamp: Thu 2009-07-30 17:47:14 +0200
message:
Fix a bug. Correct some properties for swfdec testsuite passes.
added:
testsuite/as3compile.all/Object.as
modified:
libbase/GnashAlgorithm.h
libcore/PropertyList.cpp
libcore/as_object.cpp
libcore/as_object.h
libcore/asobj/Globals.cpp
libcore/asobj/Object.cpp
libcore/asobj/Object.h
libcore/vm/ASHandlers.cpp
testsuite/as3compile.all/Makefile.am
testsuite/swfdec/PASSING
------------------------------------------------------------
revno: 11342.1.1
committer: Benjamin Wolsey <address@hidden>
branch nick: temp
timestamp: Thu 2009-07-30 12:36:03 +0200
message:
Test AVM2 Object.
modified:
testsuite/as3compile.all/Makefile.am
------------------------------------------------------------
revno: 11342.1.2
committer: Benjamin Wolsey <address@hidden>
branch nick: temp
timestamp: Thu 2009-07-30 13:20:20 +0200
message:
Add Object test, notes, more tests.
added:
testsuite/as3compile.all/Object.as
modified:
libcore/PropertyList.cpp
------------------------------------------------------------
revno: 11342.1.3
committer: Benjamin Wolsey <address@hidden>
branch nick: temp
timestamp: Thu 2009-07-30 13:33:29 +0200
message:
Register object natives separately. Get registerClass properties correct.
modified:
libcore/asobj/Globals.cpp
libcore/asobj/Object.cpp
libcore/asobj/Object.h
------------------------------------------------------------
revno: 11342.1.4
committer: Benjamin Wolsey <address@hidden>
branch nick: temp
timestamp: Thu 2009-07-30 14:21:34 +0200
message:
Correct Object properties. Add constructor also for VM opcode, though it
currently doesn't have the correct value.
modified:
libcore/asobj/Object.cpp
libcore/vm/ASHandlers.cpp
------------------------------------------------------------
revno: 11342.1.5
committer: Benjamin Wolsey <address@hidden>
branch nick: temp
timestamp: Thu 2009-07-30 15:11:28 +0200
message:
Get object properties correct.
modified:
libcore/asobj/Object.cpp
libcore/vm/ASHandlers.cpp
------------------------------------------------------------
revno: 11342.1.6
committer: Benjamin Wolsey <address@hidden>
branch nick: temp
timestamp: Thu 2009-07-30 15:51:21 +0200
message:
Passing tests.
modified:
testsuite/swfdec/PASSING
------------------------------------------------------------
revno: 11342.1.7
committer: Benjamin Wolsey <address@hidden>
branch nick: temp
timestamp: Thu 2009-07-30 17:20:46 +0200
message:
Don't erase Triggers from the container while they are still being
accessed.
use a flag instead. Fixes a memory error that's been in Gnash at least
since
0.8.5.
modified:
libbase/GnashAlgorithm.h
libcore/as_object.cpp
libcore/as_object.h
=== modified file 'libbase/GnashAlgorithm.h'
--- a/libbase/GnashAlgorithm.h 2009-04-15 15:30:11 +0000
+++ b/libbase/GnashAlgorithm.h 2009-07-30 15:20:46 +0000
@@ -72,6 +72,22 @@
typedef typename RemovePointer<T>::value_type value_type;
};
+/// Erase elements from an associative container based on a predicate
+//
+/// This removes elements from a container such as a map if they fulfil a
+/// particular condition. Because keys of associative container are const,
+/// we can't do this using iterators, because we can't write to them.
+template<typename Container, typename Predicate>
+void EraseIf(Container& c, Predicate p)
+{
+ typedef typename Container::iterator iterator;
+
+ for (iterator i = c.begin(), e = c.end(); i != e; ) {
+ iterator stored = i++;
+ if (p(*stored)) c.erase(stored);
+ }
+}
+
/// Delete a pointer safely
=== modified file 'libcore/PropertyList.cpp'
--- a/libcore/PropertyList.cpp 2009-07-29 14:33:56 +0000
+++ b/libcore/PropertyList.cpp 2009-07-30 11:20:20 +0000
@@ -31,6 +31,7 @@
#include "string_table.h"
#include <utility> // for std::make_pair
+#include <boost/bind.hpp>
// Define the following to enable printing address of each property added
//#define DEBUG_PROPERTY_ALLOC
@@ -540,12 +541,9 @@
void
PropertyList::setReachable() const
{
- for (container::const_iterator it = _props.begin();
- it != _props.end(); ++it)
- {
- it->setReachable();
- }
+ std::for_each(_props.begin(), _props.end(),
+ boost::mem_fn(&Property::setReachable));
}
-} // end of gnash namespace
+} // namespace gnash
=== modified file 'libcore/as_object.cpp'
--- a/libcore/as_object.cpp 2009-07-29 14:33:56 +0000
+++ b/libcore/as_object.cpp 2009-07-30 15:20:46 +0000
@@ -37,6 +37,7 @@
#include "Array_as.h"
#include "as_function.h"
#include "Global_as.h"
+#include "GnashAlgorithm.h"
#include <set>
#include <string>
@@ -585,7 +586,6 @@
return NULL;
}
-/*protected*/
void
as_object::set_prototype(boost::intrusive_ptr<as_object> proto, int flags)
{
@@ -642,6 +642,11 @@
Trigger& trig = trigIter->second;
+ if (trig.dead()) {
+ _trigs.erase(trigIter);
+ return;
+ }
+
// WARNING: getValue might itself invoke a trigger
// (getter-setter)... ouch ?
// TODO: in this case, return the underlying value !
@@ -653,7 +658,11 @@
getStringTable(*this).value(getName(uri)), curVal, val);
as_value newVal = trig.call(curVal, val, *this);
-
+
+ // This is a particularly clear and concise way of removing dead triggers.
+ EraseIf(_trigs, boost::bind(boost::mem_fn(&Trigger::dead),
+ boost::bind(SecondElement<TriggerContainer::value_type>(), _1)));
+
// The trigger call could have deleted the property,
// so we check for its existance again, and do NOT put
// it back in if it was deleted
@@ -666,7 +675,7 @@
}
prop->setValue(*this, newVal);
prop->clearVisible(getSWFVersion(*this));
-
+
}
// Handles read_only and static properties properly.
@@ -1362,7 +1371,7 @@
getStringTable(*this).value(key));
return false;
}
- _trigs.erase(trigIter);
+ trigIter->second.kill();
return true;
}
@@ -1391,6 +1400,8 @@
Trigger::call(const as_value& oldval, const as_value& newval,
as_object& this_obj)
{
+ assert(!_dead);
+
if ( _executing ) return newval;
_executing = true;
=== modified file 'libcore/as_object.h'
--- a/libcore/as_object.h 2009-07-29 14:33:56 +0000
+++ b/libcore/as_object.h 2009-07-30 15:20:46 +0000
@@ -67,25 +67,6 @@
/// A trigger that can be associated with a property name
class Trigger
{
- /// Name of the property
- //
- /// By storing a string_table::key we'd save CPU cycles
- /// while adding/removing triggers and some memory
- /// on each trigger, but at the cost of looking up
- /// the string_table on every invocation of the watch...
- ///
- std::string _propname;
-
- /// The trigger function
- as_function* _func;
-
- /// A custom argument to pass to the trigger
- /// after old and new value.
- as_value _customArg;
-
- /// Flag to protect from infinite loops
- bool _executing;
-
public:
Trigger(const std::string& propname, as_function& trig,
@@ -94,7 +75,8 @@
_propname(propname),
_func(&trig),
_customArg(customArg),
- _executing(false)
+ _executing(false),
+ _dead(false)
{}
/// Call the trigger
@@ -111,8 +93,43 @@
as_value call(const as_value& oldval, const as_value& newval,
as_object& this_obj);
+ /// True if this Trigger has been disposed of.
+ bool dead() const { return _dead; }
+
+ void kill() {
+ _dead = true;
+ }
+
void setReachable() const;
+private:
+
+ /// Name of the property
+ //
+ /// By storing a string_table::key we'd save CPU cycles
+ /// while adding/removing triggers and some memory
+ /// on each trigger, but at the cost of looking up
+ /// the string_table on every invocation of the watch...
+ ///
+ std::string _propname;
+
+ /// The trigger function
+ as_function* _func;
+
+ /// A custom argument to pass to the trigger
+ /// after old and new value.
+ as_value _customArg;
+
+ /// Flag to protect from infinite loops
+ bool _executing;
+
+ /// Flag to check whether this trigger has been deleted.
+ //
+ /// As a trigger can be removed during execution, it shouldn't be
+ /// erased from the container straight away, so this flag prevents
+ /// any execution.
+ bool _dead;
+
};
/// A URI for describing as_objects.
=== modified file 'libcore/asobj/Globals.cpp'
--- a/libcore/asobj/Globals.cpp 2009-07-29 14:55:35 +0000
+++ b/libcore/asobj/Globals.cpp 2009-07-30 11:33:29 +0000
@@ -1159,6 +1159,7 @@
vm.registerNative(global_setInterval, 250, 0);
vm.registerNative(global_clearInterval, 250, 1);
+ registerObjectNative(global);
registerStringNative(global);
registerArrayNative(global);
registerMovieClipNative(global);
=== modified file 'libcore/asobj/Object.cpp'
--- a/libcore/asobj/Object.cpp 2009-07-29 05:40:20 +0000
+++ b/libcore/asobj/Object.cpp 2009-07-30 13:11:28 +0000
@@ -61,31 +61,51 @@
return new as_object(getObjectInterface());
}
+void registerObjectNative(as_object& global)
+{
+ VM& vm = getVM(global);
+
+ vm.registerNative(object_watch, 101, 0);
+ vm.registerNative(object_unwatch, 101, 1);
+ vm.registerNative(object_addproperty, 101, 2);
+ vm.registerNative(as_object::valueof_method, 101, 3);
+ vm.registerNative(as_object::tostring_method, 101, 4);
+ vm.registerNative(object_hasOwnProperty, 101, 5);
+ vm.registerNative(object_isPrototypeOf, 101, 6);
+ vm.registerNative(object_isPropertyEnumerable, 101, 7);
+ vm.registerNative(object_registerClass, 101, 8);
+ vm.registerNative(object_ctor, 101, 9);
+}
// extern (used by Global.cpp)
-void object_class_init(as_object& global, const ObjectURI& uri)
+void
+object_class_init(as_object& where, const ObjectURI& uri)
{
// This is going to be the global Object "class"/"function"
static boost::intrusive_ptr<as_object> cl=NULL;
- VM& vm = getVM(global);
-
if ( cl == NULL )
{
- Global_as* gl = getGlobal(global);
+ Global_as* gl = getGlobal(where);
as_object* proto = getObjectInterface();
- cl = gl->createClass(&object_ctor, proto);
-
- // Object.registerClass() --
- // TODO: should this only be in SWF6 or higher ?
- vm.registerNative(object_registerClass, 101, 8);
- cl->init_member("registerClass", vm.getNative(101, 8));
+ cl = gl->createClass(object_ctor, proto);
+
+ // The as_function ctor takes care of initializing these, but they
+ // are different for the Object class.
+ const int readOnly = PropFlags::readOnly;
+ cl->set_member_flags(NSV::PROP_uuPROTOuu, readOnly);
+ cl->set_member_flags(NSV::PROP_CONSTRUCTOR, readOnly);
+ cl->set_member_flags(NSV::PROP_PROTOTYPE, readOnly);
+
+ VM& vm = getVM(where);
+ const int flags = as_object::DefaultFlags | PropFlags::readOnly;
+ cl->init_member("registerClass", vm.getNative(101, 8), flags);
}
// Register _global.Object (should only be visible in SWF5 up)
int flags = PropFlags::dontEnum;
- global.init_member(getName(uri), cl.get(), flags, getNamespace(uri));
+ where.init_member(getName(uri), cl.get(), flags, getNamespace(uri));
}
@@ -113,22 +133,18 @@
VM& vm = getVM(o);
// We register natives despite swf version,
-
- vm.registerNative(object_watch, 101, 0);
- vm.registerNative(object_unwatch, 101, 1);
- vm.registerNative(object_addproperty, 101, 2);
- vm.registerNative(as_object::valueof_method, 101, 3);
- vm.registerNative(as_object::tostring_method, 101, 4);
- vm.registerNative(object_hasOwnProperty, 101, 5);
- vm.registerNative(object_isPrototypeOf, 101, 6);
- vm.registerNative(object_isPropertyEnumerable, 101, 7);
-
Global_as* gl = getGlobal(o);
o.init_member("valueOf", vm.getNative(101, 3));
o.init_member("toString", vm.getNative(101, 4));
+
+ as_object* lsProto = getObjectInterface();
+
+ // TODO: this is probably an abuse of the 'createClass' function, but it
+ // gets the correct results.
o.init_member("toLocaleString",
- gl->createFunction(object_toLocaleString));
+ gl->createClass(object_toLocaleString,
+ gl->createObject(lsProto)));
int swf6flags = PropFlags::dontEnum |
PropFlags::dontDelete |
@@ -146,30 +162,30 @@
as_value
object_ctor(const fn_call& fn)
{
- if ( fn.nargs == 1 ) // copy constructor
- {
-
- as_object* obj = fn.arg(0).to_object(*getGlobal(fn)).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.
+ Global_as* gl = getGlobal(fn);
+
+ 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 (fn.nargs)
- {
+ 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());
+ if (!fn.isInstantiation()) {
+ return gl->createObject();;
+ }
+
+ as_object* proto = getObjectInterface();
+ boost::intrusive_ptr<as_object> obj = gl->createObject(proto);
return as_value(obj.get());
}
=== modified file 'libcore/asobj/Object.h'
--- a/libcore/asobj/Object.h 2009-07-16 08:30:06 +0000
+++ b/libcore/asobj/Object.h 2009-07-30 11:33:29 +0000
@@ -33,6 +33,7 @@
as_object* getObjectInterface();
+void registerObjectNative(as_object& global);
}
=== modified file 'libcore/vm/ASHandlers.cpp'
--- a/libcore/vm/ASHandlers.cpp 2009-07-15 07:37:56 +0000
+++ b/libcore/vm/ASHandlers.cpp 2009-07-30 13:11:28 +0000
@@ -2943,19 +2943,24 @@
const int nmembers = env.pop().to_int();
- boost::intrusive_ptr<as_object> new_obj_ptr(init_object_instance());
+ // TODO: see if this could call the ASnative function(101, 9).
+ Global_as* gl = getGlobal(env);
+ as_object* proto = getObjectInterface();
+ as_object* obj = gl->createObject(proto);
+
+ obj->init_member(NSV::PROP_CONSTRUCTOR, gl->getMember(NSV::CLASS_OBJECT));
// Set provided members
for (int i = 0; i < nmembers; ++i) {
as_value member_value = env.top(0);
std::string member_name = env.top(1).to_string();
- thread.setObjectMember(*new_obj_ptr, member_name, member_value);
+ thread.setObjectMember(*obj, member_name, member_value);
env.drop(2);
}
as_value new_obj;
- new_obj.set_as_object(new_obj_ptr.get());
+ new_obj.set_as_object(obj);
env.push(new_obj);
=== modified file 'testsuite/as3compile.all/Makefile.am'
--- a/testsuite/as3compile.all/Makefile.am 2009-07-29 13:41:03 +0000
+++ b/testsuite/as3compile.all/Makefile.am 2009-07-30 10:36:03 +0000
@@ -29,6 +29,7 @@
QName.as \
System.as \
Keyboard.as \
+ Object.as \
$(NULL)
BOGUS_AS3TESTS = \
=== added file 'testsuite/as3compile.all/Object.as'
--- a/testsuite/as3compile.all/Object.as 1970-01-01 00:00:00 +0000
+++ b/testsuite/as3compile.all/Object.as 2009-07-30 11:20:20 +0000
@@ -0,0 +1,85 @@
+//
+// Copyright (C) 2005, 2006, 2007, 2009 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+#include "check.as"
+
+// Important points about the AS3 Object class:
+//
+// prototype is a static, read-only property. It doesn't have the same
+// role in AS3 as in AS2. You can assign properties to the prototype
+// member, but you cannot change what it points to.
+//
+// The prototype property provides dynamic inheritance. Normally, inheritance
+// is done using a Traits object (bytecode, not available to AS). These two
+// mechanisms are separate.
+
+package main {
+
+ import flash.display.MovieClip;
+
+ public class Main extends MovieClip {
+
+
+ DEJAGNU_OBJ;
+
+ public function Main() {
+
+ xcheck_equals(Object, "[class Object]");
+ xcheck_equals(Object.prototype, "[object Object]");
+ xcheck_equals(Object.constructor, "[class Class]");
+
+ xcheck_equals(typeof(Object), "object");
+ check_equals(typeof(Object.prototype), "object");
+ xcheck_equals(typeof(Object.constructor), "object");
+
+ check(Object.prototype.hasOwnProperty("constructor"));
+ check(Object.prototype.hasOwnProperty("hasOwnProperty"));
+ check(Object.prototype.hasOwnProperty("isPrototypeOf"));
+ xcheck(Object.prototype.hasOwnProperty("propertyIsEnumerable"));
+ xcheck(Object.prototype.hasOwnProperty("setPropertyIsEnumerable"));
+ check(Object.prototype.hasOwnProperty("toString"));
+ check(Object.prototype.hasOwnProperty("valueOf"));
+
+ check(!Object.prototype.hasOwnProperty("__proto__"));
+ check(!Object.prototype.hasOwnProperty("prototype"));
+
+ xcheck(Object.prototype.isPrototypeOf(MovieClip));
+ xcheck(Object.prototype.isPrototypeOf(this));
+
+ var a = new Object();
+ xcheck_equals(a, "[object Object]");
+ check(!a.hasOwnProperty("constructor"));
+ check(!a.hasOwnProperty("hasOwnProperty"));
+ check(!a.hasOwnProperty("isPrototypeOf"));
+ check(!a.hasOwnProperty("propertyIsEnumerable"));
+ check(!a.hasOwnProperty("setPropertyIsEnumerable"));
+ check(!a.hasOwnProperty("toString"));
+ check(!a.hasOwnProperty("valueOf"));
+
+ xcheck(!a.hasOwnProperty("__proto__"));
+ check(!a.hasOwnProperty("prototype"));
+
+ // This crashes the Adobe player 9.
+ // check(Object.isPrototypeOf(this));
+
+
+ totals(27);
+ done();
+ }
+ }
+}
+
=== modified file 'testsuite/swfdec/PASSING'
--- a/testsuite/swfdec/PASSING 2009-07-10 08:33:22 +0000
+++ b/testsuite/swfdec/PASSING 2009-07-30 13:51:21 +0000
@@ -546,6 +546,9 @@
instance-name-loaded-5.swf:507414bb411ba30305034cf3078e5fa2
instance-name-loaded-6.swf:d5fbbda201d50d6bf121b7c1a78ad3c8
instance-name-loaded-7.swf:f4b4cf3a25a0010b7ff13a56a42d1aad
+instance-of-6.swf:23b56f183fbfddfb3eb7ee074f866035
+instance-of-7.swf:72c7b030a462019116bd6551153f5142
+instance-of-8.swf:fc26462c07bac41c57f3ecaabe9f5ffd
instance-of-propflags-5.swf:1cab145faaa9544b3b1488c09f6639e5
instance-of-propflags-8.swf:af7c2eee7fa1e572ff330d03d936d959
instance-of-propflags-9.swf:b125071d54db67ae00035fc87ba37a9b
@@ -721,6 +724,10 @@
object-math-5.swf:2d509f7b6e94776a2208fcbec80b7a67
object-math-6.swf:bdf73b4bfb144113a80ff78a282558d7
object-math-7.swf:15d6cb896cc58fe289ed0e6de39b3347
+object-properties-5.swf:86727344c3b46a88d41163cd01b26337
+object-properties-6.swf:c34734222b0c6eef649ab3b92b1b830f
+object-properties-7.swf:71ebb1f47408d993409748dae8d32d5e
+object-properties-8.swf:992fafbfd6ae4927116892eb205aac0f
object-resolve-propflags-9.swf:db769008cba912cd906834a4722fdb95
object-valueof-5.swf:2520f058ac5a1af3db81ba9b3002e6ab
object-valueof-6.swf:68d80a5ba580357d1dfeb3b515691e7e
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Gnash-commit] /srv/bzr/gnash/trunk r11343: Fix a bug. Correct some properties for swfdec testsuite passes.,
Benjamin Wolsey <=