summaryrefslogtreecommitdiff
path: root/community-testing/lightspark
diff options
context:
space:
mode:
authorroot <root@rshg047.dnsready.net>2011-07-16 05:34:06 +0000
committerroot <root@rshg047.dnsready.net>2011-07-16 05:34:06 +0000
commit7500119d8dd5fc921f91aac8222e472477973740 (patch)
treea2cd26c3dd70d079a9f97fc3d5549ea649baf863 /community-testing/lightspark
parent76c26b027d797f3671bf0b6c6618eda2496cf88d (diff)
Sat Jul 16 05:34:06 UTC 2011
Diffstat (limited to 'community-testing/lightspark')
-rw-r--r--community-testing/lightspark/PKGBUILD14
-rw-r--r--community-testing/lightspark/git-fixes-set-sys-in-destroystream-class.diff1180
2 files changed, 1190 insertions, 4 deletions
diff --git a/community-testing/lightspark/PKGBUILD b/community-testing/lightspark/PKGBUILD
index 4dc7cf4cd..90e48d272 100644
--- a/community-testing/lightspark/PKGBUILD
+++ b/community-testing/lightspark/PKGBUILD
@@ -3,7 +3,7 @@
pkgname=lightspark
pkgver=0.5.0rc1
-pkgrel=1
+pkgrel=2
pkgdesc='An alternative Flash Player for Linux.'
arch=('i686' 'x86_64')
url='http://lightspark.sourceforge.net'
@@ -12,12 +12,18 @@ conflicts=('lightspark-git')
depends=('mesa' 'sdl' 'gtk2' 'curl' 'zlib' 'ffmpeg' 'glew' 'pcre' 'libpulse' 'libffi' 'boost-libs' 'glibmm' 'gtkglext' 'desktop-file-utils' 'libxml++')
makedepends=('cmake' 'nasm' 'xulrunner' 'llvm' 'glproto' 'boost')
optdepends=('gnash-gtk: fallback support')
-install="lightspark.install"
-source=("http://launchpad.net/lightspark/trunk/lightspark-0.5.0/+download/lightspark-0.5.0~rc1.tar.gz")
-md5sums=('bf668cf6178fbbb75a7898bd6c6dd1e5')
+install='lightspark.install'
+source=("http://launchpad.net/lightspark/trunk/lightspark-0.5.0/+download/lightspark-0.5.0~rc1.tar.gz"
+ 'git-fixes-set-sys-in-destroystream-class.diff')
+md5sums=('bf668cf6178fbbb75a7898bd6c6dd1e5'
+ '57b1b5a975f5e2518c2a96d61b925f41')
_pkgver='0.5.0~rc1'
build() {
+ cd lightspark-${_pkgver}
+ patch -Np1 -i ${srcdir}/git-fixes-set-sys-in-destroystream-class.diff
+ cd ${srcdir}
+
rm -rf build
mkdir build
cd build
diff --git a/community-testing/lightspark/git-fixes-set-sys-in-destroystream-class.diff b/community-testing/lightspark/git-fixes-set-sys-in-destroystream-class.diff
new file mode 100644
index 000000000..d20239d29
--- /dev/null
+++ b/community-testing/lightspark/git-fixes-set-sys-in-destroystream-class.diff
@@ -0,0 +1,1180 @@
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index f8eea6b..aae2d71 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -167,7 +167,7 @@ if(Boost_FOUND)
+ ENDIF(Boost_FOUND)
+ IF(UNIX)
+ INCLUDE(FindPkgConfig REQUIRED)
+- pkg_check_modules(EXTRA_LIBS REQUIRED x11 fontconfig cairo pangocairo)
++ pkg_check_modules(EXTRA_LIBS REQUIRED x11 cairo pangocairo)
+ ENDIF(UNIX)
+
+ IF(WIN32)
+diff --git a/conf/FindFTGL.cmake b/conf/FindFTGL.cmake
+deleted file mode 100644
+index d63178f..0000000
+--- a/conf/FindFTGL.cmake
++++ /dev/null
+@@ -1,27 +0,0 @@
+-# - Find FTGL
+-# Find the native FTGL headers and libraries.
+-#
+-# FTGL_INCLUDE_DIRS - where to find pcre.h, etc.
+-# FTGL_LIBRARIES - List of libraries when using ftgl
+-# FTGL_FOUND - True if ftgl found.
+-
+-# Look for the header file.
+-FIND_PATH(FTGL_INCLUDE_DIR NAMES FTGL/ftgl.h)
+-MARK_AS_ADVANCED(FTGL_INCLUDE_DIR)
+-
+-# Look for the library.
+-FIND_LIBRARY(FTGL_LIBRARY NAMES
+- ftgl
+- ftgl_d
+-)
+-MARK_AS_ADVANCED(FTGL_LIBRARY)
+-
+-# handle the QUIETLY and REQUIRED arguments and set FTGL_FOUND to TRUE if
+-# all listed variables are TRUE
+-INCLUDE(FindPackageHandleStandardArgs)
+-FIND_PACKAGE_HANDLE_STANDARD_ARGS(FTGL DEFAULT_MSG FTGL_LIBRARY FTGL_INCLUDE_DIR)
+-
+-IF(FTGL_FOUND)
+- SET(FTGL_LIBRARIES ${FTGL_LIBRARY})
+- SET(FTGL_INCLUDE_DIRS ${FTGL_INCLUDE_DIR})
+-ENDIF(FTGL_FOUND)
+diff --git a/src/asobject.cpp b/src/asobject.cpp
+index f2f9620..6808c14 100644
+--- a/src/asobject.cpp
++++ b/src/asobject.cpp
+@@ -556,6 +556,7 @@ ASFUNCTIONBODY(ASObject,hasOwnProperty)
+ name.name_type=multiname::NAME_STRING;
+ name.name_s=args[0]->toString();
+ name.ns.push_back(nsNameAndKind("",NAMESPACE));
++ name.isAttribute=false;
+ bool ret=obj->hasPropertyByMultiname(name, true);
+ return abstract_b(ret);
+ }
+diff --git a/src/backends/decoder.cpp b/src/backends/decoder.cpp
+index 46c25bc..279d1f7 100644
+--- a/src/backends/decoder.cpp
++++ b/src/backends/decoder.cpp
+@@ -26,7 +26,7 @@
+ #include "graphics.h"
+ #include "backends/rendering.h"
+
+-#if LIBAVUTIL_VERSION_MAJOR < 52
++#if LIBAVUTIL_VERSION_MAJOR < 51
+ #define AVMEDIA_TYPE_VIDEO CODEC_TYPE_VIDEO
+ #define AVMEDIA_TYPE_AUDIO CODEC_TYPE_AUDIO
+ #endif
+diff --git a/src/backends/netutils.cpp b/src/backends/netutils.cpp
+index ce08dbc..8e4ff6a 100644
+--- a/src/backends/netutils.cpp
++++ b/src/backends/netutils.cpp
+@@ -681,7 +681,6 @@ void Downloader::allocateBuffer(size_t size)
+ //Create buffer
+ if(buffer == NULL)
+ {
+-
+ buffer = (uint8_t*) calloc(size, sizeof(uint8_t));
+ stableBuffer = buffer;
+ setg((char*)buffer,(char*)buffer,(char*)buffer);
+@@ -690,7 +689,7 @@ void Downloader::allocateBuffer(size_t size)
+ else
+ {
+ assert(!cached);
+- intptr_t curLen = (intptr_t) (egptr()-eback());
++ intptr_t curLen = receivedLength;
+ //We have to extend the buffer, so create a new one
+ if(stableBuffer!=buffer)
+ {
+diff --git a/src/backends/rendering.cpp b/src/backends/rendering.cpp
+index ea7f5ec..b52b8f2 100644
+--- a/src/backends/rendering.cpp
++++ b/src/backends/rendering.cpp
+@@ -223,13 +223,13 @@ void* RenderThread::worker(RenderThread* th)
+ LOG(LOG_ERROR,_("glX not present"));
+ return NULL;
+ }
+- int attrib[10]={GLX_BUFFER_SIZE,24,GLX_DOUBLEBUFFER,True,None};
++ int attrib[10]={GLX_RED_SIZE, 8, GLX_GREEN_SIZE, 8, GLX_BLUE_SIZE, 8, GLX_DOUBLEBUFFER, True, None};
+ GLXFBConfig* fb=glXChooseFBConfig(d, 0, attrib, &a);
+ if(!fb)
+ {
+- attrib[2]=None;
+- fb=glXChooseFBConfig(d, 0, attrib, &a);
++ attrib[6]=None;
+ LOG(LOG_ERROR,_("Falling back to no double buffering"));
++ fb=glXChooseFBConfig(d, 0, attrib, &a);
+ }
+ if(!fb)
+ {
+diff --git a/src/backends/urlutils.cpp b/src/backends/urlutils.cpp
+index 7575e49..176b7db 100644
+--- a/src/backends/urlutils.cpp
++++ b/src/backends/urlutils.cpp
+@@ -332,14 +332,14 @@ std::string URLInfo::encode(const std::string& u, ENCODING type)
+ str += '+';
+ //Additionally ENCODE_URICOMPONENT and ENCODE_URI don't encode:
+ //- _ . ! ~ * ' ( )
+- else if((type == ENCODE_URI || ENCODE_URICOMPONENT) &&
++ else if((type == ENCODE_URI || type == ENCODE_URICOMPONENT || type == ENCODE_ESCAPE) &&
+ (u[i] == '-' || u[i] == '_' || u[i] == '.' || u[i] == '!' ||
+ u[i] == '~' || u[i] == '*' || u[i] == '\'' || u[i] == '(' ||
+ u[i] == ')'))
+ str += u[i];
+ //Additionally ENCODE_URI doesn't encode:
+ //; / ? : @ & = + $ , #
+- else if(type == ENCODE_URI &&
++ else if((type == ENCODE_URI || type == ENCODE_ESCAPE) &&
+ (u[i] == ';' || u[i] == '/' || u[i] == '?' || u[i] == ':' ||
+ u[i] == '@' || u[i] == '&' || u[i] == '=' || u[i] == '+' ||
+ u[i] == '$' || u[i] == ',' || u[i] == '#'))
+diff --git a/src/parsing/streams.cpp b/src/parsing/streams.cpp
+index 8a5d7b0..b7894b0 100644
+--- a/src/parsing/streams.cpp
++++ b/src/parsing/streams.cpp
+@@ -27,167 +27,6 @@
+
+ using namespace std;
+
+-sync_stream::sync_stream():head(0),tail(0),wait_notfull(false),wait_notempty(false),buf_size(1024*1024),failed(false),ended(false),consumed(0)
+-{
+- buffer=new char[buf_size];
+- sem_init(&mutex,0,1);
+- sem_init(&notfull,0,0);
+- sem_init(&notempty,0,0);
+- setg(buffer,buffer,buffer);
+-}
+-
+-sync_stream::~sync_stream()
+-{
+- delete[] buffer;
+- sem_destroy(&mutex);
+- sem_destroy(&notfull);
+- sem_destroy(&notempty);
+-}
+-
+-void sync_stream::stop()
+-{
+- sem_wait(&mutex);
+- failed=true;
+- if(wait_notfull)
+- {
+- wait_notfull=false;
+- sem_post(&notfull);
+- sem_wait(&mutex);
+- }
+- if(wait_notempty)
+- {
+- wait_notempty=false;
+- sem_post(&notempty);
+- sem_wait(&mutex);
+- }
+- sem_post(&mutex);
+-}
+-
+-void sync_stream::eof()
+-{
+- sem_wait(&mutex);
+- ended=true;
+- if(wait_notempty)
+- {
+- wait_notempty=false;
+- sem_post(&notempty);
+- }
+- else
+- sem_post(&mutex);
+-}
+-
+-sync_stream::pos_type sync_stream::seekoff(off_type off, ios_base::seekdir dir,ios_base::openmode mode)
+-{
+- assert(off==0);
+- //The current offset is the amount of byte completely consumed plus the amount used in the buffer
+- int ret=consumed+(gptr()-eback());
+- return ret;
+-}
+-
+-sync_stream::int_type sync_stream::underflow()
+-{
+- assert(gptr()==egptr());
+-
+- sem_wait(&mutex);
+- //First of all we add the length of the buffer to the consumed variable
+- int consumedNow=(gptr()-eback());
+- consumed+=consumedNow;
+- head+=consumedNow;
+- head%=buf_size;
+- if(failed)
+- {
+- sem_post(&mutex);
+- //Return EOF
+- return -1;
+- }
+- if(tail==head)
+- {
+- if(ended) //There is no way more data will arrive
+- {
+- sem_post(&mutex);
+- //Return EOF
+- return -1;
+- }
+- wait_notempty=true;
+- sem_post(&mutex);
+- sem_wait(&notempty);
+- if(failed || ended)
+- {
+- sem_post(&mutex);
+- //Return EOF
+- return -1;
+- }
+- }
+-
+- if(head<tail)
+- setg(buffer+head,buffer+head,buffer+tail);
+- else
+- setg(buffer+head,buffer+head,buffer+buf_size);
+-
+- //Verify that there is room
+- if(wait_notfull && ((tail-head+buf_size)%buf_size)<buf_size-1)
+- {
+- wait_notfull=true;
+- sem_post(&notfull);
+- }
+- else
+- sem_post(&mutex);
+-
+- //Cast to unsigned, otherwise 0xff would become eof
+- return (unsigned char)buffer[head];
+-}
+-
+-uint32_t sync_stream::write(char* buf, int len)
+-{
+- sem_wait(&mutex);
+- if(failed)
+- {
+- sem_post(&mutex);
+- return 0;
+- }
+- if(((tail-head+buf_size)%buf_size)==buf_size-1)
+- {
+- wait_notfull=true;
+- sem_post(&mutex);
+- sem_wait(&notfull);
+- if(failed)
+- {
+- sem_post(&mutex);
+- return 0;
+- }
+- }
+-
+- if((head-tail+buf_size-1)%buf_size<len)
+- len=(head-tail+buf_size-1)%buf_size;
+-
+- if(tail+len>buf_size)
+- {
+- int i=buf_size-tail;
+- memcpy(buffer+tail,buf,i);
+- memcpy(buffer,buf+i,len-i);
+- }
+- else
+- memcpy(buffer+tail,buf,len);
+- tail+=len;
+- tail%=buf_size;
+- assert(head!=tail);
+- if(wait_notempty)
+- {
+- wait_notempty=false;
+- sem_post(&notempty);
+- }
+- else
+- sem_post(&mutex);
+- return len;
+-}
+-
+-uint32_t sync_stream::getFree()
+-{
+- sem_wait(&mutex);
+- uint32_t freeBytes=(head-tail+buf_size-1)%buf_size;
+- sem_post(&mutex);
+- return freeBytes;
+-}
+
+ zlib_filter::zlib_filter(streambuf* b):backend(b),consumed(0)
+ {
+diff --git a/src/parsing/streams.h b/src/parsing/streams.h
+index c631e45..988dcf2 100644
+--- a/src/parsing/streams.h
++++ b/src/parsing/streams.h
+@@ -43,31 +43,6 @@ public:
+ ~zlib_filter();
+ };
+
+-class DLL_PUBLIC sync_stream: public std::streambuf
+-{
+-public:
+- sync_stream();
+- void stop();
+- void eof();
+- ~sync_stream();
+- uint32_t write(char* buf, int len);
+- uint32_t getFree();
+- virtual int_type underflow();
+- virtual pos_type seekoff(off_type, std::ios_base::seekdir, std::ios_base::openmode);
+-private:
+- char* buffer;
+- int head;
+- int tail;
+- sem_t mutex;
+- sem_t notfull;
+- sem_t notempty;
+- bool wait_notfull;
+- bool wait_notempty;
+- const int buf_size;
+- bool failed;
+- bool ended;
+- int consumed;
+-};
+
+ class bytes_buf:public std::streambuf
+ {
+diff --git a/src/plugin/plugin.cpp b/src/plugin/plugin.cpp
+index ffb578d..fd60233 100644
+--- a/src/plugin/plugin.cpp
++++ b/src/plugin/plugin.cpp
+@@ -569,6 +569,7 @@ int32_t nsPluginInstance::Write(NPStream *stream, int32_t offset, int32_t len, v
+
+ NPError nsPluginInstance::DestroyStream(NPStream *stream, NPError reason)
+ {
++ sys=m_sys;
+ NPDownloader* dl=static_cast<NPDownloader*>(stream->pdata);
+ assert(dl);
+ //Check if async destructin of this downloader has been requested
+@@ -586,6 +587,7 @@ NPError nsPluginInstance::DestroyStream(NPStream *stream, NPError reason)
+ }
+ //Notify our downloader of what happened
+ URLNotify(stream->url, reason, stream->pdata);
++ sys=NULL;
+ return NPERR_NO_ERROR;
+ }
+
+diff --git a/src/scripting/flashdisplay.cpp b/src/scripting/flashdisplay.cpp
+index bfdf846..5df6f98 100644
+--- a/src/scripting/flashdisplay.cpp
++++ b/src/scripting/flashdisplay.cpp
+@@ -323,6 +323,7 @@ void Loader::execute()
+ contentLoaderInfo->incRef();
+ //Use a local variable to store the new root, as the localRoot member may change
+ _R<RootMovieClip> newRoot=_MR(RootMovieClip::getInstance(contentLoaderInfo.getPtr()));
++ newRoot->setOrigin(url.getParsedURL(), "");
+
+ _addChildAt(newRoot,0);
+
+@@ -2972,7 +2973,10 @@ ASFUNCTIONBODY(Graphics,beginGradientFill)
+ assert_and_throw(args[2]->getObjectType()==T_ARRAY);
+ Array* alphas=Class<Array>::cast(args[2]);
+
+- assert_and_throw(args[3]->getObjectType()==T_ARRAY);
++ //assert_and_throw(args[3]->getObjectType()==T_ARRAY);
++ //Work around for bug in YouTube player of July 13 2011
++ if(args[3]->getObjectType()==T_UNDEFINED)
++ return NULL;
+ Array* ratios=Class<Array>::cast(args[3]);
+
+ int NumGradient = colors->size();
+diff --git a/src/scripting/flashgeom.cpp b/src/scripting/flashgeom.cpp
+index db5236e..660bb85 100644
+--- a/src/scripting/flashgeom.cpp
++++ b/src/scripting/flashgeom.cpp
+@@ -1127,12 +1127,12 @@ ASFUNCTIONBODY(Matrix,concat)
+
+ number_t ta, tb, tc, td, tx, ty;
+
+- ta = th->a * m->a + th->c * m->b;
+- tb = th->b * m->a + th->d * m->b;
+- tc = th->a * m->c + th->c * m->d;
+- td = th->b * m->c + th->d * m->d;
+- tx = th->a * m->tx + th->c * m->ty + th->tx;
+- ty = th->b * m->tx + th->d * m->ty + th->ty;
++ ta = m->a * th->a + m->c * th->b;
++ tb = m->b * th->a + m->d * th->b;
++ tc = m->a * th->c + m->c * th->d;
++ td = m->b * th->c + m->d * th->d;
++ tx = m->a * th->tx + m->c * th->ty + m->tx;
++ ty = m->b * th->tx + m->d * th->ty + m->ty;
+
+ th->a = ta;
+ th->b = tb;
+diff --git a/src/scripting/flashutils.cpp b/src/scripting/flashutils.cpp
+index f44b61e..04cce66 100644
+--- a/src/scripting/flashutils.cpp
++++ b/src/scripting/flashutils.cpp
+@@ -784,36 +784,52 @@ ASFUNCTIONBODY(lightspark,describeType)
+ ret+=(isStatic)?"\"true\"":"\"false\"";
+ ret+=">";
+ //TODO: add support for extendsClass and implementsInterface and factory
+- auto it=args[0]->Variables.Variables.begin();
+- for(;it!=args[0]->Variables.Variables.end();it++)
++ type=static_cast<Class_base*>(args[0]);
++ do
+ {
+- if(isStatic && it->second.kind==BORROWED_TRAIT)
+- continue;
+-
+- //TODO: add support for constant, method, parameter
+- if(it->second.var.getter)
+- {
+- //Output an accessor
+- //TODO: add support in accessor for access,type,declaredBy
+- ret+="<accessor name=\"";
+- ret+=it->first.raw_buf();
+- ret+="\"/>";
+- }
+- else if(it->second.var.var)
++ auto it=type->Variables.Variables.begin();
++ for(;it!=type->Variables.Variables.end();it++)
+ {
+- //Output a variable
+- ret+="<variable name=\"";
+- ret+=it->first.raw_buf();
+- ret+="\"";
+- if(it->second.var.type)
++ if(isStatic && it->second.kind==BORROWED_TRAIT)
++ continue;
++
++ //TODO: add support for constant, method, parameter
++ if(it->second.var.getter)
++ {
++ //Output an accessor
++ //TODO: add support in accessor for access,type,declaredBy
++ ret+="<accessor name=\"";
++ ret+=it->first.raw_buf();
++ ret+="\"/>";
++ }
++ else if(it->second.var.var)
+ {
+- ret+=" type=\"";
+- ret+=it->second.var.type->class_name.getQualifiedName().raw_buf();
+- ret+="\"";
++ if(it->second.var.var->getObjectType()==T_FUNCTION)
++ {
++ //Output a method
++ //TODO: add support in method for declaredBy,returnType
++ ret+="<method name=\"";
++ ret+=it->first.raw_buf();
++ ret+="\"/>";
++ }
++ else
++ {
++ //Output a variable
++ ret+="<variable name=\"";
++ ret+=it->first.raw_buf();
++ ret+="\"";
++ if(it->second.var.type)
++ {
++ ret+=" type=\"";
++ ret+=it->second.var.type->class_name.getQualifiedName().raw_buf();
++ ret+="\"";
++ }
++ ret+="/>";
++ }
+ }
+- ret+="/>";
+ }
+ }
++ while((type=type->getPrototype())!=NULL);
+ ret+="</type>";
+
+ return Class<XML>::getInstanceS(ret);;
+diff --git a/src/scripting/toplevel.cpp b/src/scripting/toplevel.cpp
+index c64403c..69709f5 100644
+--- a/src/scripting/toplevel.cpp
++++ b/src/scripting/toplevel.cpp
+@@ -271,6 +271,10 @@ ASFUNCTIONBODY(Array,lastIndexOf)
+
+ int unsigned i = th->data.size()-1;
+ int j;
++
++ if(argslen == 2 && std::isnan(args[1]->toNumber()))
++ return abstract_i(0);
++
+ if(argslen == 2 && args[1]->getObjectType() != T_UNDEFINED && !std::isnan(args[1]->toNumber()))
+ {
+ j = args[1]->toInt(); //Preserve sign
+@@ -314,24 +318,30 @@ ASFUNCTIONBODY(Array,shift)
+ ASFUNCTIONBODY(Array,splice)
+ {
+ Array* th=static_cast<Array*>(obj);
+-
++
+ int startIndex=args[0]->toInt();
+ int deleteCount=args[1]->toUInt();
+ int totalSize=th->data.size();
+-
+- //A negative startIndex is relative to the end
+- assert_and_throw(abs(startIndex)<totalSize);
+- startIndex=(startIndex+totalSize)%totalSize;
++ Array* ret=Class<Array>::getInstanceS();
++
++ if(totalSize)
++ {
++ //A negative startIndex is relative to the end
++ assert_and_throw(abs(startIndex)<totalSize);
++ startIndex=(startIndex+totalSize)%totalSize;
++ }
+ if((startIndex+deleteCount)>totalSize)
+ deleteCount=totalSize-startIndex;
+-
+- Array* ret=Class<Array>::getInstanceS();
+- ret->data.reserve(deleteCount);
+
+- for(int i=0;i<deleteCount;i++)
+- ret->data.push_back(th->data[startIndex+i]);
+-
+- th->data.erase(th->data.begin()+startIndex,th->data.begin()+startIndex+deleteCount);
++ if(deleteCount)
++ {
++ ret->data.reserve(deleteCount);
++
++ for(int i=0;i<deleteCount;i++)
++ ret->data.push_back(th->data[startIndex+i]);
++
++ th->data.erase(th->data.begin()+startIndex,th->data.begin()+startIndex+deleteCount);
++ }
+
+ //Insert requested values starting at startIndex
+ for(unsigned int i=2,n=0;i<argslen;i++,n++)
+@@ -982,8 +992,15 @@ ASObject* XML::getVariableByMultiname(const multiname& name, bool skip_impl)
+ return NULL;
+ }
+
++ bool isAttr=name.isAttribute;
+ const tiny_string& normalizedName=name.normalizedName();
+- if(name.isAttribute)
++ const char *buf=normalizedName.raw_buf();
++ if(normalizedName[0]=='@')
++ {
++ isAttr=true;
++ buf+=1;
++ }
++ if(isAttr)
+ {
+ //Lookup attribute
+ //TODO: support namespaces
+@@ -994,7 +1011,7 @@ ASObject* XML::getVariableByMultiname(const multiname& name, bool skip_impl)
+ xmlpp::Element* element=dynamic_cast<xmlpp::Element*>(node);
+ if(element==NULL)
+ return NULL;
+- xmlpp::Attribute* attr=element->get_attribute(normalizedName.raw_buf());
++ xmlpp::Attribute* attr=element->get_attribute(buf);
+ if(attr==NULL)
+ return NULL;
+
+@@ -1021,7 +1038,7 @@ ASObject* XML::getVariableByMultiname(const multiname& name, bool skip_impl)
+ assert_and_throw(name.ns.size()>0 && name.ns[0].name=="");
+ //Normalize the name to the string form
+ assert(node);
+- const xmlpp::Node::NodeList& children=node->get_children(normalizedName.raw_buf());
++ const xmlpp::Node::NodeList& children=node->get_children(buf);
+ xmlpp::Node::NodeList::const_iterator it=children.begin();
+
+ std::vector<_R<XML>> ret;
+@@ -1055,8 +1072,15 @@ bool XML::hasPropertyByMultiname(const multiname& name, bool considerDynamic)
+ if(considerDynamic==false)
+ return ASObject::hasPropertyByMultiname(name, considerDynamic);
+
++ bool isAttr=name.isAttribute;
+ const tiny_string& normalizedName=name.normalizedName();
+- if(name.isAttribute)
++ const char *buf=normalizedName.raw_buf();
++ if(normalizedName[0]=='@')
++ {
++ isAttr=true;
++ buf+=1;
++ }
++ if(isAttr)
+ {
+ //Lookup attribute
+ //TODO: support namespaces
+@@ -1067,7 +1091,7 @@ bool XML::hasPropertyByMultiname(const multiname& name, bool considerDynamic)
+ xmlpp::Element* element=dynamic_cast<xmlpp::Element*>(node);
+ if(element==NULL)
+ return NULL;
+- xmlpp::Attribute* attr=element->get_attribute(normalizedName.raw_buf());
++ xmlpp::Attribute* attr=element->get_attribute(buf);
+ if(attr!=NULL)
+ return true;
+ }
+@@ -1078,7 +1102,7 @@ bool XML::hasPropertyByMultiname(const multiname& name, bool considerDynamic)
+ assert_and_throw(name.ns.size()>0 && name.ns[0].name=="");
+ //Normalize the name to the string form
+ assert(node);
+- const xmlpp::Node::NodeList& children=node->get_children(normalizedName.raw_buf());
++ const xmlpp::Node::NodeList& children=node->get_children(buf);
+ if(!children.empty())
+ return true;
+ }
+diff --git a/src/swf.cpp b/src/swf.cpp
+index 6378dd6..b50907e 100644
+--- a/src/swf.cpp
++++ b/src/swf.cpp
+@@ -468,6 +468,8 @@ void SystemState::setShutdownFlag()
+ shutdown=true;
+
+ sem_post(&terminated);
++ if(standalone)
++ gtk_main_quit();
+ }
+
+ void SystemState::wait()
+@@ -1132,7 +1134,7 @@ void ParseThread::execute()
+ }
+ catch(std::exception& e)
+ {
+- LOG(LOG_ERROR,_("Stream exception in ParseThread"));
++ LOG(LOG_ERROR,_("Stream exception in ParseThread ") << e.what());
+ root->parsingFailed();
+ }
+ pt=NULL;
+diff --git a/tests/Dictionary_test.mxml b/tests/Dictionary_test.mxml
+index d0d6897..226eb94 100644
+--- a/tests/Dictionary_test.mxml
++++ b/tests/Dictionary_test.mxml
+@@ -1,57 +1,57 @@
+-<?xml version="1.0"?>
+-<mx:Application name="lightspark_Dictionary_test"
+- xmlns:mx="http://www.adobe.com/2006/mxml"
+- layout="absolute"
+- applicationComplete="appComplete();"
+- backgroundColor="white">
+-
+-<mx:Script>
+-<![CDATA[
+- import Tests;
+- private function appComplete():void
+- {
+- var dict:Dictionary = new Dictionary();
+- var o:Object = new Object();
+-
+- dict["foo"] = 5;
+- dict[o] = "muffins";
+-
+- Tests.assertTrue(dict.hasOwnProperty("foo"),"hasOwnProperty with string");
+-
+- Tests.assertEquals(dict["foo"], 5, "dict[\"foo\"] = 5", true);
+- Tests.assertEquals(dict[o], "muffins", "dict[Object]", true);
+-
+- var count:int = 0;
+- for each (var tmp:* in dict)
+- count++;
+-
+- Tests.assertEquals(2, count, "iterator: primitive and object keys");
+-
+- delete dict["foo"];
+-
+- dict[2] = "number two";
+- Tests.assertTrue(dict.hasOwnProperty(2), "hasOwnProperty with number");
+- Tests.assertEquals(dict["2"], "number two", "primitive keys behaviour", true);
+- Tests.assertFalse(dict["foo"] == 5, "delete dict[\"key\"]");
+-
+- var dict2:Dictionary = new Dictionary();
+- dict2.weakKeys = true;
+- {
+- var a:Object = new Object();
+- dict[a] = "test";
+- }
+-
+- var n:int = 0;
+- for (var key:* in dict2)
+- n++;
+-
+- Tests.assertEquals(n, 1, "Dictionary.weakKeys");
+-
+- Tests.report(visual, name);
+- }
+-]]>
+-</mx:Script>
+-
+-<mx:UIComponent id="visual" />
+-
+-</mx:Application>
++<?xml version="1.0"?>
++<mx:Application name="lightspark_Dictionary_test"
++ xmlns:mx="http://www.adobe.com/2006/mxml"
++ layout="absolute"
++ applicationComplete="appComplete();"
++ backgroundColor="white">
++
++<mx:Script>
++<![CDATA[
++ import Tests;
++ private function appComplete():void
++ {
++ var dict:Dictionary = new Dictionary();
++ var o:Object = new Object();
++
++ dict["foo"] = 5;
++ dict[o] = "muffins";
++
++ Tests.assertTrue(dict.hasOwnProperty("foo"),"hasOwnProperty with string");
++
++ Tests.assertEquals(dict["foo"], 5, "dict[\"foo\"] = 5", true);
++ Tests.assertEquals(dict[o], "muffins", "dict[Object]", true);
++
++ var count:int = 0;
++ for each (var tmp:* in dict)
++ count++;
++
++ Tests.assertEquals(2, count, "iterator: primitive and object keys");
++
++ delete dict["foo"];
++
++ dict[2] = "number two";
++ Tests.assertTrue(dict.hasOwnProperty(2), "hasOwnProperty with number");
++ Tests.assertEquals(dict["2"], "number two", "primitive keys behaviour", true);
++ Tests.assertFalse(dict["foo"] == 5, "delete dict[\"key\"]");
++
++ var dict2:Dictionary = new Dictionary();
++ dict2.weakKeys = true;
++ {
++ var a:Object = new Object();
++ dict[a] = "test";
++ }
++
++ var n:int = 0;
++ for (var key:* in dict2)
++ n++;
++
++ Tests.assertEquals(n, 1, "Dictionary.weakKeys");
++
++ Tests.report(visual, name);
++ }
++]]>
++</mx:Script>
++
++<mx:UIComponent id="visual" />
++
++</mx:Application>
+diff --git a/tests/Object_test.mxml b/tests/Object_test.mxml
+index d78adab..d057823 100644
+--- a/tests/Object_test.mxml
++++ b/tests/Object_test.mxml
+@@ -13,6 +13,11 @@
+ var o:Object = {foo: "bar", foo2: "bar2", foo: "bar3"};
+ Tests.assertEquals(o.foo2,"bar2","Simple assignment in object literal");
+ Tests.assertEquals(o.foo,"bar","Duplicated assignment in object literal");
++
++ var s:String = "Lightspark";
++ var c:Class = s.constructor;
++ Tests.assertTrue(c == String, "Constructor property");
++
+ Tests.report(visual, this.name);
+ }
+ ]]>
+diff --git a/tests/XML_test.mxml b/tests/XML_test.mxml
+index cb18282..54587d7 100644
+--- a/tests/XML_test.mxml
++++ b/tests/XML_test.mxml
+@@ -44,6 +44,9 @@
+ Tests.assertTrue(Object("123")==simplexml, "equality: string and simple XML");
+ Tests.assertTrue(Object(123)==simplexml, "equality: integer and simple XML");
+
++ var cdata:XML = new XML("<![CDATA[Lightspark]"+"]>");
++ Tests.assertEquals(cdata, "Lightspark", "Only CDATA node in file");
++
+ Tests.report(visual, this.name);
+ }
+ ]]>
+diff --git a/tests/geom_Matrix_test.mxml b/tests/geom_Matrix_test.mxml
+index 667904a..89d2a5d 100644
+--- a/tests/geom_Matrix_test.mxml
++++ b/tests/geom_Matrix_test.mxml
+@@ -1,64 +1,64 @@
+-<?xml version="1.0"?>
+-<mx:Application name="lightspark_geom_Matrix_test"
+- xmlns:mx="http://www.adobe.com/2006/mxml"
+- layout="absolute"
+- applicationComplete="appComplete();"
+- backgroundColor="white">
+-
+-<mx:Script>
+-<![CDATA[
+- import flash.display.DisplayObject;
+- import flash.display.Sprite;
+- import Tests;
+-
+- private function matrixEqual(m1:Matrix, m2:Matrix):Boolean {
+- return m1.a == m2.a && m1.b == m2.b && m1.c == m2.c && m1.d == m2.d && m1.tx == m2.tx && m1.ty == m2.ty;
+- }
+-
+- private function appComplete():void
+- {
+- var mat:Matrix = new Matrix();
+- Tests.assertTrue(mat.a == 1 && mat.b == 0 && mat.c == 0 && mat.d == 1, "new Matrix()");
+-
+- var matc:Matrix = mat.clone();
+- Tests.assertTrue(matrixEqual(mat, matc), "matrix.clone");
+-
+- var matm1:Matrix = new Matrix(1, 4, 2, 5, 3, 5);
+- var matm2:Matrix = new Matrix(2, 4, 5, 7, 9, 11);
+- var matm3:Matrix = new Matrix(10, 28, 19, 55, 34, 96);
+- matm1.concat(matm2);
+- Tests.assertTrue(matrixEqual(matm1, matm3), "matrix.concat");
+-
+- mat.a = 50; mat.b = 60; mat.c = 5; mat.d = 100;
+- mat.identity();
+- Tests.assertTrue(mat.a == 1 && mat.b == 0 && mat.c == 0 && mat.d == 1, "Matrix.identity");
+-
+- var mat2:Matrix = new Matrix();
+- mat2.rotate(Math.PI / 2);
+- Tests.assertTrue(mat2.a == 0 && mat2.b == 1 && mat2.c == -1 && mat2.d == 0, "Matrix.rotate");
+-
+- var mat3:Matrix = new Matrix();
+- mat3.scale(4, 2);
+- Tests.assertTrue(mat3.a == 4 && mat3.b == 0 && mat3.c == 0 && mat3.d == 2, "Matrix.scale");
+-
+- var mat4:Matrix = new Matrix();
+- mat4.translate(4, 2);
+- Tests.assertTrue(mat4.tx == 4 && mat4.ty == 2, "Matrix.translate");
+-
+- var mati1:Matrix = new Matrix(1, 4, 2, 5, 0, 0);
+- var mati2:Matrix = mati1.clone();
+- mati2.invert();
+- mati1.concat(mati2);
+- Tests.assertTrue(matrixEqual(mati1, new Matrix(1, 0, 0, 1, 0, 0)), "matrix.invert");
+-
+- Tests.report(visual, this.name);
+- }
+-]]>
+-</mx:Script>
+-
+-<mx:UIComponent id="visual" />
+-
+-</mx:Application>
+-
+-
+-
++<?xml version="1.0"?>
++<mx:Application name="lightspark_geom_Matrix_test"
++ xmlns:mx="http://www.adobe.com/2006/mxml"
++ layout="absolute"
++ applicationComplete="appComplete();"
++ backgroundColor="white">
++
++<mx:Script>
++<![CDATA[
++ import flash.display.DisplayObject;
++ import flash.display.Sprite;
++ import Tests;
++
++ private function matrixEqual(m1:Matrix, m2:Matrix):Boolean {
++ return m1.a == m2.a && m1.b == m2.b && m1.c == m2.c && m1.d == m2.d && m1.tx == m2.tx && m1.ty == m2.ty;
++ }
++
++ private function appComplete():void
++ {
++ var mat:Matrix = new Matrix();
++ Tests.assertTrue(mat.a == 1 && mat.b == 0 && mat.c == 0 && mat.d == 1, "new Matrix()");
++
++ var matc:Matrix = mat.clone();
++ Tests.assertTrue(matrixEqual(mat, matc), "matrix.clone");
++
++ var matm1:Matrix = new Matrix(1, 4, 2, 5, 3, 5);
++ var matm2:Matrix = new Matrix(2, 4, 5, 7, 9, 11);
++ var matm3:Matrix = new Matrix(22, 32, 29, 43, 40, 58);
++ matm1.concat(matm2);
++ Tests.assertTrue(matrixEqual(matm1, matm3), "matrix.concat");
++
++ mat.a = 50; mat.b = 60; mat.c = 5; mat.d = 100;
++ mat.identity();
++ Tests.assertTrue(mat.a == 1 && mat.b == 0 && mat.c == 0 && mat.d == 1, "Matrix.identity");
++
++ var mat2:Matrix = new Matrix();
++ mat2.rotate(Math.PI / 2);
++ Tests.assertTrue(mat2.a == 0 && mat2.b == 1 && mat2.c == -1 && mat2.d == 0, "Matrix.rotate");
++
++ var mat3:Matrix = new Matrix();
++ mat3.scale(4, 2);
++ Tests.assertTrue(mat3.a == 4 && mat3.b == 0 && mat3.c == 0 && mat3.d == 2, "Matrix.scale");
++
++ var mat4:Matrix = new Matrix();
++ mat4.translate(4, 2);
++ Tests.assertTrue(mat4.tx == 4 && mat4.ty == 2, "Matrix.translate");
++
++ var mati1:Matrix = new Matrix(1, 4, 2, 5, 0, 0);
++ var mati2:Matrix = mati1.clone();
++ mati2.invert();
++ mati1.concat(mati2);
++ Tests.assertTrue(matrixEqual(mati1, new Matrix(1, 0, 0, 1, 0, 0)), "matrix.invert");
++
++ Tests.report(visual, this.name);
++ }
++]]>
++</mx:Script>
++
++<mx:UIComponent id="visual" />
++
++</mx:Application>
++
++
++
+diff --git a/tests/geom_Point_test.mxml b/tests/geom_Point_test.mxml
+index f8d926c..25bbaa3 100644
+--- a/tests/geom_Point_test.mxml
++++ b/tests/geom_Point_test.mxml
+@@ -1,52 +1,52 @@
+-<?xml version="1.0"?>
+-<mx:Application name="lightspark_geom_Point_test"
+- xmlns:mx="http://www.adobe.com/2006/mxml"
+- layout="absolute"
+- applicationComplete="appComplete();"
+- backgroundColor="white">
+-
+-<mx:Script>
+-<![CDATA[
+- import flash.geom.Point;
+- private function appComplete():void
+- {
+-
+- var point:Point = new Point();
+- Tests.assertEquals(0, point.x, "new Point().x == 0", false);
+- Tests.assertEquals(0, point.y, "new Point().y == 0", false);
+-
+- var point2:Point = new Point(6, 8);
+- Tests.assertEquals(6, point2.x, "new Point(6,8).x == 6", false);
+- Tests.assertEquals(8, point2.y, "new Point(6,8).y == 8", false);
+-
+- var point3:Point = Point.interpolate(point, point2, 0.5);
+- Tests.assertEquals(3, point3.x,"Point.interpolate (x)", false);
+- Tests.assertEquals(4, point3.y, "Point.interpolate (y)", false);
+-
+- Tests.assertEquals(10, Point.distance(point, point2), "Point.distance", false);
+-
+- var point4:Point = new Point(3, 2).add(point2);
+- Tests.assertEquals(9, point4.x, "Point.add (x)", false);
+- Tests.assertEquals(10, point4.y, "Point.add (y)", false);
+-
+- var point5:Point = point4.clone();
+- Tests.assertTrue(point4.equals(point5), "Point.equals");
+-
+- var point6:Point = new Point(0, 5);
+- point6.normalize(1);
+- Tests.assertEquals(1, point6.y, "Point.normalize", false);
+-
+- var point7:Point = new Point(0, 0);
+- point7.offset(2, 3);
+- Tests.assertEquals(2, point7.x, "Point.offset (x)", false);
+- Tests.assertEquals(3, point7.y, "Point.offset (y)", false);
+-
+- Tests.report(visual, name);
+- }
+-]]>
+-</mx:Script>
+-
+-<mx:UIComponent id="visual" />
+-
+-</mx:Application>
+-
++<?xml version="1.0"?>
++<mx:Application name="lightspark_geom_Point_test"
++ xmlns:mx="http://www.adobe.com/2006/mxml"
++ layout="absolute"
++ applicationComplete="appComplete();"
++ backgroundColor="white">
++
++<mx:Script>
++<![CDATA[
++ import flash.geom.Point;
++ private function appComplete():void
++ {
++
++ var point:Point = new Point();
++ Tests.assertEquals(0, point.x, "new Point().x == 0", false);
++ Tests.assertEquals(0, point.y, "new Point().y == 0", false);
++
++ var point2:Point = new Point(6, 8);
++ Tests.assertEquals(6, point2.x, "new Point(6,8).x == 6", false);
++ Tests.assertEquals(8, point2.y, "new Point(6,8).y == 8", false);
++
++ var point3:Point = Point.interpolate(point, point2, 0.5);
++ Tests.assertEquals(3, point3.x,"Point.interpolate (x)", false);
++ Tests.assertEquals(4, point3.y, "Point.interpolate (y)", false);
++
++ Tests.assertEquals(10, Point.distance(point, point2), "Point.distance", false);
++
++ var point4:Point = new Point(3, 2).add(point2);
++ Tests.assertEquals(9, point4.x, "Point.add (x)", false);
++ Tests.assertEquals(10, point4.y, "Point.add (y)", false);
++
++ var point5:Point = point4.clone();
++ Tests.assertTrue(point4.equals(point5), "Point.equals");
++
++ var point6:Point = new Point(0, 5);
++ point6.normalize(1);
++ Tests.assertEquals(1, point6.y, "Point.normalize", false);
++
++ var point7:Point = new Point(0, 0);
++ point7.offset(2, 3);
++ Tests.assertEquals(2, point7.x, "Point.offset (x)", false);
++ Tests.assertEquals(3, point7.y, "Point.offset (y)", false);
++
++ Tests.report(visual, name);
++ }
++]]>
++</mx:Script>
++
++<mx:UIComponent id="visual" />
++
++</mx:Application>
++
+diff --git a/tests/geom_Rectangle_test.mxml b/tests/geom_Rectangle_test.mxml
+index b8450c4..43734db 100644
+--- a/tests/geom_Rectangle_test.mxml
++++ b/tests/geom_Rectangle_test.mxml
+@@ -1,72 +1,72 @@
+-<?xml version="1.0"?>
+-<mx:Application name="lightspark_geom_Rectangle_test"
+- xmlns:mx="http://www.adobe.com/2006/mxml"
+- layout="absolute"
+- applicationComplete="appComplete();"
+- backgroundColor="white">
+-
+-<mx:Script>
+-<![CDATA[
+- import flash.geom.Rectangle;
+- import flash.geom.Point;
+-
+- private function appComplete():void
+- {
+-
+- var rect:Rectangle = new Rectangle(0, 0, 10, 10);
+-
+- Tests.assertEquals(rect.clone(), rect, "rectangle.clone");
+-
+- Tests.assertTrue(rect.contains(1, 1), "rectangle.contains")
+-
+- var point:Point = new Point(1, 1);
+- Tests.assertTrue(rect.containsPoint(point), "rectangle.containsPoint")
+-
+- var rect2:Rectangle = new Rectangle(1, 1, 9, 9);
+- Tests.assertTrue(rect.containsRect(rect2), "rectangle.containsRect")
+-
+- Tests.assertTrue(rect.equals(new Rectangle(0, 0, 10, 10)), "rectangle.equals")
+-
+- var rectinflated:Rectangle = new Rectangle(0, 0, 11, 11);
+- rect2.inflate(1, 1);
+- Tests.assertEquals(rect2, rectinflated, "rectangle.inflate");
+-
+- var rect3:Rectangle = new Rectangle(1, 1, 9, 9);
+- rect3.inflatePoint(new Point(1, 1));
+- Tests.assertEquals(rect3, rectinflated, "rectangle.inflatePoint");
+-
+- var rect4:Rectangle = new Rectangle(5, 5, 10, 10);
+- Tests.assertEquals(rect.intersection(rect4), new Rectangle(5, 5, 5, 5), "rectangle.intersection");
+-
+- Tests.assertTrue(rect.intersects(rect4), "rectangle.intersects")
+-
+- Tests.assertFalse(rect.isEmpty(), "rectangle.isEmpty")
+-
+- var rect5:Rectangle = new Rectangle(-1, -1, 10, 10);
+- rect5.offset(1, 1);
+- Tests.assertEquals(rect5, rect, "rectangle.offset");
+-
+- var rect6:Rectangle = new Rectangle(-1, -1, 10, 10);
+- var point2:Point = new Point(1, 1);
+- rect6.offsetPoint(point2);
+- Tests.assertEquals(rect6, rect, "rectangle.offsetPoint");
+-
+- rect6.setEmpty();
+- Tests.assertTrue(rect6.isEmpty(), "rectangle.setEmpty")
+-
+- var rect9:Rectangle = new Rectangle(0, 0, 10, 10);
+- Tests.assertEquals(rect9.toString(), "(x=0.00, y=0.00, w=10.00, h=10.00)", "rectangle.toString");
+-
+- var rect7:Rectangle = new Rectangle(0, 0, 10, 10);
+- var rect8:Rectangle = new Rectangle(10, 10, 10, 10);
+- Tests.assertEquals(rect7.union(rect8), new Rectangle(0, 0, 20, 20), "rectangle.union");
+-
+- Tests.report(visual, name);
+- }
+-]]>
+-</mx:Script>
+-
+-<mx:UIComponent id="visual" />
+-
+-</mx:Application>
+-
++<?xml version="1.0"?>
++<mx:Application name="lightspark_geom_Rectangle_test"
++ xmlns:mx="http://www.adobe.com/2006/mxml"
++ layout="absolute"
++ applicationComplete="appComplete();"
++ backgroundColor="white">
++
++<mx:Script>
++<![CDATA[
++ import flash.geom.Rectangle;
++ import flash.geom.Point;
++
++ private function appComplete():void
++ {
++
++ var rect:Rectangle = new Rectangle(0, 0, 10, 10);
++
++ Tests.assertEquals(rect.clone(), rect, "rectangle.clone");
++
++ Tests.assertTrue(rect.contains(1, 1), "rectangle.contains")
++
++ var point:Point = new Point(1, 1);
++ Tests.assertTrue(rect.containsPoint(point), "rectangle.containsPoint")
++
++ var rect2:Rectangle = new Rectangle(1, 1, 9, 9);
++ Tests.assertTrue(rect.containsRect(rect2), "rectangle.containsRect")
++
++ Tests.assertTrue(rect.equals(new Rectangle(0, 0, 10, 10)), "rectangle.equals")
++
++ var rectinflated:Rectangle = new Rectangle(0, 0, 11, 11);
++ rect2.inflate(1, 1);
++ Tests.assertEquals(rect2, rectinflated, "rectangle.inflate");
++
++ var rect3:Rectangle = new Rectangle(1, 1, 9, 9);
++ rect3.inflatePoint(new Point(1, 1));
++ Tests.assertEquals(rect3, rectinflated, "rectangle.inflatePoint");
++
++ var rect4:Rectangle = new Rectangle(5, 5, 10, 10);
++ Tests.assertEquals(rect.intersection(rect4), new Rectangle(5, 5, 5, 5), "rectangle.intersection");
++
++ Tests.assertTrue(rect.intersects(rect4), "rectangle.intersects")
++
++ Tests.assertFalse(rect.isEmpty(), "rectangle.isEmpty")
++
++ var rect5:Rectangle = new Rectangle(-1, -1, 10, 10);
++ rect5.offset(1, 1);
++ Tests.assertEquals(rect5, rect, "rectangle.offset");
++
++ var rect6:Rectangle = new Rectangle(-1, -1, 10, 10);
++ var point2:Point = new Point(1, 1);
++ rect6.offsetPoint(point2);
++ Tests.assertEquals(rect6, rect, "rectangle.offsetPoint");
++
++ rect6.setEmpty();
++ Tests.assertTrue(rect6.isEmpty(), "rectangle.setEmpty")
++
++ var rect9:Rectangle = new Rectangle(0, 0, 10, 10);
++ Tests.assertEquals(rect9.toString(), "(x=0.00, y=0.00, w=10.00, h=10.00)", "rectangle.toString");
++
++ var rect7:Rectangle = new Rectangle(0, 0, 10, 10);
++ var rect8:Rectangle = new Rectangle(10, 10, 10, 10);
++ Tests.assertEquals(rect7.union(rect8), new Rectangle(0, 0, 20, 20), "rectangle.union");
++
++ Tests.report(visual, name);
++ }
++]]>
++</mx:Script>
++
++<mx:UIComponent id="visual" />
++
++</mx:Application>
++