[lightspark] 03/08: Imported Upstream version 0.7.2+git20150512

Gabriele Giacone gg0-guest at moszumanska.debian.org
Tue May 12 19:02:51 UTC 2015


This is an automated email from the git hooks/post-receive script.

gg0-guest pushed a commit to branch master
in repository lightspark.

commit 0be6438bad09c20b3e6576433cdd39d526aeee7f
Author: Gabriele Giacone <1o5g4r8o at gmail.com>
Date:   Tue May 12 15:04:59 2015 +0200

    Imported Upstream version 0.7.2+git20150512
---
 CMakeLists.txt                                     |   79 +-
 ChangeLog                                          |   10 +
 README                                             |   21 +-
 conf/FindFFMpeg.cmake                              |    6 +-
 conf/FindFreetype.cmake                            |    6 +-
 conf/FindLLVM.cmake                                |   33 +-
 debian/control                                     |    2 +-
 docs/man/lightspark.1                              |   28 +-
 src/CMakeLists.txt                                 |   27 +
 src/allclasses.cpp                                 |   30 +
 src/allclasses.h                                   |   72 +
 src/asobject.cpp                                   |  461 ++++-
 src/asobject.h                                     |   66 +-
 src/backends/decoder.cpp                           |  193 +-
 src/backends/decoder.h                             |   26 +-
 src/backends/graphics.cpp                          |   92 +-
 src/backends/graphics.h                            |   28 +-
 src/backends/input.cpp                             |   15 +
 src/backends/input.h                               |    1 +
 src/backends/netutils.cpp                          |  629 +-----
 src/backends/netutils.h                            |  125 +-
 src/backends/rendering.cpp                         |    6 +-
 src/backends/rtmputils.cpp                         |    6 +-
 src/backends/rtmputils.h                           |    3 +-
 src/backends/security.cpp                          |    9 +-
 src/backends/streamcache.cpp                       |  499 +++++
 src/backends/streamcache.h                         |  197 ++
 src/backends/urlutils.cpp                          |  255 ++-
 src/backends/urlutils.h                            |   20 +-
 src/backends/xml_support.cpp                       |   83 +-
 src/backends/xml_support.h                         |    8 +-
 src/compat.h                                       |    1 +
 src/main.cpp                                       |    8 +-
 src/parsing/amf3_generator.cpp                     |  165 +-
 src/parsing/amf3_generator.h                       |   32 +
 src/parsing/tags.cpp                               |  101 +-
 src/parsing/tags.h                                 |   29 +-
 src/parsing/tags_stub.cpp                          |    6 -
 src/platforms/engineutils.cpp                      |   30 +
 src/platforms/engineutils.h                        |   11 +-
 src/plugin/npscriptobject.cpp                      |    7 +-
 src/plugin/plugin.cpp                              |   87 +-
 src/plugin/plugin.h                                |   12 +-
 src/scripting/abc.cpp                              |  289 ++-
 src/scripting/abc.h                                |   44 +-
 src/scripting/abc_codesynt.cpp                     |   25 +-
 src/scripting/abc_fast_interpreter.cpp             |   87 +-
 src/scripting/abc_interpreter.cpp                  |  103 +-
 src/scripting/abc_opcodes.cpp                      |  429 ++--
 src/scripting/abc_optimizer.cpp                    |    6 +-
 src/scripting/abctypes.h                           |    5 +-
 src/scripting/argconv.h                            |    8 +-
 src/scripting/class.cpp                            |   30 +-
 src/scripting/class.h                              |  126 +-
 .../flash/accessibility/flashaccessibility.cpp     |   42 +-
 .../flash/accessibility/flashaccessibility.h       |   19 +-
 src/scripting/flash/concurrent/Condition.cpp       |   81 +
 .../flash/concurrent/Condition.h}                  |   30 +-
 .../Mutex.cpp}                                     |   45 +-
 .../flash/concurrent/Mutex.h}                      |   31 +-
 src/scripting/flash/desktop/flashdesktop.cpp       |    5 +-
 src/scripting/flash/display/BitmapData.cpp         |  137 +-
 src/scripting/flash/display/BitmapData.h           |    3 +
 src/scripting/flash/display/DisplayObject.cpp      |   47 +-
 src/scripting/flash/display/DisplayObject.h        |    5 +-
 src/scripting/flash/display/Graphics.cpp           |  923 +++++++++
 src/scripting/flash/display/Graphics.h             |  103 +
 src/scripting/flash/display/GraphicsBitmapFill.cpp |   70 +
 .../display/GraphicsBitmapFill.h}                  |   48 +-
 .../GraphicsEndFill.cpp}                           |   32 +-
 .../flash/display/GraphicsEndFill.h}               |   26 +-
 .../flash/display/GraphicsGradientFill.cpp         |   96 +
 src/scripting/flash/display/GraphicsGradientFill.h |   55 +
 src/scripting/flash/display/GraphicsPath.cpp       |  173 ++
 .../UInteger.h => flash/display/GraphicsPath.h}    |   54 +-
 src/scripting/flash/display/GraphicsShaderFill.cpp |   73 +
 .../GraphicsShaderFill.h}                          |   33 +-
 src/scripting/flash/display/GraphicsSolidFill.cpp  |   63 +
 .../GraphicsSolidFill.h}                           |   29 +-
 src/scripting/flash/display/GraphicsStroke.cpp     |  109 +
 .../UInteger.h => flash/display/GraphicsStroke.h}  |   50 +-
 .../flash/display/GraphicsTrianglePath.cpp         |   74 +
 .../display/GraphicsTrianglePath.h}                |   47 +-
 .../flash/display/IGraphicsData.h}                 |   25 +-
 .../flash/display/IGraphicsFill.h}                 |   23 +-
 .../flash/display/IGraphicsPath.h}                 |   20 +-
 .../flash/display/IGraphicsStroke.h}               |   20 +-
 src/scripting/flash/display/TokenContainer.cpp     |   23 +-
 src/scripting/flash/display/TokenContainer.h       |    4 +-
 src/scripting/flash/display/flashdisplay.cpp       | 1006 +++------
 src/scripting/flash/display/flashdisplay.h         |  101 +-
 src/scripting/flash/errors/flasherrors.cpp         |   21 +-
 src/scripting/flash/events/flashevents.cpp         |  238 ++-
 src/scripting/flash/events/flashevents.h           |   76 +-
 src/scripting/flash/external/ExternalInterface.cpp |    8 +-
 .../flashfilesystem.cpp}                           |   29 +-
 .../flashfilesystem.h}                             |   22 +-
 src/scripting/flash/filters/flashfilters.cpp       |  321 ++-
 src/scripting/flash/filters/flashfilters.h         |  111 +-
 src/scripting/flash/geom/flashgeom.cpp             |   46 +-
 src/scripting/flash/geom/flashgeom.h               |   23 +-
 src/scripting/flash/media/flashmedia.cpp           |  151 +-
 src/scripting/flash/media/flashmedia.h             |   34 +-
 .../NetStreamPlayOptions.cpp}                      |   41 +-
 .../flashsensors.h => net/NetStreamPlayOptions.h}  |   34 +-
 .../NetStreamPlayTransitions.cpp}                  |   37 +-
 .../flash/net/NetStreamPlayTransitions.h}          |   24 +-
 src/scripting/flash/net/URLRequestHeader.cpp       |    3 +-
 src/scripting/flash/net/URLStream.cpp              |   12 +-
 src/scripting/flash/net/URLStream.h                |    1 +
 src/scripting/flash/net/XMLSocket.cpp              |    3 +-
 src/scripting/flash/net/flashnet.cpp               |  369 +++-
 src/scripting/flash/net/flashnet.h                 |   65 +-
 src/scripting/flash/printing/flashprinting.cpp     |   69 +
 .../flashprinting.h}                               |   27 +-
 src/scripting/flash/sensors/flashsensors.cpp       |    3 +-
 src/scripting/flash/sensors/flashsensors.h         |    2 +-
 src/scripting/flash/system/flashsystem.cpp         |  139 +-
 src/scripting/flash/system/flashsystem.h           |   24 +-
 src/scripting/flash/text/flashtext.cpp             |  629 +++++-
 src/scripting/flash/text/flashtext.h               |   89 +-
 src/scripting/flash/text/flashtextengine.cpp       |  333 ++-
 src/scripting/flash/text/flashtextengine.h         |  123 +-
 .../flashaccessibility.cpp => ui/ContextMenu.cpp}  |   35 +-
 .../{sensors/flashsensors.h => ui/ContextMenu.h}   |   33 +-
 src/scripting/flash/ui/ContextMenuBuiltInItems.cpp |   57 +
 .../ContextMenuBuiltInItems.h}                     |   31 +-
 .../flash/ui/ContextMenuItem.cpp}                  |   36 +-
 .../flash/ui/ContextMenuItem.h}                    |   26 +-
 src/scripting/flash/ui/Keyboard.cpp                |    9 +-
 src/scripting/flash/ui/Mouse.cpp                   |   75 +
 .../rtmputils.h => scripting/flash/ui/Mouse.h}     |   28 +-
 .../flash/utils/{flashutils.cpp => ByteArray.cpp}  | 1085 ++--------
 src/scripting/flash/utils/ByteArray.h              |  156 ++
 src/scripting/flash/utils/Dictionary.cpp           |  344 ++++
 src/scripting/flash/utils/Dictionary.h             |   64 +
 src/scripting/flash/utils/IntervalManager.cpp      |  106 +
 .../IntervalManager.h}                             |   35 +-
 src/scripting/flash/utils/IntervalRunner.cpp       |   72 +
 .../UInteger.h => flash/utils/IntervalRunner.h}    |   55 +-
 src/scripting/flash/utils/Proxy.cpp                |  251 +++
 src/scripting/flash/utils/Proxy.h                  |   61 +
 src/scripting/flash/utils/Timer.cpp                |  185 ++
 .../{toplevel/UInteger.h => flash/utils/Timer.h}   |   60 +-
 src/scripting/flash/utils/flashutils.cpp           | 1892 +----------------
 src/scripting/flash/utils/flashutils.h             |  243 +--
 src/scripting/flash/xml/flashxml.cpp               |   10 +-
 src/scripting/toplevel/ASString.cpp                |  119 +-
 src/scripting/toplevel/ASString.h                  |    7 +
 src/scripting/toplevel/Array.cpp                   |  370 +++-
 src/scripting/toplevel/Array.h                     |   30 +-
 src/scripting/toplevel/Boolean.cpp                 |   22 +-
 src/scripting/toplevel/Date.cpp                    |   28 +-
 src/scripting/toplevel/Date.h                      |    4 +
 src/scripting/toplevel/Error.cpp                   |   49 +-
 src/scripting/toplevel/Integer.cpp                 |   65 +-
 src/scripting/toplevel/Integer.h                   |    3 +
 src/scripting/toplevel/JSON.cpp                    |  774 +++++++
 src/scripting/toplevel/JSON.h                      |   51 +
 src/scripting/toplevel/Math.cpp                    |    4 +-
 src/scripting/toplevel/Number.cpp                  |  227 +-
 src/scripting/toplevel/Number.h                    |    9 +-
 src/scripting/toplevel/RegExp.cpp                  |   12 +-
 src/scripting/toplevel/UInteger.cpp                |   54 +-
 src/scripting/toplevel/UInteger.h                  |    3 +
 src/scripting/toplevel/Vector.cpp                  |  148 +-
 src/scripting/toplevel/Vector.h                    |   26 +-
 src/scripting/toplevel/XML.cpp                     | 2164 ++++++++++++++------
 src/scripting/toplevel/XML.h                       |  103 +-
 src/scripting/toplevel/XMLList.cpp                 |  633 ++++--
 src/scripting/toplevel/XMLList.h                   |   39 +-
 src/scripting/toplevel/toplevel.cpp                |  281 ++-
 src/scripting/toplevel/toplevel.h                  |   66 +-
 src/swf.cpp                                        |   58 +-
 src/swf.h                                          |    3 +
 src/swftypes.cpp                                   |   73 +-
 src/swftypes.h                                     |   25 +-
 src/threading.cpp                                  |   27 +
 src/threading.h                                    |   10 +
 src/tiny_string.cpp                                |  398 ++++
 src/tiny_string.h                                  |  353 +---
 tests/encodeURI_test.mxml                          |   67 +
 tests/make-tamarin                                 |  121 +-
 tests/methodNamespace_test.mxml                    |  141 ++
 tests/quit.as                                      |    2 +
 tests/tests                                        |  109 +-
 tools/langref_parser                               |   13 +-
 tools/mergeABCtoSWF                                |  134 ++
 tools/pygil                                        |   24 +-
 189 files changed, 15747 insertions(+), 7560 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 33dbb85..7e8c08b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -78,7 +78,7 @@ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
 
 # GCC 4.6+ is required, GCC_VERSION macro taken from GCC manual
 INCLUDE(CheckCSourceCompiles)
-IF(CMAKE_COMPILER_IS_GNUCC)
+IF(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
    CHECK_C_SOURCE_COMPILES("
    #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
    #if GCC_VERSION < 40600
@@ -88,7 +88,7 @@ IF(CMAKE_COMPILER_IS_GNUCC)
    IF(NOT GCC_IS_4_6)
 	  MESSAGE(FATAL_ERROR "GCC 4.6+ is required.")
    ENDIF(NOT GCC_IS_4_6)
-ENDIF(CMAKE_COMPILER_IS_GNUCC)
+ENDIF(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
 
 # Find put the path of the gnash executable, if available
 FIND_PROGRAM(GNASH_EXE_PATH NAMES gnash)
@@ -114,31 +114,31 @@ SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/conf)
 INCLUDE(Pack)
 # If we're gcc, then use nasm to get fastpath.  If MSVC, just use inline asm to get around
 # CMake issues 
-IF(CMAKE_COMPILER_IS_GNUCC)
+IF(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
    INCLUDE(CMakeASM-NASMCompiler)
-ENDIF(CMAKE_COMPILER_IS_GNUCC)
+ENDIF(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
 IF(${CMAKE_SYSTEM_PROCESSOR} MATCHES "^i[3-6]86$|^x86$")
 	SET(i386 1)
 	SET(LIB_SUFFIX "" CACHE STRING "Choose the suffix of the lib folder (if any) : None 32")
 	# nasm for assembly optimizations
-	IF(CMAKE_COMPILER_IS_GNUCC)
+	IF(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
 	   ENABLE_LANGUAGE(ASM-NASM)        
-	ENDIF(CMAKE_COMPILER_IS_GNUCC)
+	ENDIF(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
 ELSEIF(${CMAKE_SYSTEM_PROCESSOR} MATCHES "unknown" AND ${CMAKE_SYSTEM} MATCHES "GNU-0.3")
 	# GNU Hurd is i386
 	SET(i386 1)
 	SET(LIB_SUFFIX "" CACHE STRING "Choose the suffix of the lib folder (if any) : None 32")
 	# nasm for assembly optimizations
-	IF(CMAKE_COMPILER_IS_GNUCC)
+	IF(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
 	   ENABLE_LANGUAGE(ASM-NASM)
 	ENDIF ()
 ELSEIF(${CMAKE_SYSTEM_PROCESSOR} MATCHES "^x86_64$|^amd64$")
 	SET(x86_64 1)
 	SET(LIB_SUFFIX "" CACHE STRING "Choose the suffix of the lib folder (if any) : None 64")
 	# nasm for assembly optimizations
-	IF(CMAKE_COMPILER_IS_GNUCC)
+	IF(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
 	  ENABLE_LANGUAGE(ASM-NASM)
-	ENDIF(CMAKE_COMPILER_IS_GNUCC)
+	ENDIF(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
 ELSEIF(${CMAKE_SYSTEM_PROCESSOR} MATCHES "ppc")
 	SET(ppc 1)
 	SET(LIB_SUFFIX "" CACHE STRING "Choose the suffix of the lib folder (if any) : None ppc")
@@ -238,6 +238,15 @@ ENDIF(${LLVM_STRING_VERSION} VERSION_EQUAL 3.0)
 IF(${LLVM_STRING_VERSION} VERSION_GREATER 3.0)
 	ADD_DEFINITIONS(-DLLVM_31)
 ENDIF(${LLVM_STRING_VERSION} VERSION_GREATER 3.0)
+IF(${LLVM_STRING_VERSION} VERSION_GREATER 3.3)
+	ADD_DEFINITIONS(-DLLVM_34)
+ENDIF(${LLVM_STRING_VERSION} VERSION_GREATER 3.3)
+IF(${LLVM_STRING_VERSION} VERSION_GREATER 3.4)
+	ADD_DEFINITIONS(-DLLVM_35)
+ENDIF(${LLVM_STRING_VERSION} VERSION_GREATER 3.4)
+IF(NOT (${LLVM_STRING_VERSION} VERSION_LESS 3.6))
+	ADD_DEFINITIONS(-DLLVM_36)
+ENDIF(NOT (${LLVM_STRING_VERSION} VERSION_LESS 3.6))
 INCLUDE(FindZLIB REQUIRED)
 INCLUDE(FindFreetype REQUIRED)
 IF(NOT(ENABLE_GLES2))
@@ -287,12 +296,17 @@ ENDIF(AUDIO_BACKEND)
 
 IF(ENABLE_LIBAVCODEC)
 	pkg_check_modules(FFMPEG libavcodec libavutil libavformat)
+	pkg_check_modules(LIBAVRESAMPLE libavresample)
 	IF(NOT(FFMPEG_FOUND))
 		INCLUDE(FindFFMpeg REQUIRED)
 	ENDIF(NOT(FFMPEG_FOUND))
 	# Compatibility checks for ffmpeg deprecated functions
   INCLUDE(CheckFunctionExists REQUIRED)
-  SET(CMAKE_REQUIRED_FLAGS ${LIBAVCODEC_CFLAGS})
+  INCLUDE(CheckCSourceCompiles)
+  SET(FFMPEG_FLAGS "${LIBAVCODEC_CFLAGS} ${LIBAVRESAMPLE_FLAGS}")
+  SET(FFMPEG_INCLUDE_DIRS "${FFMPEG_INCLUDE_DIRS} ${LIBAVRESAMPLE_INCLUDE_DIRS}")
+  SET(FFMPEG_LIBRARIES "${FFMPEG_LIBRARIES};${LIBAVRESAMPLE_LIBRARIES}")
+  SET(CMAKE_REQUIRED_FLAGS ${FFMPEG_FLAGS})
   SET(CMAKE_REQUIRED_INCLUDES ${FFMPEG_INCLUDE_DIRS})
   SET(CMAKE_REQUIRED_LIBRARIES ${FFMPEG_LIBRARIES})
   CHECK_FUNCTION_EXISTS(avcodec_decode_video2 HAVE_AVCODEC_DECODE_VIDEO2)
@@ -303,7 +317,8 @@ IF(ENABLE_LIBAVCODEC)
   CHECK_FUNCTION_EXISTS(avcodec_open2 HAVE_AVCODEC_OPEN2)
   CHECK_FUNCTION_EXISTS(avformat_close_input HAVE_AVFORMAT_CLOSE_INPUT)
   CHECK_FUNCTION_EXISTS(avformat_find_stream_info HAVE_AVFORMAT_FIND_STREAM_INFO)
-  
+  CHECK_C_SOURCE_COMPILES("#include <libavcodec/avcodec.h>\nint main() { enum AVCodecID c; return 0; }" HAVE_AVCODECID)
+
   SET(CMAKE_REQUIRED_FLAGS)
   SET(CMAKE_REQUIRED_INCLUDES)
   SET(CMAKE_REQUIRED_LIBRARIES)
@@ -331,6 +346,12 @@ IF(ENABLE_LIBAVCODEC)
   IF(HAVE_AVFORMAT_FIND_STREAM_INFO)
     ADD_DEFINITIONS(-DHAVE_AVFORMAT_FIND_STREAM_INFO)
   ENDIF(HAVE_AVFORMAT_FIND_STREAM_INFO)
+  IF(HAVE_AVCODECID)
+    ADD_DEFINITIONS(-DHAVE_AVCODECID)
+  ENDIF(HAVE_AVCODECID)
+  IF(LIBAVRESAMPLE_FOUND)
+    ADD_DEFINITIONS(-DHAVE_LIBAVRESAMPLE)
+  ENDIF(LIBAVRESAMPLE_FOUND)
   ADD_DEFINITIONS(-DENABLE_LIBAVCODEC)
 ENDIF(ENABLE_LIBAVCODEC)
 
@@ -372,7 +393,7 @@ IF(ENABLE_LIBAVCODEC)
   SET(OPTIONAL_LIBRARIES ${OPTIONAL_LIBRARIES} ${FFMPEG_LIBRARIES})
 ENDIF(ENABLE_LIBAVCODEC)	
 
-IF(CMAKE_COMPILER_IS_GNUCC)
+IF(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
   IF(MINGW)
     SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed,--no-undefined -mthreads ${CMAKE_EXE_LINKER_FLAGS}")
     SET(CMAKE_SHARED_LINKER_FLAGS "-Wl,--as-needed,--no-undefined,--enable-stdcall-fixup -mthreads ${CMAKE_SHARED_LINKER_FLAGS}")
@@ -382,7 +403,13 @@ IF(CMAKE_COMPILER_IS_GNUCC)
   ENDIF()
   SET(CMAKE_EXE_LINKER_FLAGS_RELEASE "-s")
   SET(CMAKE_SHARED_LINKER_FLAGS_RELEASE "-s")
-ENDIF(CMAKE_COMPILER_IS_GNUCC)
+ENDIF(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
+IF(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
+  SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -Wl,--no-undefined ${CMAKE_EXE_LINKER_FLAGS}")
+  SET(CMAKE_SHARED_LINKER_FLAGS "-Wl,--as-needed,-z,noexecstack,--no-undefined ${CMAKE_SHARED_LINKER_FLAGS}")
+  SET(CMAKE_EXE_LINKER_FLAGS_RELEASE "-s")
+  SET(CMAKE_SHARED_LINKER_FLAGS_RELEASE "-s")
+ENDIF(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
 
 LINK_DIRECTORIES(${LLVM_LIB_DIR})
 
@@ -413,13 +440,13 @@ IF(ENABLE_MEMORY_USAGE_PROFILING)
 ENDIF(ENABLE_MEMORY_USAGE_PROFILING)
 
 # Compiler defaults flags for different profiles
-IF(CMAKE_COMPILER_IS_GNUCC)
+IF(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
   IF(MINGW)
     SET(CMAKE_CXX_FLAGS
 	   "${CMAKE_CXX_FLAGS} -mms-bitfields -mthreads -fexceptions -Wall -Wnon-virtual-dtor -Woverloaded-virtual -pipe -std=c++0x -Wdisabled-optimization -Wextra -Wno-unused-parameter -Wno-invalid-offsetof")
   ELSE()
    SET(CMAKE_CXX_FLAGS
-	  "${CMAKE_CXX_FLAGS} -Wall -Wnon-virtual-dtor -Woverloaded-virtual -pipe -fvisibility=hidden -fvisibility-inlines-hidden -std=c++0x -Wdisabled-optimization -Wextra -Wno-unused-parameter -Wno-invalid-offsetof")
+	  "${CMAKE_CXX_FLAGS} -Wall -Wnon-virtual-dtor -Woverloaded-virtual -pipe -fvisibility=hidden -fvisibility-inlines-hidden -std=c++11 -Wdisabled-optimization -Wextra -Wno-unused-parameter -Wno-invalid-offsetof")
   ENDIF()
   SET(CMAKE_CXX_FLAGS_DEBUG "-g -O0 -DEXPENSIVE_DEBUG")
   SET(CMAKE_CXX_FLAGS_PROFILE "-g -pg -O2")
@@ -427,7 +454,18 @@ IF(CMAKE_COMPILER_IS_GNUCC)
   SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-g -O2 -DNDEBUG")
   SET(CMAKE_CXX_FLAGS_LEANDEBUG "-g -O2")
   ADD_DEFINITIONS(-DLS_DATADIR="${LSDATADIR}" -DGNASH_PATH="${GNASH_EXE_PATH}" -DPRIVATELIBDIR="${PRIVATELIBDIR}")
-ENDIF(CMAKE_COMPILER_IS_GNUCC)
+ENDIF(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
+IF(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
+  SET(CMAKE_CXX_FLAGS
+	  "${CMAKE_CXX_FLAGS} -Wall -Wnon-virtual-dtor -Woverloaded-virtual -pipe -fvisibility=hidden -fvisibility-inlines-hidden -std=c++11 -Wdisabled-optimization -Wextra -Wno-unused-parameter -Wno-invalid-offsetof")
+  SET(CMAKE_CXX_FLAGS_DEBUG "-g -O0 -DEXPENSIVE_DEBUG")
+  SET(CMAKE_CXX_FLAGS_PROFILE "-g -pg -O2")
+  SET(CMAKE_CXX_FLAGS_RELEASE "-O2 -DNDEBUG")
+  SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-g -O2 -DNDEBUG")
+  SET(CMAKE_CXX_FLAGS_LEANDEBUG "-g -O2")
+  ADD_DEFINITIONS(-DLS_DATADIR="${LSDATADIR}" -DGNASH_PATH="${GNASH_EXE_PATH}" -DPRIVATELIBDIR="${PRIVATELIBDIR}")
+  ADD_DEFINITIONS(-DUSE_CLANG)
+ENDIF(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
 
 IF(MSVC)
   ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS -D_SCL_SECURE_NO_WARNINGS -DVPCOMPAT -DPTW32_STATIC_LIB -DPCRE_STATIC)
@@ -445,11 +483,16 @@ IF(HAVE_ATOMIC)
 ENDIF(HAVE_ATOMIC)
 
 # Setting the output directories, so we can build all profiles without mixmatching
-IF(CMAKE_COMPILER_IS_GNUCC)
+IF(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
+  SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${CMAKE_SYSTEM_PROCESSOR}/${CMAKE_BUILD_TYPE}/bin")
+  SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${CMAKE_SYSTEM_PROCESSOR}/${CMAKE_BUILD_TYPE}/lib${LIB_SUFFIX}")
+  #SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/objs/${CMAKE_SYSTEM_PROCESSOR}/${CMAKE_BUILD_TYPE}/lib${LIB_SUFFIX}" CACHE PATH "Static libraries output directory")
+ENDIF(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
+IF(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
   SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${CMAKE_SYSTEM_PROCESSOR}/${CMAKE_BUILD_TYPE}/bin")
   SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${CMAKE_SYSTEM_PROCESSOR}/${CMAKE_BUILD_TYPE}/lib${LIB_SUFFIX}")
   #SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/objs/${CMAKE_SYSTEM_PROCESSOR}/${CMAKE_BUILD_TYPE}/lib${LIB_SUFFIX}" CACHE PATH "Static libraries output directory")
-ENDIF(CMAKE_COMPILER_IS_GNUCC)
+ENDIF(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
 
 #Install icons and desktop file
 if(UNIX)
diff --git a/ChangeLog b/ChangeLog
index 3920617..fb7831b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,15 @@
 lightspark: An open source flash player implementation
 
+Version NEXT:
+
+	* Support LLVM up to version 3.6
+	* fix event dispatcher handling
+	* several fixes for object initialization
+	* partially implement AMF0 decoding
+	* complete rework of XML subsystem
+	* Support embedded audio
+	* Implement JSON parsing
+
 Version 0.7.2:
 
 	* Improved image support: alpha in palettes, abbreviated JPEGs
diff --git a/README b/README
index ec64d4a..957ac80 100644
--- a/README
+++ b/README
@@ -35,15 +35,20 @@ DEBUG MODE:
 To enable debug mode change the cmake command like this:
 4b) cmake -DCMAKE_BUILD_TYPE=Debug
 
-CMAKE_BUILD_TYPE available: Debug Release RelWithDebInfo Profile Sound
-support may be disabled using the following option: -DENABLE_SOUND=0
-The audio backend can be set using -DAUDIO_BACKEND=<pulseaudio|sdl>
-(default is pulseaudio)
+CMAKE_BUILD_TYPE available: Debug LeanDebug Release RelWithDebInfo Profile
+
+Sound support may be disabled using the following option:
+-DENABLE_SOUND=0 The audio backend can be set using
+-DAUDIO_BACKEND=<pulseaudio|sdl> (default is pulseaudio)
 
 EXECUTION
 =========
 
 Using `make install`, lightspark is installed in the system wide
+
+Browser plugin
+--------------
+
 Firefox plugin path and Firefox should show it in the about:plugins
 list and in the Tools->Add-ons->Plugins window.
 
@@ -57,6 +62,14 @@ Firefox is not able to deal very well with multiple plugins for the
 same MIME type. If you only see a black box where a flash app should
 be try to remove any other flash plugin you have installed.
 
+Command line
+------------
+
+The command line version of Lightspark can play a local SWF file.
+Execution: lightspark file.swf
+
+Type `lightspark` to see all command line options.
+
 Keyboard shortcuts
 ------------------
 
diff --git a/conf/FindFFMpeg.cmake b/conf/FindFFMpeg.cmake
index 2b4dd98..8246c15 100644
--- a/conf/FindFFMpeg.cmake
+++ b/conf/FindFFMpeg.cmake
@@ -23,7 +23,11 @@ FIND_LIBRARY(FFMPEG_AVFORMAT_LIBRARY NAMES
     avformat
 )
 
-SET(FFMPEG_LIBRARY ${FFMPEG_AVCODEC_LIBRARY} ${FFMPEG_AVUTIL_LIBRARY} ${FFMPEG_AVFORMAT_LIBRARY})
+FIND_LIBRARY(FFMPEG_AVRESAMPLE_LIBRARY NAMES
+    avresample
+)
+
+SET(FFMPEG_LIBRARY ${FFMPEG_AVCODEC_LIBRARY} ${FFMPEG_AVUTIL_LIBRARY} ${FFMPEG_AVFORMAT_LIBRARY} ${FFMPEG_AVRESAMPLE_LIBRARY})
 MARK_AS_ADVANCED(FFMPEG_LIBRARY)
 
 # handle the QUIETLY and REQUIRED arguments and set FFMPEG_FOUND to TRUE if 
diff --git a/conf/FindFreetype.cmake b/conf/FindFreetype.cmake
index a04d185..001ce35 100644
--- a/conf/FindFreetype.cmake
+++ b/conf/FindFreetype.cmake
@@ -52,9 +52,13 @@ FIND_PATH(FREETYPE_INCLUDE_DIR_ft2build ft2build.h
   /sw/include
   /opt/local/include
   /usr/freeware/include
+  PATH_SUFFIXES freetype2
 )
 
-FIND_PATH(FREETYPE_INCLUDE_DIR_freetype2 freetype/config/ftheader.h 
+FIND_PATH(FREETYPE_INCLUDE_DIR_freetype2
+  NAMES
+  freetype/config/ftheader.h
+  config/ftheader.h
   HINTS
   $ENV{FREETYPE_DIR}/include/freetype2
   PATHS
diff --git a/conf/FindLLVM.cmake b/conf/FindLLVM.cmake
index 7bd52e2..51b776c 100644
--- a/conf/FindLLVM.cmake
+++ b/conf/FindLLVM.cmake
@@ -51,6 +51,9 @@ else (LLVM_INCLUDE_DIR)
     /usr/lib/llvm-2.8/bin
     /usr/lib/llvm-2.9/bin
     /usr/lib/llvm-3.0/bin
+    /usr/lib/llvm-3.1/bin
+    /usr/lib/llvm-3.2/bin
+    /usr/lib/llvm-3.3/bin
     )
 
   find_program(LLVM_GCC_EXECUTABLE
@@ -147,6 +150,7 @@ else (LLVM_INCLUDE_DIR)
   exec_program(${LLVM_CONFIG_EXECUTABLE} ARGS --libdir OUTPUT_VARIABLE LLVM_LIB_DIR )
   #MESSAGE(STATUS "LLVM lib dir: " ${LLVM_LIB_DIR})
   exec_program(${LLVM_CONFIG_EXECUTABLE} ARGS --includedir OUTPUT_VARIABLE LLVM_INCLUDE_DIR )
+  #MESSAGE(STATUS "LLVM include dir: " ${LLVM_INCLUDE_DIR})
   
   INCLUDE(CheckIncludeFileCXX)
   set(CMAKE_REQUIRED_INCLUDES ${LLVM_INCLUDE_DIR})
@@ -158,7 +162,7 @@ else (LLVM_INCLUDE_DIR)
   ENDIF(HAVE_SUPPORT_TARGETSELECT_H)
 
   set(CMAKE_REQUIRED_INCLUDES ${LLVM_INCLUDE_DIR})
-  set(CMAKE_REQUIRED_DEFINITIONS -D__STDC_LIMIT_MACROS=1 -D__STDC_CONSTANT_MACROS=1)
+  set(CMAKE_REQUIRED_DEFINITIONS -D__STDC_LIMIT_MACROS=1 -D__STDC_CONSTANT_MACROS=1 -std=c++11)
   check_include_file_cxx("llvm/IRBuilder.h" HAVE_IRBUILDER_H)
   unset(CMAKE_REQUIRED_INCLUDES)
   MESSAGE(STATUS "HAVE_IRBUILDER_H: " ${HAVE_IRBUILDER_H})
@@ -168,23 +172,48 @@ else (LLVM_INCLUDE_DIR)
 
   set(CMAKE_REQUIRED_INCLUDES ${LLVM_INCLUDE_DIR})
   check_include_file_cxx("llvm/DataLayout.h" HAVE_DATALAYOUT_H)
+  check_include_file_cxx("llvm/IR/DataLayout.h" HAVE_IR_DATALAYOUT_H)
+  check_include_file_cxx("llvm/IR/Verifier.h" HAVE_IR_VERIFIER_H)
   unset(CMAKE_REQUIRED_INCLUDES)
   MESSAGE(STATUS "HAVE_DATALAYOUT_H: " ${HAVE_DATALAYOUT_H})
+  MESSAGE(STATUS "HAVE_IR_DATALAYOUT_H: " ${HAVE_IR_DATALAYOUT_H})
+  MESSAGE(STATUS "HAVE_IR_VERIFIER_H: " ${HAVE_IR_VERIFIER_H})
   IF(HAVE_DATALAYOUT_H)
     ADD_DEFINITIONS(-DHAVE_DATALAYOUT_H)
   ENDIF(HAVE_DATALAYOUT_H)
+  IF(HAVE_IR_DATALAYOUT_H)
+    ADD_DEFINITIONS(-DHAVE_IR_DATALAYOUT_H)
+  ENDIF(HAVE_IR_DATALAYOUT_H)
+  IF(HAVE_IR_VERIFIER_H)
+    ADD_DEFINITIONS(-DHAVE_IR_VERIFIER_H)
+  ENDIF(HAVE_IR_VERIFIER_H)
   
   exec_program(${LLVM_CONFIG_EXECUTABLE} ARGS --cxxflags  OUTPUT_VARIABLE LLVM_COMPILE_FLAGS )
   MESSAGE(STATUS "LLVM CXX flags: " ${LLVM_COMPILE_FLAGS})
   exec_program(${LLVM_CONFIG_EXECUTABLE} ARGS --ldflags   OUTPUT_VARIABLE LLVM_LDFLAGS )
   MESSAGE(STATUS "LLVM LD flags: " ${LLVM_LDFLAGS})
-  FIND_LLVM_LIBS( ${LLVM_CONFIG_EXECUTABLE} "core ipa ipo instrumentation bitreader bitwriter linker" LLVM_LIBS_CORE LLVM_LIBS_CORE_OBJECTS )
+  exec_program( ${LLVM_CONFIG_EXECUTABLE} ARGS --system-libs  OUTPUT_VARIABLE LLVM_SYSTEM_LIBS RETURN_VALUE LLVM_SYSTEM_LIBS_FAILED)
+  if(LLVM_SYSTEM_LIBS_FAILED)
+    SET(LLVM_SYSTEM_LIBS "")
+  endif(LLVM_SYSTEM_LIBS_FAILED)
+  FIND_LLVM_LIBS( ${LLVM_CONFIG_EXECUTABLE} "core ipa ipo instrumentation bitreader bitwriter linker" LLVM_LIBS_CORE_ONLY LLVM_LIBS_CORE_OBJECTS )
+  SET(LLVM_LIBS_CORE ${LLVM_LIBS_CORE_ONLY} ${LLVM_SYSTEM_LIBS})
+  UNSET(LLVM_LIBS_CORE_ONLY)
+  UNSET(LLVM_SYSTEM_LIBS_FAILED)
   MESSAGE(STATUS "LLVM core libs: " ${LLVM_LIBS_CORE})
+  IF(${LLVM_STRING_VERSION} VERSION_GREATER 3.5)
+  IF(APPLE AND UNIVERSAL)
+    FIND_LLVM_LIBS( ${LLVM_CONFIG_EXECUTABLE} "engine native x86 PowerPC ARM" LLVM_LIBS_JIT LLVM_LIBS_JIT_OBJECTS )
+  ELSE(APPLE AND UNIVERSAL)
+    FIND_LLVM_LIBS( ${LLVM_CONFIG_EXECUTABLE} "engine native" LLVM_LIBS_JIT LLVM_LIBS_JIT_OBJECTS )
+  ENDIF(APPLE AND UNIVERSAL)
+  ELSE(${LLVM_STRING_VERSION} VERSION_GREATER 3.5)
   IF(APPLE AND UNIVERSAL)
     FIND_LLVM_LIBS( ${LLVM_CONFIG_EXECUTABLE} "jit native x86 PowerPC ARM" LLVM_LIBS_JIT LLVM_LIBS_JIT_OBJECTS )
   ELSE(APPLE AND UNIVERSAL)
     FIND_LLVM_LIBS( ${LLVM_CONFIG_EXECUTABLE} "jit native" LLVM_LIBS_JIT LLVM_LIBS_JIT_OBJECTS )
   ENDIF(APPLE AND UNIVERSAL)
+  ENDIF(${LLVM_STRING_VERSION} VERSION_GREATER 3.5)
   MESSAGE(STATUS "LLVM JIT libs: " ${LLVM_LIBS_JIT})
   MESSAGE(STATUS "LLVM JIT objs: " ${LLVM_LIBS_JIT_OBJECTS})
   
diff --git a/debian/control b/debian/control
index 6dfcb9b..0ef2874 100644
--- a/debian/control
+++ b/debian/control
@@ -2,7 +2,7 @@ Source: lightspark
 Section: utils
 Priority: optional
 Maintainer: Alessandro Pignotti <a.pignotti at sssup.it>
-Build-Depends: g++ (>=4.5), gnash, cmake, cdbs, nasm, debhelper (>= 7), llvm-3.0-dev, libgl1-mesa-dev, libxext-dev, libcurl4-gnutls-dev | libcurl4-openssl-dev, libxml2-dev, zlib1g-dev, libavcodec-dev, libpcre3-dev, libglew1.5-dev, libboost-filesystem-dev, libboost-system-dev, libxml++2.6-dev (>= 2.33.1), libcairo2-dev, libgtk2.0-dev, libjpeg8-dev, libavformat-dev, libpango1.0-dev, libpulse-dev, librtmp-dev, liblzma-dev
+Build-Depends: g++ (>=4.5), gnash, cmake, cdbs, nasm, debhelper (>= 7), llvm-dev, libgl1-mesa-dev, libxext-dev, libcurl4-gnutls-dev | libcurl4-openssl-dev, libxml2-dev, zlib1g-dev, libavcodec-dev, libpcre3-dev, libglew1.5-dev, libboost-filesystem-dev, libboost-system-dev, libxml++2.6-dev (>= 2.33.1), libcairo2-dev, libgtk2.0-dev, libjpeg8-dev, libavformat-dev, libavresample-dev, libpango1.0-dev, libpulse-dev, librtmp-dev, liblzma-dev, libfreetype6-dev, libpng-dev
 Standards-Version: 3.8.4
 Homepage: http://lightspark.sf.net
 Vcs-git: git://github.com/alexp-sssup/lightspark.git
diff --git a/docs/man/lightspark.1 b/docs/man/lightspark.1
index 83f3526..ee38e95 100644
--- a/docs/man/lightspark.1
+++ b/docs/man/lightspark.1
@@ -2,7 +2,7 @@
 .\" First parameter, NAME, should be all caps
 .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
 .\" other parameters are allowed: see man(7), man(1)
-.TH LIGHTSPARK 1 "May 29, 2010"
+.TH LIGHTSPARK 1 "November 9, 2013"
 .\" Please adjust this date whenever revising the manpage.
 .\"
 .\" Some roff macros, for reference:
@@ -19,15 +19,15 @@
 lightspark \- a free Flash player
 .SH SYNOPSIS
 .B lightspark 
-[\-\-url|\-u http://loader.url/file.swf] [\-\-disable-interpreter|\-ni] [\-\-enable\-jit|\-j] [\-\-log\-level|\-l 0-4] [\-\-parameters\-file|\-p params-file] [\-\-version|\-v] file.swf
+[\-\-url|\-u http://loader.url/file.swf] [\-\-air] [\-\-disable-interpreter|\-ni] [\-\-enable-fast-interpreter|\-fi] [\-\-enable\-jit|\-j] [\-\-log\-level|\-l 0-4] [\-\-parameters\-file|\-p params-file] [\-\-profiling-output|\-o] [\-\-security-sandbox|\-s <sandbox type>] [\-\-exit-on-error] [\-\-HTTP-cookies <cookie>] [\-\-version|\-v] file.swf
 .SH DESCRIPTION
 .B Lightspark
 is a free, modern Flash Player implementation, this documents the options accepted by the standalone version of the program.
 .PP
 .\" TeX users may be more comfortable with the \fB<whatever>\fP and
-.\" \fI<whatever>\fP escape sequences to invode bold face and italics,
+.\" \fI<whatever>\fP escape sequences to invoke bold face and italics,
 .\" respectively.
-The player is currently in Beta, support for any particular SWF file is not guaranteed
+The player is currently in Beta, support for any particular SWF file is not guaranteed.
 .PP
 You might wish to see the project website at http://lightspark.sf.net or our 
 technical blog at http://allievi.sssup.it/techblog
@@ -41,6 +41,10 @@ Pretends to be loading the file from an url
 .IP
 Disable the ActionScript interpreter
 .HP 
+\fB\-\-enable-fast-interpreter\fP
+.IP
+Enable an experimental optimized ActionScript interpreter
+.HP 
 \fB\-\-enable-jit\fP, \fB\-j\fP
 .IP
 Enable the ActionScript JIT compilation engine
@@ -56,6 +60,22 @@ Load flash parameters from file. Every odd line will be interpreted as a paramet
 \fB\-\-profiling-output\fP profiling-file, \fB\-o\fP profiling-file
 .IP
 Output profiling data to profiling-file in a callgrind/KCachegrind compatible format
+.HP 
+\fB\-\-security-sandbox\fP type, \fB\-s\fP type
+.IP
+Run a Flash file in a given sandbox to control access to network and local files. The possible types are: remote (default), local-with-filesystem, local-with-networking, local-trusted.
+.HP
+\fB\-\-exit-on-error\fP
+.IP
+Exit as soon as the first error is encountered.
+.HP
+\fB\-\-HTTP-cookies\fP cookie
+.IP
+Set cookie to be used in HTTP requests.
+.HP
+\fB\-\-air\fP
+.IP
+Run as an AIR application: grant permission to access both local files and network, and enable AIR APIs.
 .HP
 \fB\-\-version\fP, \fB\-v\fP
 .IP
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index e86fb44..2f9c824 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -47,6 +47,7 @@ SET(LIBSPARK_SOURCES
   backends/rendering_context.cpp
   backends/rtmputils.cpp
   backends/security.cpp
+  backends/streamcache.cpp
   backends/urlutils.cpp
   backends/xml_support.cpp
   parsing/amf3_generator.cpp
@@ -65,6 +66,8 @@ SET(LIBSPARK_SOURCES
   scripting/abc_opcodes.cpp
   scripting/abctypes.cpp
   scripting/flash/accessibility/flashaccessibility.cpp
+  scripting/flash/concurrent/Mutex.cpp
+  scripting/flash/concurrent/Condition.cpp
   scripting/flash/desktop/flashdesktop.cpp
   scripting/flash/display/BitmapContainer.cpp
   scripting/flash/display/BitmapData.cpp
@@ -72,22 +75,45 @@ SET(LIBSPARK_SOURCES
   scripting/flash/display/IBitmapDrawable.cpp
   scripting/flash/display/flashdisplay.cpp
   scripting/flash/display/TokenContainer.cpp
+  scripting/flash/display/Graphics.cpp
+  scripting/flash/display/GraphicsBitmapFill.cpp
+  scripting/flash/display/GraphicsEndFill.cpp
+  scripting/flash/display/GraphicsGradientFill.cpp
+  scripting/flash/display/GraphicsPath.cpp
+  scripting/flash/display/GraphicsShaderFill.cpp
+  scripting/flash/display/GraphicsSolidFill.cpp
+  scripting/flash/display/GraphicsStroke.cpp
+  scripting/flash/display/GraphicsTrianglePath.cpp
   scripting/flash/events/flashevents.cpp
   scripting/flash/external/ExternalInterface.cpp
   scripting/flash/filters/flashfilters.cpp
+  scripting/flash/filesystem/flashfilesystem.cpp
   scripting/flash/geom/flashgeom.cpp
   scripting/flash/media/flashmedia.cpp
   scripting/flash/net/flashnet.cpp
   scripting/flash/net/URLRequestHeader.cpp
   scripting/flash/net/URLStream.cpp
   scripting/flash/net/XMLSocket.cpp
+  scripting/flash/net/NetStreamPlayOptions.cpp
+  scripting/flash/net/NetStreamPlayTransitions.cpp
+  scripting/flash/printing/flashprinting.cpp
   scripting/flash/errors/flasherrors.cpp
   scripting/flash/sensors/flashsensors.cpp
   scripting/flash/system/flashsystem.cpp
   scripting/flash/text/flashtext.cpp
   scripting/flash/text/flashtextengine.cpp
   scripting/flash/utils/flashutils.cpp
+  scripting/flash/utils/ByteArray.cpp
+  scripting/flash/utils/Dictionary.cpp
+  scripting/flash/utils/Proxy.cpp
+  scripting/flash/utils/Timer.cpp
+  scripting/flash/utils/IntervalManager.cpp
+  scripting/flash/utils/IntervalRunner.cpp
   scripting/flash/ui/Keyboard.cpp
+  scripting/flash/ui/Mouse.cpp
+  scripting/flash/ui/ContextMenu.cpp
+  scripting/flash/ui/ContextMenuItem.cpp
+  scripting/flash/ui/ContextMenuBuiltInItems.cpp
   scripting/flash/xml/flashxml.cpp
   scripting/toplevel/Array.cpp
   scripting/toplevel/ASString.cpp
@@ -95,6 +121,7 @@ SET(LIBSPARK_SOURCES
   scripting/toplevel/Date.cpp
   scripting/toplevel/Error.cpp
   scripting/toplevel/Integer.cpp
+  scripting/toplevel/JSON.cpp
   scripting/toplevel/Math.cpp
   scripting/toplevel/Number.cpp
   scripting/toplevel/RegExp.cpp
diff --git a/src/allclasses.cpp b/src/allclasses.cpp
index 8b9a47c..e3c559f 100644
--- a/src/allclasses.cpp
+++ b/src/allclasses.cpp
@@ -19,24 +19,50 @@
 
 #include "scripting/toplevel/ASString.h"
 #include "scripting/toplevel/Date.h"
+#include "scripting/toplevel/JSON.h"
 #include "scripting/toplevel/Math.h"
 #include "scripting/toplevel/RegExp.h"
 #include "scripting/toplevel/Vector.h"
 #include "scripting/toplevel/XML.h"
 #include "scripting/toplevel/XMLList.h"
 #include "scripting/flash/accessibility/flashaccessibility.h"
+#include "scripting/flash/concurrent/Mutex.h"
+#include "scripting/flash/concurrent/Condition.h"
 #include "scripting/flash/desktop/flashdesktop.h"
 #include "scripting/flash/display/flashdisplay.h"
 #include "scripting/flash/display/BitmapData.h"
+#include "scripting/flash/display/Graphics.h"
+#include "scripting/flash/display/GraphicsBitmapFill.h"
+#include "scripting/flash/display/GraphicsEndFill.h"
+#include "scripting/flash/display/GraphicsGradientFill.h"
+#include "scripting/flash/display/GraphicsPath.h"
+#include "scripting/flash/display/GraphicsShaderFill.h"
+#include "scripting/flash/display/GraphicsSolidFill.h"
+#include "scripting/flash/display/GraphicsStroke.h"
+#include "scripting/flash/display/GraphicsTrianglePath.h"
+#include "scripting/flash/display/IGraphicsData.h"
+#include "scripting/flash/display/IGraphicsFill.h"
+#include "scripting/flash/display/IGraphicsPath.h"
+#include "scripting/flash/display/IGraphicsStroke.h"
 #include "scripting/flash/events/flashevents.h"
+#include "scripting/flash/filesystem/flashfilesystem.h"
 #include "scripting/flash/filters/flashfilters.h"
 #include "scripting/flash/net/flashnet.h"
 #include "scripting/flash/net/URLRequestHeader.h"
 #include "scripting/flash/net/URLStream.h"
 #include "scripting/flash/net/XMLSocket.h"
+#include "scripting/flash/net/NetStreamPlayOptions.h"
+#include "scripting/flash/net/NetStreamPlayTransitions.h"
+#include "scripting/flash/printing/flashprinting.h"
 #include "scripting/flash/system/flashsystem.h"
 #include "scripting/flash/sensors/flashsensors.h"
 #include "scripting/flash/utils/flashutils.h"
+#include "scripting/flash/utils/ByteArray.h"
+#include "scripting/flash/utils/Dictionary.h"
+#include "scripting/flash/utils/Proxy.h"
+#include "scripting/flash/utils/Timer.h"
+#include "scripting/flash/utils/IntervalManager.h"
+#include "scripting/flash/utils/IntervalRunner.h"
 #include "scripting/flash/geom/flashgeom.h"
 #include "scripting/flash/external/ExternalInterface.h"
 #include "scripting/flash/media/flashmedia.h"
@@ -45,6 +71,10 @@
 #include "scripting/flash/text/flashtext.h"
 #include "scripting/flash/text/flashtextengine.h"
 #include "scripting/flash/ui/Keyboard.h"
+#include "scripting/flash/ui/Mouse.h"
+#include "scripting/flash/ui/ContextMenu.h"
+#include "scripting/flash/ui/ContextMenuItem.h"
+#include "scripting/flash/ui/ContextMenuBuiltInItems.h"
 
 using namespace lightspark;
 
diff --git a/src/allclasses.h b/src/allclasses.h
index dbb3a2c..27fc777 100644
--- a/src/allclasses.h
+++ b/src/allclasses.h
@@ -28,6 +28,7 @@ REGISTER_CLASS_NAME(Date,"")
 REGISTER_CLASS_NAME2(Global,"global","")
 REGISTER_CLASS_NAME2(IFunction,"Function","")
 REGISTER_CLASS_NAME2(Integer,"int","")
+REGISTER_CLASS_NAME(JSON,"")
 REGISTER_CLASS_NAME(Math,"")
 REGISTER_CLASS_NAME(Namespace,"")
 REGISTER_CLASS_NAME(Number,"")
@@ -52,9 +53,14 @@ REGISTER_CLASS_NAME(XMLList,"")
 REGISTER_CLASS_NAME(Vector,"__AS3__.vec")
 
 //Accessibility
+REGISTER_CLASS_NAME(Accessibility,"flash.accessibility")
 REGISTER_CLASS_NAME(AccessibilityProperties,"flash.accessibility")
 REGISTER_CLASS_NAME(AccessibilityImplementation,"flash.accessibility")
 
+//Concurrent
+REGISTER_CLASS_NAME(ASMutex,"flash.concurrent")
+REGISTER_CLASS_NAME(ASCondition,"flash.concurrent")
+
 //Desktop (AIR)
 REGISTER_CLASS_NAME(NativeApplication,"flash.desktop")
 
@@ -69,6 +75,20 @@ REGISTER_CLASS_NAME(DisplayObjectContainer,"flash.display")
 REGISTER_CLASS_NAME(FrameLabel,"flash.display")
 REGISTER_CLASS_NAME(GradientType,"flash.display")
 REGISTER_CLASS_NAME(Graphics,"flash.display")
+REGISTER_CLASS_NAME(GraphicsBitmapFill,"flash.display")
+REGISTER_CLASS_NAME(GraphicsEndFill,"flash.display")
+REGISTER_CLASS_NAME(GraphicsGradientFill,"flash.display")
+REGISTER_CLASS_NAME(GraphicsPath,"flash.display")
+REGISTER_CLASS_NAME(GraphicsPathCommand,"flash.display")
+REGISTER_CLASS_NAME(GraphicsPathWinding,"flash.display")
+REGISTER_CLASS_NAME(GraphicsShaderFill,"flash.display")
+REGISTER_CLASS_NAME(GraphicsSolidFill,"flash.display")
+REGISTER_CLASS_NAME(GraphicsStroke,"flash.display")
+REGISTER_CLASS_NAME(GraphicsTrianglePath,"flash.display")
+REGISTER_CLASS_NAME(IGraphicsData,"flash.display")
+REGISTER_CLASS_NAME(IGraphicsFill,"flash.display")
+REGISTER_CLASS_NAME(IGraphicsPath,"flash.display")
+REGISTER_CLASS_NAME(IGraphicsStroke,"flash.display")
 REGISTER_CLASS_NAME(IBitmapDrawable,"flash.display")
 REGISTER_CLASS_NAME(InteractiveObject,"flash.display")
 REGISTER_CLASS_NAME(InterpolationMethod,"flash.display")
@@ -91,6 +111,7 @@ REGISTER_CLASS_NAME(StageQuality,"flash.display")
 
 //Events
 REGISTER_CLASS_NAME(AsyncErrorEvent,"flash.events")
+REGISTER_CLASS_NAME(ContextMenuEvent,"flash.events")
 REGISTER_CLASS_NAME(DRMErrorEvent,"flash.events")
 REGISTER_CLASS_NAME(DRMStatusEvent,"flash.events")
 REGISTER_CLASS_NAME(DataEvent,"flash.events")
@@ -100,6 +121,7 @@ REGISTER_CLASS_NAME(EventDispatcher,"flash.events")
 REGISTER_CLASS_NAME(EventPhase,"flash.events")
 REGISTER_CLASS_NAME(FocusEvent,"flash.events")
 REGISTER_CLASS_NAME(FullScreenEvent,"flash.events")
+REGISTER_CLASS_NAME(GestureEvent,"flash.events")
 REGISTER_CLASS_NAME(HTTPStatusEvent,"flash.events")
 REGISTER_CLASS_NAME(IEventDispatcher,"flash.events")
 REGISTER_CLASS_NAME(IOErrorEvent,"flash.events")
@@ -107,6 +129,7 @@ REGISTER_CLASS_NAME(InvokeEvent,"flash.events")
 REGISTER_CLASS_NAME(KeyboardEvent,"flash.events")
 REGISTER_CLASS_NAME(MouseEvent,"flash.events")
 REGISTER_CLASS_NAME(NetStatusEvent,"flash.events")
+REGISTER_CLASS_NAME(PressAndTapGestureEvent,"flash.events")
 REGISTER_CLASS_NAME(ProgressEvent,"flash.events")
 REGISTER_CLASS_NAME(SecurityErrorEvent,"flash.events")
 REGISTER_CLASS_NAME(StageVideoEvent,"flash.events")
@@ -114,14 +137,32 @@ REGISTER_CLASS_NAME(StageVideoAvailabilityEvent,"flash.events")
 REGISTER_CLASS_NAME(StatusEvent,"flash.events")
 REGISTER_CLASS_NAME(TextEvent,"flash.events")
 REGISTER_CLASS_NAME(TimerEvent,"flash.events")
+REGISTER_CLASS_NAME(TouchEvent,"flash.events")
+REGISTER_CLASS_NAME(TransformGestureEvent,"flash.events")
+REGISTER_CLASS_NAME(UncaughtErrorEvent,"flash.events")
+REGISTER_CLASS_NAME(UncaughtErrorEvents,"flash.events")
+REGISTER_CLASS_NAME(VideoEvent,"flash.events")
 
 //External interface (browser interaction)
 REGISTER_CLASS_NAME(ExternalInterface,"flash.external")
 
+//filesystem
+REGISTER_CLASS_NAME(FileStream,"flash.filesystem")
+
 //Filters
 REGISTER_CLASS_NAME(BitmapFilter,"flash.filters")
+REGISTER_CLASS_NAME(BitmapFilterQuality,"flash.filters")
 REGISTER_CLASS_NAME(DropShadowFilter,"flash.filters")
 REGISTER_CLASS_NAME(GlowFilter,"flash.filters")
+REGISTER_CLASS_NAME(GradientGlowFilter,"flash.filters")
+REGISTER_CLASS_NAME(BevelFilter,"flash.filters")
+REGISTER_CLASS_NAME(ColorMatrixFilter,"flash.filters")
+REGISTER_CLASS_NAME(BlurFilter,"flash.filters")
+REGISTER_CLASS_NAME(ConvolutionFilter,"flash.filters")
+REGISTER_CLASS_NAME(DisplacementMapFilter,"flash.filters")
+REGISTER_CLASS_NAME(GradientBevelFilter,"flash.filters")
+REGISTER_CLASS_NAME(ShaderFilter,"flash.filters")
+
 
 //Geom
 REGISTER_CLASS_NAME(ColorTransform,"flash.geom")
@@ -130,6 +171,8 @@ REGISTER_CLASS_NAME(Point,"flash.geom")
 REGISTER_CLASS_NAME2(Rectangle,"Rectangle","flash.geom")
 REGISTER_CLASS_NAME(Transform,"flash.geom")
 REGISTER_CLASS_NAME(Vector3D,"flash.geom")
+REGISTER_CLASS_NAME(Matrix3D,"flash.geom")
+REGISTER_CLASS_NAME(PerspectiveProjection,"flash.geom")
 
 //Media
 REGISTER_CLASS_NAME(Sound,"flash.media")
@@ -142,11 +185,18 @@ REGISTER_CLASS_NAME(Video,"flash.media")
 REGISTER_CLASS_NAME(VideoStatus,"flash.media")
 
 //Net
+REGISTER_CLASS_NAME(LocalConnection,"flash.net")
 REGISTER_CLASS_NAME(NetConnection,"flash.net")
+REGISTER_CLASS_NAME(NetGroup,"flash.net")
 REGISTER_CLASS_NAME(NetStream,"flash.net")
+REGISTER_CLASS_NAME(NetStreamAppendBytesAction,"flash.net")
+REGISTER_CLASS_NAME(NetStreamPlayTransitions,"flash.net")
+REGISTER_CLASS_NAME(NetStreamPlayOptions,"flash.net")
 REGISTER_CLASS_NAME(ObjectEncoding,"flash.net")
 REGISTER_CLASS_NAME(Responder,"flash.net")
 REGISTER_CLASS_NAME(SharedObject,"flash.net")
+REGISTER_CLASS_NAME(SharedObjectFlushStatus,"flash.net")
+REGISTER_CLASS_NAME(ASSocket,"flash.net")
 REGISTER_CLASS_NAME(URLLoader,"flash.net")
 REGISTER_CLASS_NAME(URLLoaderDataFormat,"flash.net")
 REGISTER_CLASS_NAME(URLRequest,"flash.net")
@@ -156,6 +206,13 @@ REGISTER_CLASS_NAME(URLStream,"flash.net")
 REGISTER_CLASS_NAME(URLVariables,"flash.net")
 REGISTER_CLASS_NAME(XMLSocket,"flash.net")
 
+REGISTER_CLASS_NAME(DRMManager,"flash.net.drm")
+
+//Printing
+REGISTER_CLASS_NAME(PrintJob,"flash.printing")
+REGISTER_CLASS_NAME(PrintJobOptions,"flash.printing")
+REGISTER_CLASS_NAME(PrintJobOrientation,"flash.printing")
+
 //Errors
 REGISTER_CLASS_NAME(EOFError,"flash.errors")
 REGISTER_CLASS_NAME(IOError,"flash.errors")
@@ -175,6 +232,7 @@ REGISTER_CLASS_NAME(LoaderContext,"flash.system")
 REGISTER_CLASS_NAME(Security,"flash.system")
 REGISTER_CLASS_NAME(SecurityDomain,"flash.system")
 REGISTER_CLASS_NAME(System,"flash.system")
+REGISTER_CLASS_NAME(ASWorker,"flash.system")
 
 //Text
 REGISTER_CLASS_NAME2(ASFont,"Font","flash.text")
@@ -189,18 +247,28 @@ REGISTER_CLASS_NAME(TextFieldAutoSize,"flash.text")
 REGISTER_CLASS_NAME(TextFieldType,"flash.text")
 REGISTER_CLASS_NAME(TextFormat,"flash.text")
 REGISTER_CLASS_NAME(TextFormatAlign,"flash.text")
+REGISTER_CLASS_NAME(TextInteractionMode,"flash.text")
 REGISTER_CLASS_NAME(TextLineMetrics,"flash.text")
 REGISTER_CLASS_NAME(StaticText,"flash.text")
 REGISTER_CLASS_NAME(StyleSheet,"flash.text")
 
 //Text engine
 REGISTER_CLASS_NAME(ContentElement,"flash.text.engine")
+REGISTER_CLASS_NAME(EastAsianJustifier,"flash.text.engine")
 REGISTER_CLASS_NAME(ElementFormat,"flash.text.engine")
 REGISTER_CLASS_NAME(FontDescription,"flash.text.engine")
+REGISTER_CLASS_NAME(FontMetrics,"flash.text.engine")
+REGISTER_CLASS_NAME(FontLookup,"flash.text.engine")
 REGISTER_CLASS_NAME(FontWeight,"flash.text.engine")
+REGISTER_CLASS_NAME(Kerning,"flash.text.engine")
+REGISTER_CLASS_NAME(LineJustification,"flash.text.engine")
+REGISTER_CLASS_NAME(SpaceJustifier,"flash.text.engine")
+REGISTER_CLASS_NAME(TextBaseline,"flash.text.engine")
 REGISTER_CLASS_NAME(TextBlock,"flash.text.engine")
 REGISTER_CLASS_NAME(TextElement,"flash.text.engine")
+REGISTER_CLASS_NAME(TextJustifier,"flash.text.engine")
 REGISTER_CLASS_NAME(TextLine,"flash.text.engine")
+REGISTER_CLASS_NAME(TextLineValidity,"flash.text.engine")
 
 //Utils
 REGISTER_CLASS_NAME(ByteArray,"flash.utils")
@@ -216,6 +284,10 @@ REGISTER_CLASS_NAME(Timer,"flash.utils")
 REGISTER_CLASS_NAME(Keyboard,"flash.ui")
 REGISTER_CLASS_NAME(KeyboardType,"flash.ui")
 REGISTER_CLASS_NAME(KeyLocation,"flash.ui")
+REGISTER_CLASS_NAME(Mouse,"flash.ui")
+REGISTER_CLASS_NAME(ContextMenu,"flash.ui")
+REGISTER_CLASS_NAME(ContextMenuItem,"flash.ui")
+REGISTER_CLASS_NAME(ContextMenuBuiltInItems,"flash.ui")
 
 //XML
 REGISTER_CLASS_NAME(XMLDocument,"flash.xml")
diff --git a/src/asobject.cpp b/src/asobject.cpp
index f11f461..3253e27 100644
--- a/src/asobject.cpp
+++ b/src/asobject.cpp
@@ -24,6 +24,7 @@
 #include <limits>
 #include "compat.h"
 #include "parsing/amf3_generator.h"
+#include "scripting/argconv.h"
 #include "scripting/toplevel/ASString.h"
 #include "scripting/toplevel/Date.h"
 #include "scripting/toplevel/XML.h"
@@ -37,7 +38,13 @@ string ASObject::toDebugString()
 {
 	check();
 	string ret;
-	if(getClass())
+	if(this->is<Class_base>())
+	{
+		ret = "[class ";
+		ret+=this->as<Class_base>()->class_name.getQualifiedName().raw_buf();
+		ret+="]";
+	}
+	else if(getClass())
 	{
 		ret="[object ";
 		ret+=getClass()->class_name.name.raw_buf();
@@ -47,11 +54,9 @@ string ASObject::toDebugString()
 		ret = "Undefined";
 	else if(this->is<Null>())
 		ret = "Null";
-	else if(this->is<Class_base>())
+	else if(this->is<Template_base>())
 	{
-		ret = "[class ";
-		ret+=this->as<Class_base>()->class_name.getQualifiedName().raw_buf();
-		ret+="]";
+		ret = "[templated class]";
 	}
 	else
 	{
@@ -60,6 +65,33 @@ string ASObject::toDebugString()
 	return ret;
 }
 
+void ASObject::setProxyProperty(const multiname &name)
+{
+	if (this->proxyMultiName)
+		this->proxyMultiName->ns.clear();
+	else
+		this->proxyMultiName = new (getVm()->vmDataMemory) multiname(getVm()->vmDataMemory);
+	this->proxyMultiName->isAttribute = name.isAttribute;
+	this->proxyMultiName->ns.reserve(name.ns.size());
+	for(unsigned int i=0;i<name.ns.size();i++)
+	{
+		this->proxyMultiName->ns.push_back(name.ns[i]);
+	}
+	
+}
+
+void ASObject::applyProxyProperty(multiname &name)
+{
+	if (!this->proxyMultiName)
+		return;
+	name.isAttribute = this->proxyMultiName->isAttribute;
+	name.ns.clear();
+	name.ns.reserve(this->proxyMultiName->ns.size());
+	for(unsigned int i=0;i<this->proxyMultiName->ns.size();i++)
+	{
+		name.ns.push_back(this->proxyMultiName->ns[i]);
+	}
+}
 tiny_string ASObject::toString()
 {
 	check();
@@ -85,6 +117,14 @@ tiny_string ASObject::toString()
 	}
 }
 
+tiny_string ASObject::toLocaleString()
+{
+	_NR<ASObject> str = executeASMethod("toLocaleString", {""}, NULL, 0);
+	if (str.isNull())
+		return "";
+	return str->toString();
+}
+
 TRISTATE ASObject::isLess(ASObject* r)
 {
 	check();
@@ -105,7 +145,7 @@ int variables_map::getNextEnumerable(unsigned int start) const
 		++it;
 	}
 
-	while(it->second.kind!=DYNAMIC_TRAIT)
+	while(it->second.kind!=DYNAMIC_TRAIT || !it->second.isenumerable)
 	{
 		++i;
 		++it;
@@ -141,14 +181,15 @@ _R<ASObject> ASObject::nextValue(uint32_t index)
 void ASObject::sinit(Class_base* c)
 {
 	c->setDeclaredMethodByQName("hasOwnProperty",AS3,Class<IFunction>::getFunction(hasOwnProperty),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("setPropertyIsEnumerable",AS3,Class<IFunction>::getFunction(setPropertyIsEnumerable),NORMAL_METHOD,true);
 
 	c->prototype->setVariableByQName("toString","",Class<IFunction>::getFunction(_toString),DYNAMIC_TRAIT);
-	c->prototype->setVariableByQName("toLocaleString","",Class<IFunction>::getFunction(_toString),DYNAMIC_TRAIT);
+	c->prototype->setVariableByQName("toLocaleString","",Class<IFunction>::getFunction(_toLocaleString),DYNAMIC_TRAIT);
 	c->prototype->setVariableByQName("valueOf","",Class<IFunction>::getFunction(valueOf),DYNAMIC_TRAIT);
 	c->prototype->setVariableByQName("hasOwnProperty","",Class<IFunction>::getFunction(hasOwnProperty),DYNAMIC_TRAIT);
 	c->prototype->setVariableByQName("isPrototypeOf","",Class<IFunction>::getFunction(isPrototypeOf),DYNAMIC_TRAIT);
 	c->prototype->setVariableByQName("propertyIsEnumerable","",Class<IFunction>::getFunction(propertyIsEnumerable),DYNAMIC_TRAIT);
-	
+
 }
 
 void ASObject::buildTraits(ASObject* o)
@@ -166,6 +207,8 @@ bool ASObject::isEqual(ASObject* r)
 	{
 		case T_NULL:
 		case T_UNDEFINED:
+			if (!this->isConstructed() && !this->is<Class_base>())
+				return true;
 			return false;
 		case T_NUMBER:
 		case T_INTEGER:
@@ -190,6 +233,8 @@ bool ASObject::isEqual(ASObject* r)
 				return x->toString()==toString();
 		}
 	}
+	if (r->is<ObjectConstructor>())
+		return this == r->getClass();
 
 	LOG(LOG_CALLS,_("Equal comparison between type ")<<getObjectType()<< _(" and type ") << r->getObjectType());
 	if(classdef)
@@ -215,7 +260,7 @@ uint16_t ASObject::toUInt16()
 
 int32_t ASObject::toInt()
 {
-	return 0;
+	return toPrimitive()->toInt();
 }
 
 /* Implements ECMA's ToPrimitive (9.1) and [[DefaultValue]] (8.6.2.6) */
@@ -328,6 +373,46 @@ _R<ASObject> ASObject::call_toString()
 	return _MR(ret);
 }
 
+bool ASObject::has_toJSON()
+{
+	multiname toJSONName(NULL);
+	toJSONName.name_type=multiname::NAME_STRING;
+	toJSONName.name_s_id=getSys()->getUniqueStringId("toJSON");
+	toJSONName.ns.push_back(nsNameAndKind("",NAMESPACE));
+	toJSONName.ns.push_back(nsNameAndKind(AS3,NAMESPACE));
+	toJSONName.isAttribute = false;
+	return ASObject::hasPropertyByMultiname(toJSONName, true, true);
+}
+
+tiny_string ASObject::call_toJSON()
+{
+	multiname toJSONName(NULL);
+	toJSONName.name_type=multiname::NAME_STRING;
+	toJSONName.name_s_id=getSys()->getUniqueStringId("toJSON");
+	toJSONName.ns.push_back(nsNameAndKind("",NAMESPACE));
+	toJSONName.ns.push_back(nsNameAndKind(AS3,NAMESPACE));
+	toJSONName.isAttribute = false;
+	assert(ASObject::hasPropertyByMultiname(toJSONName, true, true));
+
+	_NR<ASObject> o=getVariableByMultiname(toJSONName,SKIP_IMPL);
+	assert_and_throw(o->is<IFunction>());
+	IFunction* f=o->as<IFunction>();
+
+	incRef();
+	ASObject *ret=f->call(this,NULL,0);
+	tiny_string res;
+	if (ret->is<ASString>())
+	{
+		res += "\"";
+		res += ret->toString();
+		res += "\"";
+	}
+	else 
+		res = ret->toString();
+	
+	return res;
+}
+
 bool ASObject::isPrimitive() const
 {
 	// ECMA 3, section 4.3.2, T_INTEGER and T_UINTEGER are added
@@ -336,7 +421,10 @@ bool ASObject::isPrimitive() const
 		type==T_STRING || type==T_BOOLEAN || type==T_INTEGER ||
 		type==T_UINTEGER;
 }
-
+bool ASObject::isConstructed() const
+{
+	return traitsInitialized && constructIndicator;
+}
 variables_map::variables_map(MemoryAccount* m):
 	Variables(std::less<mapType::key_type>(), reporter_allocator<mapType::value_type>(m)),slots_vars(m)
 {
@@ -376,13 +464,14 @@ bool ASObject::hasPropertyByMultiname(const multiname& name, bool considerDynami
 	if(classdef && classdef->borrowedVariables.findObjVar(name, NO_CREATE_TRAIT, DECLARED_TRAIT)!=NULL)
 		return true;
 
+	NS_KIND nskind;
 	//Check prototype inheritance chain
 	if(getClass() && considerPrototype)
 	{
 		Prototype* proto = getClass()->prototype.getPtr();
 		while(proto)
 		{
-			if(proto->getObj()->findGettable(name) != NULL)
+			if(proto->getObj()->findGettable(name,nskind) != NULL)
 				return true;
 			proto=proto->prevPrototype.getPtr();
 		}
@@ -470,7 +559,7 @@ bool ASObject::deleteVariableByMultiname(const multiname& name)
 		return true;
 	}
 	//Only dynamic traits are deletable
-	if (obj->kind != DYNAMIC_TRAIT)
+	if (obj->kind != DYNAMIC_TRAIT && obj->kind != INSTANCE_TRAIT)
 		return false;
 
 	assert(obj->getter==NULL && obj->setter==NULL && obj->var!=NULL);
@@ -537,7 +626,20 @@ void ASObject::setVariableByMultiname(const multiname& name, ASObject* o, CONST_
 		}
 	}
 
-	//Do not lookup in the prototype chain. This is tested behaviour
+	//Do not set variables in prototype chain. Still have to do
+	//lookup to throw a correct error in case a named function
+	//exists in prototype chain. See Tamarin test
+	//ecma3/Boolean/ecma4_sealedtype_1_rt
+	if(!obj && cls && cls->isSealed)
+	{
+		variable *protoObj = cls->findSettableInPrototype(name);
+		if (protoObj && 
+		    ((protoObj->var && protoObj->var->is<Function>()) ||
+		     protoObj->setter))
+		{
+			throwError<ReferenceError>(kCannotAssignToMethodError, name.normalizedName(), cls ? cls->getQualifiedClassName() : "");
+		}
+	}
 
 	if(!obj)
 	{
@@ -595,24 +697,26 @@ void ASObject::setVariableByQName(uint32_t nameId, const nsNameAndKind& ns, ASOb
 }
 
 void ASObject::initializeVariableByMultiname(const multiname& name, ASObject* o, multiname* typemname,
-		ABCContext* context, TRAIT_KIND traitKind)
+		ABCContext* context, TRAIT_KIND traitKind, bool bOverwrite)
 {
 	check();
-
-	variable* obj=findSettable(name);
-	if(obj)
+	if (!bOverwrite)
 	{
-		//Initializing an already existing variable
-		LOG(LOG_NOT_IMPLEMENTED,"Variable " << name << "already initialized");
-		o->decRef();
-		return;
+		variable* obj=findSettable(name);
+		if(obj)
+		{
+			//Initializing an already existing variable
+			LOG(LOG_NOT_IMPLEMENTED,"Variable " << name << " already initialized");
+			if (o != NULL)
+				o->decRef();
+			return;
+		}
 	}
-
-	Variables.initializeVar(name, o, typemname, context, traitKind);
+	Variables.initializeVar(name, o, typemname, context, traitKind,this);
 }
 
 variable::variable(TRAIT_KIND _k, ASObject* _v, multiname* _t, const Type* _type)
-		: var(_v),typeUnion(NULL),setter(NULL),getter(NULL),kind(_k),traitState(NO_STATE)
+		: var(_v),typeUnion(NULL),setter(NULL),getter(NULL),kind(_k),traitState(NO_STATE),isenumerable(true)
 {
 	if(_type)
 	{
@@ -731,7 +835,7 @@ variable* variables_map::findObjVar(const multiname& mname, TRAIT_KIND createKin
 	return &inserted->second;
 }
 
-const variable* variables_map::findObjVar(const multiname& mname, uint32_t traitKinds) const
+const variable* variables_map::findObjVar(const multiname& mname, uint32_t traitKinds, NS_KIND &nskind) const
 {
 	uint32_t name=mname.normalizedNameId();
 	assert(!mname.ns.empty());
@@ -746,6 +850,7 @@ const variable* variables_map::findObjVar(const multiname& mname, uint32_t trait
 		const nsNameAndKind& ns=ret->first.ns;
 		if(ns==*nsIt)
 		{
+			nskind = ns.getImpl().kind;
 			if(ret->second.kind & traitKinds)
 				return &ret->second;
 			else
@@ -764,29 +869,86 @@ const variable* variables_map::findObjVar(const multiname& mname, uint32_t trait
 	return NULL;
 }
 
-void variables_map::initializeVar(const multiname& mname, ASObject* obj, multiname* typemname, ABCContext* context, TRAIT_KIND traitKind)
+void variables_map::initializeVar(const multiname& mname, ASObject* obj, multiname* typemname, ABCContext* context, TRAIT_KIND traitKind, ASObject* mainObj)
 {
 	const Type* type = NULL;
 	 /* If typename is a builtin type, we coerce obj.
 	  * It it's not it must be a user defined class,
-	  * so we only allow Null and Undefined (which are both coerced to Null) */
-
-	type = Type::getBuiltinType(typemname);
+	  * so we try to find the class it is derived from and create an apropriate uninitialized instance */
+	if (type == NULL)
+		type = Type::getBuiltinType(typemname);
+	if (type == NULL)
+		type = Type::getTypeFromMultiname(typemname,context);
 	if(type==NULL)
 	{
-		assert_and_throw(obj->is<Null>() || obj->is<Undefined>());
-		if(obj->is<Undefined>())
+		if (obj == NULL) // create dynamic object
+		{
+			obj = getSys()->getUndefinedRef();
+		}
+		else
 		{
-			//Casting undefined to an object (of unknown class)
-			//results in Null
-			obj->decRef();
-			obj = getSys()->getNullRef();
+			assert_and_throw(obj->is<Null>() || obj->is<Undefined>());
+			if(obj->is<Undefined>())
+			{
+				//Casting undefined to an object (of unknown class)
+				//results in Null
+				obj->decRef();
+				obj = getSys()->getNullRef();
+			}
 		}
 	}
 	else
-		obj = type->coerce(obj);
-
-	assert(traitKind==DECLARED_TRAIT || traitKind==CONSTANT_TRAIT);
+	{
+		if (obj == NULL) // create dynamic object
+		{
+			if (type == Type::anyType)
+			{
+				// type could not be found, so it's stored as an uninitialized variable
+				LOG(LOG_CALLS,"add uninitialized var:"<<mname);
+				uninitializedVar v;
+				mainObj->incRef();
+				v.mainObj = mainObj;
+				v.mname = &mname;
+				v.traitKind = traitKind;
+				v.typemname = typemname;
+				context->addUninitializedVar(v);
+				obj = getSys()->getUndefinedRef();
+				obj = type->coerce(obj);
+			}
+			else if(mainObj->is<Class_base>() &&
+				mainObj->as<Class_base>()->class_name.getQualifiedName() == typemname->qualifiedString())
+			{
+				// avoid recursive construction
+				obj = getSys()->getNullRef();
+			}
+			else if (type != Class_object::getClass() &&
+					dynamic_cast<const Class_base*>(type))
+			{
+				if (!((Class_base*)type)->super)
+				{
+					// super type could not be found, so the class is stored as an uninitialized variable
+					LOG(LOG_CALLS,"add uninitialized class var:"<<mname);
+					uninitializedVar v;
+					mainObj->incRef();
+					v.mainObj = mainObj;
+					v.mname = &mname;
+					v.traitKind = traitKind;
+					v.typemname = typemname;
+					context->addUninitializedVar(v);
+					obj = getSys()->getUndefinedRef();
+					obj = type->coerce(obj);
+				}
+				else
+					obj = ((Class_base*)type)->getInstance(false,NULL,0);
+			}
+			else
+			{
+				obj = getSys()->getUndefinedRef();
+				obj = type->coerce(obj);
+			}
+		}
+	}
+	assert(traitKind==DECLARED_TRAIT || traitKind==CONSTANT_TRAIT || traitKind == INSTANCE_TRAIT);
 
 	uint32_t name=mname.normalizedNameId();
 	Variables.insert(make_pair(varName(name, mname.ns[0]), variable(traitKind, obj, typemname, type)));
@@ -826,6 +988,16 @@ ASFUNCTIONBODY(ASObject,_toString)
 	return Class<ASString>::getInstanceS(ret);
 }
 
+ASFUNCTIONBODY(ASObject,_toLocaleString)
+{
+	if (!obj->has_toString())
+		throwError<TypeError>(kCallNotFoundError, "toString", obj->getClassName());
+
+	_R<ASObject> res = obj->call_toString();
+	res->incRef();
+	return res.getPtr();
+}
+
 ASFUNCTIONBODY(ASObject,hasOwnProperty)
 {
 	assert_and_throw(argslen==1);
@@ -867,7 +1039,8 @@ ASFUNCTIONBODY(ASObject,isPrototypeOf)
 
 ASFUNCTIONBODY(ASObject,propertyIsEnumerable)
 {
-	assert_and_throw(argslen==1);
+	if (argslen == 0)
+		return abstract_b(false);
 	multiname name(NULL);
 	name.name_type=multiname::NAME_STRING;
 	name.name_s_id=getSys()->getUniqueStringId(args[0]->toString());
@@ -886,16 +1059,41 @@ ASFUNCTIONBODY(ASObject,propertyIsEnumerable)
 		return abstract_b(true);
 	return abstract_b(false);
 }
+ASFUNCTIONBODY(ASObject,setPropertyIsEnumerable)
+{
+	tiny_string propname;
+	bool isEnum;
+	ARG_UNPACK(propname) (isEnum, true);
+	multiname name(NULL);
+	name.name_type=multiname::NAME_STRING;
+	name.name_s_id=getSys()->getUniqueStringId(args[0]->toString());
+	name.ns.push_back(nsNameAndKind("",NAMESPACE));
+	name.isAttribute=false;
+	variable* v =obj->Variables.findObjVar(name, NO_CREATE_TRAIT,DYNAMIC_TRAIT);
+	if (v)
+		v->isenumerable = isEnum;
+	return NULL;
+}
 
 ASFUNCTIONBODY(ASObject,_constructor)
 {
 	return NULL;
 }
 
+ASFUNCTIONBODY(ASObject,_constructorNotInstantiatable)
+{
+	throwError<ArgumentError>(kCantInstantiateError, obj->getClassName());
+	return NULL;
+}
+
 void ASObject::initSlot(unsigned int n, const multiname& name)
 {
 	Variables.initSlot(n,name.name_s_id,name.ns[0]);
 }
+void ASObject::appendSlot(const multiname& name)
+{
+	Variables.appendSlot(name.name_s_id,name.ns[0]);
+}
 
 int32_t ASObject::getVariableByMultiname_i(const multiname& name)
 {
@@ -906,9 +1104,9 @@ int32_t ASObject::getVariableByMultiname_i(const multiname& name)
 	return ret->toInt();
 }
 
-const variable* ASObject::findGettableImpl(const variables_map& map, const multiname& name)
+const variable* ASObject::findGettableImpl(const variables_map& map, const multiname& name, NS_KIND &nskind)
 {
-	const variable* ret=map.findObjVar(name,DECLARED_TRAIT|DYNAMIC_TRAIT);
+	const variable* ret=map.findObjVar(name,DECLARED_TRAIT|DYNAMIC_TRAIT,nskind);
 	if(ret)
 	{
 		//It seems valid for a class to redefine only the setter, so if we can't find
@@ -919,20 +1117,20 @@ const variable* ASObject::findGettableImpl(const variables_map& map, const multi
 	return ret;
 }
 
-const variable* ASObject::findGettable(const multiname& name) const
+const variable* ASObject::findGettable(const multiname& name, NS_KIND &nskind) const
 {
-	return findGettableImpl(Variables,name);
+	return findGettableImpl(Variables,name,nskind);
 }
 
-const variable* ASObject::findVariableByMultiname(const multiname& name, GET_VARIABLE_OPTION opt, Class_base* cls)
+const variable* ASObject::findVariableByMultiname(const multiname& name, GET_VARIABLE_OPTION opt, Class_base* cls, NS_KIND &nskind)
 {
 	//Get from the current object without considering borrowed properties
-	const variable* var=findGettable(name);
+	const variable* var=findGettable(name,nskind);
 
 	if(!var && cls)
 	{
 		//Look for borrowed traits before
-		var=cls->findBorrowedGettable(name);
+		var=cls->findBorrowedGettable(name,nskind);
 	}
 
 	if(!var && cls)
@@ -941,7 +1139,7 @@ const variable* ASObject::findVariableByMultiname(const multiname& name, GET_VAR
 		Prototype* proto = cls->prototype.getPtr();
 		while(proto)
 		{
-			var = proto->getObj()->findGettable(name);
+			var = proto->getObj()->findGettable(name,nskind);
 			if(var)
 				break;
 			proto = proto->prevPrototype.getPtr();
@@ -954,10 +1152,24 @@ _NR<ASObject> ASObject::getVariableByMultiname(const multiname& name, GET_VARIAB
 {
 	check();
 	assert(!cls || classdef->isSubClass(cls));
-	const variable* obj=findVariableByMultiname(name, opt, cls);
+	NS_KIND nskind;
+	const variable* obj=findVariableByMultiname(name, opt, cls,nskind);
 
 	if(!obj)
 		return NullRef;
+	if (this->is<Class_base>() && 
+			(!obj->var || 
+			 (obj->var->getObjectType() != T_UNDEFINED && 
+			  obj->var->getObjectType() != T_NULL && 
+			  obj->var->getObjectType() != T_FUNCTION )))
+	{
+		LOG(LOG_CALLS,"accessing class:"<<name<<" "<< this->as<Class_base>()->getQualifiedClassName()<<" "<<nskind);
+		if (obj->kind == INSTANCE_TRAIT &&
+				nskind != NAMESPACE && 
+				nskind != PACKAGE_INTERNAL_NAMESPACE && 
+				nskind != STATIC_PROTECTED_NAMESPACE)
+			throwError<TypeError>(kCallOfNonFunctionError,name.normalizedName());
+	}
 
 	if(obj->getter)
 	{
@@ -1080,6 +1292,9 @@ void variables_map::dumpVariables()
 			case CONSTANT_TRAIT:
 				kind="Declared: ";
 				break;
+			case INSTANCE_TRAIT:
+				kind="Declared (instance)";
+				break;
 			case DYNAMIC_TRAIT:
 				kind="Dynamic: ";
 				break;
@@ -1112,8 +1327,8 @@ void variables_map::destroyContents()
 	Variables.clear();
 }
 
-ASObject::ASObject(MemoryAccount* m):Variables(m),classdef(NULL),
-	type(T_OBJECT),traitsInitialized(false),implEnable(true)
+ASObject::ASObject(MemoryAccount* m):Variables(m),classdef(NULL),proxyMultiName(NULL),
+	type(T_OBJECT),traitsInitialized(false),constructIndicator(false),implEnable(true)
 {
 #ifndef NDEBUG
 	//Stuff only used in debugging
@@ -1121,8 +1336,8 @@ ASObject::ASObject(MemoryAccount* m):Variables(m),classdef(NULL),
 #endif
 }
 
-ASObject::ASObject(Class_base* c):Variables((c)?c->memoryAccount:NULL),classdef(NULL),
-	type(T_OBJECT),traitsInitialized(false),implEnable(true)
+ASObject::ASObject(Class_base* c):Variables((c)?c->memoryAccount:NULL),classdef(NULL),proxyMultiName(NULL),
+	type(T_OBJECT),traitsInitialized(false),constructIndicator(false),implEnable(true)
 {
 	setClass(c);
 #ifndef NDEBUG
@@ -1131,8 +1346,8 @@ ASObject::ASObject(Class_base* c):Variables((c)?c->memoryAccount:NULL),classdef(
 #endif
 }
 
-ASObject::ASObject(const ASObject& o):Variables((o.classdef)?o.classdef->memoryAccount:NULL),classdef(NULL),
-	type(o.type),traitsInitialized(false),implEnable(true)
+ASObject::ASObject(const ASObject& o):Variables((o.classdef)?o.classdef->memoryAccount:NULL),classdef(NULL),proxyMultiName(NULL),
+	type(o.type),traitsInitialized(false),constructIndicator(false),implEnable(true)
 {
 	if(o.classdef)
 		setClass(o.classdef);
@@ -1169,6 +1384,9 @@ void ASObject::finalize()
 		classdef->decRef();
 		classdef=NULL;
 	}
+	if (proxyMultiName)
+		delete proxyMultiName;
+	proxyMultiName = NULL;
 }
 
 ASObject::~ASObject()
@@ -1446,6 +1664,139 @@ ASObject *ASObject::describeType() const
 	return Class<XML>::getInstanceS(root);
 }
 
+tiny_string ASObject::toJSON(std::vector<ASObject *> &path, IFunction *replacer, const tiny_string &spaces,const tiny_string& filter)
+{
+	if (has_toJSON())
+	{
+		return call_toJSON();
+	}
+
+	tiny_string newline = (spaces.empty() ? "" : "\n");
+	tiny_string res;
+	if (this->isPrimitive())
+	{
+		switch(this->type)
+		{
+			case T_STRING:
+			{
+				res += "\"";
+				tiny_string sub = this->toString();
+				for (CharIterator it=sub.begin(); it!=sub.end(); it++)
+				{
+					switch (*it)
+					{
+						case '\b':
+							res += "\\b";
+							break;
+						case '\f':
+							res += "\\f";
+							break;
+						case '\n':
+							res += "\\n";
+							break;
+						case '\r':
+							res += "\\r";
+							break;
+						case '\t':
+							res += "\\t";
+							break;
+						case '\"':
+							res += "\\\"";
+							break;
+						case '\\':
+							res += "\\\\";
+							break;
+						default:
+							if (*it < 0x20 || *it > 0xff)
+							{
+								char hexstr[7];
+								sprintf(hexstr,"\\u%04x",*it);
+								res += hexstr;
+							}
+							else
+								res += *it;
+							break;
+					}
+				}
+				res += "\"";
+				break;
+			}
+			case T_UNDEFINED:
+				res += "null";
+				break;
+			default:
+				res += this->toString();
+				break;
+		}
+	}
+	else
+	{
+		res += "{";
+		const variables_map::const_var_iterator beginIt = Variables.Variables.begin();
+		const variables_map::const_var_iterator endIt = Variables.Variables.end();
+		bool bfirst = true;
+		for(variables_map::const_var_iterator varIt=beginIt; varIt != endIt; ++varIt)
+		{
+			// check for cylic reference
+			if (varIt->second.var->getObjectType() != T_UNDEFINED &&
+				varIt->second.var->getObjectType() != T_NULL &&
+				varIt->second.var->getObjectType() != T_BOOLEAN &&
+					(varIt->second.var == this ||
+					 std::find(path.begin(),path.end(), varIt->second.var) != path.end() ||
+					 std::find(path.begin(),path.end(), this) != path.end() ))
+				throwError<TypeError>(kJSONCyclicStructure);
+
+			if (replacer != NULL)
+			{
+				if (!bfirst)
+					res += ",";
+				res += newline+spaces;
+				res += "\"";
+				res += getSys()->getStringFromUniqueId(varIt->first.nameId);
+				res += "\"";
+				res += ":";
+				if (!spaces.empty())
+					res += " ";
+				ASObject* params[2];
+				
+				params[0] = Class<ASString>::getInstanceS(getSys()->getStringFromUniqueId(varIt->first.nameId));
+				params[1] = varIt->second.var;
+				params[1]->incRef();
+				ASObject *funcret=replacer->call(getSys()->getNullRef(), params, 2);
+				LOG(LOG_ERROR,"funcall:"<<res<<"|"<<funcret);
+				if (funcret)
+					res += funcret->toString();
+				else
+					res += varIt->second.var->toJSON(path,replacer,spaces+spaces,filter);
+				bfirst = false;
+			}
+			else if (filter.empty() || filter.find(tiny_string(" ")+getSys()->getStringFromUniqueId(varIt->first.nameId)+" ") != tiny_string::npos)
+			{
+				if (!bfirst)
+					res += ",";
+				res += newline+spaces;
+				res += "\"";
+				res += getSys()->getStringFromUniqueId(varIt->first.nameId);
+				res += "\"";
+				res += ":";
+				if (!spaces.empty())
+					res += " ";
+				res += varIt->second.var->toJSON(path,replacer,spaces+spaces,filter);
+				bfirst = false;
+			}
+			if (varIt->second.var->getObjectType() != T_UNDEFINED &&
+				varIt->second.var->getObjectType() != T_NULL &&
+				varIt->second.var->getObjectType() != T_BOOLEAN)
+				path.push_back(varIt->second.var);
+		}
+		if (!bfirst)
+			res += newline+spaces.substr_bytes(0,spaces.numBytes()/2);
+
+		res += "}";
+	}
+	return res;
+}
+
 bool ASObject::hasprop_prototype()
 {
 	variable* var=Variables.findObjVar(BUILTIN_STRINGS::PROTOTYPE,nsNameAndKind(BUILTIN_NAMESPACES::EMPTY_NS),
@@ -1491,7 +1842,7 @@ void ASObject::setprop_prototype(_NR<ASObject>& o)
 		ret->setVar(obj);
 }
 
-tiny_string ASObject::getClassName()
+tiny_string ASObject::getClassName() const
 {
 	if (getClass())
 		return getClass()->getQualifiedClassName();
diff --git a/src/asobject.h b/src/asobject.h
index 2064223..958007a 100644
--- a/src/asobject.h
+++ b/src/asobject.h
@@ -122,6 +122,25 @@
 		REGISTER_GETTER(c,name); \
 		REGISTER_SETTER(c,name)
 
+#define CLASS_DYNAMIC_NOT_FINAL 0
+#define CLASS_FINAL 1
+#define CLASS_SEALED 2
+
+// TODO: Every class should have a constructor
+#define CLASS_SETUP_NO_CONSTRUCTOR(c, superClass, attributes) \
+	c->setSuper(Class<superClass>::getRef()); \
+	c->setConstructor(NULL); \
+	c->isFinal = ((attributes) & CLASS_FINAL) != 0;	\
+	c->isSealed = ((attributes) & CLASS_SEALED) != 0
+
+#define CLASS_SETUP(c, superClass, constructor, attributes) \
+	CLASS_SETUP_NO_CONSTRUCTOR(c, superClass, attributes); \
+	c->setConstructor(Class<IFunction>::getFunction(constructor));
+
+#define CLASS_SETUP_CONSTRUCTOR_LENGTH(c, superClass, constructor, ctorlength, attributes) \
+	CLASS_SETUP_NO_CONSTRUCTOR(c, superClass, attributes); \
+	c->setConstructor(Class<IFunction>::getFunction((constructor), (ctorlength)));
+
 namespace lightspark
 {
 
@@ -134,7 +153,7 @@ class Loader;
 class Type;
 class ABCContext;
 
-enum TRAIT_KIND { NO_CREATE_TRAIT=0, DECLARED_TRAIT=1, DYNAMIC_TRAIT=2, CONSTANT_TRAIT=9 /* constants are also declared traits */ };
+enum TRAIT_KIND { NO_CREATE_TRAIT=0, DECLARED_TRAIT=1, DYNAMIC_TRAIT=2, INSTANCE_TRAIT=5, CONSTANT_TRAIT=9 /* constants are also declared traits */ };
 enum TRAIT_STATE { NO_STATE=0, HAS_GETTER_SETTER=1, TYPE_RESOLVED=2 };
 
 struct variable
@@ -150,8 +169,9 @@ struct variable
 	IFunction* getter;
 	TRAIT_KIND kind;
 	TRAIT_STATE traitState;
+	bool isenumerable:1;
 	variable(TRAIT_KIND _k)
-		: var(NULL),typeUnion(NULL),setter(NULL),getter(NULL),kind(_k),traitState(NO_STATE) {}
+		: var(NULL),typeUnion(NULL),setter(NULL),getter(NULL),kind(_k),traitState(NO_STATE),isenumerable(true) {}
 	variable(TRAIT_KIND _k, ASObject* _v, multiname* _t, const Type* type);
 	void setVar(ASObject* v);
 	/*
@@ -201,9 +221,9 @@ public:
 	/**
 	 * Const version of findObjVar, useful when looking for getters
 	 */
-	const variable* findObjVar(const multiname& mname, uint32_t traitKinds) const;
+	const variable* findObjVar(const multiname& mname, uint32_t traitKinds, NS_KIND &nskind) const;
 	//Initialize a new variable specifying the type (TODO: add support for const)
-	void initializeVar(const multiname& mname, ASObject* obj, multiname* typemname, ABCContext* context, TRAIT_KIND traitKind);
+	void initializeVar(const multiname& mname, ASObject* obj, multiname *typemname, ABCContext* context, TRAIT_KIND traitKind, ASObject* mainObj);
 	void killObjVar(const multiname& mname);
 	ASObject* getSlot(unsigned int n)
 	{
@@ -221,6 +241,10 @@ public:
 	 */
 	void setSlotNoCoerce(unsigned int n,ASObject* o);
 	void initSlot(unsigned int n, uint32_t nameId, const nsNameAndKind& ns);
+	void appendSlot(uint32_t nameId, const nsNameAndKind& ns)
+	{
+		initSlot(slots_vars.size()+1, nameId, ns);
+	}
 	int size() const
 	{
 		return Variables.size();
@@ -251,20 +275,22 @@ friend class IFunction; //Needed for clone
 private:
 	variables_map Variables;
 	Class_base* classdef;
-	const variable* findGettable(const multiname& name) const DLL_LOCAL;
+	const variable* findGettable(const multiname& name, NS_KIND &nskind) const DLL_LOCAL;
 	variable* findSettable(const multiname& name, bool* has_getter=NULL) DLL_LOCAL;
+	multiname* proxyMultiName;
 protected:
 	ASObject(MemoryAccount* m);
 	ASObject(const ASObject& o);
 	virtual ~ASObject();
 	SWFOBJECT_TYPE type;
 	bool traitsInitialized:1;
+	bool constructIndicator:1;
 	void serializeDynamicProperties(ByteArray* out, std::map<tiny_string, uint32_t>& stringMap,
 				std::map<const ASObject*, uint32_t>& objMap,
 				std::map<const Class_base*, uint32_t> traitsMap) const;
 	void setClass(Class_base* c);
 	static variable* findSettableImpl(variables_map& map, const multiname& name, bool* has_getter);
-	static const variable* findGettableImpl(const variables_map& map, const multiname& name);
+	static const variable* findGettableImpl(const variables_map& map, const multiname& name, NS_KIND &nskind);
 public:
 	ASObject(Class_base* c);
 #ifndef NDEBUG
@@ -274,11 +300,16 @@ public:
 	bool implEnable:1;
 	Class_base* getClass() const { return classdef; }
 	ASFUNCTION(_constructor);
+	// constructor for subclasses that can't be instantiated.
+	// Throws ArgumentError.
+	ASFUNCTION(_constructorNotInstantiatable);
 	ASFUNCTION(_toString);
+	ASFUNCTION(_toLocaleString);
 	ASFUNCTION(hasOwnProperty);
 	ASFUNCTION(valueOf);
 	ASFUNCTION(isPrototypeOf);
 	ASFUNCTION(propertyIsEnumerable);
+	ASFUNCTION(setPropertyIsEnumerable);
 	void check() const;
 	static void s_incRef(ASObject* o)
 	{
@@ -313,7 +344,7 @@ public:
 	 * Helper method using the get the raw variable struct instead of calling the getter.
 	 * It is used by getVariableByMultiname and by early binding code
 	 */
-	const variable* findVariableByMultiname(const multiname& name, GET_VARIABLE_OPTION opt, Class_base* cls);
+	const variable* findVariableByMultiname(const multiname& name, GET_VARIABLE_OPTION opt, Class_base* cls, NS_KIND &nskind);
 	/*
 	 * Gets a variable of this object. It looks through all classes (beginning at cls),
 	 * then the prototype chain, and then instance variables.
@@ -348,7 +379,7 @@ public:
 	 * Called by ABCVm::buildTraits to create DECLARED_TRAIT or CONSTANT_TRAIT and set their type
 	 */
 	void initializeVariableByMultiname(const multiname& name, ASObject* o, multiname* typemname,
-			ABCContext* context, TRAIT_KIND traitKind);
+			ABCContext* context, TRAIT_KIND traitKind,bool bOverwrite);
 	/*
 	 * Called by ABCVm::initProperty (implementation of ABC instruction), it is allowed to set CONSTANT_TRAIT
 	 */
@@ -375,6 +406,7 @@ public:
 		Variables.setSlotNoCoerce(n,o);
 	}
 	void initSlot(unsigned int n, const multiname& name);
+	void appendSlot(const multiname& name);
 	unsigned int numVariables() const;
 	tiny_string getNameAt(int i) const
 	{
@@ -387,6 +419,7 @@ public:
 	}
 	/* Implements ECMA's 9.8 ToString operation, but returns the concrete value */
 	tiny_string toString();
+	tiny_string toLocaleString();
 	virtual int32_t toInt();
 	virtual uint32_t toUInt();
 	uint16_t toUInt16();
@@ -396,6 +429,9 @@ public:
 	_R<ASObject> toPrimitive(TP_HINT hint = NO_HINT);
 	bool isPrimitive() const;
 
+	bool isInitialized() const {return traitsInitialized;}
+	virtual bool isConstructed() const;
+	
 	/* helper functions for calling the "valueOf" and
 	 * "toString" AS-functions which may be members of this
 	 *  object */
@@ -403,9 +439,11 @@ public:
 	_R<ASObject> call_valueOf();
 	bool has_toString();
 	_R<ASObject> call_toString();
+	bool has_toJSON();
+	tiny_string call_toJSON();
 
 	/* Helper function for calling getClass()->getQualifiedClassName() */
-	virtual tiny_string getClassName();
+	virtual tiny_string getClassName() const;
 
 	ASFUNCTION(generator);
 
@@ -441,6 +479,7 @@ public:
 
 	virtual ASObject *describeType() const;
 
+	virtual tiny_string toJSON(std::vector<ASObject *> &path, IFunction *replacer, const tiny_string &spaces,const tiny_string& filter);
 	/* returns true if the current object is of type T */
 	template<class T> bool is() const { return dynamic_cast<const T*>(this); }
 	/* returns this object casted to the given type.
@@ -451,6 +490,15 @@ public:
 
 	/* Returns a debug string identifying this object */
 	virtual std::string toDebugString();
+	
+	/* stores proxy namespace settings for internal usage */
+	void setProxyProperty(const multiname& name); 
+	/* applies proxy namespace settings to name for internal usage */
+	void applyProxyProperty(multiname &name); 
+	
+	void dumpVariables() { Variables.dumpVariables(); }
+	
+	void setConstructIndicator() { constructIndicator = true; }
 };
 
 class Number;
diff --git a/src/backends/decoder.cpp b/src/backends/decoder.cpp
index 18e72e0..3c360d4 100755
--- a/src/backends/decoder.cpp
+++ b/src/backends/decoder.cpp
@@ -295,6 +295,8 @@ bool FFMpegVideoDecoder::decodePacket(AVPacket* pkt, uint32_t time)
 #else
 	int ret=avcodec_decode_video(codecContext, frameIn, &frameOk, pkt->data, pkt->size);
 #endif
+	if (ret < 0)
+		return false;
 
 	assert_and_throw(ret==(int)pkt->size);
 	if(frameOk)
@@ -451,19 +453,7 @@ void AudioDecoder::skipAll()
 #ifdef ENABLE_LIBAVCODEC
 FFMpegAudioDecoder::FFMpegAudioDecoder(LS_AUDIO_CODEC audioCodec, uint8_t* initdata, uint32_t datalen):ownedContext(true)
 {
-	CodecID codecId;
-	switch(audioCodec)
-	{
-		case AAC:
-			codecId=CODEC_ID_AAC;
-			break;
-		case MP3:
-			codecId=CODEC_ID_MP3;
-			break;
-		default:
-			::abort();
-	}
-	AVCodec* codec=avcodec_find_decoder(codecId);
+	AVCodec* codec=avcodec_find_decoder(LSToFFMpegCodec(audioCodec));
 	assert(codec);
 
 	codecContext=avcodec_alloc_context3(codec);
@@ -490,7 +480,33 @@ FFMpegAudioDecoder::FFMpegAudioDecoder(LS_AUDIO_CODEC audioCodec, uint8_t* initd
 #endif
 }
 
-FFMpegAudioDecoder::FFMpegAudioDecoder(AVCodecContext* _c):codecContext(_c)
+FFMpegAudioDecoder::FFMpegAudioDecoder(LS_AUDIO_CODEC lscodec, int sampleRate, int channels, bool):ownedContext(true)
+{
+	status=INIT;
+
+	CodecID codecId = LSToFFMpegCodec(lscodec);
+	AVCodec* codec=avcodec_find_decoder(codecId);
+	assert(codec);
+	codecContext=avcodec_alloc_context3(codec);
+	codecContext->codec_id = codecId;
+	codecContext->sample_rate = sampleRate;
+	codecContext->channels = channels;
+
+#ifdef HAVE_AVCODEC_OPEN2
+	if(avcodec_open2(codecContext, codec, NULL)<0)
+#else
+	if(avcodec_open(codecContext, codec)<0)
+#endif //HAVE_AVCODEC_ALLOC_CONTEXT3
+		return;
+
+	if(fillDataAndCheckValidity())
+		status=VALID;
+#if HAVE_AVCODEC_DECODE_AUDIO4
+	frameIn=avcodec_alloc_frame();
+#endif
+}
+
+FFMpegAudioDecoder::FFMpegAudioDecoder(AVCodecContext* _c):ownedContext(false),codecContext(_c)
 {
 	status=INIT;
 	AVCodec* codec=avcodec_find_decoder(codecContext->codec_id);
@@ -520,6 +536,21 @@ FFMpegAudioDecoder::~FFMpegAudioDecoder()
 #endif
 }
 
+CodecID FFMpegAudioDecoder::LSToFFMpegCodec(LS_AUDIO_CODEC LSCodec)
+{
+	switch(LSCodec)
+	{
+		case AAC:
+			return CODEC_ID_AAC;
+		case MP3:
+			return CODEC_ID_MP3;
+		case ADPCM:
+			return CODEC_ID_ADPCM_SWF;
+		default:
+			return CODEC_ID_NONE;
+	}
+}
+
 bool FFMpegAudioDecoder::fillDataAndCheckValidity()
 {
 	if(codecContext->sample_rate!=0)
@@ -556,8 +587,25 @@ uint32_t FFMpegAudioDecoder::decodeData(uint8_t* data, int32_t datalen, uint32_t
 #if HAVE_AVCODEC_DECODE_AUDIO3 || HAVE_AVCODEC_DECODE_AUDIO4
 	AVPacket pkt;
 	av_init_packet(&pkt);
-	pkt.data=data;
-	pkt.size=datalen;
+
+	// If some data was left unprocessed on previous call,
+	// concatenate.
+	std::vector<uint8_t> combinedBuffer;
+	if (overflowBuffer.empty())
+	{
+		pkt.data=data;
+		pkt.size=datalen;
+	}
+	else
+	{
+		combinedBuffer.assign(overflowBuffer.begin(), overflowBuffer.end());
+		if (datalen > 0)
+			combinedBuffer.insert(combinedBuffer.end(), data, data+datalen);
+		pkt.data = &combinedBuffer[0];
+		pkt.size = combinedBuffer.size();
+		overflowBuffer.clear();
+	}
+
 #if HAVE_AVCODEC_DECODE_AUDIO4
 	avcodec_get_frame_defaults(frameIn);
 	int frameOk=0;
@@ -566,21 +614,36 @@ uint32_t FFMpegAudioDecoder::decodeData(uint8_t* data, int32_t datalen, uint32_t
 		ret=-1;
 	else
 	{
-		//This is suboptimal but equivalent to what libavcodec
-		//does for the compatibility version of avcodec_decode_audio3
-		memcpy(curTail.samples, frameIn->extended_data[0], frameIn->linesize[0]);
-		maxLen=frameIn->linesize[0];
+		if (frameIn->format != AV_SAMPLE_FMT_S16)
+		{
+			maxLen = resampleFrameToS16(curTail);
+		}
+		else 
+		{
+			//This is suboptimal but equivalent to what libavcodec
+			//does for the compatibility version of avcodec_decode_audio3
+			memcpy(curTail.samples, frameIn->extended_data[0], frameIn->linesize[0]);
+			maxLen=frameIn->linesize[0];
+		}
 	}
 #else
 	int32_t ret=avcodec_decode_audio3(codecContext, curTail.samples, &maxLen, &pkt);
 #endif
+
+	if (ret > 0)
+	{
+		pkt.data += ret;
+		pkt.size -= ret;
+
+		if (pkt.size > 0)
+		{
+			overflowBuffer.assign(pkt.data, pkt.data+pkt.size);
+		}
+	}
+
 #else
 	int32_t ret=avcodec_decode_audio2(codecContext, curTail.samples, &maxLen, data, datalen);
 #endif
-	assert_and_throw(ret==datalen);
-
-	if(status==INIT && fillDataAndCheckValidity())
-		status=VALID;
 
 	curTail.len=maxLen;
 	assert(!(curTail.len&0x80000000));
@@ -588,6 +651,10 @@ uint32_t FFMpegAudioDecoder::decodeData(uint8_t* data, int32_t datalen, uint32_t
 	curTail.current=curTail.samples;
 	curTail.time=time;
 	samplesBuffer.commitLast();
+
+	if(status==INIT && fillDataAndCheckValidity())
+		status=VALID;
+
 	return maxLen;
 }
 
@@ -604,10 +671,17 @@ uint32_t FFMpegAudioDecoder::decodePacket(AVPacket* pkt, uint32_t time)
 		ret=-1;
 	else
 	{
-		//This is suboptimal but equivalent to what libavcodec
-		//does for the compatibility version of avcodec_decode_audio3
-		memcpy(curTail.samples, frameIn->extended_data[0], frameIn->linesize[0]);
-		maxLen=frameIn->linesize[0];
+		if (frameIn->format != AV_SAMPLE_FMT_S16)
+		{
+			maxLen = resampleFrameToS16(curTail);
+		}
+		else 
+		{
+			//This is suboptimal but equivalent to what libavcodec
+			//does for the compatibility version of avcodec_decode_audio3
+			memcpy(curTail.samples, frameIn->extended_data[0], frameIn->linesize[0]);
+			maxLen=frameIn->linesize[0];
+		}
 	}
 #elif HAVE_AVCODEC_DECODE_AUDIO3
 	int ret=avcodec_decode_audio3(codecContext, curTail.samples, &maxLen, pkt);
@@ -639,6 +713,61 @@ uint32_t FFMpegAudioDecoder::decodePacket(AVPacket* pkt, uint32_t time)
 	samplesBuffer.commitLast();
 	return maxLen;
 }
+#if HAVE_AVCODEC_DECODE_AUDIO4
+int FFMpegAudioDecoder::resampleFrameToS16(FrameSamples& curTail)
+{
+	int maxLen;
+#ifdef HAVE_LIBAVRESAMPLE
+	AVAudioResampleContext * avr = avresample_alloc_context();
+	av_opt_set_int(avr, "in_channel_layout",  frameIn->channel_layout, 0);
+	av_opt_set_int(avr, "out_channel_layout", frameIn->channel_layout,  0);
+	av_opt_set_int(avr, "in_sample_rate",     frameIn->sample_rate,     0);
+	av_opt_set_int(avr, "out_sample_rate",    frameIn->sample_rate,     0);
+	av_opt_set_int(avr, "in_sample_fmt",      frameIn->format,   0);
+	av_opt_set_int(avr, "out_sample_fmt",     AV_SAMPLE_FMT_S16,    0);
+	avresample_open(avr);
+
+	uint8_t *output;
+	int out_linesize;
+	int out_samples = avresample_available(avr) + av_rescale_rnd(avresample_get_delay(avr) + frameIn->linesize[0], frameIn->sample_rate, frameIn->sample_rate, AV_ROUND_UP);
+	av_samples_alloc(&output, &out_linesize, frameIn->nb_samples, out_samples, AV_SAMPLE_FMT_S16, 0);
+	maxLen = avresample_convert(avr, &output, out_linesize, out_samples, frameIn->extended_data, frameIn->linesize[0], frameIn->nb_samples)*4;
+	memcpy(curTail.samples, output, maxLen);
+	av_freep(&output);
+	avresample_free(&avr);
+#else
+	LOG(LOG_ERROR, "unexpected sample format and can't resample, recompile with libavresample");
+	memset(curTail.samples, 0, frameIn->linesize[0]);
+	maxLen = frameIn->linesize[0];
+#endif
+	return maxLen;
+}
+#endif
+
+uint32_t FFMpegAudioDecoder::decodeStreamSomePackets(std::istream& s, uint32_t time)
+{
+	const size_t BUF_SIZE = 4096;
+	uint32_t ret;
+	uint8_t inbuf[BUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE];
+	s.read((char*)inbuf, BUF_SIZE);
+	if (s.gcount() == 0)
+		return 0;
+
+	ret = decodeData(inbuf, s.gcount(), time);
+
+	// Keep the overflowBuffer from growing without bounds
+	size_t overflowSize = overflowBuffer.size();
+	while (overflowSize > BUF_SIZE)
+	{
+		ret = decodeData(NULL, 0, time);
+		if (overflowBuffer.size() == overflowSize)
+			break;
+		overflowSize = overflowBuffer.size();
+	}
+
+	return ret;
+}
+
 #endif //ENABLE_LIBAVCODEC
 
 StreamDecoder::~StreamDecoder()
@@ -721,7 +850,13 @@ FFMpegStreamDecoder::FFMpegStreamDecoder(std::istream& s)
 	if(videoFound)
 	{
 		//Pass the frame rate from the container, the once from the codec is often wrong
-		double frameRate=av_q2d(formatCtx->streams[videoIndex]->r_frame_rate);
+		AVStream *stream = formatCtx->streams[videoIndex];
+#if LIBAVUTIL_VERSION_MAJOR < 54
+		AVRational rateRational = stream->r_frame_rate;
+#else
+		AVRational rateRational = stream->avg_frame_rate;
+#endif
+		double frameRate=av_q2d(rateRational);
 		customVideoDecoder=new FFMpegVideoDecoder(formatCtx->streams[videoIndex]->codec,frameRate);
 		videoDecoder=customVideoDecoder;
 	}
diff --git a/src/backends/decoder.h b/src/backends/decoder.h
index cddf058..2abbcbe 100644
--- a/src/backends/decoder.h
+++ b/src/backends/decoder.h
@@ -28,6 +28,24 @@ extern "C"
 {
 #include <libavcodec/avcodec.h>
 #include <libavformat/avformat.h>
+#ifdef HAVE_LIBAVRESAMPLE
+#include <libavresample/avresample.h>
+#endif
+#include <libavutil/opt.h>
+#include <libavutil/mathematics.h>
+#ifndef AVCODEC_MAX_AUDIO_FRAME_SIZE
+#define AVCODEC_MAX_AUDIO_FRAME_SIZE 192000 // 1 second of 48khz 32bit audio
+#endif
+#ifdef HAVE_AVCODECID
+#define CodecID AVCodecID
+#define CODEC_ID_NONE AV_CODEC_ID_NONE
+#define CODEC_ID_H264 AV_CODEC_ID_H264
+#define CODEC_ID_FLV1 AV_CODEC_ID_FLV1
+#define CODEC_ID_VP6F AV_CODEC_ID_VP6F
+#define CODEC_ID_AAC AV_CODEC_ID_AAC
+#define CODEC_ID_MP3 AV_CODEC_ID_MP3
+#define CODEC_ID_ADPCM_SWF AV_CODEC_ID_ADPCM_SWF
+#endif
 #define MAX_AUDIO_FRAME_SIZE AVCODEC_MAX_AUDIO_FRAME_SIZE
 }
 #else
@@ -40,7 +58,8 @@ namespace lightspark
 {
 
 enum LS_VIDEO_CODEC { H264=0, H263, VP6 };
-enum LS_AUDIO_CODEC { LINEAR_PCM_PLATFORM_ENDIAN=0, ADPCM=1, MP3=2, LINEAR_PCM_LE=3, AAC=10 };
+// "Audio coding formats" from Chapter 11 in SWF documentation
+enum LS_AUDIO_CODEC { CODEC_NONE=-1, LINEAR_PCM_PLATFORM_ENDIAN=0, ADPCM=1, MP3=2, LINEAR_PCM_LE=3, AAC=10 };
 
 class Decoder
 {
@@ -277,12 +296,16 @@ class FFMpegAudioDecoder: public AudioDecoder
 private:
 	bool ownedContext;
 	AVCodecContext* codecContext;
+	std::vector<uint8_t> overflowBuffer;
 	bool fillDataAndCheckValidity();
+	CodecID LSToFFMpegCodec(LS_AUDIO_CODEC lscodec);
 #if HAVE_AVCODEC_DECODE_AUDIO4
 	AVFrame* frameIn;
+	int resampleFrameToS16(FrameSamples& curTail);
 #endif
 public:
 	FFMpegAudioDecoder(LS_AUDIO_CODEC codec, uint8_t* initdata, uint32_t datalen);
+	FFMpegAudioDecoder(LS_AUDIO_CODEC codec, int sampleRate, int channels, bool);
 	/*
 	   Specialized constructor used by FFMpegStreamDecoder
 	*/
@@ -293,6 +316,7 @@ public:
 	*/
 	uint32_t decodePacket(AVPacket* pkt, uint32_t time);
 	uint32_t decodeData(uint8_t* data, int32_t datalen, uint32_t time);
+	uint32_t decodeStreamSomePackets(std::istream& s, uint32_t time);
 };
 #endif
 
diff --git a/src/backends/graphics.cpp b/src/backends/graphics.cpp
index b8a79a2..f6ac15c 100644
--- a/src/backends/graphics.cpp
+++ b/src/backends/graphics.cpp
@@ -458,10 +458,20 @@ bool CairoTokenRenderer::cairoPathFromTokens(cairo_t* cr, const std::vector<Geom
 				cairo_stroke(stroke_cr);
 
 				const LINESTYLE2& style = tokens[i].lineStyle;
-				const RGBA& color = style.Color;
 
 				cairo_set_operator(stroke_cr, CAIRO_OPERATOR_OVER);
-				cairo_set_source_rgba(stroke_cr, color.rf(), color.gf(), color.bf(), color.af());
+				if (style.HasFillFlag)
+				{
+					cairo_pattern_t* pattern = FILLSTYLEToCairo(style.FillType, scaleCorrection);
+					if (pattern)
+					{
+						cairo_set_source(stroke_cr, pattern);
+						cairo_pattern_destroy(pattern);
+					}
+				} else {
+					const RGBA& color = style.Color;
+					cairo_set_source_rgba(stroke_cr, color.rf(), color.gf(), color.bf(), color.af());
+				}
 
 				// TODO: EndCapStyle
 				if (style.StartCapStyle == 0)
@@ -838,12 +848,6 @@ void CairoPangoRenderer::pangoLayoutFromData(PangoLayout* layout, const TextData
 		pango_layout_set_width(layout,PANGO_SCALE*tData.width);
 		pango_layout_set_wrap(layout,PANGO_WRAP_WORD);//I think this is what Adobe does
 	}
-	//In case autoSize is NONE, we also have the height
-	if(tData.autoSize == TextData::AUTO_SIZE::AS_NONE)
-	{
-		pango_layout_set_width(layout,PANGO_SCALE*tData.width);
-		pango_layout_set_height(layout,PANGO_SCALE*tData.height);//TODO:Not sure what Pango does if the text is too long to fit
-	}
 
 	/* setup font description */
 	desc = pango_font_description_new();
@@ -870,9 +874,19 @@ void CairoPangoRenderer::executeDraw(cairo_t* cr)
 		cairo_paint(cr);
 	}
 
+	/* text scroll position */
+	int32_t translateX = textData.scrollH;
+	int32_t translateY = 0;
+	if (textData.scrollV > 1)
+	{
+		translateY = -PANGO_PIXELS(lineExtents(layout, textData.scrollV-1).y);
+	}
+
 	/* draw the text */
 	cairo_set_source_rgb (cr, textData.textColor.Red/255., textData.textColor.Green/255., textData.textColor.Blue/255.);
+	cairo_translate(cr, translateX, translateY);
 	pango_cairo_show_layout(cr, layout);
+	cairo_translate(cr, -translateX, -translateY);
 
 	if(textData.border)
 	{
@@ -917,6 +931,68 @@ bool CairoPangoRenderer::getBounds(const TextData& _textData, uint32_t& w, uint3
 	return (h!=0) && (w!=0);
 }
 
+PangoRectangle CairoPangoRenderer::lineExtents(PangoLayout *layout, int lineNumber)
+{
+	PangoRectangle rect;
+	memset(&rect, 0, sizeof(PangoRectangle));
+	int i = 0;
+	PangoLayoutIter* lineIter = pango_layout_get_iter(layout);
+	do
+	{
+		if (i == lineNumber)
+		{
+			pango_layout_iter_get_line_extents(lineIter, NULL, &rect);
+			break;
+		}
+
+		i++;
+	} while (pango_layout_iter_next_line(lineIter));
+	pango_layout_iter_free(lineIter);
+
+	return rect;
+}
+
+std::vector<LineData> CairoPangoRenderer::getLineData(const TextData& _textData)
+{
+	//TODO:check locking
+	Locker l(pangoMutex);
+	cairo_surface_t* cairoSurface=cairo_image_surface_create_for_data(NULL, CAIRO_FORMAT_ARGB32, 0, 0, 0);
+	cairo_t *cr=cairo_create(cairoSurface);
+
+	PangoLayout* layout;
+	layout = pango_cairo_create_layout(cr);
+	pangoLayoutFromData(layout, _textData);
+
+	int XOffset = _textData.scrollH;
+	int YOffset = PANGO_PIXELS(lineExtents(layout, _textData.scrollV-1).y);
+	std::vector<LineData> data;
+	data.reserve(pango_layout_get_line_count(layout));
+	PangoLayoutIter* lineIter = pango_layout_get_iter(layout);
+	do
+	{
+		PangoRectangle rect;
+		pango_layout_iter_get_line_extents(lineIter, NULL, &rect);
+		PangoLayoutLine* line = pango_layout_iter_get_line(lineIter);
+		data.emplace_back(PANGO_PIXELS(rect.x) - XOffset,
+				  PANGO_PIXELS(rect.y) - YOffset,
+				  PANGO_PIXELS(rect.width),
+				  PANGO_PIXELS(rect.height),
+				  _textData.text.bytePosToIndex(line->start_index),
+				  _textData.text.substr_bytes(line->start_index, line->length).numChars(),
+				  PANGO_PIXELS(PANGO_ASCENT(rect)),
+				  PANGO_PIXELS(PANGO_DESCENT(rect)),
+				  PANGO_PIXELS(PANGO_LBEARING(rect)),
+				  0); // FIXME
+	} while (pango_layout_iter_next_line(lineIter));
+	pango_layout_iter_free(lineIter);
+
+	g_object_unref(layout);
+	cairo_destroy(cr);
+	cairo_surface_destroy(cairoSurface);
+
+	return data;
+}
+
 void CairoPangoRenderer::applyCairoMask(cairo_t* cr, int32_t xOffset, int32_t yOffset) const
 {
 	assert(false);
diff --git a/src/backends/graphics.h b/src/backends/graphics.h
index 63ba009..674a967 100644
--- a/src/backends/graphics.h
+++ b/src/backends/graphics.h
@@ -344,7 +344,7 @@ class TextData
 {
 public:
 	/* the default values are from the spec for flash.text.TextField and flash.text.TextFormat */
-	TextData() : width(100), height(100), textWidth(0), textHeight(0), font("Times New Roman"), background(false), backgroundColor(0xFFFFFF),
+	TextData() : width(100), height(100), textWidth(0), textHeight(0), font("Times New Roman"), scrollH(0), scrollV(1), background(false), backgroundColor(0xFFFFFF),
 		border(false), borderColor(0x000000), multiline(false), textColor(0x000000),
 		autoSize(AS_NONE), fontSize(12), wordWrap(false) {}
 	uint32_t width;
@@ -353,6 +353,8 @@ public:
 	uint32_t textHeight;
 	tiny_string text;
 	tiny_string font;
+	int32_t scrollH; // pixels, 0-based
+	int32_t scrollV; // lines, 1-based
 	bool background;
 	RGB backgroundColor;
 	bool border;
@@ -365,6 +367,28 @@ public:
 	bool wordWrap;
 };
 
+class LineData {
+public:
+	LineData(int32_t x, int32_t y, int32_t _width,
+		 int32_t _height, int32_t _firstCharOffset, int32_t _length,
+		 number_t _ascent, number_t _descent, number_t _leading,
+		 number_t _indent):
+		extents(x, x+_width, y, y+_height), 
+		firstCharOffset(_firstCharOffset), length(_length),
+		ascent(_ascent), descent(_descent), leading(_leading),
+		indent(_indent) {}
+	// position and size
+	RECT extents;
+	// Offset of the first character on this line
+	int32_t firstCharOffset;
+	// length of the line in characters
+	int32_t length;
+	number_t ascent;
+	number_t descent;
+	number_t leading;
+	number_t indent;
+};
+
 class CairoPangoRenderer : public CairoRenderer
 {
 	static StaticMutex pangoMutex;
@@ -375,6 +399,7 @@ class CairoPangoRenderer : public CairoRenderer
 	TextData textData;
 	static void pangoLayoutFromData(PangoLayout* layout, const TextData& tData);
 	void applyCairoMask(cairo_t* cr, int32_t offsetX, int32_t offsetY) const;
+	static PangoRectangle lineExtents(PangoLayout *layout, int lineNumber);
 public:
 	CairoPangoRenderer(const TextData& _textData, const MATRIX& _m,
 			int32_t _x, int32_t _y, int32_t _w, int32_t _h, float _s, float _a, const std::vector<MaskData>& _ms)
@@ -385,6 +410,7 @@ public:
 		@param w,h,tw,th are the (text)width and (text)height of the textData.
 	*/
 	static bool getBounds(const TextData& _textData, uint32_t& w, uint32_t& h, uint32_t& tw, uint32_t& th);
+	static std::vector<LineData> getLineData(const TextData& _textData);
 };
 
 class InvalidateQueue
diff --git a/src/backends/input.cpp b/src/backends/input.cpp
index 96ea76c..fd3591d 100644
--- a/src/backends/input.cpp
+++ b/src/backends/input.cpp
@@ -141,6 +141,12 @@ bool InputThread::worker(GdkEvent *event)
 			ret=TRUE;
 			break;
 		}
+		case GDK_LEAVE_NOTIFY:
+		{
+			handleMouseLeave();
+			ret=TRUE;
+			break;
+		}
 		default:
 //#ifdef EXPENSIVE_DEBUG
 //			LOG(LOG_INFO, "GDKTYPE " << event->type);
@@ -292,6 +298,15 @@ void InputThread::handleScrollEvent(uint32_t x, uint32_t y, GdkScrollDirection d
 		_MR(Class<MouseEvent>::getInstanceS("mouseWheel",localX,localY,true,buttonState,NullRef,delta)));
 }
 
+void InputThread::handleMouseLeave()
+{
+	if(m_sys->currentVm == NULL)
+		return;
+
+	m_sys->currentVm->addEvent(m_sys->mainClip->getStage(),
+		_MR(Class<Event>::getInstanceS("mouseLeave")));
+}
+
 void InputThread::initKeyTable()
 {
 	int i = 0;
diff --git a/src/backends/input.h b/src/backends/input.h
index c1897f8..f02711f 100644
--- a/src/backends/input.h
+++ b/src/backends/input.h
@@ -78,6 +78,7 @@ private:
 	void handleMouseUp(uint32_t x, uint32_t y, unsigned int buttonState);
 	void handleMouseMove(uint32_t x, uint32_t y, unsigned int buttonState);
 	void handleScrollEvent(uint32_t x, uint32_t y, GdkScrollDirection direction, unsigned int buttonState);
+        void handleMouseLeave();
 
 	void initKeyTable();
 	bool handleKeyboardShortcuts(const GdkEventKey *keyevent);
diff --git a/src/backends/netutils.cpp b/src/backends/netutils.cpp
index 408c14b..1c397aa 100644
--- a/src/backends/netutils.cpp
+++ b/src/backends/netutils.cpp
@@ -24,6 +24,7 @@
 #include "backends/config.h"
 #include "backends/netutils.h"
 #include "backends/rtmputils.h"
+#include "backends/streamcache.h"
 #include "compat.h"
 #include <string>
 #include <algorithm>
@@ -165,25 +166,26 @@ StandaloneDownloadManager::~StandaloneDownloadManager()
  * \return A pointer to a newly created \c Downloader for the given URL.
  * \see DownloadManager::destroy()
  */
-Downloader* StandaloneDownloadManager::download(const URLInfo& url, bool cached, ILoadable* owner)
+Downloader* StandaloneDownloadManager::download(const URLInfo& url, _R<StreamCache> cache, ILoadable* owner)
 {
+	bool cached = dynamic_cast<FileStreamCache *>(cache.getPtr()) != NULL;
 	LOG(LOG_INFO, _("NET: STANDALONE: DownloadManager::download '") << url.getParsedURL()
 			<< "'" << (cached ? _(" - cached") : ""));
 	ThreadedDownloader* downloader;
 	if(url.getProtocol() == "file")
 	{
 		LOG(LOG_INFO, _("NET: STANDALONE: DownloadManager: local file"));
-		downloader=new LocalDownloader(url.getPath(), cached, owner);
+		downloader=new LocalDownloader(url.getPath(), cache, owner);
 	}
 	else if(url.getProtocol().substr(0, 4) == "rtmp")
 	{
 		LOG(LOG_INFO, _("NET: STANDALONE: DownloadManager: RTMP stream"));
-		downloader=new RTMPDownloader(url.getParsedURL(), url.getStream(), owner);
+		downloader=new RTMPDownloader(url.getParsedURL(), cache, url.getStream(), owner);
 	}
 	else
 	{
 		LOG(LOG_INFO, _("NET: STANDALONE: DownloadManager: remote file"));
-		downloader=new CurlDownloader(url.getParsedURL(), cached, owner);
+		downloader=new CurlDownloader(url.getParsedURL(), cache, owner);
 	}
 	downloader->enableFencingWaiting();
 	addDownloader(downloader);
@@ -201,7 +203,8 @@ Downloader* StandaloneDownloadManager::download(const URLInfo& url, bool cached,
  * \return A pointer to a newly created \c Downloader for the given URL.
  * \see DownloadManager::destroy()
  */
-Downloader* StandaloneDownloadManager::downloadWithData(const URLInfo& url, const std::vector<uint8_t>& data,
+Downloader* StandaloneDownloadManager::downloadWithData(const URLInfo& url, _R<StreamCache> cache, 
+		const std::vector<uint8_t>& data,
 		const std::list<tiny_string>& headers, ILoadable* owner)
 {
 	LOG(LOG_INFO, _("NET: STANDALONE: DownloadManager::downloadWithData '") << url.getParsedURL());
@@ -209,14 +212,14 @@ Downloader* StandaloneDownloadManager::downloadWithData(const URLInfo& url, cons
 	if(url.getProtocol() == "file")
 	{
 		LOG(LOG_INFO, _("NET: STANDALONE: DownloadManager: local file - Ignoring data field"));
-		downloader=new LocalDownloader(url.getPath(), false, owner);
+		downloader=new LocalDownloader(url.getPath(), cache, owner);
 	}
 	else if(url.getProtocol() == "rtmpe")
 		throw RunTimeException("RTMPE does not support additional data");
 	else
 	{
 		LOG(LOG_INFO, _("NET: STANDALONE: DownloadManager: remote file"));
-		downloader=new CurlDownloader(url.getParsedURL(), data, headers, owner);
+		downloader=new CurlDownloader(url.getParsedURL(), cache, data, headers, owner);
 	}
 	downloader->enableFencingWaiting();
 	addDownloader(downloader);
@@ -229,20 +232,15 @@ Downloader* StandaloneDownloadManager::downloadWithData(const URLInfo& url, cons
  *
  * Constructor for the Downloader class. Can only be called from derived classes.
  * \param[in] _url The URL for the Downloader.
- * \param[in] _cached Whether or not to cache this download.
+ * \param[in] _cache StreamCache instance for caching this download.
  */
-Downloader::Downloader(const tiny_string& _url, bool _cached, ILoadable* o):
-	cacheOpened(0),dataAvailable(0),terminated(0),hasTerminated(false),cacheHasOpened(false), //LOCKING
-	waitingForCache(false),waitingForData(false),waitingForTermination(false), //STATUS
-	forceStop(true),failed(false),finished(false),                //FLAGS
+Downloader::Downloader(const tiny_string& _url, _R<StreamCache> _cache, ILoadable* o):
 	url(_url),originalURL(url),                                   //PROPERTIES
-	buffer(NULL),stableBuffer(NULL),                              //BUFFERING
+	cache(_cache),                                                //CACHING
 	owner(o),                                                     //PROGRESS
-	cachePos(0),cacheSize(0),keepCache(false),cached(_cached),    //CACHING
 	redirected(false),requestStatus(0),                           //HTTP REDIR, STATUS & HEADERS
-	length(0),receivedLength(0)                                   //DOWNLOADED DATA
+	length(0)                                                     //DOWNLOADED DATA
 {
-	setg(NULL,NULL,NULL);
 }
 
 /**
@@ -252,18 +250,13 @@ Downloader::Downloader(const tiny_string& _url, bool _cached, ILoadable* o):
  * \param[in] _url The URL for the Downloader.
  * \param[in] data Additional data to send to the host
  */
-Downloader::Downloader(const tiny_string& _url, const std::vector<uint8_t>& _data, const std::list<tiny_string>& h, ILoadable* o):
-	cacheOpened(0),dataAvailable(0),terminated(0),hasTerminated(false),cacheHasOpened(false), //LOCKING
-	waitingForCache(false),waitingForData(false),waitingForTermination(false), //STATUS
-	forceStop(true),failed(false),finished(false),                   //FLAGS
+Downloader::Downloader(const tiny_string& _url, _R<StreamCache> _cache, const std::vector<uint8_t>& _data, const std::list<tiny_string>& h, ILoadable* o):
 	url(_url),originalURL(url),                                      //PROPERTIES
-	buffer(NULL),stableBuffer(NULL),                                 //BUFFERING
+	cache(_cache),                                                   //CACHING
 	owner(o),                                                        //PROGRESS
-	cachePos(0),cacheSize(0),keepCache(false),cached(false),         //CACHING
 	redirected(false),requestStatus(0),requestHeaders(h),data(_data),//HTTP REDIR, STATUS & HEADERS
-	length(0),receivedLength(0)                                      //DOWNLOADED DATA
+	length(0)                                                        //DOWNLOADED DATA
 {
-	setg(NULL,NULL,NULL);
 }
 
 /**
@@ -275,263 +268,6 @@ Downloader::Downloader(const tiny_string& _url, const std::vector<uint8_t>& _dat
  */
 Downloader::~Downloader()
 {
-	waitForTermination();
-
-	Mutex::Lock l(mutex);
-
-	if(cached)
-	{
-		if(cache.is_open())
-			cache.close();
-		if(!keepCache && cacheFilename != "")
-			unlink(cacheFilename.raw_buf());
-	}
-	if(buffer != NULL)
-	{
-		free(buffer);
-	}
-	if(stableBuffer != NULL && stableBuffer!=buffer)
-	{
-		free(stableBuffer);
-	}
-}
-
-/**
- * \brief Called by the streambuf API
- *
- * Called by the streambuf API when there is no more data to read.
- * Waits for the mutex at start and releases the mutex when finished.
- * \throw RunTimeException Cache file could not be read
- */
-Downloader::int_type Downloader::underflow()
-{
-	Mutex::Lock l(mutex);
-	//Let's see if the other buffer contains new data
-	syncBuffers();
-	if(egptr()-gptr()>0)
-	{
-		//There is data already
-		return *(uint8_t*)gptr();
-	}
-	const unsigned int startOffset=getOffset();
-	const unsigned int startReceivedLength=receivedLength;
-	assert(startOffset<=startReceivedLength);
-	//If we have read all available data
-	if(startReceivedLength==startOffset)
-	{
-		//The download has failed or has finished
-		if(failed || finished)
-			return EOF;
-		//We haven't reached the end of the download, more bytes should follow
-		else
-		{
-			waitForData_locked();
-			syncBuffers();
-
-			//Check if we haven't failed or finished (and there wasn't any new data)
-			if(failed || (finished && startReceivedLength==receivedLength))
-				return EOF;
-		}
-	}
-
-	//We should have an initialized buffer here since there is some data
-	assert_and_throw(buffer != NULL);
-	//Temporary pointers to new streambuf read positions
-	char* begin;
-	char* cur;
-	char* end;
-	//Index in the buffer pointing to the data to be returned
-	uint32_t index;
-
-	if(cached)
-	{
-		waitForCache();
-
-		size_t newCacheSize = receivedLength-(cachePos+cacheSize);
-		if(newCacheSize > cacheMaxSize)
-			newCacheSize = cacheMaxSize;
-
-		//Move the start of our new window to the end of our last window
-		cachePos = cachePos+cacheSize;
-		cacheSize = newCacheSize;
-		//Seek to the start of our new window
-		cache.seekg(cachePos);
-		//Read into our buffer window
-		cache.read((char*)stableBuffer, cacheSize);
-		if(cache.fail())
-		{
-			throw RunTimeException(_("Downloader::underflow: reading from cache file failed"));
-		}
-
-		begin=(char*)stableBuffer;
-		cur=(char*)stableBuffer;
-		end=(char*)stableBuffer+cacheSize;
-		index=0;
-
-	}
-	else
-	{
-		begin=(char*)stableBuffer;
-		cur=(char*)stableBuffer+startOffset;
-		end=(char*)stableBuffer+receivedLength;
-		index=startOffset;
-	}
-
-	//If we've failed, don't bother any more
-	if(failed)
-		return EOF;
-
-	//Set our new iterators in the buffer (begin, cursor, end)
-	setg(begin, cur, end);
-
-	//Cast to unsigned, otherwise 0xff would become eof
-	return (unsigned char)stableBuffer[index];
-}
-
-/**
-  * Internal function to synchronize oldBuffer and buffer
-  *
-  * \pre Must be called from a function called by the streambuf API
-  */
-void Downloader::syncBuffers()
-{
-	if(stableBuffer!=buffer)
-	{
-		//The buffer have been changed
-		free(stableBuffer);
-		stableBuffer=buffer;
-		//Remember the relative positions of the input pointers
-		intptr_t curPos = (intptr_t) (gptr()-eback());
-		intptr_t curLen = (intptr_t) (egptr()-eback());
-		//Do some pointer arithmetic to point the input pointers to the right places in the new buffer
-		setg((char*)stableBuffer,(char*)(stableBuffer+curPos),(char*)(stableBuffer+curLen));
-	}
-}
-
-/**
- * \brief Called by the streambuf API
- *
- * Called by the streambuf API to seek to an absolute position
- * Mutex must be locked on entry.
- * \throw RunTimeException Cache file could not be read
- */
-Downloader::pos_type Downloader::seekpos(pos_type pos, std::ios_base::openmode mode)
-{
-	assert_and_throw(mode==std::ios_base::in);
-	assert_and_throw(buffer && stableBuffer);
-
-	syncBuffers();
-
-	// read from stream until we have enough data
-	uint32_t tmplen = receivedLength;
-	while (!hasTerminated && pos > receivedLength) 
-	{
-		waitForData_locked();
-		syncBuffers();
-		if (tmplen == receivedLength)
-			break; // no new data read
-		tmplen = receivedLength;
-	}
-	
-	if(cached)
-	{
-		waitForCache();
-
-		//The requested position is inside our current window
-		if(pos >= cachePos && pos <= cachePos+cacheSize)
-		{
-			//Just move our cursor to the correct position in our window
-			setg((char*)stableBuffer, (char*)stableBuffer+pos-cachePos, (char*)stableBuffer+cacheSize);
-		}
-		//The requested position is outside our current window
-		else if(pos <= receivedLength)
-		{
-			cachePos = pos;
-			cacheSize = receivedLength-pos;
-			if(cacheSize > cacheMaxSize)
-				cacheSize = cacheMaxSize;
-
-			//Seek to the requested position
-			cache.seekg(cachePos);
-			//Read into our window
-			cache.read((char*)stableBuffer, cacheSize);
-			if(cache.fail())
-				throw RunTimeException(_("Downloader::seekpos: reading from cache file failed"));
-
-			//Our window starts at position pos
-			setg((char*) stableBuffer, (char*) stableBuffer, ((char*) stableBuffer)+cacheSize);
-		}
-		//The requested position is bigger then our current amount of available data
-		else if(pos > receivedLength)
-			return -1;
-	}
-	else
-	{
-		//The requested position is valid
-		if(pos <= receivedLength)
-			setg((char*)stableBuffer,(char*)stableBuffer+pos,(char*)stableBuffer+receivedLength);
-		//The requested position is bigger then our current amount of available data
-		else
-			return -1;
-	}
-
-	return pos;
-}
-
-/**
- * \brief Called by the streambuf API
- *
- * Called by the streambuf API to seek to a relative position
- * Waits for the mutex at start and releases the mutex when finished.
- */
-Downloader::pos_type Downloader::seekoff(off_type off, std::ios_base::seekdir dir, std::ios_base::openmode mode)
-{
-	assert_and_throw(mode==std::ios_base::in);
-	assert_and_throw(buffer != NULL);
-
-	Mutex::Lock l(mutex);
-	if (off != 0)
-	{
-		switch (dir)
-		{
-			case std::ios_base::beg:
-				seekpos(off,mode);
-				break;
-			case std::ios_base::cur:
-			{
-				pos_type tmp = getOffset();
-				seekpos(tmp+off,mode);
-				break;
-			}
-			case std::ios_base::end:
-				l.release();
-				waitForTermination();
-				l.acquire();
-				if (finished)
-					seekpos(length+off,mode);
-				break;
-			default:
-				break;
-		}
-	}
-
-	return getOffset();
-}
-
-/**
- * \brief Get the position of the read cursor in the (virtual) downloaded data
- *
- * Get the position of the read cursor in the (virtual) downloaded data.
- * If downloading to memory this method returns the position of the read cursor in the buffer.
- * If downloading to a cache file, this method returns the position of the read cursor in the buffer
- * + the position of the buffer window into the cache file.
- */
-Downloader::pos_type Downloader::getOffset() const
-{
-	pos_type ret = gptr()-eback();
-	if(cached)
-		ret+=cachePos;
-	return ret;
 }
 
 /**
@@ -541,28 +277,13 @@ Downloader::pos_type Downloader::getOffset() const
  * signals \c dataAvailable if it is being waited for.
  * It also signals \c terminated to mark the end of the download.
  * A download should finish be either calling \c setFailed() or \c setFinished(), not both.
- * \post \c failed == \c true & \c finished == \c true
  * \post \c length == \c receivedLength
- * \post Signals \c dataAvailable if it is being waited for (\c waitingForData == \c true). 
- * \post \c waitingForTermination == \c false
- * \post Signals \c terminated
  */
 void Downloader::setFailed()
 {
-	failed=true;
-	finished = true;
+	cache->markFinished(true);
 	//Set the final length
-	length = receivedLength;
-
-	//If we are waiting for data to become available, signal dataAvailable
-	if(waitingForData)
-	{
-		waitingForData = false;
-		dataAvailable.signal();
-	}
-
-	waitingForTermination = false;
-	terminated.signal();
+	length = cache->getReceivedLength();
 }
 
 /**
@@ -572,139 +293,13 @@ void Downloader::setFailed()
  * signals \c dataAvailable if it is being waited for.
  * It also signals \c terminated to mark the end of the download.
  * A download should finish be either calling \c setFailed() or \c setFinished(), not both.
- * \post \c finished == \ctrue
  * \post \c length == \c receivedLength
- * \post Signals \c dataAvailable if it is being waited for (\c waitingForData == true).
- * \post \c waitingForTermination == \c false
- * \post Signals \c terminated
  */
 void Downloader::setFinished()
 {
-	finished=true;
+	cache->markFinished();
 	//Set the final length
-	length = receivedLength;
-
-	//If we are waiting for data to become available, signal dataAvailable
-	if(waitingForData)
-	{
-		waitingForData = false;
-		dataAvailable.signal();
-	}
-
-	waitingForTermination = false;
-	terminated.signal();
-}
-
-/**
- * \brief (Re)allocates the buffer
- *
- * (Re)allocates the buffer to a given size
- * Waits for mutex at start and releases mutex when finished.
- * \post \c buffer is (re)allocated
- * mutex must be locked on entry
- */
-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);
-	}
-	//If the buffer already exists, reallocate
-	else
-	{
-		assert(!cached);
-		intptr_t curLen = receivedLength;
-		//We have to extend the buffer, so create a new one
-		if(stableBuffer!=buffer)
-		{
-			//We're already filling a different buffer from the one used to read
-			//Extend it!
-			buffer = (uint8_t*)realloc(buffer,size);
-		}
-		else
-		{
-			//Create a different buffer
-			buffer = (uint8_t*) calloc(size, sizeof(uint8_t));
-			//Copy the stableBuffer into this
-			memcpy(buffer,stableBuffer,curLen);
-		}
-		//Synchronization of the buffers will be done at the first chance
-	}
-}
-
-/**
- * \brief Creates & opens a temporary cache file
- *
- * Creates a temporary cache file in /tmp and calls \c openExistingCache() with that file.
- * Waits for mutex at start and releases mutex when finished.
- * \throw RunTimeException Temporary file could not be created
- * \throw RunTimeException Called when the downloader isn't cached or when the cache is already open
- * \see Downloader::openExistingCache()
- * mutex must be hold prior calling
- */
-void Downloader::openCache()
-{
-	//Only act if the downloader is cached and the cache hasn't been opened yet
-	if(cached && !cache.is_open())
-	{
-		//Create a temporary file(name)
-		std::string cacheFilenameS = Config::getConfig()->getCacheDirectory() + "/" + Config::getConfig()->getCachePrefix() + "XXXXXX";
-		char* cacheFilenameC = g_newa(char,cacheFilenameS.length()+1);
-		strncpy(cacheFilenameC, cacheFilenameS.c_str(), cacheFilenameS.length());
-		cacheFilenameC[cacheFilenameS.length()] = '\0';
-		//char cacheFilenameC[30] = "/tmp/lightsparkdownloadXXXXXX";
-		//strcpy(cacheFilenameC, "/tmp/lightsparkdownloadXXXXXX");
-		int fd = g_mkstemp(cacheFilenameC);
-		if(fd == -1)
-			throw RunTimeException(_("Downloader::openCache: cannot create temporary file"));
-		//We are using fstream to read/write to the cache, so we don't need this FD
-		close(fd);
-
-		//Let the openExistingCache function handle the rest
-		openExistingCache(tiny_string(cacheFilenameC, true));
-	}
-	else
-		throw RunTimeException(_("Downloader::openCache: downloader isn't cached or called twice"));
-}
-
-/**
- * \brief Opens an existing cache file
- *
- * Opens an existing cache file, allocates the buffer and signals \c cacheOpened.
- * Waits for mutex at start and releases mutex when finished.
- * \post \c cacheFilename is set
- * \post \c cache file is opened
- * \post \c buffer is initialized
- * \post \c cacheOpened is signalled
- * \throw RunTimeException File could not be opened
- * \throw RunTimeException Called when the downloader isn't cached or when the cache is already open
- * \see Downloader::allocateBuffer()
- * mutex must be hold on entering
- */
-void Downloader::openExistingCache(tiny_string filename)
-{
-	//Only act if the downloader is cached and the cache hasn't been opened yet
-	if(cached && !cache.is_open())
-	{
-		//Save the filename
-		cacheFilename = filename;
-
-		//Open the cache file
-		cache.open(cacheFilename.raw_buf(), std::fstream::binary | std::fstream::in | std::fstream::out);
-		if(!cache.is_open())
-			throw RunTimeException(_("Downloader::openCache: cannot open temporary cache file"));
-
-		allocateBuffer(cacheMaxSize);
-
-		LOG(LOG_INFO, _("NET: Downloading to cache file: ") << cacheFilename);
-
-		cacheOpened.signal();
-	}
-	else
-		throw RunTimeException(_("Downloader::openCache: downloader isn't cached or called twice"));
+	length = cache->getReceivedLength();
 }
 
 /**
@@ -712,27 +307,14 @@ void Downloader::openExistingCache(tiny_string filename)
  *
  * Sets the expected length of the download.
  * Can be called multiple times if the length isn't known up front (reallocating the buffer on the fly).
- * Waits for mutex at start and releases mutex when finished.
- * \post \c buffer is (re)allocated 
- * mutex must be hold prior calling
  */
 void Downloader::setLength(uint32_t _length)
 {
 	//Set the length
 	length=_length;
 
-	//The first call to this function should open the cache
-	if(cached)
-	{
-		if(!cache.is_open())
-			openCache();
-	}
-	else
-	{
-		if(buffer == NULL)
-			LOG(LOG_INFO, _("NET: Downloading to memory"));
-		allocateBuffer(length);
-	}
+	cache->reserve(length);
+
 	notifyOwnerAboutBytesTotal();
 }
 
@@ -752,39 +334,9 @@ void Downloader::append(uint8_t* buf, uint32_t added)
 	if(added==0)
 		return;
 
-	Mutex::Lock l(mutex);
-
-	//If the added data would overflow the buffer, grow it
-	if((receivedLength+added)>length)
-	{
-		uint32_t newLength;
-		assert(length>=receivedLength);
-		//If reallocating the buffer ask for a minimum amount of space
-		if((receivedLength+added)-length > bufferMinGrowth)
-			newLength = receivedLength + added;
-		else
-			newLength = length + bufferMinGrowth;
-		assert(newLength>=receivedLength+added);
-
-		setLength(newLength);
-	}
-
-	if(cached)
-	{
-		//Seek to where we last wrote data
-		cache.seekp(receivedLength);
-		cache.write((char*) buf, added);
-	}
-	else
-		memcpy(buffer+receivedLength, buf, added);
-
-	receivedLength += added;
-
-	if(waitingForData)
-	{
-		waitingForData = false;
-		dataAvailable.signal();
-	}
+	cache->append((unsigned char *)buf, added);
+	if (cache->getReceivedLength() > length)
+		setLength(cache->getReceivedLength());
 
 	notifyOwnerAboutBytesLoaded();
 }
@@ -824,8 +376,6 @@ void Downloader::parseHeaders(const char* _headers, bool _setLength)
  */
 void Downloader::parseHeader(std::string header, bool _setLength)
 {
-	Mutex::Lock l(mutex);
-
 	if(header.substr(0, 9) == "HTTP/1.1 " || header.substr(0, 9) == "HTTP/1.0 ") 
 	{
 		std::string status = header.substr(9, 3);
@@ -891,83 +441,8 @@ void Downloader::parseHeader(std::string header, bool _setLength)
  */
 void Downloader::stop()
 {
-	failed = true;
-	finished = true;
-	length = receivedLength;
-
-	waitingForData = false;
-	dataAvailable.signal();
-
-	waitingForTermination = false;
-	terminated.signal();
-}
-
-/**
- * \brief Wait for the cache file to be opened
- *
- * If \c !cacheHasOpened: wait for the \c cacheOpened signal and set \c cacheHasOpened to \c true
- * Waits for the mutex at start and releases the mutex when finished.
- * \post \c cacheOpened signals has been handled
- * \post \c cacheHasOpened = true
- * mutex must be locked on entry
- */
-void Downloader::waitForCache()
-{
-	if(!cacheHasOpened)
-	{
-		waitingForCache = true;
-
-		mutex.unlock();
-		cacheOpened.wait();
-		mutex.lock();
-
-		cacheHasOpened = true;
-	}
-}
-
-/**
- * \brief Wait for data to become available
- *
- * Wait for data to become available.
- * Waits for the mutex at start and releases the mutex when finished.
- * \post \c dataAvailable signal has been handled
- */
-void Downloader::waitForData_locked()
-{
-	waitingForData = true;
-	mutex.unlock();
-	dataAvailable.wait();
-	mutex.lock();
-}
-
-/**
- * \brief Wait for termination of the downloader
- *
- * If \c getSys()->isShuttingDown(), calls \c setFailed() and returns.
- * Otherwise if \c !hasTerminated: wait for the \c terminated signal and set \c hasTerminated to \c true
- * Waits for the mutex at start and releases the mutex when finished.
- * \post \c terminated signal has been handled
- * \post \c hasTerminated = true
- */
-void Downloader::waitForTermination()
-{
-	Mutex::Lock l(mutex);
-	if(getSys()->isShuttingDown())
-	{
-		setFailed();
-		return;
-	}
-
-	if(!hasTerminated)
-	{
-		waitingForTermination = true;
-
-		l.release();
-		terminated.wait();
-		l.acquire();
-
-		hasTerminated = true;
-	}
+	cache->markFinished(true);
+	length = cache->getReceivedLength();
 }
 
 void Downloader::notifyOwnerAboutBytesTotal() const
@@ -979,7 +454,7 @@ void Downloader::notifyOwnerAboutBytesTotal() const
 void Downloader::notifyOwnerAboutBytesLoaded() const
 {
 	if(owner)
-		owner->setBytesLoaded(receivedLength);
+		owner->setBytesLoaded(cache->getReceivedLength());
 }
 
 void ThreadedDownloader::enableFencingWaiting()
@@ -1010,8 +485,8 @@ void ThreadedDownloader::waitFencing()
  * \param[in] _url The URL for the Downloader.
  * \param[in] _cached Whether or not to cache this download.
  */
-ThreadedDownloader::ThreadedDownloader(const tiny_string& url, bool cached, ILoadable* o):
-	Downloader(url, cached, o),fenceState(false)
+ThreadedDownloader::ThreadedDownloader(const tiny_string& url, _R <StreamCache> cache, ILoadable* o):
+	Downloader(url, cache, o),fenceState(false)
 {
 }
 
@@ -1022,9 +497,10 @@ ThreadedDownloader::ThreadedDownloader(const tiny_string& url, bool cached, ILoa
  * \param[in] _url The URL for the Downloader.
  * \param[in] data Additional data to send to the host
  */
-ThreadedDownloader::ThreadedDownloader(const tiny_string& url, const std::vector<uint8_t>& data,
+ThreadedDownloader::ThreadedDownloader(const tiny_string& url, _R<StreamCache> cache,
+				       const std::vector<uint8_t>& data,
 				       const std::list<tiny_string>& headers, ILoadable* o):
-	Downloader(url, data, headers, o),fenceState(false)
+	Downloader(url, cache, data, headers, o),fenceState(false)
 {
 }
 
@@ -1046,8 +522,8 @@ ThreadedDownloader::~ThreadedDownloader()
  * \param[in] _url The URL for the Downloader.
  * \param[in] _cached Whether or not to cache this download.
  */
-CurlDownloader::CurlDownloader(const tiny_string& _url, bool _cached, ILoadable* o):
-	ThreadedDownloader(_url, _cached, o)
+CurlDownloader::CurlDownloader(const tiny_string& _url, _R<StreamCache> _cache, ILoadable* o):
+	ThreadedDownloader(_url, _cache, o)
 {
 }
 
@@ -1057,9 +533,10 @@ CurlDownloader::CurlDownloader(const tiny_string& _url, bool _cached, ILoadable*
  * \param[in] _url The URL for the Downloader.
  * \param[in] data Additional data to send to the host
  */
-CurlDownloader::CurlDownloader(const tiny_string& _url, const std::vector<uint8_t>& _data,
+CurlDownloader::CurlDownloader(const tiny_string& _url, _R<StreamCache> _cache,
+			       const std::vector<uint8_t>& _data,
 			       const std::list<tiny_string>& _headers, ILoadable* o):
-	ThreadedDownloader(_url, _data, _headers, o)
+	ThreadedDownloader(_url, _cache, _data, _headers, o)
 {
 }
 
@@ -1180,7 +657,7 @@ void CurlDownloader::execute()
 int CurlDownloader::progress_callback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow)
 {
 	CurlDownloader* th=static_cast<CurlDownloader*>(clientp);
-	return th->threadAborting || th->failed;
+	return th->threadAborting || th->cache->hasFailed();
 }
 
 /**
@@ -1224,7 +701,8 @@ size_t CurlDownloader::write_header(void *buffer, size_t size, size_t nmemb, voi
  * \param[in] _url The URL for the Downloader.
  * \param[in] _cached Whether or not to cache this download.
  */
-LocalDownloader::LocalDownloader(const tiny_string& _url, bool _cached, ILoadable* o):ThreadedDownloader(_url, _cached, o)
+LocalDownloader::LocalDownloader(const tiny_string& _url, _R<StreamCache> _cache, ILoadable* o):
+	ThreadedDownloader(_url, _cache, o)
 {
 }
 
@@ -1256,18 +734,14 @@ void LocalDownloader::execute()
 		LOG(LOG_INFO, _("NET: LocalDownloader::execute: reading local file: ") << url.raw_buf());
 		//If the caching is selected, we override the normal behaviour and use the local file as the cache file
 		//This prevents unneeded copying of the file's data
-		if(isCached())
-		{
-			Mutex::Lock l(mutex);
-			//Make sure we don't delete the local file afterwards
-			keepCache = true;
 
-			openExistingCache(url);
+		FileStreamCache *fileCache = dynamic_cast<FileStreamCache *>(cache.getPtr());
+		if (fileCache)
+		{
+			fileCache->useExistingFile(url);
 
-			cache.seekg(0, std::ios::end);
 			//Report that we've downloaded everything already
-			length = cache.tellg();
-			receivedLength = length;
+			length = fileCache->getReceivedLength();
 			notifyOwnerAboutBytesLoaded();
 			notifyOwnerAboutBytesTotal();
 		}
@@ -1280,7 +754,6 @@ void LocalDownloader::execute()
 			{
 				file.seekg(0, std::ios::end);
 				{
-					Mutex::Lock l(mutex);
 					setLength(file.tellg());
 				}
 				file.seekg(0, std::ios::beg);
@@ -1290,7 +763,7 @@ void LocalDownloader::execute()
 				bool readFailed = 0;
 				while(!file.eof())
 				{
-					if(file.fail() || hasFailed())
+					if(file.fail() || cache->hasFailed())
 					{
 						readFailed = 1;
 						break;
@@ -1329,7 +802,7 @@ DownloaderThreadBase::DownloaderThreadBase(_NR<URLRequest> request, IDownloaderT
 	}
 }
 
-bool DownloaderThreadBase::createDownloader(bool cached,
+bool DownloaderThreadBase::createDownloader(_R<StreamCache> cache,
 					    _NR<EventDispatcher> dispatcher,
 					    ILoadable* owner,
 					    bool checkPolicyFile)
@@ -1355,11 +828,11 @@ bool DownloaderThreadBase::createDownloader(bool cached,
 	if(postData.empty())
 	{
 		//This is a GET request
-		downloader=getSys()->downloadManager->download(url, cached, owner);
+		downloader=getSys()->downloadManager->download(url, cache, owner);
 	}
 	else
 	{
-		downloader=getSys()->downloadManager->downloadWithData(url, postData, requestHeaders, owner);
+		downloader=getSys()->downloadManager->downloadWithData(url, cache, postData, requestHeaders, owner);
 	}
 
 	return true;
diff --git a/src/backends/netutils.h b/src/backends/netutils.h
index de2789b..2f1f6fd 100644
--- a/src/backends/netutils.h
+++ b/src/backends/netutils.h
@@ -29,6 +29,7 @@
 #include "swftypes.h"
 #include "thread_pool.h"
 #include "backends/urlutils.h"
+#include "backends/streamcache.h"
 #include "smartrefs.h"
 
 namespace lightspark
@@ -57,8 +58,9 @@ protected:
 	void cleanUp();
 public:
 	virtual ~DownloadManager();
-	virtual Downloader* download(const URLInfo& url, bool cached, ILoadable* owner)=0;
-	virtual Downloader* downloadWithData(const URLInfo& url, const std::vector<uint8_t>& data,
+	virtual Downloader* download(const URLInfo& url, _R<StreamCache> cache, ILoadable* owner)=0;
+	virtual Downloader* downloadWithData(const URLInfo& url, _R<StreamCache> cache, 
+			const std::vector<uint8_t>& data,
 			const std::list<tiny_string>& headers, ILoadable* owner)=0;
 	virtual void destroy(Downloader* downloader)=0;
 	void stopAll();
@@ -72,57 +74,22 @@ class DLL_PUBLIC StandaloneDownloadManager:public DownloadManager
 public:
 	StandaloneDownloadManager();
 	~StandaloneDownloadManager();
-	Downloader* download(const URLInfo& url, bool cached, ILoadable* owner);
-	Downloader* downloadWithData(const URLInfo& url, const std::vector<uint8_t>& data,
+	Downloader* download(const URLInfo& url, _R<StreamCache> cache, ILoadable* owner);
+	Downloader* downloadWithData(const URLInfo& url, _R<StreamCache> cache,
+			const std::vector<uint8_t>& data,
 			const std::list<tiny_string>& headers, ILoadable* owner);
 	void destroy(Downloader* downloader);
 };
 
-class DLL_PUBLIC Downloader: public std::streambuf
+class DLL_PUBLIC Downloader
 {
-private:
-	//Handles streambuf out-of-data events
-	virtual int_type underflow();
-	//Seeks to absolute position
-	virtual pos_type seekoff(off_type, std::ios_base::seekdir, std::ios_base::openmode);
-	//Seeks to relative position
-	virtual pos_type seekpos(pos_type, std::ios_base::openmode);
-	//Helper to get the current offset
-	pos_type getOffset() const;
 protected:
 	//Abstract base class, can't be constructed
-	Downloader(const tiny_string& _url, bool _cached, ILoadable* o);
-	Downloader(const tiny_string& _url, const std::vector<uint8_t>& data,
+	Downloader(const tiny_string& _url, _R<StreamCache> _cache, ILoadable* o);
+	Downloader(const tiny_string& _url, _R<StreamCache> _cache, const std::vector<uint8_t>& data,
 		   const std::list<tiny_string>& headers, ILoadable* o);
-	//-- LOCKING
-	//Provides internal mutual exclusing
-	Mutex mutex;
-	//Signals the cache opening
-	Semaphore cacheOpened;
-	//Signals new bytes available for reading
-	Semaphore dataAvailable;
-	//Signals termination of the download
-	Semaphore terminated;
-	//True if the download is terminated
-	bool hasTerminated;
-	//True if cache has opened
-	bool cacheHasOpened;
-
-	//-- STATUS
-	//True if the downloader is waiting for the cache to be opened
-	bool waitingForCache;
-	//True if the downloader is waiting for data
-	bool waitingForData;
-	void waitForData_locked();
-	//True if the downloader is waiting for termination
-	bool waitingForTermination;
 
 	//-- FLAGS
-	//This flag forces a stop in internal code
-	bool forceStop;
-	//These flags specify what type of termination happened
-	bool failed;
-	bool finished;
 	//Mark the download as failed
 	void setFailed();
 	//Mark the download as finished
@@ -132,43 +99,14 @@ protected:
 	tiny_string url;
 	tiny_string originalURL;
 
-	//-- BUFFERING
-	//This will hold the whole download (non-cached) or a window into the download (cached)
-	uint8_t* buffer;
-	//We can't change the used buffer (for example when resizing) asynchronously. We can only do that on underflows
-	uint8_t* stableBuffer;
-	//Minimum growth of the buffer
-	static const size_t bufferMinGrowth = 4096;
-	//(Re)allocate the buffer
-	void allocateBuffer(size_t size);
-	//Synchronize stableBuffer and buffer
-	void syncBuffers();
+	//-- CACHING
+        _R<StreamCache> cache;
 
 	//-- PROGRESS MONITORING
 	ILoadable* owner;
 	void notifyOwnerAboutBytesTotal() const;
 	void notifyOwnerAboutBytesLoaded() const;
 
-	//-- CACHING
-	//Cache filename
-	tiny_string cacheFilename;
-	//Cache fstream
-	std::fstream cache;
-	//Position of the cache buffer into the file
-	uint32_t cachePos;
-	//Size of data in the buffer
-	uint32_t cacheSize;
-	//Maximum size of the cache buffer
-	static const size_t cacheMaxSize = 8192;
-	//True if the cache file doesn't need to be deleted on destruction
-	bool keepCache:1;
-	//True if the file is cached to disk (default = false)
-	bool cached:1;
-	//Creates & opens a temporary cache file
-	void openCache();
-	//Opens an existing cache file
-	void openExistingCache(tiny_string filename);
-
 	//-- HTTP REDIRECTION, STATUS & HEADERS
 	bool redirected:1;
 	void setRedirected(const tiny_string& newURL)
@@ -187,10 +125,6 @@ protected:
 	//-- DOWNLOADED DATA
 	//File length (can change in certain cases, resulting in reallocation of the buffer (non-cached))
 	uint32_t length;
-	//Amount of data already received
-	uint32_t receivedLength;
-	//Append data to the internal buffer
-	void append(uint8_t* buffer, uint32_t length);
 	//Set the length of the downloaded file, can be called multiple times to accomodate a growing file
 	void setLength(uint32_t _length);
 public:
@@ -198,28 +132,23 @@ public:
 	virtual ~Downloader();
 	//Stop the download
 	void stop();
-	//Wait for cache to be opened
-	void waitForCache();
-	//Wait for data to become available
-	void waitForData() { Mutex::Lock l(mutex); waitForData_locked(); }
-	//Wait for the download to terminate
-	void waitForTermination();
 
 	//True if the download has failed
-	bool hasFailed() { return failed; }
+	bool hasFailed() { return cache->hasFailed(); }
 	//True if the download has finished
 	//Can be used in conjunction with failed to find out if it finished successfully
-	bool hasFinished() { return finished; }
-
-	//True if the download is cached
-	bool isCached() { return cached; }
+	bool hasFinished() { return cache->hasTerminated(); }
 
 	const tiny_string& getURL() { return url; }
 
+	//Wait until the downloader completes
+	void waitForTermination() { return cache->waitForTermination(); }
+
+	_R<StreamCache> getCache() { return cache; }
 	//Gets the total length of the downloaded file (may change)
 	uint32_t getLength() { return length; }
 	//Gets the length of downloaded data
-	uint32_t getReceivedLength() { return receivedLength; }
+	uint32_t getReceivedLength() { return cache->getReceivedLength(); }
 
 	size_t getHeaderCount() { return headers.size(); }
 	tiny_string getHeader(const char* header) { return getHeader(tiny_string(header)); }
@@ -232,7 +161,8 @@ public:
 	bool isRedirected() { return redirected; }
 	const tiny_string& getOriginalURL() { return originalURL; }
 	uint16_t getRequestStatus() { return requestStatus; }
-
+	//Append data to the internal buffer
+	void append(uint8_t* buffer, uint32_t length);
 };
 
 class ThreadedDownloader : public Downloader, public IThreadJob
@@ -245,8 +175,9 @@ public:
 	void waitFencing();
 protected:
 	//Abstract base class, can not be constructed
-	ThreadedDownloader(const tiny_string& url, bool cached, ILoadable* o);
-	ThreadedDownloader(const tiny_string& url, const std::vector<uint8_t>& data,
+	ThreadedDownloader(const tiny_string& url, _R<StreamCache> cache, ILoadable* o);
+	ThreadedDownloader(const tiny_string& url, _R<StreamCache> cache,
+			   const std::vector<uint8_t>& data,
 			   const std::list<tiny_string>& headers, ILoadable* o);
 //	//This class can only get destroyed by DownloadManager
 //	virtual ~ThreadedDownloader();
@@ -262,8 +193,8 @@ private:
 	void execute();
 	void threadAbort();
 public:
-	CurlDownloader(const tiny_string& _url, bool _cached, ILoadable* o);
-	CurlDownloader(const tiny_string& _url, const std::vector<uint8_t>& data,
+	CurlDownloader(const tiny_string& _url, _R<StreamCache> cache, ILoadable* o);
+	CurlDownloader(const tiny_string& _url, _R<StreamCache> cache, const std::vector<uint8_t>& data,
 		       const std::list<tiny_string>& headers, ILoadable* o);
 };
 
@@ -280,7 +211,7 @@ private:
 	//Size of the reading buffer
 	static const size_t bufSize = 8192;
 public:
-	LocalDownloader(const tiny_string& _url, bool _cached, ILoadable* o);
+	LocalDownloader(const tiny_string& _url, _R<StreamCache> _cache, ILoadable* o);
 };
 
 class IDownloaderThreadListener
@@ -306,7 +237,7 @@ protected:
 	std::list<tiny_string> requestHeaders;
 	Spinlock downloaderLock;
 	Downloader* downloader;
-	bool createDownloader(bool cached,
+	bool createDownloader(_R<StreamCache> cache,
 			      _NR<EventDispatcher> dispatcher=NullRef,
 			      ILoadable* owner=NULL,
 			      bool checkPolicyFile=true);
diff --git a/src/backends/rendering.cpp b/src/backends/rendering.cpp
index 08228db..b80a320 100644
--- a/src/backends/rendering.cpp
+++ b/src/backends/rendering.cpp
@@ -46,10 +46,10 @@ using namespace std;
 /* calculate FPS every second */
 const Glib::TimeVal RenderThread::FPS_time(/*seconds*/1,/*microseconds*/0);
 
-static GStaticPrivate renderThread = G_STATIC_PRIVATE_INIT; /* TLS */
+DEFINE_AND_INITIALIZE_TLS(renderThread);
 RenderThread* lightspark::getRenderThread()
 {
-	RenderThread* ret = (RenderThread*)g_static_private_get(&renderThread);
+	RenderThread* ret = (RenderThread*)tls_get(&renderThread);
 	/* If this is NULL, then you are not calling from the render thread,
 	 * which is disallowed! (OpenGL is not threadsafe)
 	 */
@@ -326,7 +326,7 @@ void RenderThread::worker()
 {
 	setTLSSys(m_sys);
 	/* set TLS variable for getRenderThread() */
-	g_static_private_set(&renderThread, this, NULL);
+	tls_set(&renderThread, this);
 
 	ThreadProfile* profile=m_sys->allocateProfiler(RGB(200,0,0));
 	profile->setTag("Render");
diff --git a/src/backends/rtmputils.cpp b/src/backends/rtmputils.cpp
index 131ae48..3b6865b 100644
--- a/src/backends/rtmputils.cpp
+++ b/src/backends/rtmputils.cpp
@@ -20,6 +20,7 @@
 #include "backends/rtmputils.h"
 #include "logger.h"
 #include "swf.h"
+#include "backends/streamcache.h"
 
 #ifdef ENABLE_RTMP
 #include <librtmp/rtmp.h>
@@ -28,8 +29,9 @@
 using namespace lightspark;
 using namespace std;
 
-RTMPDownloader::RTMPDownloader(const tiny_string& _url, const tiny_string& _stream, ILoadable* o):
-	ThreadedDownloader(_url, true, o),
+RTMPDownloader::RTMPDownloader(const tiny_string& _url, _R<StreamCache> _cache,
+			       const tiny_string& _stream, ILoadable* o):
+	ThreadedDownloader(_url, _cache, o),
 	stream(_stream)
 {
 }
diff --git a/src/backends/rtmputils.h b/src/backends/rtmputils.h
index 7e9de51..6082152 100644
--- a/src/backends/rtmputils.h
+++ b/src/backends/rtmputils.h
@@ -34,7 +34,8 @@ private:
 	void threadAbort();
 	tiny_string stream;
 public:
-	RTMPDownloader(const tiny_string& _url, const tiny_string& _stream, ILoadable* o);
+	RTMPDownloader(const tiny_string& _url, _R<StreamCache> _cache,
+		       const tiny_string& _stream, ILoadable* o);
 };
 
 };
diff --git a/src/backends/security.cpp b/src/backends/security.cpp
index f460560..b43c8ca 100644
--- a/src/backends/security.cpp
+++ b/src/backends/security.cpp
@@ -1001,7 +1001,7 @@ bool URLPolicyFile::retrievePolicyFile(vector<unsigned char>& outData)
 	bool ok = true;
 
 	//No caching needed for this download, we don't expect very big files
-	Downloader* downloader=getSys()->downloadManager->download(url, false, NULL);
+	Downloader* downloader=getSys()->downloadManager->download(url, _MR(new MemoryStreamCache), NULL);
 
 	//Wait until the file is fetched
 	downloader->waitForTermination();
@@ -1023,7 +1023,8 @@ bool URLPolicyFile::retrievePolicyFile(vector<unsigned char>& outData)
 
 	//Policy files must have on of the following content-types to be valid:
 	//text/*, application/xml or application/xhtml+xml
-	tiny_string contentType = downloader->getHeader("content-type");
+	std::list<tiny_string> contenttypelist = downloader->getHeader("content-type").split(';');
+	tiny_string contentType = contenttypelist.size() == 0 ? "" : contenttypelist.front();
 	if(ok && (subtype == HTTP || subtype == HTTPS) && 
 	   contentType.substr(0, 5) != "text/" &&
 	   contentType != "application/xml" &&
@@ -1052,11 +1053,13 @@ bool URLPolicyFile::retrievePolicyFile(vector<unsigned char>& outData)
 
 	if (ok)
 	{
-		istream s(downloader);
+		std::streambuf *sbuf = downloader->getCache()->createReader();
+		istream s(sbuf);
 		size_t bufLength = downloader->getLength();
 		size_t offset = outData.size();
 		outData.resize(offset+bufLength);
 		s.read((char*)&outData[offset], bufLength);
+		delete sbuf;
 	}
 
 	getSys()->downloadManager->destroy(downloader);
diff --git a/src/backends/streamcache.cpp b/src/backends/streamcache.cpp
new file mode 100644
index 0000000..6db1b58
--- /dev/null
+++ b/src/backends/streamcache.cpp
@@ -0,0 +1,499 @@
+/**************************************************************************
+    Lightspark, a free flash player implementation
+
+    Copyright (C) 2013  Antti Ajanki (antti.ajanki at iki.fi)
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+**************************************************************************/
+
+#include <string.h>
+#include <unistd.h>
+#include <glib.h>
+#include "backends/streamcache.h"
+#include "backends/config.h"
+#include "exceptions.h"
+#include "logger.h"
+
+using namespace std;
+using namespace lightspark;
+
+StreamCache::StreamCache()
+  : receivedLength(0), failed(false), terminated(false)
+{
+}
+
+void StreamCache::markFinished(bool _failed)
+{
+	Locker locker(stateMutex);
+	if (terminated)
+		return;
+
+	failed = _failed;
+	terminated = true;
+	stateCond.broadcast();
+}
+
+void StreamCache::waitForData(size_t currentOffset)
+{
+	Locker locker(stateMutex);
+	while (receivedLength <= currentOffset && !terminated)
+		stateCond.wait(stateMutex);
+}
+
+void StreamCache::waitForTermination()
+{
+	Locker locker(stateMutex);
+	while (!terminated)
+		stateCond.wait(stateMutex);
+}
+
+void StreamCache::append(const unsigned char* buffer, size_t length)
+{
+	if (!buffer || length == 0 || terminated)
+		return;
+
+	handleAppend(buffer, length);
+
+	{
+		Locker locker(stateMutex);
+		receivedLength += length;
+		stateCond.broadcast();
+	}
+}
+
+class lightspark::MemoryChunk {
+public:
+	MemoryChunk(size_t len);
+	~MemoryChunk();
+	unsigned char * const buffer;
+	const size_t capacity;
+	ACQUIRE_RELEASE_VARIABLE(size_t, used);
+};
+
+MemoryChunk::MemoryChunk(size_t len) :
+	buffer(new unsigned char[len]), capacity(len), used(0)
+{
+}
+
+MemoryChunk::~MemoryChunk()
+{
+	delete[] buffer;
+}
+
+MemoryStreamCache::MemoryStreamCache():
+	writeChunk(NULL), nextChunkSize(0)
+{
+}
+
+MemoryStreamCache::~MemoryStreamCache()
+{
+	for (auto it=chunks.begin(); it!=chunks.end(); ++it)
+		delete *it;
+}
+
+// Rounds val up to the next multiple of pow(2, s).
+static size_t nextMultipleOf2Pow(size_t val, size_t s)
+{
+	return ((size_t)((double)(val-1) / (1 << s)) + 1) << s;
+}
+
+void MemoryStreamCache::allocateChunk(size_t minLength)
+{
+	size_t len = imax(imax(minLength, minChunkSize), nextChunkSize);
+	len = nextMultipleOf2Pow(len, 12);
+	assert(len >= minLength);
+	nextChunkSize = len;
+
+	{
+		Locker locker(chunkListMutex);
+		writeChunk = new MemoryChunk(len);
+		chunks.push_back(writeChunk);
+	}
+}
+
+void MemoryStreamCache::handleAppend(const unsigned char* data, size_t length)
+{
+	assert(length > 0);
+
+	if (!writeChunk || (ACQUIRE_READ(writeChunk->used) >= writeChunk->capacity))
+		allocateChunk(length);
+
+	assert(writeChunk);
+
+	size_t used = ACQUIRE_READ(writeChunk->used);
+	if (writeChunk->capacity >= used + length)
+	{
+		// Data fits in to the current chunk
+		memcpy(writeChunk->buffer + used, data, length);
+		RELEASE_WRITE(writeChunk->used, used + length);
+	}
+	else
+	{
+		// Write as much as possible to the current buffer
+		size_t unused = writeChunk->capacity - used;
+		memcpy(writeChunk->buffer + used, data, unused);
+		RELEASE_WRITE(writeChunk->used, writeChunk->capacity);
+
+		// allocate a new chunk by a recursive call
+		handleAppend(data + unused, length - unused);
+	}
+}
+
+void MemoryStreamCache::reserve(size_t expectedLength)
+{
+	if (expectedLength <= receivedLength)
+		return;
+
+	// Set the next chunk to be large enough to hold the remaining
+	// of the stream. The memory will be actually allocated in
+	// append().
+	size_t unused = 0;
+	if (writeChunk)
+		unused = writeChunk->capacity - ACQUIRE_READ(writeChunk->used);
+
+	size_t allocated = receivedLength + unused;
+	if (expectedLength > allocated)
+		nextChunkSize = expectedLength - allocated;
+}
+
+std::streambuf *MemoryStreamCache::createReader()
+{
+	incRef();
+	return new MemoryStreamCache::Reader(_MR(this));
+}
+
+MemoryStreamCache::Reader::Reader(_R<MemoryStreamCache> b) :
+	buffer(b), chunkIndex(0), chunkStartOffset(0)
+{
+	setg(NULL, NULL, NULL);
+}
+
+/**
+ * \brief Called by the streambuf API
+ *
+ * Called by the streambuf API when there is no more data to read.
+ */
+int MemoryStreamCache::Reader::underflow()
+{
+	Locker locker(buffer->chunkListMutex);
+
+	// Wait until there is some data to be read or until terminated
+	bool hasMoreChunks = chunkIndex+1 < buffer->chunks.size();
+	bool lastChunkHasBytes = (chunkIndex+1 == buffer->chunks.size()) && 
+		((size_t)(gptr() - eback()) < ACQUIRE_READ(buffer->chunks[chunkIndex]->used));
+	if (!buffer->hasTerminated() && !hasMoreChunks && !lastChunkHasBytes)
+	{
+		locker.release();
+		buffer->waitForData(getOffset());
+		locker.acquire();
+	}
+
+	if (chunkIndex >= buffer->chunks.size())
+	{
+		// This can only happen if the stream is terminated
+		// before any data is written.
+		assert(chunkIndex == 0);
+		assert(buffer->hasTerminated());
+		return EOF;
+	}
+
+	MemoryChunk *chunk = buffer->chunks[chunkIndex];
+	size_t used = ACQUIRE_READ(chunk->used);
+	unsigned char *cursor;
+	unsigned char *end = chunk->buffer + used;
+
+	if (gptr() == NULL)
+	{
+		// On the first call gptr() is NULL (as set in the
+		// constructor). Nothing has been read yet.
+		cursor = chunk->buffer;
+	}
+	else if ((unsigned char*)gptr() < end)
+	{
+		// Data left in this chunk
+		cursor = (unsigned char*)gptr();
+	}
+	else if (chunkIndex == buffer->chunks.size()-1)
+	{
+		// This is the last received chunk and there is no
+		// data to be read => we're finished
+		assert(buffer->hasTerminated());
+		return EOF;
+	}
+	else
+	{
+		// Move to the next chunk
+		chunkStartOffset = chunkStartOffset + used;
+		chunkIndex++;
+
+		// chunkIndex is still valid, because the case
+		// size()-1 was handled above
+		assert_and_throw(chunkIndex < buffer->chunks.size());
+
+		chunk = buffer->chunks[chunkIndex];
+		cursor = chunk->buffer;
+		end = chunk->buffer + ACQUIRE_READ(chunk->used);
+	}
+
+	setg((char *)chunk->buffer, (char *)cursor, (char *)end);
+
+	assert(cursor != end); // there is at least one byte to return
+	return (int)cursor[0];
+}
+
+/**
+ * \brief Called by the streambuf API
+ *
+ * Called by the streambuf API to seek to a relative position
+ */
+streampos MemoryStreamCache::Reader::seekoff(streamoff off, std::ios_base::seekdir dir,
+					     std::ios_base::openmode mode)
+{
+	if (mode != std::ios_base::in)
+		return -1;
+
+	switch (dir)
+	{
+		case std::ios_base::beg:
+			seekpos(off, mode);
+			break;
+		case std::ios_base::cur:
+			// TODO: optimize by checking if the new
+			// offset is in the current chunk
+			seekpos(getOffset() + off, mode);
+			break;
+		case std::ios_base::end:
+			buffer->waitForTermination();
+			if (buffer->hasFailed())
+				return -1;
+
+			seekpos((streampos)buffer->getReceivedLength() + off, mode);
+			break;
+		default:
+			break;
+	}
+
+	return getOffset();
+}
+
+/**
+ * \brief Called by the streambuf API
+ *
+ * Called by the streambuf API to seek to an absolute position
+ */
+streampos MemoryStreamCache::Reader::seekpos(streampos pos, std::ios_base::openmode mode)
+{
+	if (mode != std::ios_base::in || pos < 0)
+		return -1;
+
+	if (pos >= (streampos)buffer->getReceivedLength())
+		buffer->waitForTermination();
+
+	Locker locker(buffer->chunkListMutex);
+	streampos offset = 0;
+	for (auto it=buffer->chunks.begin(); it!=buffer->chunks.end(); ++it)
+	{
+		streampos used = (streampos)ACQUIRE_READ((*it)->used);
+		if (pos >= offset + used)
+		{
+			offset += used;
+		}
+		else
+		{
+			setg((char *)(*it)->buffer,
+			     (char *)((*it)->buffer + (pos - offset)),
+			     (char *)((*it)->buffer + used));
+			return pos;
+		}
+	}
+
+	return -1;
+}
+
+/**
+ * Get the position of the read cursor in the (virtual) downloaded data.
+ */
+streampos MemoryStreamCache::Reader::getOffset() const
+{
+	return chunkStartOffset + (size_t)(gptr() - eback());
+}
+
+FileStreamCache::FileStreamCache()
+  : keepCache(false)
+{
+}
+
+FileStreamCache::~FileStreamCache()
+{
+	if (cache.is_open())
+		cache.close();
+	if (!keepCache && !cacheFilename.empty())
+		unlink(cacheFilename.raw_buf());
+}
+
+void FileStreamCache::handleAppend(const unsigned char* buffer, size_t length)
+{
+	if (!cache.is_open())
+		openCache();
+
+	cache.write((const char*)buffer, length);
+	cache.sync();
+}
+
+/**
+ * \brief Creates & opens a temporary cache file
+ *
+ * Creates a temporary cache file in /tmp and calls \c openExistingCache() with that file.
+ * Waits for mutex at start and releases mutex when finished.
+ * \throw RunTimeException Temporary file could not be created
+ * \throw RunTimeException Called when  the cache is already open
+ * \see Downloader::openExistingCache()
+ */
+void FileStreamCache::openCache()
+{
+	if (cache.is_open())
+	{
+		markFinished(true);
+		throw RunTimeException(_("FileStreamCache::openCache called twice"));
+	}
+
+	//Create a temporary file(name)
+	std::string cacheFilenameS = Config::getConfig()->getCacheDirectory() + "/" + Config::getConfig()->getCachePrefix() + "XXXXXX";
+	char* cacheFilenameC = g_newa(char,cacheFilenameS.length()+1);
+	strncpy(cacheFilenameC, cacheFilenameS.c_str(), cacheFilenameS.length());
+	cacheFilenameC[cacheFilenameS.length()] = '\0';
+	int fd = g_mkstemp(cacheFilenameC);
+	if(fd == -1)
+	{
+		markFinished(true);
+		throw RunTimeException(_("FileStreamCache::openCache: cannot create temporary file"));
+	}
+
+	//We are using fstream to read/write to the cache, so we don't need this FD
+	close(fd);
+
+	//Let the openExistingCache function handle the rest
+	openExistingCache(tiny_string(cacheFilenameC, true));
+}
+
+/**
+ * \brief Opens an existing cache file
+ *
+ * Opens an existing cache file, allocates the buffer and signals \c cacheOpened.
+ * \post \c cacheFilename is set
+ * \post \c cache file is opened
+ * \throw RunTimeException File could not be opened
+ * \throw RunTimeException Called when the cache is already open
+ */
+void FileStreamCache::openExistingCache(const tiny_string& filename, bool forWriting)
+{
+	if (cache.is_open())
+	{
+		markFinished(true);
+		throw RunTimeException(_("FileStreamCache::openCache called twice"));
+	}
+
+	cacheFilename = filename;
+
+	//Open the cache file
+	ios_base::openmode mode;
+	if (forWriting)
+		mode = std::fstream::binary | std::fstream::out;
+	else
+		mode = std::fstream::binary | std::fstream::in;
+	cache.open(cacheFilename.raw_buf(), mode);
+	if (!cache.is_open())
+	{
+		markFinished(true);
+		throw RunTimeException(_("FileStreamCache::openCache: cannot open temporary cache file"));
+	}
+
+	LOG(LOG_INFO, _("NET: Downloading to cache file: ") << cacheFilename);
+}
+
+void FileStreamCache::useExistingFile(const tiny_string& filename)
+{
+	//Make sure we don't delete the local file afterwards
+	keepCache = true;
+
+	cacheFilename = filename;
+	openExistingCache(filename, false);
+
+	cache.seekg(0, std::ios::end);
+	receivedLength = cache.tellg();
+
+	// We already have the whole file
+	markFinished();
+}
+
+void FileStreamCache::waitForCache()
+{
+	if (cache.is_open())
+		return;
+
+	// Cache file will be opened when the first byte is received
+	waitForData(0);
+
+	// Check if the stream was terminated before anything was written
+	if (!cache.is_open())
+		throw RunTimeException(_("FileStreamCache::waitForCache: cache file is not open"));
+}
+
+std::streambuf *FileStreamCache::createReader()
+{
+	waitForCache();
+
+	incRef();
+	FileStreamCache::Reader *fbuf = new FileStreamCache::Reader(_MR(this));
+	fbuf->open(cacheFilename.raw_buf(), std::fstream::binary | std::fstream::in);
+	if (!fbuf->is_open())
+	{
+		delete fbuf;
+		throw RunTimeException(_("FileStreamCache::createReader: opening cache file for reading failed"));
+	}
+	return fbuf;
+}
+
+FileStreamCache::Reader::Reader(_R<FileStreamCache> b) : buffer(b)
+{
+}
+
+int FileStreamCache::Reader::underflow()
+{
+	if (!buffer->hasTerminated())
+		buffer->waitForData(seekoff(0, ios_base::cur, ios_base::in));
+
+	return filebuf::underflow();
+}
+
+streamsize FileStreamCache::Reader::xsgetn(char* s, streamsize n)
+{
+	streamsize read=filebuf::xsgetn(s, n);
+
+	// If not enough data was available, wait for writer
+	while (read < n)
+	{
+		buffer->waitForData(seekoff(0, ios_base::cur, ios_base::in));
+
+		streamsize b = filebuf::xsgetn(s+read, n-read);
+
+		// No more data after waiting, this must be EOF
+		if (b == 0)
+			return read;
+
+		read += b;
+	}
+
+	return read;
+}
diff --git a/src/backends/streamcache.h b/src/backends/streamcache.h
new file mode 100644
index 0000000..82a14fd
--- /dev/null
+++ b/src/backends/streamcache.h
@@ -0,0 +1,197 @@
+/**************************************************************************
+    Lightspark, a free flash player implementation
+
+    Copyright (C) 2013  Antti Ajanki (antti.ajanki at iki.fi)
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+**************************************************************************/
+
+#ifndef BACKENDS_STREAMCACHE_H
+#define BACKENDS_STREAMCACHE_H 1
+
+#include <list>
+#include <istream>
+#include <fstream>
+#include <cstdint>
+#include "threading.h"
+#include "tiny_string.h"
+#include "smartrefs.h"
+#include "compat.h"
+
+namespace lightspark
+{
+
+/*
+ * A single-writer-multiple-reader buffer for downloaded streams.
+ *
+ * Writing is done by one thread by calling append(), reading is done
+ * through streambuf interface (constructred by createReader()) in a
+ * separate thread. There can be several readers in multiple threads.
+ *
+ * This is an abstract base class.
+ */
+class DLL_PUBLIC StreamCache : public RefCountable {
+protected:
+	StreamCache() DLL_LOCAL;
+
+	// stateMutex must be held while receivedLength, failed or
+	// terminated are accessed
+	Mutex stateMutex;
+	// stateCond is signalled when data is received or the stream
+	// is terminated
+	Cond stateCond;
+	// Amount of data already received
+	size_t receivedLength;
+	// Has the stream been completely downloaded or failed?
+	bool failed:1;
+	bool terminated:1;
+
+	// Wait until more than currentOffset bytes has been received
+	// or until terminated
+	void waitForData(size_t currentOffset) DLL_LOCAL;
+
+	// Derived class implements this to store received data
+	virtual void handleAppend(const unsigned char* buffer, size_t length)=0;
+
+public:
+	virtual ~StreamCache() {}
+
+	// Gets the length of downloaded data
+	size_t getReceivedLength() const { return receivedLength; }
+
+	bool hasTerminated() const { return terminated; }
+	bool hasFailed() const { return failed; }
+
+	// Wait until the writer calls markTerminated
+	void waitForTermination();
+
+	// Set the expected length of the stream.
+	// The default implementation does nothing, but the derived
+	// classes can allocate memory here.
+	virtual void reserve(size_t expectedLength) {}
+
+	// Write new data to the buffer (writer thread)
+	void append(const unsigned char* buffer, size_t length);
+
+	// Writer should call this when all of the stream has been
+	// append()'ed
+	void markFinished(bool failed=false);
+
+	// Create a streambuf for reading from this buffer (reader
+	// thread). Every call returns a new, independent streambuf.
+	// The caller must delete the returned value.
+	virtual std::streambuf *createReader()=0;
+};
+
+class MemoryChunk;
+
+/*
+ * MemoryStreamCache buffers the stream in memory.
+ */
+class DLL_PUBLIC MemoryStreamCache : public StreamCache {
+private:
+	class DLL_LOCAL Reader : public std::streambuf {
+	private:
+		_R<MemoryStreamCache> buffer;
+		// The chunk that is currently being read
+		unsigned int chunkIndex;
+		// Offset at the start of current chunk
+		size_t chunkStartOffset;
+
+		// Handles streambuf out-of-data events
+		virtual int underflow();
+		// Seeks to absolute position
+		virtual std::streampos seekoff(std::streamoff, std::ios_base::seekdir, std::ios_base::openmode);
+		// Seeks to relative position
+		virtual std::streampos seekpos(std::streampos, std::ios_base::openmode);
+		// Helper to get the current offset
+		std::streampos getOffset() const;
+	public:
+		Reader(_R<MemoryStreamCache> b);
+	};
+
+	// Stream is stored into a sequence of memory chunks. The
+	// chunks can grow, but they are never moved, so both readers
+	// and writer can safely use them. However, the mutex must be
+	// held when the container is accessed.
+	Mutex chunkListMutex;
+	std::vector<MemoryChunk *> chunks;
+
+	// The last chunk, the next write will happen here (writer thread)
+	MemoryChunk *writeChunk;
+
+	// Variables controlling the memory allocation
+	size_t nextChunkSize;
+	static const size_t minChunkSize = 4*4096;
+
+	// Allocate a new chunk, append it to chunks, update writeChunk
+	void allocateChunk(size_t minLength) DLL_LOCAL;
+
+	virtual void handleAppend(const unsigned char* buffer, size_t length) DLL_LOCAL;
+
+public:
+	MemoryStreamCache();
+	virtual ~MemoryStreamCache();
+
+	virtual void reserve(size_t expectedLength);
+
+	virtual std::streambuf *createReader();
+};
+
+/*
+ * FileStreamCache saves the stream in a temporary file.
+ */
+class DLL_PUBLIC FileStreamCache : public StreamCache {
+private:
+	/*
+	 * Extends filebuf to wait for writer thread to supply more
+	 * data when the end of temporary file is reached.
+	 */
+	class DLL_LOCAL Reader : public std::filebuf {
+	private:
+		_R<FileStreamCache> buffer;
+		virtual int underflow();
+		virtual std::streamsize xsgetn(char* s, std::streamsize n);
+	public:
+		Reader(_R<FileStreamCache> buffer);
+	};
+
+	//Cache filename
+	tiny_string cacheFilename;
+	//Cache fstream
+	std::fstream cache;
+	//True if the cache file doesn't need to be deleted on destruction
+	bool keepCache:1;
+
+	void openCache() DLL_LOCAL;
+	void openExistingCache(const tiny_string& filename, bool forWriting=true) DLL_LOCAL;
+
+	// Block until the cache file is opened by the writer stream
+	void waitForCache() DLL_LOCAL;
+
+	virtual void handleAppend(const unsigned char* buffer, size_t length) DLL_LOCAL;
+
+public:
+	FileStreamCache();
+	virtual ~FileStreamCache();
+
+	virtual std::streambuf *createReader();
+
+	// Use an existing file as cache. Must be called before append().
+	void useExistingFile(const tiny_string& filename);
+};
+
+};
+
+#endif // BACKENDS_STREAMCACHE_H
diff --git a/src/backends/urlutils.cpp b/src/backends/urlutils.cpp
index ebeaf9c..2511948 100644
--- a/src/backends/urlutils.cpp
+++ b/src/backends/urlutils.cpp
@@ -22,15 +22,39 @@
 #include "backends/urlutils.h"
 #include "compat.h"
 #include "scripting/toplevel/Integer.h"
+#include "scripting/toplevel/Error.h"
+#include "scripting/class.h"
 #include <string>
 #include <algorithm>
 #include <cctype>
 #include <sstream>
 #include <iostream>
 #include <fstream>
+#ifdef __MINGW32__
+#include <malloc.h>
+#else
+#include <alloca.h>
+#endif
 
 using namespace lightspark;
 
+std::list<uint32_t> URLInfo::uriReservedAndHash =
+	{';', '/', '?', ':', '@', '&', '=', '+', '$', ',', '#'};
+std::list<uint32_t> URLInfo::uriUnescaped = 
+	{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
+	 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B',
+	 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
+	 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3',
+	 '4', '5', '6', '7', '8', '9', '-', '_', '.', '!', '~', '*', '\'', '(',
+	 ')'};
+std::list<uint32_t> URLInfo::uriReservedAndUnescapedAndHash =
+	{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
+	 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B',
+	 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
+	 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3',
+	 '4', '5', '6', '7', '8', '9', '-', '_', '.', '!', '~', '*', '\'', '(',
+	 ')', ';', '/', '?', ':', '@', '&', '=', '+', '$', ',', '#'};
+
 std::ostream& lightspark::operator<<(std::ostream& s, const URLInfo& u)
 {
 	s << u.getParsedURL();
@@ -50,11 +74,15 @@ URLInfo::URLInfo(const tiny_string& u)
 	if(colonPos == std::string::npos)
 		invalidReason = MISSING_PROTOCOL;
 
-	std::string protocolStr = str.substr(0, colonPos);
-	std::transform(protocolStr.begin(), protocolStr.end(), protocolStr.begin(), ::tolower);
+	std::string protocolStr;
+	if (colonPos != std::string::npos) 
+	{
+		protocolStr = str.substr(0, colonPos);
+		std::transform(protocolStr.begin(), protocolStr.end(), protocolStr.begin(), ::tolower);
+	}
 	protocol = protocolStr;
 
-	size_t hostnamePos = colonPos+3;
+	size_t hostnamePos = colonPos != std::string::npos ? colonPos+3 : std::string::npos;
 	size_t portPos = std::string::npos;
 	size_t pathPos = std::string::npos;
 	size_t queryPos = std::string::npos;
@@ -93,8 +121,12 @@ URLInfo::URLInfo(const tiny_string& u)
 	}
 
 	//Parse the host string
-	std::string hostnameStr = str.substr(hostnamePos, std::min(std::min(pathPos, portPos), queryPos)-hostnamePos);
-	std::transform(hostnameStr.begin(), hostnameStr.end(), hostnameStr.begin(), ::tolower);
+	std::string hostnameStr;
+	if (hostnamePos != std::string::npos)
+	{
+		hostnameStr= str.substr(hostnamePos, std::min(std::min(pathPos, portPos), queryPos)-hostnamePos);
+		std::transform(hostnameStr.begin(), hostnameStr.end(), hostnameStr.begin(), ::tolower);
+	}
 	hostname = hostnameStr;
 
 	port = 0;
@@ -287,7 +319,7 @@ bool URLInfo::isSubOf(const URLInfo& url) const
 }
 bool URLInfo::isSubPathOf(const tiny_string& parent, const tiny_string& child)
 {
-	return child.substr(0, parent.numChars()) == parent;
+	return child.substr_bytes(0, parent.numBytes()) == parent;
 }
 bool URLInfo::isSubDomainOf(const tiny_string& parent, const tiny_string& child)
 {
@@ -332,6 +364,11 @@ bool URLInfo::sameHost(const URLInfo& other) const
 
 tiny_string URLInfo::encode(const tiny_string& u, ENCODING type)
 {
+	if (type == ENCODE_URI)
+		return encodeURI(u, uriReservedAndUnescapedAndHash);
+	else if (type == ENCODE_URICOMPONENT)
+		return encodeURI(u, uriUnescaped);
+
 	tiny_string str;
 	char buf[7];
 	
@@ -355,20 +392,6 @@ tiny_string URLInfo::encode(const tiny_string& u, ENCODING type)
 			//ENCODE_FORM encodes spaces as + instead of %20
 			else if(type == ENCODE_FORM && *i == ' ')
 				str += '+';
-			//Additionally ENCODE_URICOMPONENT and ENCODE_URI don't encode:
-			//- _ . ! ~ * ' ( )
-			else if((type == ENCODE_URI || type == ENCODE_URICOMPONENT) && 
-					(*i == '-' || *i == '_' || *i == '.' || *i == '!' ||
-						*i == '~' || *i == '*' || *i == '\'' ||	*i == '(' ||
-						*i == ')'))
-				str += *i;
-			//Additionally ENCODE_URI doesn't encode:
-			//; / ? : @ & = + $ , # 
-			else if((type == ENCODE_URI) && 
-						(*i == ';' || *i == '/' || *i == '?' || *i == ':' ||
-							*i == '@' || *i == '&' || *i == '=' || *i == '+' ||
-							*i == '$' || *i == ',' || *i == '#'))
-				str += *i;
 			// ENCODE_ESCAPE doesn't encode:
 			//@ - _ . * + /
 			else if(type == ENCODE_ESCAPE && 
@@ -390,8 +413,72 @@ tiny_string URLInfo::encode(const tiny_string& u, ENCODING type)
 	return str;
 }
 
-std::string URLInfo::decode(const std::string& u, ENCODING type)
+tiny_string URLInfo::encodeURI(const tiny_string& u, const std::list<uint32_t>& unescapedChars) {
+	tiny_string res;
+	CharIterator c = u.begin();
+	CharIterator end = u.end();
+	while (c != end)
+	{
+		if (std::find(unescapedChars.begin(), unescapedChars.end(), *c) == unescapedChars.end())
+		{
+			if ((*c >= 0xD800) && (*c <= 0xDFFF))
+			{
+				res += encodeSurrogatePair(c, end);
+			}
+			else
+			{
+				res += encodeSingleChar(*c);
+			}
+		}
+		else
+		{
+			res += *c;
+		}
+		++c;
+	}
+	return res;
+}
+
+tiny_string URLInfo::encodeSurrogatePair(CharIterator& c, const CharIterator& end)
+{
+	if ((*c < 0xD800) || (*c >= 0xDC00))
+		throwError<URIError>(kInvalidURIError, "encodeURI");
+	uint32_t highSurrogate = *c;
+	++c;
+	if ((c == end) || ((*c < 0xDC00) || (*c > 0xDFFF)))
+		throwError<URIError>(kInvalidURIError, "encodeURI");
+	uint32_t lowSurrogate = *c;
+	return encodeSingleChar((highSurrogate - 0xD800)*0x400 +
+				(lowSurrogate - 0xDC00) + 0x10000);
+}
+
+tiny_string URLInfo::encodeSingleChar(uint32_t codepoint)
 {
+	char octets[6];
+	gint numOctets = g_unichar_to_utf8(codepoint, octets);
+	tiny_string encoded;
+	for (int i=0; i<numOctets; i++)
+	{
+		encoded += encodeOctet(octets[i]);
+	}
+
+	return encoded;
+}
+
+tiny_string URLInfo::encodeOctet(char c) {
+	gchar *buf = (gchar *)alloca(6);
+	g_snprintf(buf, 6, "%%%.2X", (unsigned char)c);
+	buf[5] = '\0';
+	return tiny_string(buf, true);
+}
+
+tiny_string URLInfo::decode(const std::string& u, ENCODING type)
+{
+	if (type == ENCODE_URI)
+		return decodeURI(u, uriReservedAndHash);
+	else if (type == ENCODE_URICOMPONENT)
+		return decodeURI(u, {});
+
 	std::string str;
 	//The string can only shrink
 	str.reserve(u.length());
@@ -419,26 +506,6 @@ std::string URLInfo::decode(const std::string& u, ENCODING type)
 				str += stringBuf;
 				i+=2;
 			}
-			//ENCODE_URI and ENCODE_URICOMPONENT don't decode:
-			//- _ . ! ~ * ' ( ) 
-			else if((type == ENCODE_URI || type == ENCODE_URICOMPONENT) && 
-					(stringBuf == "%2D" || stringBuf == "%5F" || stringBuf == "%2E" || stringBuf == "%21" ||
-					 stringBuf == "%7E" || stringBuf == "%2A" || stringBuf == "%27" || stringBuf == "%28" || 
-					 stringBuf == "%29"))
-			{
-				str += stringBuf;
-				i+=2;
-			}
-			//Additionally ENCODE_URI doesn't decode:
-			//; / ? : @ & = + $ , # 
-			else if(type == ENCODE_URI && 
-					(stringBuf == "%23" || stringBuf == "%24" || stringBuf == "%26" || stringBuf == "%2B" ||
-					 stringBuf == "%2C" || stringBuf == "%2F" || stringBuf == "%3A" || stringBuf == "%3B" ||
-					 stringBuf == "%3D" || stringBuf == "%3F" || stringBuf == "%40"))
-			{
-				str += stringBuf;
-				i+=2;
-			}
 			//All encoded characters that weren't excluded above are now decoded
 			else
 			{	
@@ -466,6 +533,112 @@ std::string URLInfo::decode(const std::string& u, ENCODING type)
 	return str;
 }
 
+tiny_string URLInfo::decodeURI(const tiny_string& u, const std::list<uint32_t>& reservedChars)
+{
+	tiny_string res;
+	CharIterator c = u.begin();
+	CharIterator end = u.end();
+	while (c != end)
+	{
+		if (*c == '%')
+		{
+			CharIterator encodeBegin = c;
+			uint32_t decoded = decodeSingleChar(c, end);
+			if (std::find(reservedChars.begin(), reservedChars.end(), decoded) == reservedChars.end())
+			{
+				res += decoded;
+			}
+			else
+			{
+				CharIterator it = encodeBegin;
+				while (it != c)
+				{
+					res += *it;
+					++it;
+				}
+			}
+		}
+		else
+		{
+			res += *c;
+			++c;
+		}
+	}
+
+	return res;
+}
+
+uint32_t URLInfo::decodeSingleChar(CharIterator& c, const CharIterator& end)
+{
+	uint32_t decoded = decodeSingleEscapeSequence(c, end);
+	if ((decoded & 0x80) != 0) {
+		decoded = decodeRestOfUTF8Sequence(decoded, c, end);
+	}
+	return decoded;
+}
+
+uint32_t URLInfo::decodeRestOfUTF8Sequence(uint32_t firstOctet, CharIterator& c, const CharIterator& end) {
+	unsigned int numOctets = 0;
+	uint32_t mask = 0x80;
+	while ((firstOctet & mask) != 0) {
+		numOctets++;
+		mask = mask >> 1;
+	}
+	if (numOctets <= 1 || numOctets > 4)
+		throwError<URIError>(kInvalidURIError, "decodeURI");
+
+	char *octets = (char *)alloca(numOctets);
+	octets[0] = firstOctet;
+	for (unsigned int i=1; i<numOctets; i++) {
+		octets[i] = decodeSingleEscapeSequence(c, end);
+	}
+
+	if (isSurrogateUTF8Sequence(octets, numOctets))
+	{
+		LOG(LOG_NOT_IMPLEMENTED, "decodeURI: decoding surrogate pairs");
+		return REPLACEMENT_CHARACTER;
+	}
+
+	gunichar unichar = g_utf8_get_char_validated(octets, numOctets);
+	if ((unichar == (gunichar)-1) || 
+	    (unichar == (gunichar)-2) ||
+	    (unichar >= 0x10FFFF))
+		throwError<URIError>(kInvalidURIError, "decodeURI");
+
+	return (uint32_t)unichar;
+}
+
+uint32_t URLInfo::decodeSingleEscapeSequence(CharIterator& c, const CharIterator& end)
+{
+	if (*c != '%')
+		throwError<URIError>(kInvalidURIError, "decodeURI");
+	++c;
+	uint32_t h1 = decodeHexDigit(c, end);
+	uint32_t h2 = decodeHexDigit(c, end);
+	return (h1 << 4) + h2;
+}
+
+bool URLInfo::isSurrogateUTF8Sequence(const char *octets, unsigned int numOctets)
+{
+	// Surrogate code points: 0xD800 - 0xDFFF
+	// UTF-8 encoded: 0xED 0xA0 0x80 - 0xED 0xBF 0xBF
+	return (numOctets == 3) &&
+		((unsigned char)octets[0] == 0xED) &&
+		((unsigned char)octets[1] >= 0xA0) &&
+		((unsigned char)octets[1] <= 0xBF);
+}
+
+uint32_t URLInfo::decodeHexDigit(CharIterator& c, const CharIterator& end)
+{
+	if (c == end || !isxdigit(*c))
+		throwError<URIError>(kInvalidURIError, "decodeURI");
+
+	gint h = g_unichar_xdigit_value(*c);
+	assert((h >= 0) && (h < 16));
+	++c;
+	return (uint32_t) h;
+}
+
 bool URLInfo::isRTMP() const
 {
 	return protocol == "rtmp" || protocol == "rtmpe" || protocol == "rtmps" ||
diff --git a/src/backends/urlutils.h b/src/backends/urlutils.h
index 7c95982..6d1f633 100644
--- a/src/backends/urlutils.h
+++ b/src/backends/urlutils.h
@@ -35,6 +35,10 @@ class DLL_PUBLIC URLInfo
 {
 	friend std::ostream& operator<<(std::ostream& s, const URLInfo& u);
 private:
+	static std::list<uint32_t> uriReservedAndHash;
+	static std::list<uint32_t> uriUnescaped;
+	static std::list<uint32_t> uriReservedAndUnescapedAndHash;
+	static const uint32_t REPLACEMENT_CHARACTER = 0xFFFD;
 	tiny_string url; //The URL space encoded
 	tiny_string parsedURL; //The URL normalized and space encoded
 	tiny_string protocol; //Part after
@@ -51,6 +55,16 @@ private:
 	INVALID_REASON invalidReason;
 	uint16_t port; //Part after first : after hostname
 	bool valid;
+	static tiny_string encodeURI(const tiny_string& u, const std::list<uint32_t>& unescapedChars);
+	static tiny_string encodeSurrogatePair(CharIterator& c, const CharIterator& end);
+	static tiny_string encodeSingleChar(uint32_t codepoint);
+	static tiny_string encodeOctet(char c);
+	static tiny_string decodeURI(const tiny_string& u, const std::list<uint32_t>& reservedChars);
+	static uint32_t decodeSingleEscapeSequence(CharIterator& c, const CharIterator& end);
+	static uint32_t decodeSingleChar(CharIterator& c, const CharIterator& end);
+	static uint32_t decodeRestOfUTF8Sequence(uint32_t firstOctet, CharIterator& c, const CharIterator& end);
+	static uint32_t decodeHexDigit(CharIterator& c, const CharIterator& end);
+	static bool isSurrogateUTF8Sequence(const char *octets, unsigned int numOctets);
 public:
 	URLInfo():invalidReason(IS_EMPTY),valid(false) {};
 	URLInfo(const tiny_string& u);
@@ -109,11 +123,7 @@ public:
 	{
 		return std::string(encode(tiny_string(u), type));
 	}
-	static tiny_string decode(const tiny_string& u, ENCODING type=ENCODE_URICOMPONENT)
-	{
-		return tiny_string(decode(std::string(u.raw_buf()), type));
-	};
-	static std::string decode(const std::string& u, ENCODING type=ENCODE_URICOMPONENT);
+	static tiny_string decode(const std::string& u, ENCODING type=ENCODE_URICOMPONENT);
 };
 
 };
diff --git a/src/backends/xml_support.cpp b/src/backends/xml_support.cpp
index 2aefaee..8d1af9d 100644
--- a/src/backends/xml_support.cpp
+++ b/src/backends/xml_support.cpp
@@ -40,6 +40,7 @@ void RecoveryDomParser::parse_memory_raw(const unsigned char* contents, size_typ
 
 	xmlSAXHandlerV1* handler=(xmlSAXHandlerV1*)calloc(1,sizeof(xmlSAXHandlerV1));
 	initxmlDefaultSAXHandler(handler, 0);
+	handler->comment = comment;
 	context_->recovery=1;
 	free(context_->sax);
 	context_->sax=(xmlSAXHandler*)handler;
@@ -60,7 +61,8 @@ void RecoveryDomParser::parse_memory_raw(const unsigned char* contents, size_typ
 	if(!context_->wellFormed)
 		LOG(LOG_ERROR, "XML data not well formed!");
 
-	doc_ = new RecoveryDocument(context_->myDoc);
+	if (context_->myDoc)
+		doc_ = new RecoveryDocument(context_->myDoc);
 	// This is to indicate to release_underlying that we took the
 	// ownership on the doc.
 	context_->myDoc = 0;
@@ -74,7 +76,7 @@ void RecoveryDomParser::parse_memory_raw(const unsigned char* contents, size_typ
 #endif
 
 xmlpp::Node* XMLBase::buildFromString(const string& str,
-				      bool ignoreEmptyTextNodes,
+				      bool ignoreEmptyTextNodes, bool *hasParent,
 				      const string& default_ns)
 {
 	string buf = parserQuirks(str);
@@ -86,27 +88,42 @@ xmlpp::Node* XMLBase::buildFromString(const string& str,
 	{
 	}
 	xmlpp::Document* doc=parser.get_document();
-	if(doc && doc->get_root_node())
+	if(doc)
 	{
-		xmlpp::Element *root = doc->get_root_node();
-		// It would be better to remove empty nodes during
-		// parsing, but xmlpp doesn't offer an interface.
-		if (ignoreEmptyTextNodes)
-			removeWhitespaceNodes(root);
-		addDefaultNamespace(root, default_ns);
-		return root;
+		if (!doc->get_root_node())
+		{
+			buf = removeWhitespace(str)+"<parent></parent>";
+			try
+			{
+				parser.parse_memory_raw((const unsigned char*)buf.c_str(), buf.size());
+			}
+			catch(const exception& e)
+			{
+			}
+			doc=parser.get_document();
+		}
+		if (doc && doc->get_root_node())
+		{
+			*hasParent = true;
+			xmlpp::Element *root = doc->get_root_node();
+			// It would be better to remove empty nodes during
+			// parsing, but xmlpp doesn't offer an interface.
+			if (ignoreEmptyTextNodes)
+				removeWhitespaceNodes(root);
+			addDefaultNamespace(root, default_ns);
+			return root;
+		}
 	}
-
-	LOG(LOG_ERROR, "XML parsing failed, creating text node");
 	//If everything fails, create a fake document and add a single text string child
+	// see 10.3.1 in ECMA 357
 	if (default_ns.empty())
-		buf="<a></a>";
+		buf="<parent></parent>";
 	else
-		buf="<a xmlns=\"" + default_ns + "\"></a>";
+		buf="<parent xmlns=\"" + default_ns + "\"></parent>";
 	parser.parse_memory_raw((const unsigned char*)buf.c_str(), buf.size());
 
+	*hasParent = false;
 	return parser.get_document()->get_root_node()->add_child_text(str);
-	// TODO: node's parent (root) should be inaccessible from AS code
 }
 
 void XMLBase::addDefaultNamespace(xmlpp::Element *root, const string& default_ns)
@@ -136,15 +153,25 @@ void XMLBase::addDefaultNamespaceRecursive(xmlNodePtr node, xmlNsPtr ns)
 	}
 }
 
-xmlpp::Node* XMLBase::buildCopy(const xmlpp::Node* src)
+xmlpp::Node* XMLBase::buildCopy(const xmlpp::Node* src, bool *hasParent)
 {
+	const xmlpp::ContentNode* contentnode;
 	const xmlpp::TextNode* textnode=dynamic_cast<const xmlpp::TextNode*>(src);
 	if(textnode)
 	{
-		return buildFromString(textnode->get_content(), false);
+		return buildFromString(textnode->get_content(), false,hasParent);
+	}
+	else if ((contentnode = dynamic_cast<const xmlpp::ContentNode*>(src)))
+	{
+		// ContentNode but not TextNode => comment, PI or CData
+		// These can't be root nodes so we add a dummy root.
+		*hasParent = false;
+		xmlpp::Element* root = parser.get_document()->create_root_node("dummy_root");
+		return root->import_node(contentnode);
 	}
 	else
 	{
+		*hasParent = true;
 		return parser.get_document()->create_root_node_by_import(src);
 	}
 }
@@ -210,3 +237,25 @@ void XMLBase::removeWhitespaceNodes(xmlpp::Element *node)
 		}
 	}
 }
+tiny_string XMLBase::removeWhitespace(tiny_string val)
+{
+	bool bwhite = true;
+	uint32_t start = 0;
+	CharIterator it = val.begin();
+	CharIterator itend = val.begin();
+	while (it != val.end())
+	{
+		if (!g_unichar_isspace(*it))
+		{
+			itend=it;
+			itend++;
+			bwhite = false;
+		}
+		else if (bwhite)
+			start++;
+		it++;
+	}
+	if (bwhite)
+		return "";
+	return val.substr(start,itend);
+}
diff --git a/src/backends/xml_support.h b/src/backends/xml_support.h
index 5ef59b1..a8a6a5b 100644
--- a/src/backends/xml_support.h
+++ b/src/backends/xml_support.h
@@ -25,6 +25,7 @@
 #include <libxml++/exceptions/internal_error.h>
 //For xmlCreateFileParserCtxt().
 #include <libxml/parserInternals.h>
+#include "tiny_string.h"
 
 namespace lightspark
 {
@@ -57,16 +58,19 @@ protected:
 	LSDomParser parser;
 	xmlpp::Node* buildFromString(const std::string& str,
 				     bool ignoreEmptyTextnodes,
+				     bool *hasParent,
 				     const std::string& default_ns=std::string());
 	void addDefaultNamespace(xmlpp::Element *root, const std::string& default_ns);
 	void addDefaultNamespaceRecursive(xmlNodePtr node, xmlNsPtr ns);
 	// Set the root to be a copy of src. If src is a text node,
 	// create a new element node with the same content.
-	xmlpp::Node* buildCopy(const xmlpp::Node* node);
-	static std::string parserQuirks(const std::string& str);
+	xmlpp::Node* buildCopy(const xmlpp::Node* node, bool *hasParent);
 	static std::string quirkCData(const std::string& str);
 	static std::string quirkXMLDeclarationInMiddle(const std::string& str);
 	void removeWhitespaceNodes(xmlpp::Element *node);
+	tiny_string removeWhitespace(tiny_string val);
+public:
+	static std::string parserQuirks(const std::string& str);
 };
 
 };
diff --git a/src/compat.h b/src/compat.h
index 5934b65..0cc00c3 100644
--- a/src/compat.h
+++ b/src/compat.h
@@ -116,6 +116,7 @@ _CRTIMP char* __cdecl __MINGW_NOTHROW   _strdup (const char*) __MINGW_ATTRIB_MAL
 
 //Boolean type with acquire release barrier semantics
 #define ACQUIRE_RELEASE_FLAG(x) std::atomic_bool x
+#define ACQUIRE_RELEASE_VARIABLE(t, x) std::atomic<t> x
 #define ACQUIRE_READ(x) x.load(std::memory_order_acquire)
 #define RELEASE_WRITE(x, v) x.store(v, std::memory_order_release)
 
diff --git a/src/main.cpp b/src/main.cpp
index d0099bd..6f8d331 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -246,6 +246,7 @@ int main(int argc, char* argv[])
 #ifdef PROFILING_SUPPORT
 			" [--profiling-output|-o profiling-file]" <<
 #endif
+			" [--version|-v]" <<
 			" <file.swf>");
 		exit(1);
 	}
@@ -286,7 +287,12 @@ int main(int argc, char* argv[])
 	{
 		sys->mainClip->setOrigin(url, fileName);
 		sys->parseParametersFromURL(sys->mainClip->getOrigin());
-		sandboxType = SecurityManager::REMOTE;
+		if (sandboxType != SecurityManager::REMOTE &&
+		    sys->mainClip->getOrigin().getProtocol() != "file")
+		{
+			LOG(LOG_INFO, _("Switching to remote sandbox because of remote url"));
+			sandboxType = SecurityManager::REMOTE;
+		}
 	}
 #ifndef _WIN32
 	//When running in a local sandbox, set the root URL to the current working dir
diff --git a/src/parsing/amf3_generator.cpp b/src/parsing/amf3_generator.cpp
index 455cde7..0801c0a 100644
--- a/src/parsing/amf3_generator.cpp
+++ b/src/parsing/amf3_generator.cpp
@@ -26,6 +26,7 @@
 #include "toplevel/XML.h"
 #include <iostream>
 #include <fstream>
+#include "scripting/flash/utils/ByteArray.h"
 
 using namespace std;
 using namespace lightspark;
@@ -273,6 +274,7 @@ _R<ASObject> Amf3Deserializer::parseXML(std::vector<ASObject*>& objMap, bool leg
 	return _MR(xmlObj);
 }
 
+
 _R<ASObject> Amf3Deserializer::parseValue(std::vector<tiny_string>& stringMap,
 			std::vector<ASObject*>& objMap,
 			std::vector<TraitsRef>& traitsMap) const
@@ -281,33 +283,144 @@ _R<ASObject> Amf3Deserializer::parseValue(std::vector<tiny_string>& stringMap,
 	uint8_t marker;
 	if(!input->readByte(marker))
 		throw ParseException("Not enough data to parse AMF3 object");
+	if (input->getCurrentObjectEncoding() == ObjectEncoding::AMF3)
+	{
+		switch(marker)
+		{
+			case null_marker:
+				return _MR(getSys()->getNullRef());
+			case undefined_marker:
+				return _MR(getSys()->getUndefinedRef());
+			case false_marker:
+				return _MR(abstract_b(false));
+			case true_marker:
+				return _MR(abstract_b(true));
+			case integer_marker:
+				return parseInteger();
+			case double_marker:
+				return parseDouble();
+			case string_marker:
+				return _MR(Class<ASString>::getInstanceS(parseStringVR(stringMap)));
+			case xml_doc_marker:
+				return parseXML(objMap, true);
+			case array_marker:
+				return parseArray(stringMap, objMap, traitsMap);
+			case object_marker:
+				return parseObject(stringMap, objMap, traitsMap);
+			case xml_marker:
+				return parseXML(objMap, false);
+			default:
+				LOG(LOG_ERROR,"Unsupported marker " << (uint32_t)marker);
+				throw UnsupportedException("Unsupported marker");
+		}
+	
+	}
+	else
+	{
+		switch(marker)
+		{
+			case amf0_number_marker:
+				return parseDouble();
+			case amf0_boolean_marker:
+				return _MR(abstract_b(input->readByte(marker)));
+			case amf0_string_marker:
+				return _MR(Class<ASString>::getInstanceS(parseStringAMF0()));
+			case amf0_object_marker:
+				return parseObjectAMF0(stringMap,objMap,traitsMap);
+			case amf0_null_marker:
+				return _MR(getSys()->getNullRef());
+			case amf0_undefined_marker:
+				return _MR(getSys()->getUndefinedRef());
+			case amf0_reference_marker:
+				LOG(LOG_ERROR,"unimplemented marker " << (uint32_t)marker);
+				throw UnsupportedException("unimplemented marker");
+			case amf0_ecma_array_marker:
+				return parseECMAArrayAMF0(stringMap,objMap,traitsMap);
+			case amf0_strict_array_marker:
+				LOG(LOG_ERROR,"unimplemented marker " << (uint32_t)marker);
+				throw UnsupportedException("unimplemented marker");
+			case amf0_date_marker:
+				LOG(LOG_ERROR,"unimplemented marker " << (uint32_t)marker);
+				throw UnsupportedException("unimplemented marker");
+			case amf0_long_string_marker:
+				LOG(LOG_ERROR,"unimplemented marker " << (uint32_t)marker);
+				throw UnsupportedException("unimplemented marker");
+			case amf0_xml_document_marker:
+				return parseXML(objMap, false);
+			case amf0_typed_object_marker:
+				LOG(LOG_ERROR,"unimplemented marker " << (uint32_t)marker);
+				throw UnsupportedException("unimplemented marker");
+			case amf0_avmplus_object_marker:
+				input->setCurrentObjectEncoding(ObjectEncoding::AMF3);
+				return parseValue(stringMap, objMap, traitsMap);
+			default:
+				LOG(LOG_ERROR,"Unsupported marker " << (uint32_t)marker);
+				throw UnsupportedException("Unsupported marker");
+		}
+	}
+}
+tiny_string Amf3Deserializer::parseStringAMF0() const
+{
+	uint16_t strLen;
+	if(!input->readShort(strLen))
+		throw ParseException("Not enough data to parse integer");
+	
+	string retStr;
+	for(uint32_t i=0;i<strLen;i++)
+	{
+		uint8_t c;
+		if(!input->readByte(c))
+			throw ParseException("Not enough data to parse string");
+		retStr.push_back(c);
+	}
+	return retStr;
+}
+_R<ASObject> Amf3Deserializer::parseECMAArrayAMF0(std::vector<tiny_string>& stringMap,
+			std::vector<ASObject*>& objMap,
+			std::vector<TraitsRef>& traitsMap) const
+{
+	uint32_t count;
+	if(!input->readUnsignedInt(count))
+		throw ParseException("Not enough data to parse AMF3 array");
+
+	_R<ASObject> ret=_MR(Class<ASObject>::getInstanceS());
 
-	switch(marker)
+	//Read name, value pairs
+	while(count)
 	{
-		case null_marker:
-			return _MR(getSys()->getNullRef());
-		case undefined_marker:
-			return _MR(getSys()->getUndefinedRef());
-		case false_marker:
-			return _MR(abstract_b(false));
-		case true_marker:
-			return _MR(abstract_b(true));
-		case integer_marker:
-			return parseInteger();
-		case double_marker:
-			return parseDouble();
-		case string_marker:
-			return _MR(Class<ASString>::getInstanceS(parseStringVR(stringMap)));
-		case xml_doc_marker:
-			return parseXML(objMap, true);
-		case array_marker:
-			return parseArray(stringMap, objMap, traitsMap);
-		case object_marker:
-			return parseObject(stringMap, objMap, traitsMap);
-		case xml_marker:
-			return parseXML(objMap, false);
-		default:
-			LOG(LOG_ERROR,"Unsupported marker " << (uint32_t)marker);
-			throw UnsupportedException("Unsupported marker");
+		tiny_string varName = parseStringAMF0();
+		if (varName == "")
+			throw ParseException("empty key in AMF0 ECMA array");
+		_R<ASObject> value=parseValue(stringMap, objMap, traitsMap);
+		value->incRef();
+
+		ret->setVariableByQName(varName,"",value.getPtr(),DYNAMIC_TRAIT);
+		count--;
 	}
+	return ret;
 }
+_R<ASObject> Amf3Deserializer::parseObjectAMF0(std::vector<tiny_string>& stringMap,
+			std::vector<ASObject*>& objMap,
+			std::vector<TraitsRef>& traitsMap) const
+{
+	_R<ASObject> ret=_MR(Class<ASObject>::getInstanceS());
+
+	while (true)
+	{
+		tiny_string varName = parseStringAMF0();
+		if (varName == "")
+		{
+			uint8_t marker = 0;
+			input->readByte(marker);
+			if (marker == amf0_object_end_marker )
+				return ret;
+			throw ParseException("empty key in AMF0 object");
+		}
+		_R<ASObject> value=parseValue(stringMap, objMap, traitsMap);
+		value->incRef();
+
+		ret->setVariableByQName(varName,"",value.getPtr(),DYNAMIC_TRAIT);
+	}
+	return _R<ASObject>(getSys()->getUndefinedRef());
+}
+
diff --git a/src/parsing/amf3_generator.h b/src/parsing/amf3_generator.h
index 360685a..ae2cd69 100644
--- a/src/parsing/amf3_generator.h
+++ b/src/parsing/amf3_generator.h
@@ -50,6 +50,28 @@ enum markers_type
 	xml_marker = 0xb
 };
 
+enum amf0_markers_type
+{
+	amf0_number_marker       = 0x00,
+	amf0_boolean_marker      = 0x01,
+	amf0_string_marker       = 0x02,
+	amf0_object_marker       = 0x03,
+	amf0_movieclip_marker    = 0x04,
+	amf0_null_marker         = 0x05,
+	amf0_undefined_marker    = 0x06,
+	amf0_reference_marker    = 0x07,
+	amf0_ecma_array_marker   = 0x08,
+	amf0_object_end_marker   = 0x09,
+	amf0_strict_array_marker = 0x0A,
+	amf0_date_marker         = 0x0B,
+	amf0_long_string_marker  = 0x0C,
+	amf0_unsupported_marker  = 0x0D,
+	amf0_recordset_marker    = 0x0E,
+	amf0_xml_document_marker = 0x0F,
+	amf0_typed_object_marker = 0x10,
+	amf0_avmplus_object_marker = 0x11
+};
+
 class TraitsRef
 {
 public:
@@ -64,6 +86,7 @@ class Amf3Deserializer
 private:
 	ByteArray* input;
 	tiny_string parseStringVR(std::vector<tiny_string>& stringMap) const;
+	
 	_R<ASObject> parseObject(std::vector<tiny_string>& stringMap,
 			std::vector<ASObject*>& objMap,
 			std::vector<TraitsRef>& traitsMap) const;
@@ -76,6 +99,15 @@ private:
 	_R<ASObject> parseInteger() const;
 	_R<ASObject> parseDouble() const;
 	_R<ASObject> parseXML(std::vector<ASObject*>& objMap, bool legacyXML) const;
+
+
+	tiny_string parseStringAMF0() const;
+	_R<ASObject> parseECMAArrayAMF0(std::vector<tiny_string>& stringMap,
+			std::vector<ASObject*>& objMap,
+			std::vector<TraitsRef>& traitsMap) const;
+	_R<ASObject> parseObjectAMF0(std::vector<tiny_string>& stringMap,
+			std::vector<ASObject*>& objMap,
+			std::vector<TraitsRef>& traitsMap) const;
 public:
 	Amf3Deserializer(ByteArray* i):input(i) {}
 	_R<ASObject> readObject() const;
diff --git a/src/parsing/tags.cpp b/src/parsing/tags.cpp
index 665147d..6cdb962 100644
--- a/src/parsing/tags.cpp
+++ b/src/parsing/tags.cpp
@@ -24,10 +24,16 @@
 #include <list>
 #include <algorithm>
 #include <sstream>
+#ifdef __MINGW32__
+#include <malloc.h>
+#else
+#include <alloca.h>
+#endif
 #include "scripting/abc.h"
 #include "parsing/tags.h"
 #include "backends/geometry.h"
 #include "backends/security.h"
+#include "backends/streamcache.h"
 #include "swftypes.h"
 #include "logger.h"
 #include "compat.h"
@@ -35,6 +41,7 @@
 #include "scripting/flash/display/BitmapData.h"
 #include "scripting/flash/text/flashtext.h"
 #include "scripting/flash/media/flashmedia.h"
+#include "backends/audio.h"
 
 #undef RGB
 
@@ -383,6 +390,7 @@ DefineSpriteTag::DefineSpriteTag(RECORDHEADER h, std::istream& in, RootMovieClip
 			case SYMBOL_CLASS_TAG:
 			case ABC_TAG:
 			case CONTROL_TAG:
+			case ACTION_TAG:
 				delete tag;
 				throw ParseException("Control tag inside a sprite. Should not happen.");
 			case FRAMELABEL_TAG:
@@ -1181,8 +1189,7 @@ void PlaceObject2Tag::execute(DisplayObjectContainer* parent) const
 	//TODO: support clipping
 	if(ClipDepth!=0)
 	{
-		LOG(LOG_ERROR,"ClipDepth is not supported");
-		return;
+		LOG(LOG_ERROR,"ClipDepth is not supported, but object is created anyway");
 	}
 
 	if(!PlaceFlagHasCharacter && !PlaceFlagMove)
@@ -1436,6 +1443,7 @@ ASObject* DefineButtonTag::instance(Class_base* c) const
 			assert_and_throw(state);
 			//The matrix must be set before invoking the constructor
 			state->setLegacyMatrix(i->PlaceMatrix);
+			state->name = "";
 			/*
 			 * TODO: BlendMode, filerList, PlaceDepth, ColorTransfrom
 			 */
@@ -1532,7 +1540,7 @@ FileAttributesTag::FileAttributesTag(RECORDHEADER h, std::istream& in):Tag(h)
 	UB(24,bs);
 }
 
-DefineSoundTag::DefineSoundTag(RECORDHEADER h, std::istream& in,RootMovieClip* root):DictionaryTag(h,root)
+DefineSoundTag::DefineSoundTag(RECORDHEADER h, std::istream& in,RootMovieClip* root):DictionaryTag(h,root),SoundData(new MemoryStreamCache)
 {
 	LOG(LOG_TRACE,_("DefineSound Tag"));
 	in >> SoundId;
@@ -1542,8 +1550,13 @@ DefineSoundTag::DefineSoundTag(RECORDHEADER h, std::istream& in,RootMovieClip* r
 	SoundSize=UB(1,bs);
 	SoundType=UB(1,bs);
 	in >> SoundSampleCount;
-	//TODO: read and parse actual sound data
-	ignore(in,h.getLength()-7);
+
+	//TODO: get rid of the temporary copy
+	unsigned int soundDataLength = h.getLength()-7;
+	unsigned char *tmp = (unsigned char *)alloca(soundDataLength);
+	in.read((char *)tmp, soundDataLength);
+	SoundData->append(tmp, in.gcount());
+	SoundData->markFinished();
 }
 
 ASObject* DefineSoundTag::instance(Class_base* c) const
@@ -1556,8 +1569,82 @@ ASObject* DefineSoundTag::instance(Class_base* c) const
 	else
 		retClass=Class<Sound>::getClass();
 
-	//TODO: use the tag sound data
-	return new (retClass->memoryAccount) Sound(retClass);
+	return new (retClass->memoryAccount) Sound(retClass, SoundData,
+		AudioFormat(getAudioCodec(), getSampleRate(), getChannels()));
+}
+
+LS_AUDIO_CODEC DefineSoundTag::getAudioCodec() const
+{
+	return (LS_AUDIO_CODEC)SoundFormat;
+}
+
+int DefineSoundTag::getSampleRate() const
+{
+	switch(SoundRate)
+	{
+		case 0:
+			return 5500;
+		case 1:
+			return 11000;
+		case 2:
+			return 22000;
+		case 3:
+			return 44000;
+	}
+
+	// not reached
+	assert(false && "invalid sample rate");
+	return 0;
+}
+
+int DefineSoundTag::getChannels() const
+{
+	return (int)SoundType + 1;
+}
+
+_R<MemoryStreamCache> DefineSoundTag::getSoundData() const
+{
+	return SoundData;
+}
+
+std::streambuf *DefineSoundTag::createSoundStream() const
+{
+	return SoundData->createReader();
+}
+
+StartSoundTag::StartSoundTag(RECORDHEADER h, std::istream& in):ActionTag(h)
+{
+	LOG(LOG_TRACE,_("StartSound Tag"));
+	in >> SoundId >> SoundInfo;
+}
+
+void StartSoundTag::execute(RootMovieClip* root) const
+{
+	DefineSoundTag *soundTag = \
+		dynamic_cast<DefineSoundTag *>(root->dictionaryLookup(SoundId));
+
+	if (SoundInfo.SyncStop || SoundInfo.HasEnvelope || SoundInfo.HasLoops ||
+	    SoundInfo.HasOutPoint || SoundInfo.HasInPoint)
+	{
+		LOG(LOG_NOT_IMPLEMENTED, "StartSoundTag: some modifiers not supported");
+		if (SoundInfo.SyncStop)
+			return;
+	}
+
+	play(soundTag);
+}
+
+void StartSoundTag::play(const DefineSoundTag *soundTag) const
+{
+	SoundChannel *schannel = Class<SoundChannel>::getInstanceS(
+		soundTag->getSoundData(),
+		AudioFormat(soundTag->getAudioCodec(),
+			    soundTag->getSampleRate(),
+			    soundTag->getChannels()));
+
+	// SoundChannel thread keeps one reference, which will be
+	// removed thread is finished
+	schannel->decRef();
 }
 
 ScriptLimitsTag::ScriptLimitsTag(RECORDHEADER h, std::istream& in):ControlTag(h)
diff --git a/src/parsing/tags.h b/src/parsing/tags.h
index 3af0f4d..40d7bb7 100644
--- a/src/parsing/tags.h
+++ b/src/parsing/tags.h
@@ -31,7 +31,7 @@
 namespace lightspark
 {
 
-enum TAGTYPE {TAG=0,DISPLAY_LIST_TAG,SHOW_TAG,CONTROL_TAG,DICT_TAG,FRAMELABEL_TAG,SYMBOL_CLASS_TAG,ABC_TAG,END_TAG};
+enum TAGTYPE {TAG=0,DISPLAY_LIST_TAG,SHOW_TAG,CONTROL_TAG,DICT_TAG,FRAMELABEL_TAG,SYMBOL_CLASS_TAG,ACTION_TAG,ABC_TAG,END_TAG};
 
 void ignore(std::istream& i, int count);
 
@@ -94,6 +94,17 @@ public:
 	virtual void execute(RootMovieClip* root) const=0;
 };
 
+/*
+ * Initiates an action. Action is executed after a frame is parsed.
+ */
+class ActionTag: public ControlTag
+{
+public:
+	ActionTag(RECORDHEADER h):ControlTag(h){}
+	virtual TAGTYPE getType()const{ return ACTION_TAG; }
+	virtual void execute(RootMovieClip* root) const=0;
+};
+
 class DefineShapeTag: public DictionaryTag
 {
 protected:
@@ -212,6 +223,8 @@ public:
 	ASObject* instance(Class_base* c=NULL) const;
 };
 
+class MemoryStreamCache;
+
 class DefineSoundTag: public DictionaryTag
 {
 private:
@@ -221,16 +234,28 @@ private:
 	char SoundSize;
 	char SoundType;
 	UI32_SWF SoundSampleCount;
+	_R<MemoryStreamCache> SoundData;
 public:
 	DefineSoundTag(RECORDHEADER h, std::istream& s, RootMovieClip* root);
 	virtual int getId() const { return SoundId; }
 	ASObject* instance(Class_base* c=NULL) const;
+	LS_AUDIO_CODEC getAudioCodec() const;
+	int getSampleRate() const;
+	int getChannels() const;
+	_R<MemoryStreamCache> getSoundData() const;
+	std::streambuf *createSoundStream() const;
 };
 
-class StartSoundTag: public Tag
+class StartSoundTag: public ActionTag
 {
+private:
+	UI16_SWF SoundId;
+	SOUNDINFO SoundInfo;
+
+	void play(const DefineSoundTag *soundTag) const;
 public:
 	StartSoundTag(RECORDHEADER h, std::istream& s);
+	virtual void execute(RootMovieClip* root) const;
 };
 
 class SoundStreamHeadTag: public Tag
diff --git a/src/parsing/tags_stub.cpp b/src/parsing/tags_stub.cpp
index e1b0365..80162fd 100644
--- a/src/parsing/tags_stub.cpp
+++ b/src/parsing/tags_stub.cpp
@@ -39,12 +39,6 @@ DefineFontInfoTag::DefineFontInfoTag(RECORDHEADER h, std::istream& in):Tag(h)
 	skip(in);
 }
 
-StartSoundTag::StartSoundTag(RECORDHEADER h, std::istream& in):Tag(h)
-{
-	LOG(LOG_NOT_IMPLEMENTED,_("StartSound Tag"));
-	skip(in);
-}
-
 SoundStreamHeadTag::SoundStreamHeadTag(RECORDHEADER h, std::istream& in):Tag(h)
 {
 	LOG(LOG_NOT_IMPLEMENTED,_("SoundStreamHead Tag"));
diff --git a/src/platforms/engineutils.cpp b/src/platforms/engineutils.cpp
index 4152b48..6efcfc7 100644
--- a/src/platforms/engineutils.cpp
+++ b/src/platforms/engineutils.cpp
@@ -99,3 +99,33 @@ void EngineData::showWindow(uint32_t w, uint32_t h)
 	gtk_widget_show(widget);
 	gtk_widget_map(widget);
 }
+
+void EngineData::showMouseCursor()
+{
+	if (!widget)
+		return;
+
+	gdk_threads_enter();
+	GdkWindow* gdkwindow = gtk_widget_get_window(widget);
+	if (gdkwindow)
+		gdk_window_set_cursor(gdkwindow, NULL);
+	gdk_threads_leave();
+}
+
+void EngineData::hideMouseCursor()
+{
+	if (!widget)
+		return;
+
+	gdk_threads_enter();
+	GdkCursor* cursor = gdk_cursor_new(GDK_BLANK_CURSOR);
+	if (cursor)
+	{
+		GdkWindow* gdkwindow = gtk_widget_get_window(widget);
+		if (gdkwindow)
+			gdk_window_set_cursor(gdkwindow, cursor);
+		gdk_cursor_unref(cursor);
+	}
+	gdk_threads_leave();
+}
+
diff --git a/src/platforms/engineutils.h b/src/platforms/engineutils.h
index ee3d1ab..44cdb6e 100644
--- a/src/platforms/engineutils.h
+++ b/src/platforms/engineutils.h
@@ -99,8 +99,11 @@ public:
 		assert(!inputHandlerId);
 		inputHandler = ic;
 		gtk_widget_set_can_focus(widget,TRUE);
-		gtk_widget_add_events(widget,GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK |
-						GDK_POINTER_MOTION_MASK | GDK_EXPOSURE_MASK);
+		gtk_widget_add_events(widget,
+			GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
+			GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK |
+			GDK_POINTER_MOTION_MASK | GDK_EXPOSURE_MASK |
+			GDK_LEAVE_NOTIFY_MASK);
 		inputHandlerId = g_signal_connect(widget, "event", G_CALLBACK(inputDispatch), this);
 	}
 	void removeInputHandler()
@@ -141,6 +144,10 @@ public:
 
 	static void startGTKMain();
 	static void quitGTKMain();
+
+	/* show/hide mouse cursor, must be called from the gtk thread */
+	void showMouseCursor();
+	void hideMouseCursor();
 };
 
 };
diff --git a/src/plugin/npscriptobject.cpp b/src/plugin/npscriptobject.cpp
index e95ca66..0c528d8 100644
--- a/src/plugin/npscriptobject.cpp
+++ b/src/plugin/npscriptobject.cpp
@@ -814,8 +814,11 @@ bool NPScriptObject::callExternalHandler(NPP instance, const char* scriptString,
 		//SUCCESS
 		if(!NPVARIANT_IS_OBJECT(resultVariant))
 		{
-			//Something very wrong happended, our forged function is not a function!
-			LOG(LOG_ERROR,"Could not evaluate wrapper function in external interface");
+			std::map<const NPObject*, std::unique_ptr<ExtObject>> npObjectsMap;
+			NPVariantObject tmp(npObjectsMap, instance, resultVariant);
+			std::map<const ExtObject*, ASObject*> asObjectsMap;
+			*(result) = tmp.getASObject(asObjectsMap);
+			NPN_ReleaseVariantValue(&resultVariant);
 		}
 		else
 		{
diff --git a/src/plugin/plugin.cpp b/src/plugin/plugin.cpp
index e8338e0..9dd4f82 100644
--- a/src/plugin/plugin.cpp
+++ b/src/plugin/plugin.cpp
@@ -20,6 +20,7 @@
 
 #include "version.h"
 #include "backends/security.h"
+#include "backends/streamcache.h"
 #include "plugin/plugin.h"
 #include "logger.h"
 #include "compat.h"
@@ -63,18 +64,22 @@ NPDownloadManager::NPDownloadManager(NPP _instance):instance(_instance)
  * \return A pointer to a newly created \c Downloader for the given URL.
  * \see DownloadManager::destroy()
  */
-lightspark::Downloader* NPDownloadManager::download(const lightspark::URLInfo& url, bool cached, lightspark::ILoadable* owner)
+lightspark::Downloader* NPDownloadManager::download(const lightspark::URLInfo& url, _R<StreamCache> cache, lightspark::ILoadable* owner)
 {
 	// Handle RTMP requests internally, not through NPAPI
 	if(url.isRTMP())
 	{
-		return StandaloneDownloadManager::download(url, cached, owner);
+		return StandaloneDownloadManager::download(url, cache, owner);
 	}
 
+	// FIXME: dynamic_cast fails because the linker doesn't find
+	// typeinfo for FileStreamCache
+	//bool cached = dynamic_cast<FileStreamCache *>(cache.getPtr()) != NULL;
+	bool cached = false;
 	LOG(LOG_INFO, _("NET: PLUGIN: DownloadManager::download '") << url.getParsedURL() << 
 			"'" << (cached ? _(" - cached") : ""));
 	//Register this download
-	NPDownloader* downloader=new NPDownloader(url.getParsedURL(), cached, instance, owner);
+	NPDownloader* downloader=new NPDownloader(url.getParsedURL(), cache, instance, owner);
 	addDownloader(downloader);
 	return downloader;
 }
@@ -88,18 +93,19 @@ lightspark::Downloader* NPDownloadManager::download(const lightspark::URLInfo& u
  * \return A pointer to a newly created \c Downloader for the given URL.
  * \see DownloadManager::destroy()
  */
-lightspark::Downloader* NPDownloadManager::downloadWithData(const lightspark::URLInfo& url, const std::vector<uint8_t>& data, 
+lightspark::Downloader* NPDownloadManager::downloadWithData(const lightspark::URLInfo& url,
+		_R<StreamCache> cache, const std::vector<uint8_t>& data,
 		const std::list<tiny_string>& headers, lightspark::ILoadable* owner)
 {
 	// Handle RTMP requests internally, not through NPAPI
 	if(url.isRTMP())
 	{
-		return StandaloneDownloadManager::downloadWithData(url, data, headers, owner);
+		return StandaloneDownloadManager::downloadWithData(url, cache, data, headers, owner);
 	}
 
 	LOG(LOG_INFO, _("NET: PLUGIN: DownloadManager::downloadWithData '") << url.getParsedURL());
 	//Register this download
-	NPDownloader* downloader=new NPDownloader(url.getParsedURL(), data, headers, instance, owner);
+	NPDownloader* downloader=new NPDownloader(url.getParsedURL(), cache, data, headers, instance, owner);
 	addDownloader(downloader);
 	return downloader;
 }
@@ -139,7 +145,7 @@ void NPDownloadManager::destroy(lightspark::Downloader* downloader)
  * \param[in] _url The URL for the Downloader.
  */
 NPDownloader::NPDownloader(const lightspark::tiny_string& _url, lightspark::ILoadable* owner):
-	Downloader(_url, false, owner),instance(NULL),cleanupInDestroyStream(true),state(INIT)
+	Downloader(_url, _MR(new MemoryStreamCache), owner),instance(NULL),cleanupInDestroyStream(true),state(INIT)
 {
 }
 
@@ -151,8 +157,8 @@ NPDownloader::NPDownloader(const lightspark::tiny_string& _url, lightspark::ILoa
  * \param[in] _instance The netscape plugin instance
  * \param[in] owner The \c LoaderInfo object that keeps track of this download
  */
-NPDownloader::NPDownloader(const lightspark::tiny_string& _url, bool _cached, NPP _instance, lightspark::ILoadable* owner):
-	Downloader(_url, _cached, owner),instance(_instance),cleanupInDestroyStream(false),state(INIT)
+NPDownloader::NPDownloader(const lightspark::tiny_string& _url, _R<StreamCache> _cache, NPP _instance, lightspark::ILoadable* owner):
+	Downloader(_url, _cache, owner),instance(_instance),cleanupInDestroyStream(false),state(INIT)
 {
 	NPN_PluginThreadAsyncCall(instance, dlStartCallback, this);
 }
@@ -165,9 +171,10 @@ NPDownloader::NPDownloader(const lightspark::tiny_string& _url, bool _cached, NP
  * \param[in] _instance The netscape plugin instance
  * \param[in] owner The \c LoaderInfo object that keeps track of this download
  */
-NPDownloader::NPDownloader(const lightspark::tiny_string& _url, const std::vector<uint8_t>& _data,
+NPDownloader::NPDownloader(const lightspark::tiny_string& _url, _R<StreamCache> _cache,
+		const std::vector<uint8_t>& _data,
 		const std::list<tiny_string>& headers, NPP _instance, lightspark::ILoadable* owner):
-	Downloader(_url, _data, headers, owner),instance(_instance),cleanupInDestroyStream(false),state(INIT)
+	Downloader(_url, _cache, _data, headers, owner),instance(_instance),cleanupInDestroyStream(false),state(INIT)
 {
 	NPN_PluginThreadAsyncCall(instance, dlStartCallback, this);
 }
@@ -313,36 +320,14 @@ void NS_DestroyPluginInstance(nsPluginInstanceBase * aPlugin)
 //
 nsPluginInstance::nsPluginInstance(NPP aInstance, int16_t argc, char** argn, char** argv) : 
 	nsPluginInstanceBase(), mInstance(aInstance),mInitialized(FALSE),mWindow(0),
-	mainDownloaderStream(NULL),mainDownloader(NULL),scriptObject(NULL),m_pt(NULL)
+	mainDownloaderStreambuf(NULL),mainDownloaderStream(NULL),
+	mainDownloader(NULL),scriptObject(NULL),m_pt(NULL)
 {
 	LOG(LOG_INFO, "Lightspark version " << VERSION << " Copyright 2009-2013 Alessandro Pignotti and others");
 	setTLSSys( NULL );
 	m_sys=new lightspark::SystemState(0, lightspark::SystemState::FLASH);
 	//Files running in the plugin have REMOTE sandbox
 	m_sys->securityManager->setSandboxType(lightspark::SecurityManager::REMOTE);
-	//Parse OBJECT/EMBED tag attributes
-	string baseURL;
-	for(int i=0;i<argc;i++)
-	{
-		if(argn[i]==NULL || argv[i]==NULL)
-			continue;
-		if(strcasecmp(argn[i],"flashvars")==0)
-		{
-			m_sys->parseParametersFromFlashvars(argv[i]);
-		}
-		else if(strcasecmp(argn[i],"base")==0)
-		{
-			baseURL = argv[i];
-			//This is a directory, not a file
-			baseURL += "/";
-		}
-		//The SWF file url should be getted from NewStream
-	}
-	//basedir is a qualified URL or a path relative to the HTML page
-	URLInfo page(getPageURL());
-	m_sys->mainClip->setBaseURL(page.goToURL(baseURL).getURL());
-
-	m_sys->downloadManager=new NPDownloadManager(mInstance);
 
 	int p_major, p_minor, n_major, n_minor;
 	NPN_Version(&p_major, &p_minor, &n_major, &n_minor);
@@ -351,6 +336,33 @@ nsPluginInstance::nsPluginInstance(NPP aInstance, int16_t argc, char** argn, cha
 			(NPScriptObjectGW *) NPN_CreateObject(mInstance, &NPScriptObjectGW::npClass);
 		m_sys->extScriptObject = scriptObject->getScriptObject();
 		scriptObject->m_sys = m_sys;
+		//Parse OBJECT/EMBED tag attributes
+		string baseURL;
+		for(int i=0;i<argc;i++)
+		{
+			if(argn[i]==NULL || argv[i]==NULL)
+				continue;
+			if(strcasecmp(argn[i],"flashvars")==0)
+			{
+				m_sys->parseParametersFromFlashvars(argv[i]);
+			}
+			else if(strcasecmp(argn[i],"base")==0)
+			{
+				baseURL = argv[i];
+				//This is a directory, not a file
+				baseURL += "/";
+			}
+			else if(strcasecmp(argn[i],"name")==0)
+			{
+				m_sys->extScriptObject->setProperty(argn[i],argv[i]);
+			}
+			//The SWF file url should be getted from NewStream
+		}
+		//basedir is a qualified URL or a path relative to the HTML page
+		URLInfo page(getPageURL());
+		m_sys->mainClip->setBaseURL(page.goToURL(baseURL).getURL());
+		
+		m_sys->downloadManager=new NPDownloadManager(mInstance);
 	}
 	else
 		LOG(LOG_ERROR, "PLUGIN: Browser doesn't support NPRuntime");
@@ -366,6 +378,8 @@ nsPluginInstance::~nsPluginInstance()
 	setTLSSys(m_sys);
 	if(mainDownloader)
 		mainDownloader->stop();
+	if (mainDownloaderStreambuf)
+		delete mainDownloaderStreambuf;
 
 	// Kill all stuff relating to NPScriptObject which is still running
 	static_cast<NPScriptObject*>(m_sys->extScriptObject)->destroy();
@@ -644,7 +658,8 @@ NPError nsPluginInstance::NewStream(NPMIMEType type, NPStream* stream, NPBool se
 		dl=new NPDownloader(stream->url,m_sys->mainClip->loaderInfo.getPtr());
 		dl->setLength(stream->end);
 		mainDownloader=dl;
-		mainDownloaderStream.rdbuf(mainDownloader);
+		mainDownloaderStreambuf = mainDownloader->getCache()->createReader();
+		mainDownloaderStream.rdbuf(mainDownloaderStreambuf);
 		m_pt=new lightspark::ParseThread(mainDownloaderStream,m_sys->mainClip);
 		m_sys->addJob(m_pt);
 	}
diff --git a/src/plugin/plugin.h b/src/plugin/plugin.h
index a8a5823..4e4962f 100644
--- a/src/plugin/plugin.h
+++ b/src/plugin/plugin.h
@@ -44,8 +44,11 @@ private:
 	NPP instance;
 public:
 	NPDownloadManager(NPP i);
-	lightspark::Downloader* download(const lightspark::URLInfo& url, bool cached, lightspark::ILoadable* owner);
-	lightspark::Downloader* downloadWithData(const lightspark::URLInfo& url, const std::vector<uint8_t>& data, 
+	lightspark::Downloader* download(const lightspark::URLInfo& url,
+					 _R<StreamCache> cache,
+					 lightspark::ILoadable* owner);
+	lightspark::Downloader* downloadWithData(const lightspark::URLInfo& url,
+			_R<StreamCache> cache, const std::vector<uint8_t>& data,
 			const std::list<tiny_string>& headers, lightspark::ILoadable* owner);
 	void destroy(lightspark::Downloader* downloader);
 };
@@ -63,8 +66,8 @@ public:
 	STATE state;
 	//Constructor used for the main file
 	NPDownloader(const lightspark::tiny_string& _url, lightspark::ILoadable* owner);
-	NPDownloader(const lightspark::tiny_string& _url, bool _cached, NPP _instance, lightspark::ILoadable* owner);
-	NPDownloader(const lightspark::tiny_string& _url, const std::vector<uint8_t>& _data,
+	NPDownloader(const lightspark::tiny_string& _url, _R<StreamCache> cache, NPP _instance, lightspark::ILoadable* owner);
+	NPDownloader(const lightspark::tiny_string& _url, _R<StreamCache> cache, const std::vector<uint8_t>& _data,
 			const std::list<tiny_string>& headers, NPP _instance, lightspark::ILoadable* owner);
 };
 
@@ -135,6 +138,7 @@ private:
 	GdkNativeWindow mWindow;
 	int mX, mY;
 
+	std::streambuf *mainDownloaderStreambuf;
 	std::istream mainDownloaderStream;
 	NPDownloader* mainDownloader;
 	NPScriptObjectGW* scriptObject;
diff --git a/src/scripting/abc.cpp b/src/scripting/abc.cpp
index ef1cf30..0b96a18 100644
--- a/src/scripting/abc.cpp
+++ b/src/scripting/abc.cpp
@@ -23,12 +23,21 @@
 
 #include "compat.h"
 
-#include <llvm/Module.h>
 #include <llvm/ExecutionEngine/ExecutionEngine.h>
+#ifndef LLVM_36
 #include <llvm/ExecutionEngine/JIT.h>
+#endif
 #include <llvm/PassManager.h>
-#include <llvm/LLVMContext.h>
-#ifdef HAVE_DATALAYOUT_H
+#ifdef HAVE_IR_DATALAYOUT_H
+#  include <llvm/IR/Module.h>
+#  include <llvm/IR/LLVMContext.h>
+#else
+#  include <llvm/Module.h>
+#  include <llvm/LLVMContext.h>
+#endif
+#ifdef HAVE_IR_DATALAYOUT_H
+#  include <llvm/IR/DataLayout.h>
+#elif defined HAVE_DATALAYOUT_H
 #  include <llvm/DataLayout.h>
 #else
 #  include <llvm/Target/TargetData.h>
@@ -39,7 +48,11 @@
 #include <llvm/Target/TargetSelect.h>
 #endif
 #include <llvm/Target/TargetOptions.h>
-#include <llvm/Analysis/Verifier.h>
+#ifdef HAVE_IR_VERIFIER_H
+#  include <llvm/IR/Verifier.h>
+#else
+#  include <llvm/Analysis/Verifier.h>
+#endif
 #include <llvm/Transforms/Scalar.h> 
 #include "logger.h"
 #include "swftypes.h"
@@ -49,24 +62,47 @@
 #include "swf.h"
 #include "scripting/toplevel/ASString.h"
 #include "scripting/toplevel/Date.h"
+#include "scripting/toplevel/JSON.h"
 #include "scripting/toplevel/Math.h"
 #include "scripting/toplevel/RegExp.h"
 #include "scripting/toplevel/Vector.h"
 #include "scripting/toplevel/XML.h"
 #include "scripting/toplevel/XMLList.h"
 #include "scripting/flash/accessibility/flashaccessibility.h"
+#include "scripting/flash/concurrent/Mutex.h"
+#include "scripting/flash/concurrent/Condition.h"
 #include "scripting/flash/desktop/flashdesktop.h"
 #include "scripting/flash/display/flashdisplay.h"
 #include "scripting/flash/display/BitmapData.h"
+#include "scripting/flash/display/Graphics.h"
+#include "scripting/flash/display/GraphicsBitmapFill.h"
+#include "scripting/flash/display/GraphicsEndFill.h"
+#include "scripting/flash/display/GraphicsGradientFill.h"
+#include "scripting/flash/display/GraphicsPath.h"
+#include "scripting/flash/display/GraphicsShaderFill.h"
+#include "scripting/flash/display/GraphicsSolidFill.h"
+#include "scripting/flash/display/GraphicsStroke.h"
+#include "scripting/flash/display/GraphicsTrianglePath.h"
+#include "scripting/flash/display/IGraphicsData.h"
+#include "scripting/flash/display/IGraphicsFill.h"
+#include "scripting/flash/display/IGraphicsPath.h"
+#include "scripting/flash/display/IGraphicsStroke.h"
 #include "scripting/flash/events/flashevents.h"
+#include "scripting/flash/filesystem/flashfilesystem.h"
 #include "scripting/flash/filters/flashfilters.h"
 #include "scripting/flash/net/flashnet.h"
 #include "scripting/flash/net/URLRequestHeader.h"
 #include "scripting/flash/net/URLStream.h"
 #include "scripting/flash/net/XMLSocket.h"
+#include "scripting/flash/net/NetStreamPlayOptions.h"
+#include "scripting/flash/net/NetStreamPlayTransitions.h"
+#include "scripting/flash/printing/flashprinting.h"
 #include "scripting/flash/system/flashsystem.h"
 #include "scripting/flash/sensors/flashsensors.h"
 #include "scripting/flash/utils/flashutils.h"
+#include "scripting/flash/utils/Dictionary.h"
+#include "scripting/flash/utils/Proxy.h"
+#include "scripting/flash/utils/Timer.h"
 #include "scripting/flash/geom/flashgeom.h"
 #include "scripting/flash/external/ExternalInterface.h"
 #include "scripting/flash/media/flashmedia.h"
@@ -75,6 +111,10 @@
 #include "scripting/flash/text/flashtext.h"
 #include "scripting/flash/text/flashtextengine.h"
 #include "scripting/flash/ui/Keyboard.h"
+#include "scripting/flash/ui/Mouse.h"
+#include "scripting/flash/ui/ContextMenu.h"
+#include "scripting/flash/ui/ContextMenuItem.h"
+#include "scripting/flash/ui/ContextMenuBuiltInItems.h"
 #include "scripting/class.h"
 #include "exceptions.h"
 #include "scripting/abc.h"
@@ -82,10 +122,10 @@
 using namespace std;
 using namespace lightspark;
 
-static GStaticPrivate is_vm_thread = G_STATIC_PRIVATE_INIT; /* TLS */
+DEFINE_AND_INITIALIZE_TLS(is_vm_thread);
 bool lightspark::isVmThread()
 {
-	return g_static_private_get(&is_vm_thread);
+	return GPOINTER_TO_INT(tls_get(&is_vm_thread));
 }
 
 DoABCTag::DoABCTag(RECORDHEADER h, std::istream& in):ControlTag(h)
@@ -196,13 +236,11 @@ void ABCVm::registerClasses()
 	builtin->registerBuiltin("Namespace","",Class<Namespace>::getRef());
 	builtin->registerBuiltin("AS3","",_MR(Class<Namespace>::getInstanceS(AS3)));
 	builtin->registerBuiltin("Date","",Class<Date>::getRef());
+	builtin->registerBuiltin("JSON","",Class<JSON>::getRef());
 	builtin->registerBuiltin("RegExp","",Class<RegExp>::getRef());
 	builtin->registerBuiltin("QName","",Class<ASQName>::getRef());
 	builtin->registerBuiltin("uint","",Class<UInteger>::getRef());
 	builtin->registerBuiltin("Vector","__AS3__.vec",_MR(Template<Vector>::getTemplate()));
-	//Some instances must be included, they are not created by AS3 code
-	builtin->registerBuiltin("Vector$Object","__AS3__.vec",Template<Vector>::getTemplateInstance(Class<ASObject>::getClass()));
-	builtin->registerBuiltin("Vector$Number","__AS3__.vec",Template<Vector>::getTemplateInstance(Class<Number>::getClass()));
 	builtin->registerBuiltin("Error","",Class<ASError>::getRef());
 	builtin->registerBuiltin("SecurityError","",Class<SecurityError>::getRef());
 	builtin->registerBuiltin("ArgumentError","",Class<ArgumentError>::getRef());
@@ -234,6 +272,10 @@ void ABCVm::registerClasses()
 
 	builtin->registerBuiltin("AccessibilityProperties","flash.accessibility",Class<AccessibilityProperties>::getRef());
 	builtin->registerBuiltin("AccessibilityImplementation","flash.accessibility",Class<AccessibilityImplementation>::getRef());
+	builtin->registerBuiltin("Accessibility","flash.accessibility",Class<Accessibility>::getRef());
+
+	builtin->registerBuiltin("Mutex","flash.concurrent",Class<ASMutex>::getRef());
+	builtin->registerBuiltin("Condition","flash.concurrent",Class<ASCondition>::getRef());
 
 	builtin->registerBuiltin("MovieClip","flash.display",Class<MovieClip>::getRef());
 	builtin->registerBuiltin("DisplayObject","flash.display",Class<DisplayObject>::getRef());
@@ -246,6 +288,20 @@ void ABCVm::registerClasses()
 	builtin->registerBuiltin("Shape","flash.display",Class<Shape>::getRef());
 	builtin->registerBuiltin("Stage","flash.display",Class<Stage>::getRef());
 	builtin->registerBuiltin("Graphics","flash.display",Class<Graphics>::getRef());
+	builtin->registerBuiltin("GraphicsBitmapFill","flash.display",Class<GraphicsBitmapFill>::getRef());
+	builtin->registerBuiltin("GraphicsEndFill","flash.display",Class<GraphicsEndFill>::getRef());
+	builtin->registerBuiltin("GraphicsGradientFill","flash.display",Class<GraphicsGradientFill>::getRef());
+	builtin->registerBuiltin("GraphicsPath","flash.display",Class<GraphicsPath>::getRef());
+	builtin->registerBuiltin("GraphicsPathCommand","flash.display",Class<GraphicsPathCommand>::getRef());
+	builtin->registerBuiltin("GraphicsPathWinding","flash.display",Class<GraphicsPathWinding>::getRef());
+	builtin->registerBuiltin("GraphicsShaderFill","flash.display",Class<GraphicsShaderFill>::getRef());
+	builtin->registerBuiltin("GraphicsSolidFill","flash.display",Class<GraphicsSolidFill>::getRef());
+	builtin->registerBuiltin("GraphicsStroke","flash.display",Class<GraphicsStroke>::getRef());
+	builtin->registerBuiltin("GraphicsTrianglePath","flash.display",Class<GraphicsTrianglePath>::getRef());
+	builtin->registerBuiltin("IGraphicsData","flash.display",InterfaceClass<IGraphicsData>::getRef());
+	builtin->registerBuiltin("IGraphicsFill","flash.display",InterfaceClass<IGraphicsFill>::getRef());
+	builtin->registerBuiltin("IGraphicsPath","flash.display",InterfaceClass<IGraphicsPath>::getRef());
+	builtin->registerBuiltin("IGraphicsStroke","flash.display",InterfaceClass<IGraphicsStroke>::getRef());
 	builtin->registerBuiltin("GradientType","flash.display",Class<GradientType>::getRef());
 	builtin->registerBuiltin("BlendMode","flash.display",Class<BlendMode>::getRef());
 	builtin->registerBuiltin("LineScaleMode","flash.display",Class<LineScaleMode>::getRef());
@@ -256,10 +312,6 @@ void ABCVm::registerClasses()
 	builtin->registerBuiltin("BitmapData","flash.display",Class<BitmapData>::getRef());
 	builtin->registerBuiltin("Bitmap","flash.display",Class<Bitmap>::getRef());
 	builtin->registerBuiltin("IBitmapDrawable","flash.display",InterfaceClass<IBitmapDrawable>::getRef());
-	builtin->registerBuiltin("GraphicsGradientFill","flash.display",
-			Class<ASObject>::getStubClass(QName("GraphicsGradientFill","flash.display")));
-	builtin->registerBuiltin("GraphicsPath","flash.display",
-			Class<ASObject>::getStubClass(QName("GraphicsPath","flash.display")));
 	builtin->registerBuiltin("MorphShape","flash.display",Class<MorphShape>::getRef());
 	builtin->registerBuiltin("SpreadMethod","flash.display",Class<SpreadMethod>::getRef());
 	builtin->registerBuiltin("InterpolationMethod","flash.display",Class<InterpolationMethod>::getRef());
@@ -270,24 +322,17 @@ void ABCVm::registerClasses()
 	builtin->registerBuiltin("BitmapDataChannel","flash.display",Class<BitmapDataChannel>::getRef());
 
 	builtin->registerBuiltin("BitmapFilter","flash.filters",Class<BitmapFilter>::getRef());
+	builtin->registerBuiltin("BitmapFilterQuality","flash.filters",Class<BitmapFilterQuality>::getRef());
 	builtin->registerBuiltin("DropShadowFilter","flash.filters",Class<DropShadowFilter>::getRef());
 	builtin->registerBuiltin("GlowFilter","flash.filters",Class<GlowFilter>::getRef());
-	builtin->registerBuiltin("GradientGlowFilter","flash.filters",
-			Class<ASObject>::getStubClass(QName("GradientGlowFilter","flash.filters"), Class<BitmapFilter>::getRef()));
-	builtin->registerBuiltin("BevelFilter","flash.filters",
-			Class<ASObject>::getStubClass(QName("BevelFilter","flash.filters"), Class<BitmapFilter>::getRef()));
-	builtin->registerBuiltin("ColorMatrixFilter","flash.filters",
-			Class<ASObject>::getStubClass(QName("ColorMatrixFilter","flash.filters"), Class<BitmapFilter>::getRef()));
-	builtin->registerBuiltin("BlurFilter","flash.filters",
-			Class<ASObject>::getStubClass(QName("BlurFilter","flash.filters"), Class<BitmapFilter>::getRef()));
-	builtin->registerBuiltin("ConvolutionFilter","flash.filters",
-			Class<ASObject>::getStubClass(QName("ConvolutionFilter","flash.filters"), Class<BitmapFilter>::getRef()));
-	builtin->registerBuiltin("DisplacementMapFilter","flash.filters",
-			Class<ASObject>::getStubClass(QName("DisplacementMapFilter","flash.filters"), Class<BitmapFilter>::getRef()));
-	builtin->registerBuiltin("GradientBevelFilter","flash.filters",
-			Class<ASObject>::getStubClass(QName("GradientBevelFilter","flash.filters"), Class<BitmapFilter>::getRef()));
-	builtin->registerBuiltin("ShaderFilter","flash.filters",
-			Class<ASObject>::getStubClass(QName("ShaderFilter","flash.filters"), Class<BitmapFilter>::getRef()));
+	builtin->registerBuiltin("GradientGlowFilter","flash.filters",Class<GradientGlowFilter>::getRef());
+	builtin->registerBuiltin("BevelFilter","flash.filters",Class<BevelFilter>::getRef());
+	builtin->registerBuiltin("ColorMatrixFilter","flash.filters",Class<ColorMatrixFilter>::getRef());
+	builtin->registerBuiltin("BlurFilter","flash.filters",Class<BlurFilter>::getRef());
+	builtin->registerBuiltin("ConvolutionFilter","flash.filters",Class<ConvolutionFilter>::getRef());
+	builtin->registerBuiltin("DisplacementMapFilter","flash.filters",Class<DisplacementMapFilter>::getRef());
+	builtin->registerBuiltin("GradientBevelFilter","flash.filters",Class<GradientBevelFilter>::getRef());
+	builtin->registerBuiltin("ShaderFilter","flash.filters",Class<ShaderFilter>::getRef());
 
 	builtin->registerBuiltin("AntiAliasType","flash.text",Class<AntiAliasType>::getRef());
 	builtin->registerBuiltin("Font","flash.text",Class<ASFont>::getRef());
@@ -303,15 +348,25 @@ void ABCVm::registerClasses()
 	builtin->registerBuiltin("TextFormat","flash.text",Class<TextFormat>::getRef());
 	builtin->registerBuiltin("TextFormatAlign","flash.text",Class<TextFormatAlign>::getRef());
 	builtin->registerBuiltin("TextLineMetrics","flash.text",Class<TextLineMetrics>::getRef());
+	builtin->registerBuiltin("TextInteractionMode","flash.text",Class<TextInteractionMode>::getRef());
 	builtin->registerBuiltin("StaticText","flash.text",Class<StaticText>::getRef());
 
 	builtin->registerBuiltin("ContentElement","flash.text.engine",Class<ContentElement>::getRef());
 	builtin->registerBuiltin("ElementFormat","flash.text.engine",Class<ElementFormat>::getRef());
 	builtin->registerBuiltin("FontDescription","flash.text.engine",Class<FontDescription>::getRef());
+	builtin->registerBuiltin("FontMetrics","flash.text.engine",Class<FontMetrics>::getRef());
+	builtin->registerBuiltin("FontLookup","flash.text.engine",Class<FontLookup>::getRef());
 	builtin->registerBuiltin("FontWeight","flash.text.engine",Class<FontWeight>::getRef());
+	builtin->registerBuiltin("Kerning","flash.text.engine",Class<Kerning>::getRef());
+	builtin->registerBuiltin("LineJustification","flash.text.engine",Class<LineJustification>::getRef());
+	builtin->registerBuiltin("TextBaseline","flash.text.engine",Class<TextBaseline>::getRef());
 	builtin->registerBuiltin("TextBlock","flash.text.engine",Class<TextBlock>::getRef());
 	builtin->registerBuiltin("TextElement","flash.text.engine",Class<TextElement>::getRef());
 	builtin->registerBuiltin("TextLine","flash.text.engine",Class<TextLine>::getRef());
+	builtin->registerBuiltin("TextLineValidity","flash.text.engine",Class<TextLineValidity>::getRef());
+	builtin->registerBuiltin("TextJustifier","flash.text.engine",Class<TextJustifier>::getRef());
+	builtin->registerBuiltin("SpaceJustifier","flash.text.engine",Class<SpaceJustifier>::getRef());
+	builtin->registerBuiltin("EastAsianJustifier","flash.text.engine",Class<EastAsianJustifier>::getRef());
 
 	builtin->registerBuiltin("XMLDocument","flash.xml",Class<XMLDocument>::getRef());
 	builtin->registerBuiltin("XMLNode","flash.xml",Class<XMLNode>::getRef());
@@ -323,10 +378,8 @@ void ABCVm::registerClasses()
 	builtin->registerBuiltin("Dictionary","flash.utils",Class<Dictionary>::getRef());
 	builtin->registerBuiltin("Proxy","flash.utils",Class<Proxy>::getRef());
 	builtin->registerBuiltin("Timer","flash.utils",Class<Timer>::getRef());
-	builtin->registerBuiltin("getQualifiedClassName","flash.utils",
-			_MR(Class<IFunction>::getFunction(getQualifiedClassName)));
-	builtin->registerBuiltin("getQualifiedSuperclassName","flash.utils",
-			_MR(Class<IFunction>::getFunction(getQualifiedSuperclassName)));
+	builtin->registerBuiltin("getQualifiedClassName","flash.utils",_MR(Class<IFunction>::getFunction(getQualifiedClassName)));
+	builtin->registerBuiltin("getQualifiedSuperclassName","flash.utils",_MR(Class<IFunction>::getFunction(getQualifiedSuperclassName)));
 	builtin->registerBuiltin("getDefinitionByName","flash.utils",_MR(Class<IFunction>::getFunction(getDefinitionByName)));
 	builtin->registerBuiltin("getTimer","flash.utils",_MR(Class<IFunction>::getFunction(getTimer)));
 	builtin->registerBuiltin("setInterval","flash.utils",_MR(Class<IFunction>::getFunction(setInterval)));
@@ -334,6 +387,8 @@ void ABCVm::registerClasses()
 	builtin->registerBuiltin("clearInterval","flash.utils",_MR(Class<IFunction>::getFunction(clearInterval)));
 	builtin->registerBuiltin("clearTimeout","flash.utils",_MR(Class<IFunction>::getFunction(clearTimeout)));
 	builtin->registerBuiltin("describeType","flash.utils",_MR(Class<IFunction>::getFunction(describeType)));
+	builtin->registerBuiltin("escapeMultiByte","flash.utils",_MR(Class<IFunction>::getFunction(escapeMultiByte)));
+	builtin->registerBuiltin("unescapeMultiByte","flash.utils",_MR(Class<IFunction>::getFunction(unescapeMultiByte)));
 	builtin->registerBuiltin("IExternalizable","flash.utils",InterfaceClass<IExternalizable>::getRef());
 	builtin->registerBuiltin("IDataInput","flash.utils",InterfaceClass<IDataInput>::getRef());
 	builtin->registerBuiltin("IDataOutput","flash.utils",InterfaceClass<IDataOutput>::getRef());
@@ -344,7 +399,8 @@ void ABCVm::registerClasses()
 	builtin->registerBuiltin("Transform","flash.geom",Class<Transform>::getRef());
 	builtin->registerBuiltin("Point","flash.geom",Class<Point>::getRef());
 	builtin->registerBuiltin("Vector3D","flash.geom",Class<Vector3D>::getRef());
-	builtin->registerBuiltin("Matrix3D","flash.geom",Class<ASObject>::getStubClass(QName("Matrix3D", "flash.geom")));
+	builtin->registerBuiltin("Matrix3D","flash.geom",Class<Matrix3D>::getRef());
+	builtin->registerBuiltin("PerspectiveProjection","flash.geom",Class<PerspectiveProjection>::getRef());
 
 	builtin->registerBuiltin("EventDispatcher","flash.events",Class<EventDispatcher>::getRef());
 	builtin->registerBuiltin("Event","flash.events",Class<Event>::getRef());
@@ -369,13 +425,24 @@ void ABCVm::registerClasses()
 	builtin->registerBuiltin("DRMStatusEvent","flash.events",Class<DRMStatusEvent>::getRef());
 	builtin->registerBuiltin("StageVideoEvent","flash.events",Class<StageVideoEvent>::getRef());
 	builtin->registerBuiltin("StageVideoAvailabilityEvent","flash.events",Class<StageVideoAvailabilityEvent>::getRef());
+	builtin->registerBuiltin("TouchEvent","flash.events",Class<TouchEvent>::getRef());
+	builtin->registerBuiltin("GestureEvent","flash.events",Class<GestureEvent>::getRef());
+	builtin->registerBuiltin("PressAndTapGestureEvent","flash.events",Class<PressAndTapGestureEvent>::getRef());
+	builtin->registerBuiltin("TransformGestureEvent","flash.events",Class<TransformGestureEvent>::getRef());
+	builtin->registerBuiltin("ContextMenuEvent","flash.events",Class<ContextMenuEvent>::getRef());
+	builtin->registerBuiltin("UncaughtErrorEvent","flash.events",Class<UncaughtErrorEvent>::getRef());
+	builtin->registerBuiltin("UncaughtErrorEvents","flash.events",Class<UncaughtErrorEvents>::getRef());
+	builtin->registerBuiltin("VideoEvent","flash.events",Class<VideoEvent>::getRef());
 
 	builtin->registerBuiltin("navigateToURL","flash.net",_MR(Class<IFunction>::getFunction(navigateToURL)));
 	builtin->registerBuiltin("sendToURL","flash.net",_MR(Class<IFunction>::getFunction(sendToURL)));
-	builtin->registerBuiltin("LocalConnection","flash.net",Class<ASObject>::getStubClass(QName("LocalConnection","flash.net")));
+	builtin->registerBuiltin("LocalConnection","flash.net",Class<LocalConnection>::getRef());
 	builtin->registerBuiltin("NetConnection","flash.net",Class<NetConnection>::getRef());
+	builtin->registerBuiltin("NetGroup","flash.net",Class<NetGroup>::getRef());
 	builtin->registerBuiltin("NetStream","flash.net",Class<NetStream>::getRef());
-	builtin->registerBuiltin("NetStreamPlayOptions","flash.net",Class<ASObject>::getStubClass(QName("NetStreamPlayOptions","flash.net")));
+	builtin->registerBuiltin("NetStreamAppendBytesAction","flash.net",Class<NetStreamAppendBytesAction>::getRef());
+	builtin->registerBuiltin("NetStreamPlayOptions","flash.net",Class<NetStreamPlayOptions>::getRef());
+	builtin->registerBuiltin("NetStreamPlayTransitions","flash.net",Class<NetStreamPlayTransitions>::getRef());
 	builtin->registerBuiltin("URLLoader","flash.net",Class<URLLoader>::getRef());
 	builtin->registerBuiltin("URLStream","flash.net",Class<URLStream>::getRef());
 	builtin->registerBuiltin("URLLoaderDataFormat","flash.net",Class<URLLoaderDataFormat>::getRef());
@@ -384,13 +451,17 @@ void ABCVm::registerClasses()
 	builtin->registerBuiltin("URLRequestMethod","flash.net",Class<URLRequestMethod>::getRef());
 	builtin->registerBuiltin("URLVariables","flash.net",Class<URLVariables>::getRef());
 	builtin->registerBuiltin("SharedObject","flash.net",Class<SharedObject>::getRef());
+	builtin->registerBuiltin("SharedObjectFlushStatus","flash.net",Class<SharedObjectFlushStatus>::getRef());
 	builtin->registerBuiltin("ObjectEncoding","flash.net",Class<ObjectEncoding>::getRef());
-	builtin->registerBuiltin("Socket","flash.net",Class<ASObject>::getStubClass(QName("Socket","flash.net")));
+	builtin->registerBuiltin("Socket","flash.net",Class<ASSocket>::getRef());
 	builtin->registerBuiltin("Responder","flash.net",Class<Responder>::getRef());
 	builtin->registerBuiltin("XMLSocket","flash.net",Class<XMLSocket>::getRef());
 	builtin->registerBuiltin("registerClassAlias","flash.net",_MR(Class<IFunction>::getFunction(registerClassAlias)));
 	builtin->registerBuiltin("getClassByAlias","flash.net",_MR(Class<IFunction>::getFunction(getClassByAlias)));
 
+	builtin->registerBuiltin("DRMManager","flash.net.drm",Class<DRMManager>::getRef());
+
+
 	builtin->registerBuiltin("fscommand","flash.system",_MR(Class<IFunction>::getFunction(fscommand)));
 	builtin->registerBuiltin("Capabilities","flash.system",Class<Capabilities>::getRef());
 	builtin->registerBuiltin("Security","flash.system",Class<Security>::getRef());
@@ -398,6 +469,7 @@ void ABCVm::registerClasses()
 	builtin->registerBuiltin("SecurityDomain","flash.system",Class<SecurityDomain>::getRef());
 	builtin->registerBuiltin("LoaderContext","flash.system",Class<LoaderContext>::getRef());
 	builtin->registerBuiltin("System","flash.system",Class<System>::getRef());
+	builtin->registerBuiltin("Worker","flash.system",Class<ASWorker>::getRef());
 
 	builtin->registerBuiltin("SoundTransform","flash.media",Class<SoundTransform>::getRef());
 	builtin->registerBuiltin("Video","flash.media",Class<Video>::getRef());
@@ -411,8 +483,10 @@ void ABCVm::registerClasses()
 	builtin->registerBuiltin("Keyboard","flash.ui",Class<Keyboard>::getRef());
 	builtin->registerBuiltin("KeyboardType","flash.ui",Class<KeyboardType>::getRef());
 	builtin->registerBuiltin("KeyLocation","flash.ui",Class<KeyLocation>::getRef());
-	builtin->registerBuiltin("ContextMenu","flash.ui",Class<ASObject>::getStubClass(QName("ContextMenu","flash.ui")));
-	builtin->registerBuiltin("ContextMenuItem","flash.ui",Class<ASObject>::getStubClass(QName("ContextMenuItem","flash.ui")));
+	builtin->registerBuiltin("ContextMenu","flash.ui",Class<ContextMenu>::getRef());
+	builtin->registerBuiltin("ContextMenuItem","flash.ui",Class<ContextMenuItem>::getRef());
+	builtin->registerBuiltin("ContextMenuBuiltInItems","flash.ui",Class<ContextMenuBuiltInItems>::getRef());
+	builtin->registerBuiltin("Mouse","flash.ui",Class<Mouse>::getRef());
 
 	builtin->registerBuiltin("Accelerometer", "flash.sensors",Class<Accelerometer>::getRef());
 
@@ -424,15 +498,15 @@ void ABCVm::registerClasses()
 	builtin->registerBuiltin("ScriptTimeoutError","flash.errors",Class<ScriptTimeoutError>::getRef());
 	builtin->registerBuiltin("StackOverflowError","flash.errors",Class<StackOverflowError>::getRef());
 
-	builtin->registerBuiltin("PrintJob","flash.printing",
-				 Class<ASObject>::getStubClass(QName("PrintJob","flash.printing"), Class<EventDispatcher>::getRef()));
-	builtin->registerBuiltin("PrintJobOptions","flash.printing",Class<ASObject>::getStubClass(QName("PrintJobOptions","flash.printing")));
-	builtin->registerBuiltin("PrintJobOrientation","flash.printing",Class<ASObject>::getStubClass(QName("PrintJobOrientation","flash.printing")));
+	builtin->registerBuiltin("PrintJob","flash.printing",Class<PrintJob>::getRef());
+	builtin->registerBuiltin("PrintJobOptions","flash.printing",Class<PrintJobOptions>::getRef());
+	builtin->registerBuiltin("PrintJobOrientation","flash.printing",Class<PrintJobOrientation>::getRef());
 
 	builtin->registerBuiltin("isNaN","",_MR(Class<IFunction>::getFunction(isNaN)));
 	builtin->registerBuiltin("isFinite","",_MR(Class<IFunction>::getFunction(isFinite)));
 	builtin->registerBuiltin("isXMLName","",_MR(Class<IFunction>::getFunction(_isXMLName)));
 
+
 	//If needed add AIR definitions
 	if(getSys()->flashMode==SystemState::AIR)
 	{
@@ -440,10 +514,12 @@ void ABCVm::registerClasses()
 
 		builtin->registerBuiltin("InvokeEvent","flash.events",Class<InvokeEvent>::getRef());
 
-		builtin->registerBuiltin("FileStream","flash.filesystem",
-				Class<ASObject>::getStubClass(QName("FileStream","flash.filestream")));
+		builtin->registerBuiltin("FileStream","flash.filesystem",Class<FileStream>::getRef());
 	}
 
+	Class_object::getRef()->getClass()->prototype = _MNR(new_objectPrototype());
+	Class_object::getRef()->getClass()->initStandardProps();
+
 	getSys()->systemDomain->registerGlobalScope(builtin);
 }
 
@@ -623,6 +699,8 @@ multiname* ABCContext::s_getMultiname(ABCContext* th, ASObject* n, ASObject* n2,
  */
 multiname* ABCContext::getMultinameImpl(ASObject* n, ASObject* n2, unsigned int midx)
 {
+	if (constant_pool.multiname_count == 0)
+		return NULL;
 	multiname* ret;
 	multiname_info* m=&constant_pool.multinames[midx];
 
@@ -701,6 +779,16 @@ multiname* ABCContext::getMultinameImpl(ASObject* n, ASObject* n2, unsigned int
 				{
 					multiname_info* p=&constant_pool.multinames[m->param_types[i]];
 					name += "$";
+					tiny_string nsname;
+					if (p->ns < constant_pool.namespaces.size())
+					{
+						// TODO there's no documentation about how to handle derived classes
+						// We just prepend the namespace to the template class, so we can find it when needed
+						namespace_info nsi = constant_pool.namespaces[p->ns];
+						nsname = getString(nsi.name);
+						if (nsname != "")
+							name += nsname+"$";
+					}
 					name += getString(p->name);
 				}
 				ret->ns.push_back(nsNameAndKind(this, td->ns));
@@ -740,10 +828,16 @@ multiname* ABCContext::getMultinameImpl(ASObject* n, ASObject* n2, unsigned int
 			if (n->is<ASQName>())
 			{
 				ASQName *qname = n->as<ASQName>();
+				// don't overwrite any static parts
+				if (!m->dynamic)
+					m->dynamic=new (getVm()->vmDataMemory) multiname(getVm()->vmDataMemory);
+				ret=m->dynamic;
+				ret->isAttribute=m->cached->isAttribute;
 				ret->ns.clear();
 				ret->ns.push_back(nsNameAndKind(qname->getURI(),NAMESPACE));
 			}
-
+			else
+				n->applyProxyProperty(*ret);
 			ret->setName(n);
 			n->decRef();
 			break;
@@ -754,9 +848,8 @@ multiname* ABCContext::getMultinameImpl(ASObject* n, ASObject* n2, unsigned int
 			assert(n && !n2);
 			assert_and_throw(n->classdef==Class<Namespace>::getClass());
 			Namespace* tmpns=static_cast<Namespace*>(n);
-			//TODO: What is the right kind?
 			ret->ns.clear();
-			ret->ns.push_back(nsNameAndKind(tmpns->uri,NAMESPACE));
+			ret->ns.push_back(nsNameAndKind(tmpns->uri,tmpns->nskind));
 			n->decRef();
 			break;
 		}
@@ -767,7 +860,7 @@ multiname* ABCContext::getMultinameImpl(ASObject* n, ASObject* n2, unsigned int
 			assert_and_throw(n2->classdef==Class<Namespace>::getClass());
 			Namespace* tmpns=static_cast<Namespace*>(n2);
 			ret->ns.clear();
-			ret->ns.push_back(nsNameAndKind(tmpns->uri,NAMESPACE));
+			ret->ns.push_back(nsNameAndKind(tmpns->uri,tmpns->nskind));
 			ret->setName(n);
 			n->decRef();
 			n2->decRef();
@@ -1254,7 +1347,7 @@ Class_inherit* ABCVm::findClassInherit(const string& s, RootMovieClip* root)
 	Class_inherit* derived_class_tmp=static_cast<Class_inherit*>(derived_class);
 	if(derived_class_tmp->isBinded())
 	{
-		LOG(LOG_ERROR, "Class already binded to a tag. Not binding");
+		LOG(LOG_ERROR, "Class already binded to a tag. Not binding:"<<s<< " class:"<<derived_class_tmp->getQualifiedClassName());
 		return NULL;
 	}
 	return derived_class_tmp;
@@ -1450,6 +1543,19 @@ void ABCContext::runScriptInit(unsigned int i, ASObject* g)
 		ret->decRef();
 
 	entry->decRef();
+	
+	// initialize vars where type was not known during script init
+	// this may happen for variables of private classes defined in this script
+	LOG(LOG_CALLS,"initialize uninitialized vars");
+	auto it = uninitializedVars.begin();
+	while (it != uninitializedVars.end())
+	{
+		uninitializedVar v = *it;
+		v.mainObj->initializeVariableByMultiname(*v.mname,NULL,v.typemname,this,v.traitKind,true);
+		v.mainObj->decRef();
+		uninitializedVars.pop_front();
+		it = uninitializedVars.begin();
+	}
 	LOG(LOG_CALLS, "Finished script init for script " << i );
 }
 
@@ -1460,13 +1566,15 @@ void ABCVm::Run(ABCVm* th)
 	while(getVm()!=th);
 
 	/* set TLS variable for isVmThread() */
-        g_static_private_set(&is_vm_thread,(void*)1,NULL);
+        tls_set(&is_vm_thread, GINT_TO_POINTER(1));
 
 	if(th->m_sys->useJit)
 	{
 #ifdef LLVM_31
 		llvm::TargetOptions Opts;
+#ifndef LLVM_34
 		Opts.JITExceptionHandling = true;
+#endif
 #else
 		llvm::JITExceptionHandling = true;
 #endif
@@ -1479,7 +1587,11 @@ void ABCVm::Run(ABCVm* th)
 #endif
 		llvm::InitializeNativeTarget();
 		th->module=new llvm::Module(llvm::StringRef("abc jit"),th->llvm_context());
+#ifdef LLVM_36
+		llvm::EngineBuilder eb(std::unique_ptr<llvm::Module>(th->module));
+#else
 		llvm::EngineBuilder eb(th->module);
+#endif
 		eb.setEngineKind(llvm::EngineKind::JIT);
 #ifdef LLVM_31
 		eb.setTargetOptions(Opts);
@@ -1489,11 +1601,17 @@ void ABCVm::Run(ABCVm* th)
 		assert_and_throw(th->ex);
 
 		th->FPM=new llvm::FunctionPassManager(th->module);
-#ifdef HAVE_DATALAYOUT_H
+#ifdef LLVM_36
+		th->FPM->add(new llvm::DataLayoutPass());
+#else
+#ifdef LLVM_35
+		th->FPM->add(new llvm::DataLayoutPass(*th->ex->getDataLayout()));
+#elif defined HAVE_DATALAYOUT_H || defined HAVE_IR_DATALAYOUT_H
 		th->FPM->add(new llvm::DataLayout(*th->ex->getDataLayout()));
 #else
 		th->FPM->add(new llvm::TargetData(*th->ex->getTargetData()));
 #endif
+#endif
 #ifdef EXPENSIVE_DEBUG
 		//This is pretty heavy, do not enable in release
 		th->FPM->add(llvm::createVerifierPass());
@@ -1848,8 +1966,13 @@ ASObject* ABCContext::getConstant(int kind, int index)
 		case 0x06: //Double
 			return abstract_d(constant_pool.doubles[index]);
 		case 0x08: //Namespace
+		{
 			assert_and_throw(constant_pool.namespaces[index].name);
-			return Class<Namespace>::getInstanceS(getString(constant_pool.namespaces[index].name));
+			Namespace* ret = Class<Namespace>::getInstanceS(getString(constant_pool.namespaces[index].name));
+			if (constant_pool.namespaces[index].kind != 0)
+				ret->nskind =(NS_KIND)(int)(constant_pool.namespaces[index].kind);
+			return ret;
+		}
 		case 0x0a: //False
 			return abstract_b(false);
 		case 0x0b: //True
@@ -1864,6 +1987,23 @@ ASObject* ABCContext::getConstant(int kind, int index)
 	}
 }
 
+void ABCContext::addUninitializedVar(uninitializedVar &v)
+{
+	auto it = uninitializedVars.begin();
+	bool bfound = false;
+	while (it != uninitializedVars.end())
+	{
+		if (it->mainObj == v.mainObj && it->mname == v.mname)
+		{
+			bfound = true;
+			break;
+		}
+		it++;
+	}
+	if (!bfound)
+		uninitializedVars.push_back(v);
+}
+
 void ABCContext::buildTrait(ASObject* obj, const traits_info* t, bool isBorrowed, int scriptid)
 {
 	multiname* mname=getMultiname(t->name,NULL);
@@ -1873,7 +2013,7 @@ void ABCContext::buildTrait(ASObject* obj, const traits_info* t, bool isBorrowed
 		LOG(LOG_CALLS,_("Next slot has flags ") << (t->kind>>4));
 
 	if(t->kind&traits_info::Metadata)
-        {
+	{
 		for(unsigned int i=0;i<t->metadata_count;i++)
 		{
 			metadata_info& minfo = metadata[t->metadata[i]];
@@ -1894,10 +2034,10 @@ void ABCContext::buildTrait(ASObject* obj, const traits_info* t, bool isBorrowed
 				return;
 			ASObject* ret;
 
+			QName className(getSys()->getStringFromUniqueId(mname->name_s_id),mname->ns[0].getImpl().name);
 			//check if this class has the 'interface' flag, i.e. it is an interface
 			if((instances[t->classi].flags)&0x04)
 			{
-				QName className(getSys()->getStringFromUniqueId(mname->name_s_id),mname->ns[0].getImpl().name);
 
 				MemoryAccount* memoryAccount = getSys()->allocateMemoryAccount(className.name);
 				Class_inherit* ci=new (getSys()->unaccountedMemory) Class_inherit(className, memoryAccount);
@@ -1938,13 +2078,27 @@ void ABCContext::buildTrait(ASObject* obj, const traits_info* t, bool isBorrowed
 				//do interfaces have cinit methods?
 				//TODO: call them, set constructor property, do something
 				if(classes[t->classi].cinit != 0)
-					LOG(LOG_NOT_IMPLEMENTED,"Interface cinit (static)");
+				{
+					method_info* m=&methods[classes[t->classi].cinit];
+					if (m->body)
+						LOG(LOG_NOT_IMPLEMENTED,"Interface cinit (static):"<<className);
+				}
 				if(instances[t->classi].init != 0)
-					LOG(LOG_NOT_IMPLEMENTED,"Interface cinit (constructor)");
+				{
+					method_info* m=&methods[instances[t->classi].init];
+					if (m->body)
+						LOG(LOG_NOT_IMPLEMENTED,"Interface cinit (constructor):"<<className);
+				}
 				ret = ci;
 			}
 			else
-				ret=getSys()->getUndefinedRef();
+			{
+				MemoryAccount* memoryAccount = getSys()->allocateMemoryAccount(className.name);
+				Class_inherit* c=new (getSys()->unaccountedMemory) Class_inherit(className, memoryAccount);
+				root->applicationDomain->classesBeingDefined.insert(make_pair(mname, c));
+				ret=c;
+			}
+
 
 			obj->setVariableByQName(mname->name_s_id,mname->ns[0],ret,DECLARED_TRAIT);
 
@@ -1957,7 +2111,7 @@ void ABCContext::buildTrait(ASObject* obj, const traits_info* t, bool isBorrowed
 		case traits_info::Setter:
 		case traits_info::Method:
 		{
-			//methods can also be defined at toplevel (not only traits_info::Function!)
+		//methods can also be defined at toplevel (not only traits_info::Function!)
 			if(kind == traits_info::Getter)
 				LOG(LOG_CALLS,"Getter trait: " << *mname << _(" #") << t->method);
 			else if(kind == traits_info::Setter)
@@ -2020,10 +2174,12 @@ void ABCContext::buildTrait(ASObject* obj, const traits_info* t, bool isBorrowed
 
 			LOG(LOG_CALLS,_("Const ") << *mname <<_(" type ")<< *tname<< " = " << ret->toDebugString());
 
-			obj->initializeVariableByMultiname(*mname, ret, tname, this, CONSTANT_TRAIT);
+			obj->initializeVariableByMultiname(*mname, ret, tname, this, CONSTANT_TRAIT,false);
 
 			if(t->slot_id)
 				obj->initSlot(t->slot_id, *mname);
+			//else // slot_id 0 seems to mean appending new slot
+			//	obj->appendSlot(*mname);
 			break;
 		}
 		case traits_info::Slot:
@@ -2038,20 +2194,21 @@ void ABCContext::buildTrait(ASObject* obj, const traits_info* t, bool isBorrowed
 			if(t->vindex)
 			{
 				ret=getConstant(t->vkind,t->vindex);
-				LOG(LOG_CALLS,_("Slot ") << t->slot_id << ' ' << *mname <<_(" type ")<<*tname<< " = " << ret->toDebugString() );
+				LOG(LOG_CALLS,_("Slot ") << t->slot_id << ' ' << *mname <<_(" type ")<<*tname<< " = " << ret->toDebugString() <<" "<<isBorrowed);
 			}
 			else
 			{
-				LOG(LOG_CALLS,_("Slot ")<< t->slot_id<<  _(" vindex 0 ") << *mname <<_(" type ")<<*tname);
-				//The Undefined is coerced to the right type by the initializeVar..
-				ret = getSys()->getUndefinedRef();
+				LOG(LOG_CALLS,_("Slot ")<< t->slot_id<<  _(" vindex 0 ") << *mname <<_(" type ")<<*tname<<" "<<isBorrowed);
+				ret = NULL;
 			}
 
-			obj->initializeVariableByMultiname(*mname, ret, tname, this, DECLARED_TRAIT);
+			obj->initializeVariableByMultiname(*mname, ret, tname, this, isBorrowed ? INSTANCE_TRAIT : DECLARED_TRAIT,false);
 
 			if(t->slot_id)
 				obj->initSlot(t->slot_id, *mname);
-
+			//else // slot_id 0 seems to mean appending new slot
+			//	obj->appendSlot(*mname);
+			
 			break;
 		}
 		default:
diff --git a/src/scripting/abc.h b/src/scripting/abc.h
index c5677cf..2a74073 100644
--- a/src/scripting/abc.h
+++ b/src/scripting/abc.h
@@ -142,6 +142,15 @@ struct typed_opcode_handler
 	ARGS_TYPE type;
 };
 
+struct uninitializedVar
+{
+	uninitializedVar():mname(NULL),mainObj(NULL),typemname(NULL),traitKind(NO_CREATE_TRAIT) {}
+	const multiname* mname;
+	ASObject* mainObj;
+	multiname* typemname;
+	TRAIT_KIND traitKind;
+};
+
 class ABCContext
 {
 friend class ABCVm;
@@ -174,6 +183,9 @@ public:
 	uint32_t namespaceBaseId;
 
 	std::vector<bool> hasRunScriptInit;
+	// list of vars that have to be initialized after script init is done
+	std::list<uninitializedVar> uninitializedVars;
+	void addUninitializedVar(uninitializedVar& v);
 	/**
 		Construct and insert in the a object a given trait
 		@param obj the tarhget object
@@ -195,8 +207,6 @@ public:
 
 	bool isinstance(ASObject* obj, multiname* name);
 
-	std::map<const multiname*, Class_base*> classesBeingDefined;
-
 #ifdef PROFILING_SUPPORT
 	void dumpProfilingData(std::ostream& f) const;
 #endif
@@ -246,6 +256,28 @@ private:
 		_R<ApplicationDomain> appDomain = getCurrentApplicationDomain(th);
 		appDomain->writeToDomainMemory<T>(addr, val);
 	}
+
+	static void loadNumber(call_context* th)
+	{
+		ASObject* arg1=th->runtime_stack_pop();
+		number_t addr=arg1->toNumber();
+		arg1->decRef();
+		_R<ApplicationDomain> appDomain = getCurrentApplicationDomain(th);
+		number_t ret=appDomain->readFromDomainMemory<number_t>(addr);
+		th->runtime_stack_push(abstract_d(ret));
+	}
+	static void storeNumber(call_context* th)
+	{
+		ASObject* arg1=th->runtime_stack_pop();
+		ASObject* arg2=th->runtime_stack_pop();
+		number_t addr=arg1->toNumber();
+		arg1->decRef();
+		number_t val=arg2->toNumber();
+		arg2->decRef();
+		_R<ApplicationDomain> appDomain = getCurrentApplicationDomain(th);
+		appDomain->writeToDomainMemory<number_t>(addr, val);
+	}
+
 	static void callSuper(call_context* th, int n, int m, method_info** called_mi, bool keepReturn);
 	static void callProperty(call_context* th, int n, int m, method_info** called_mi, bool keepReturn);
 	static void callImpl(call_context* th, ASObject* f, ASObject* obj, ASObject** args, int m, method_info** called_mi, bool keepReturn);
@@ -299,6 +331,7 @@ private:
 	static void decLocal_i(call_context* th, int n);
 	static void decLocal(call_context* th, int n);
 	static void coerce(call_context* th, int n);
+	static void checkDeclaredTraits(ASObject* obj);
 	static ASObject* getProperty(ASObject* obj, multiname* name);
 	static int32_t getProperty_i(ASObject* obj, multiname* name);
 	static void setProperty(ASObject* value,ASObject* obj, multiname* name);
@@ -380,6 +413,7 @@ private:
 	static uint32_t decrement_i(ASObject*);
 	static bool strictEquals(ASObject*,ASObject*);
 	static ASObject* esc_xattr(ASObject* o);
+	static ASObject* esc_xelem(ASObject* o);
 	static bool instanceOf(ASObject* value, ASObject* type);
 	static Namespace* pushNamespace(call_context* th, int n);
 	static void dxns(call_context* th, int n);
@@ -390,7 +424,10 @@ private:
 
 	//Internal utilities
 	static void method_reset(method_info* th);
-	static void newClassRecursiveLink(Class_base* target, Class_base* c);
+
+	static void SetAllClassLinks();
+	static void AddClassLinks(Class_base* target);
+	static bool newClassRecursiveLink(Class_base* target, Class_base* c);
 	static ASObject* constructFunction(call_context* th, IFunction* f, ASObject** args, int argslen);
 	void parseRPCMessage(_R<ByteArray> message, _NR<ASObject> client, _NR<Responder> responder);
 
@@ -405,6 +442,7 @@ private:
 	static typed_opcode_handler opcode_table_voidptr[];
 	static typed_opcode_handler opcode_table_bool_t[];
 
+
 	//Synchronization
 	Mutex event_queue_mutex;
 	Cond sem_event_cond;
diff --git a/src/scripting/abc_codesynt.cpp b/src/scripting/abc_codesynt.cpp
index 2018be3..bb8e9a5 100644
--- a/src/scripting/abc_codesynt.cpp
+++ b/src/scripting/abc_codesynt.cpp
@@ -25,18 +25,29 @@
 #endif
 
 #include "compat.h"
-#include <llvm/Module.h>
-#include <llvm/DerivedTypes.h>
 #include <llvm/ExecutionEngine/ExecutionEngine.h>
 #include <llvm/PassManager.h>
-#include <llvm/Constants.h>
-#ifdef HAVE_IRBUILDER_H
+#ifdef HAVE_IR_DATALAYOUT_H
+#  include <llvm/IR/Constants.h>
+#  include <llvm/IR/DerivedTypes.h>
+#  include <llvm/IR/Module.h>
+#  include <llvm/IR/LLVMContext.h>
+#else
+#  include <llvm/Constants.h>
+#  include <llvm/DerivedTypes.h>
+#  include <llvm/Module.h>
+#  include <llvm/LLVMContext.h>
+#endif
+#ifdef HAVE_IR_DATALAYOUT_H
+#  include <llvm/IR/IRBuilder.h>
+#elif defined HAVE_IRBUILDER_H
 #  include <llvm/IRBuilder.h>
 #else
 #  include <llvm/Support/IRBuilder.h>
 #endif
-#include <llvm/LLVMContext.h>
-#ifdef HAVE_DATALAYOUT_H
+#ifdef HAVE_IR_DATALAYOUT_H
+#  include <llvm/IR/DataLayout.h>
+#elif defined HAVE_DATALAYOUT_H
 #  include <llvm/DataLayout.h>
 #else
 #  include <llvm/Target/TargetData.h>
@@ -279,7 +290,7 @@ void ABCVm::registerFunctions()
 	llvm::FunctionType* FT=NULL;
 
 	//Create types
-#ifdef HAVE_DATALAYOUT_H
+#if defined HAVE_DATALAYOUT_H || defined HAVE_IR_DATALAYOUT_H
 	ptr_type=ex->getDataLayout()->getIntPtrType(llvm_context());
 #else
 	ptr_type=ex->getTargetData()->getIntPtrType(llvm_context());
diff --git a/src/scripting/abc_fast_interpreter.cpp b/src/scripting/abc_fast_interpreter.cpp
index e49334e..f3a48e9 100644
--- a/src/scripting/abc_fast_interpreter.cpp
+++ b/src/scripting/abc_fast_interpreter.cpp
@@ -75,6 +75,12 @@ ASObject* ABCVm::executeFunctionFast(const SyntheticFunction* function, call_con
 
 		switch(opcode)
 		{
+			case 0x01:
+			{
+				//bkpt
+				LOG(LOG_CALLS, _("bkpt") );
+				break;
+			}
 			case 0x02:
 			{
 				//nop
@@ -565,6 +571,20 @@ ASObject* ABCVm::executeFunctionFast(const SyntheticFunction* function, call_con
 				loadIntN<uint32_t>(context);
 				break;
 			}
+			case 0x38:
+			{
+				//lf32
+				LOG(LOG_CALLS, "lf32");
+				loadNumber(context);
+				break;
+			}
+			case 0x39:
+			{
+				//lf32
+				LOG(LOG_CALLS, "lf64");
+				loadNumber(context);
+				break;
+			}
 			case 0x3a:
 			{
 				//si8
@@ -802,7 +822,12 @@ ASObject* ABCVm::executeFunctionFast(const SyntheticFunction* function, call_con
 				//getlocal
 				uint32_t i=data->uints[0];
 				instructionPointer+=4;
-				assert_and_throw(context->locals[i]);
+				if (!context->locals[i])
+				{
+					LOG(LOG_CALLS, _("getLocal ") << i << " not set, pushing Undefined");
+					context->runtime_stack_push(getSys()->getUndefinedRef());
+					break;
+				}
 				context->locals[i]->incRef();
 				LOG(LOG_CALLS, _("getLocal ") << i << _(": ") << context->locals[i]->toDebugString() );
 				context->runtime_stack_push(context->locals[i]);
@@ -896,6 +921,27 @@ ASObject* ABCVm::executeFunctionFast(const SyntheticFunction* function, call_con
 				setSlot(v1, v2, t);
 				break;
 			}
+			case 0x6e:
+			{
+				//getglobalSlot
+				uint32_t t=data->uints[0];
+				instructionPointer+=4;
+
+				Global* globalscope = getGlobalScope(context);
+				context->runtime_stack_push(globalscope->getSlot(t));
+				break;
+			}
+			case 0x6f:
+			{
+				//setglobalSlot
+				uint32_t t=data->uints[0];
+				instructionPointer+=4;
+
+				Global* globalscope = getGlobalScope(context);
+				ASObject* obj=context->runtime_stack_pop();
+				globalscope->setSlot(t,obj);
+				break;
+			}
 			case 0x70:
 			{
 				//convert_s
@@ -905,16 +951,12 @@ ASObject* ABCVm::executeFunctionFast(const SyntheticFunction* function, call_con
 			}
 			case 0x71:
 			{
-				//FIXME: Properly escape as described in ECMA-357 section 10.2
-				//esc_xelem
 				ASObject* val=context->runtime_stack_pop();
-				context->runtime_stack_push(convert_s(val));
+				context->runtime_stack_push(esc_xelem(val));
 				break;
 			}
 			case 0x72:
 			{
-				//FIXME: Properly escape as described in ECMA-357 section 10.2
-				//esc_xattr
 				ASObject* val=context->runtime_stack_pop();
 				context->runtime_stack_push(esc_xattr(val));
 				break;
@@ -946,6 +988,18 @@ ASObject* ABCVm::executeFunctionFast(const SyntheticFunction* function, call_con
 				context->runtime_stack_push(abstract_b(convert_b(val)));
 				break;
 			}
+			case 0x77:
+			{
+				//convert_o
+				ASObject* val=context->runtime_stack_pop();
+				if (val->is<Null>())
+					throwError<TypeError>(kConvertNullToObjectError);
+				if (val->is<Undefined>())
+					throwError<TypeError>(kConvertUndefinedToObjectError);
+					
+				context->runtime_stack_push(val);
+				break;
+			}
 			case 0x78:
 			{
 				//checkfilter
@@ -1362,7 +1416,12 @@ ASObject* ABCVm::executeFunctionFast(const SyntheticFunction* function, call_con
 			{
 				//getlocal_n
 				int i=opcode&3;
-				assert_and_throw(context->locals[i]);
+				if (!context->locals[i])
+				{
+					LOG(LOG_CALLS, _("getLocal ") << i << " not set, pushing Undefined");
+					context->runtime_stack_push(getSys()->getUndefinedRef());
+					break;
+				}
 				LOG(LOG_CALLS, "getLocal " << i << ": " << context->locals[i]->toDebugString() );
 				context->locals[i]->incRef();
 				context->runtime_stack_push(context->locals[i]);
@@ -1382,6 +1441,20 @@ ASObject* ABCVm::executeFunctionFast(const SyntheticFunction* function, call_con
 				context->locals[i]=obj;
 				break;
 			}
+			case 0xf2:
+			{
+				//bkptline
+				LOG(LOG_CALLS, _("bkptline") );
+				instructionPointer+=4;
+				break;
+			}
+			case 0xf3:
+			{
+				//timestamp
+				LOG(LOG_CALLS, _("timestamp") );
+				instructionPointer+=4;
+				break;
+			}
 			//lightspark custom opcodes
 			case 0xfb:
 			{
diff --git a/src/scripting/abc_interpreter.cpp b/src/scripting/abc_interpreter.cpp
index c6af09d..366bc54 100644
--- a/src/scripting/abc_interpreter.cpp
+++ b/src/scripting/abc_interpreter.cpp
@@ -73,6 +73,12 @@ ASObject* ABCVm::executeFunction(const SyntheticFunction* function, call_context
 		context->exec_pos = code.tellg();
 		switch(opcode)
 		{
+			case 0x01:
+			{
+				//bkpt
+				LOG(LOG_CALLS, _("bkpt") );
+				break;
+			}
 			case 0x02:
 			{
 				//nop
@@ -663,6 +669,20 @@ ASObject* ABCVm::executeFunction(const SyntheticFunction* function, call_context
 				loadIntN<uint32_t>(context);
 				break;
 			}
+			case 0x38:
+			{
+				//lf32
+				LOG(LOG_CALLS, "lf32");
+				loadNumber(context);
+				break;
+			}
+			case 0x39:
+			{
+				//lf32
+				LOG(LOG_CALLS, "lf64");
+				loadNumber(context);
+				break;
+			}
 			case 0x3a:
 			{
 				//si8
@@ -684,6 +704,20 @@ ASObject* ABCVm::executeFunction(const SyntheticFunction* function, call_context
 				storeIntN<uint32_t>(context);
 				break;
 			}
+			case 0x3d:
+			{
+				//sf32
+				LOG(LOG_CALLS, "sf32");
+				storeNumber(context);
+				break;
+			}
+			case 0x3e:
+			{
+				//sf32
+				LOG(LOG_CALLS, "sf64");
+				storeNumber(context);
+				break;
+			}
 			case 0x40:
 			{
 				//newfunction
@@ -909,7 +943,12 @@ ASObject* ABCVm::executeFunction(const SyntheticFunction* function, call_context
 				//getlocal
 				u30 i;
 				code >> i;
-				assert_and_throw(context->locals[i]);
+				if (!context->locals[i])
+				{
+					LOG(LOG_CALLS, _("getLocal ") << i << " not set, pushing Undefined");
+					context->runtime_stack_push(getSys()->getUndefinedRef());
+					break;
+				}
 				context->locals[i]->incRef();
 				LOG(LOG_CALLS, _("getLocal ") << i << _(": ") << context->locals[i]->toDebugString() );
 				context->runtime_stack_push(context->locals[i]);
@@ -1003,6 +1042,27 @@ ASObject* ABCVm::executeFunction(const SyntheticFunction* function, call_context
 				setSlot(v1, v2, t);
 				break;
 			}
+			case 0x6e:
+			{
+				//getglobalSlot
+				u30 t;
+				code >> t;
+
+				Global* globalscope = getGlobalScope(context);
+				context->runtime_stack_push(globalscope->getSlot(t));
+				break;
+			}
+			case 0x6f:
+			{
+				//setglobalSlot
+				u30 t;
+				code >> t;
+
+				Global* globalscope = getGlobalScope(context);
+				ASObject* obj=context->runtime_stack_pop();
+				globalscope->setSlot(t,obj);
+				break;
+			}
 			case 0x70:
 			{
 				//convert_s
@@ -1012,16 +1072,12 @@ ASObject* ABCVm::executeFunction(const SyntheticFunction* function, call_context
 			}
 			case 0x71:
 			{
-				//FIXME: Properly escape as described in ECMA-357 section 10.2
-				//esc_xelem
 				ASObject* val=context->runtime_stack_pop();
-				context->runtime_stack_push(convert_s(val));
+				context->runtime_stack_push(esc_xelem(val));
 				break;
 			}
 			case 0x72:
 			{
-				//FIXME: Properly escape as described in ECMA-357 section 10.2
-				//esc_xattr
 				ASObject* val=context->runtime_stack_pop();
 				context->runtime_stack_push(esc_xattr(val));
 				break;
@@ -1053,6 +1109,18 @@ ASObject* ABCVm::executeFunction(const SyntheticFunction* function, call_context
 				context->runtime_stack_push(abstract_b(convert_b(val)));
 				break;
 			}
+			case 0x77:
+			{
+				//convert_o
+				ASObject* val=context->runtime_stack_pop();
+				if (val->is<Null>())
+					throwError<TypeError>(kConvertNullToObjectError);
+				if (val->is<Undefined>())
+					throwError<TypeError>(kConvertUndefinedToObjectError);
+					
+				context->runtime_stack_push(val);
+				break;
+			}
 			case 0x78:
 			{
 				//checkfilter
@@ -1244,7 +1312,7 @@ ASObject* ABCVm::executeFunction(const SyntheticFunction* function, call_context
 				ASObject* v1=context->runtime_stack_pop();
 				ASObject* v2=context->runtime_stack_pop();
 
-				ASObject* ret=abstract_i(urShift(v1, v2));
+				ASObject* ret=abstract_ui(urShift(v1, v2));
 				context->runtime_stack_push(ret);
 				break;
 			}
@@ -1457,7 +1525,12 @@ ASObject* ABCVm::executeFunction(const SyntheticFunction* function, call_context
 			{
 				//getlocal_n
 				int i=opcode&3;
-				assert_and_throw(context->locals[i]);
+				if (!context->locals[i])
+				{
+					LOG(LOG_CALLS, _("getLocal ") << i << " not set, pushing Undefined");
+					context->runtime_stack_push(getSys()->getUndefinedRef());
+					break;
+				}
 				LOG(LOG_CALLS, _("getLocal ") << i << _(": ") << context->locals[i]->toDebugString() );
 				context->locals[i]->incRef();
 				context->runtime_stack_push(context->locals[i]);
@@ -1507,6 +1580,20 @@ ASObject* ABCVm::executeFunction(const SyntheticFunction* function, call_context
 				code >> t;
 				break;
 			}
+			case 0xf2:
+			{
+				//bkptline
+				LOG(LOG_CALLS, _("bkptline") );
+				u30 t;
+				code >> t;
+				break;
+			}
+			case 0xf3:
+			{
+				//timestamp
+				LOG(LOG_CALLS, _("timestamp") );
+				break;
+			}
 			default:
 				LOG(LOG_ERROR,_("Not interpreted instruction @") << code.tellg());
 				LOG(LOG_ERROR,_("dump ") << hex << (unsigned int)opcode << dec);
diff --git a/src/scripting/abc_opcodes.cpp b/src/scripting/abc_opcodes.cpp
index 1cc8c23..ab18b5e 100644
--- a/src/scripting/abc_opcodes.cpp
+++ b/src/scripting/abc_opcodes.cpp
@@ -27,6 +27,7 @@
 #include "scripting/toplevel/RegExp.h"
 #include "scripting/toplevel/XML.h"
 #include "scripting/toplevel/XMLList.h"
+#include "scripting/flash/utils/Proxy.h"
 
 using namespace std;
 using namespace lightspark;
@@ -52,7 +53,7 @@ int32_t ABCVm::bitAnd_oi(ASObject* val1, int32_t val2)
 
 void ABCVm::setProperty(ASObject* value,ASObject* obj,multiname* name)
 {
-	LOG(LOG_CALLS,_("setProperty ") << *name << ' ' << obj);
+	LOG(LOG_CALLS,_("setProperty ") << *name << ' ' << obj->toDebugString()<<" " << value->toString());
 
 	//Do not allow to set contant traits
 	obj->setVariableByMultiname(*name,value,ASObject::CONST_NOT_ALLOWED);
@@ -140,12 +141,9 @@ void ABCVm::coerce_a()
 
 ASObject* ABCVm::checkfilter(ASObject* o)
 {
-	Class_base* xmlClass=Class<XML>::getClass();
-	Class_base* xmlListClass=Class<XMLList>::getClass();
-
-	if (o->getClass()!=xmlClass && o->getClass()!=xmlListClass)
-		throw Class<TypeError>::getInstanceS();
-
+	LOG(LOG_CALLS, _("checkfilter") );
+	if (!o->is<XML>() && !o->is<XMLList>())
+		throwError<TypeError>(kFilterError, o->getClassName());
 	return o;
 }
 
@@ -289,14 +287,29 @@ void ABCVm::callProperty(call_context* th, int n, int m, method_info** called_mi
 	LOG(LOG_CALLS, (keepReturn ? "callProperty " : "callPropVoid") << *name << ' ' << m);
 
 	ASObject* obj=th->runtime_stack_pop();
-	if(obj->classdef)
-		LOG(LOG_CALLS,obj->classdef->class_name);
+	checkDeclaredTraits(obj);
+
+	if(obj->is<Null>())
+		throwError<TypeError>(kConvertNullToObjectError);
+	if (obj->is<Undefined>())
+		throwError<TypeError>(kConvertUndefinedToObjectError);
 
 	//We should skip the special implementation of get
 	_NR<ASObject> o=obj->getVariableByMultiname(*name, ASObject::SKIP_IMPL);
 	name->resetNameIfObject();
-
-	if(!o.isNull())
+	if(o.isNull() && obj->is<Class_base>())
+	{
+		// check super classes
+		_NR<Class_base> tmpcls = obj->as<Class_base>()->super;
+		while (tmpcls && !tmpcls.isNull())
+		{
+			o=tmpcls->getVariableByMultiname(*name, ASObject::SKIP_IMPL);
+			if(!o.isNull())
+				break;
+			tmpcls = tmpcls->super;
+		}	
+	}
+	if(!o.isNull() && !(obj->classdef && obj->classdef->isSubClass(Class<Proxy>::getClass())))
 	{
 		o->incRef();
 		callImpl(th, o.getPtr(), obj, args, m, called_mi, keepReturn);
@@ -311,54 +324,76 @@ void ABCVm::callProperty(call_context* th, int n, int m, method_info** called_mi
 			callPropertyName.name_type=multiname::NAME_STRING;
 			callPropertyName.name_s_id=getSys()->getUniqueStringId("callProperty");
 			callPropertyName.ns.push_back(nsNameAndKind(flash_proxy,NAMESPACE));
-			_NR<ASObject> o=obj->getVariableByMultiname(callPropertyName,ASObject::SKIP_IMPL);
+			_NR<ASObject> oproxy=obj->getVariableByMultiname(callPropertyName,ASObject::SKIP_IMPL);
 
-			if(!o.isNull())
+			if(!oproxy.isNull())
 			{
-				assert_and_throw(o->getObjectType()==T_FUNCTION);
-
-				IFunction* f=static_cast<IFunction*>(o.getPtr());
-				//Create a new array
-				ASObject** proxyArgs=g_newa(ASObject*, m+1);
-				//Well, I don't how to pass multiname to an as function. I'll just pass the name as a string
-				proxyArgs[0]=Class<ASString>::getInstanceS(getSys()->getStringFromUniqueId(name->name_s_id));
-				for(int i=0;i<m;i++)
-					proxyArgs[i+1]=args[i];
-
-				//We now suppress special handling
-				LOG(LOG_CALLS,_("Proxy::callProperty"));
-				f->incRef();
-				obj->incRef();
-				ASObject* ret=f->call(obj,proxyArgs,m+1);
-				//call getMethodInfo only after the call, so it's updated
-				if(called_mi)
-					*called_mi=f->getMethodInfo();
-				f->decRef();
-				if(keepReturn)
-					th->runtime_stack_push(ret);
+				assert_and_throw(oproxy->getObjectType()==T_FUNCTION);
+				if(!o.isNull())
+				{
+					o->incRef();
+					callImpl(th, o.getPtr(), obj, args, m, called_mi, keepReturn);
+				}
 				else
-					ret->decRef();
-
-				obj->decRef();
+				{
+					IFunction* f=static_cast<IFunction*>(oproxy.getPtr());
+					//Create a new array
+					ASObject** proxyArgs=g_newa(ASObject*, m+1);
+					ASObject* namearg = Class<ASString>::getInstanceS(name->normalizedName());
+					namearg->setProxyProperty(*name);
+					proxyArgs[0]=namearg;
+					for(int i=0;i<m;i++)
+						proxyArgs[i+1]=args[i];
+					
+					//We now suppress special handling
+					LOG(LOG_CALLS,_("Proxy::callProperty"));
+					f->incRef();
+					obj->incRef();
+					ASObject* ret=f->call(obj,proxyArgs,m+1);
+					//call getMethodInfo only after the call, so it's updated
+					if(called_mi)
+						*called_mi=f->getMethodInfo();
+					f->decRef();
+					if(keepReturn)
+						th->runtime_stack_push(ret);
+					else
+						ret->decRef();
+					
+					obj->decRef();
+				}
 				LOG(LOG_CALLS,_("End of calling ") << *name);
 				return;
 			}
 		}
+		obj->decRef();
+		for(int i=0;i<m;i++)
+			args[i]->decRef();
+		//LOG(LOG_NOT_IMPLEMENTED,"callProperty: " << name->qualifiedString() << " not found on " << obj->toDebugString());
+		throwError<TypeError>(kCallNotFoundError, name->qualifiedString(), obj->getClassName());
 
-		LOG(LOG_NOT_IMPLEMENTED,"callProperty: " << name->normalizedName() << " not found on " << obj->toDebugString());
 		if(keepReturn)
 			th->runtime_stack_push(getSys()->getUndefinedRef());
 
-		obj->decRef();
-		for(int i=0;i<m;i++)
-			args[i]->decRef();
 	}
 	LOG(LOG_CALLS,_("End of calling ") << *name);
 }
+void ABCVm::checkDeclaredTraits(ASObject* obj)
+{
+	if(!obj->isInitialized() &&
+			!obj->is<Null>() &&
+			!obj->is<Undefined>() &&
+			!obj->is<IFunction>() &&
+			!obj->is<Function_object>() &&
+			!obj->is<Class_base>() &&
+			obj->getClass() &&
+			(obj->getClass() != Class_object::getClass()))
+		obj->getClass()->setupDeclaredTraits(obj);
+}
 
 int32_t ABCVm::getProperty_i(ASObject* obj, multiname* name)
 {
 	LOG(LOG_CALLS, _("getProperty_i ") << *name );
+	checkDeclaredTraits(obj);
 
 	//TODO: implement exception handling to find out if no integer can be returned
 	int32_t ret=obj->getVariableByMultiname_i(*name);
@@ -369,14 +404,18 @@ int32_t ABCVm::getProperty_i(ASObject* obj, multiname* name)
 
 ASObject* ABCVm::getProperty(ASObject* obj, multiname* name)
 {
-	LOG(LOG_CALLS, _("getProperty ") << *name << ' ' << obj);
-
+	LOG(LOG_CALLS, _("getProperty ") << *name << ' ' << obj << ' '<<obj->isInitialized());
+	checkDeclaredTraits(obj);
+		
 	_NR<ASObject> prop=obj->getVariableByMultiname(*name);
 	ASObject *ret;
 
 	if(prop.isNull())
 	{
-		LOG(LOG_NOT_IMPLEMENTED,"getProperty: " << name->normalizedName() << " not found on " << obj->toDebugString());
+		if (obj->getClass() && obj->getClass()->isSealed)
+			throwError<ReferenceError>(kReadSealedError, name->normalizedName(), obj->getClass()->getQualifiedClassName());
+		if (Log::getLevel() >= LOG_NOT_IMPLEMENTED && obj->getClassName() != "Object")
+			LOG(LOG_NOT_IMPLEMENTED,"getProperty: " << name->normalizedName() << " not found on " << obj->toDebugString());
 		ret = getSys()->getUndefinedRef();
 	}
 	else
@@ -588,34 +627,36 @@ ASObject* ABCVm::constructFunction(call_context* th, IFunction* f, ASObject** ar
 	if(f->inClass)
 		throwError<TypeError>(kCannotCallMethodAsConstructor, "");
 
-	assert(f->is<SyntheticFunction>());
-	SyntheticFunction* sf=f->as<SyntheticFunction>();
-	assert(sf->prototype);
-	ASObject* ret=new_functionObject(sf->prototype);
+	assert(f->prototype);
+	ASObject* ret=new_functionObject(f->prototype);
 #ifndef NDEBUG
 	ret->initialized=false;
 #endif
-	if (sf->mi->body)
+	if (f->is<SyntheticFunction>())
 	{
-		LOG(LOG_CALLS,_("Building method traits"));
-		for(unsigned int i=0;i<sf->mi->body->trait_count;i++)
-			th->context->buildTrait(ret,&sf->mi->body->traits[i],false);
+		SyntheticFunction* sf=f->as<SyntheticFunction>();
+		if (sf->mi->body)
+		{
+			LOG(LOG_CALLS,_("Building method traits"));
+			for(unsigned int i=0;i<sf->mi->body->trait_count;i++)
+				th->context->buildTrait(ret,&sf->mi->body->traits[i],false);
+		}
 	}
 #ifndef NDEBUG
 	ret->initialized=true;
 #endif
 
-	sf->incRef();
-	ret->setVariableByQName("constructor","",sf,DYNAMIC_TRAIT);
+	f->incRef();
+	ret->setVariableByQName("constructor","",f,DYNAMIC_TRAIT);
 
 	ret->incRef();
 
-	sf->incRef();
-	ASObject* ret2=sf->call(ret,args,argslen);
-	sf->decRef();
+	f->incRef();
+	ASObject* ret2=f->call(ret,args,argslen);
+	f->decRef();
 
 	//ECMA: "return ret2 if it is an object, else ret"
-	if(ret2 && !ret2->is<Undefined>())
+	if(ret2 && !ret2->isPrimitive())
 	{
 		ret->decRef();
 		ret = ret2;
@@ -655,15 +696,6 @@ void ABCVm::construct(call_context* th, int m)
 			break;
 		}
 
-		case T_UNDEFINED:
-		case T_NULL:
-		{
-			//Inc ref count to make up for decremnt later
-			obj->incRef();
-			ret=obj;
-			break;
-		}
-
 		case T_FUNCTION:
 		{
 			ret = constructFunction(th, obj->as<IFunction>(), args, m);
@@ -707,7 +739,7 @@ void ABCVm::constructGenericType(call_context* th, int m)
 
 	/* Instantiate the template to obtain a class */
 
-	std::vector<Type*> t(m);
+	std::vector<const Type*> t(m);
 	for(int i=0;i<m;++i)
 	{
 		if(args[i]->is<Class_base>())
@@ -1311,6 +1343,7 @@ void ABCVm::getLex(call_context* th, int n)
 		if(!it->considerDynamic)
 			opt=(ASObject::GET_VARIABLE_OPTION)(opt | ASObject::SKIP_IMPL);
 
+		checkDeclaredTraits(it->object.getPtr());
 		_NR<ASObject> prop=it->object->getVariableByMultiname(*name, opt);
 		if(!prop.isNull())
 		{
@@ -1326,7 +1359,8 @@ void ABCVm::getLex(call_context* th, int n)
 		o=getCurrentApplicationDomain(th)->getVariableAndTargetByMultiname(*name, target);
 		if(o==NULL)
 		{
-			LOG(LOG_NOT_IMPLEMENTED,"getLex: " << *name<< " not found, pushing Undefined");
+			LOG(LOG_NOT_IMPLEMENTED,"getLex: " << *name<< " not found");
+			throwError<ReferenceError>(kUndefinedVarError);
 			th->runtime_stack_push(getSys()->getUndefinedRef());
 			name->resetNameIfObject();
 			return;
@@ -1419,7 +1453,8 @@ ASObject* ABCVm::findPropStrict(call_context* th, multiname* name)
 			ret=target;
 		else
 		{
-			LOG(LOG_NOT_IMPLEMENTED,"findPropStrict: " << *name << " not found, pushing Undefined");
+			LOG(LOG_NOT_IMPLEMENTED,"findPropStrict: " << *name << " not found");
+			throwError<ReferenceError>(kUndefinedVarError);
 			return getSys()->getUndefinedRef();
 		}
 	}
@@ -1464,7 +1499,7 @@ bool ABCVm::lessEquals(ASObject* obj1, ASObject* obj2)
 
 void ABCVm::initProperty(ASObject* obj, ASObject* value, multiname* name)
 {
-	LOG(LOG_CALLS, _("initProperty ") << *name << ' ' << obj);
+	checkDeclaredTraits(obj);
 
 	//Allow to set contant traits
 	obj->setVariableByMultiname(*name,value,ASObject::CONST_ALLOWED);
@@ -1482,12 +1517,16 @@ void ABCVm::callSuper(call_context* th, int n, int m, method_info** called_mi, b
 	LOG(LOG_CALLS,(keepReturn ? "callSuper " : "callSuperVoid ") << *name << ' ' << m);
 
 	ASObject* obj=th->runtime_stack_pop();
+	if(obj->is<Null>())
+		throwError<TypeError>(kConvertNullToObjectError);
+	if (obj->is<Undefined>())
+		throwError<TypeError>(kConvertUndefinedToObjectError);
 
 	assert_and_throw(th->inClass);
 	assert_and_throw(th->inClass->super);
 	assert_and_throw(obj->getClass());
 	assert_and_throw(obj->getClass()->isSubClass(th->inClass));
-	_NR<ASObject> f = obj->getVariableByMultiname(*name,ASObject::NONE,th->inClass->super.getPtr());
+	_NR<ASObject> f = obj->getVariableByMultiname(*name, ASObject::SKIP_IMPL,th->inClass->super.getPtr());
 	name->resetNameIfObject();
 	if(!f.isNull())
 	{
@@ -1496,7 +1535,11 @@ void ABCVm::callSuper(call_context* th, int n, int m, method_info** called_mi, b
 	}
 	else
 	{
-		LOG(LOG_ERROR,_("Calling an undefined function ") << getSys()->getStringFromUniqueId(name->name_s_id));
+		obj->decRef();
+		for(int i=0;i<m;i++)
+			args[i]->decRef();
+		//LOG(LOG_ERROR,_("Calling an undefined function ") << getSys()->getStringFromUniqueId(name->name_s_id));
+		throwError<ReferenceError>(kCallNotFoundError, name->qualifiedString(), obj->getClassName());
 		if(keepReturn)
 			th->runtime_stack_push(getSys()->getUndefinedRef());
 	}
@@ -1723,6 +1766,7 @@ void ABCVm::constructProp(call_context* th, int n, int m)
 
 	ASObject* obj=th->runtime_stack_pop();
 
+	checkDeclaredTraits(obj);
 	_NR<ASObject> o=obj->getVariableByMultiname(*name);
 
 	if(o.isNull())
@@ -1810,62 +1854,77 @@ void ABCVm::newObject(call_context* th, int n)
 void ABCVm::getDescendants(call_context* th, int n)
 {
 	multiname* name=th->context->getMultiname(n,th);
-	LOG(LOG_CALLS,"getDescendants " << *name);
 	ASObject* obj=th->runtime_stack_pop();
+	LOG(LOG_CALLS,"getDescendants " << *name << " " <<name->isAttribute<< " "<<obj->getClassName());
 	//The name must be a QName
 	assert_and_throw(name->name_type==multiname::NAME_STRING);
 	XML::XMLVector ret;
 	//TODO: support multiname and namespaces
+	XMLList* targetobject = NULL;
 	if(obj->getClass()==Class<XML>::getClass())
 	{
 		XML* xmlObj=Class<XML>::cast(obj);
-		xmlObj->getDescendantsByQName(getSys()->getStringFromUniqueId(name->name_s_id), "", ret);
+		targetobject = xmlObj->getChildrenlist();
+		tiny_string ns_uri = "";
+		if (name->ns.size() > 0)
+		{
+			ns_uri = name->ns[0].getImpl().name;
+			if (ns_uri.empty() && name->ns.size() == 1)
+				ns_uri="*";
+		}
+		xmlObj->getDescendantsByQName(getSys()->getStringFromUniqueId(name->name_s_id), ns_uri,name->isAttribute, ret);
 	}
 	else if(obj->getClass()==Class<XMLList>::getClass())
 	{
 		XMLList* xmlObj=Class<XMLList>::cast(obj);
-		xmlObj->getDescendantsByQName(getSys()->getStringFromUniqueId(name->name_s_id), "", ret);
+		tiny_string ns_uri = "";
+		if (name->ns.size() > 0)
+		{
+			ns_uri = name->ns[0].getImpl().name;
+			if (ns_uri.empty() && name->ns.size() == 1)
+				ns_uri="*";
+		}
+		targetobject = xmlObj;
+		xmlObj->getDescendantsByQName(getSys()->getStringFromUniqueId(name->name_s_id), ns_uri,name->isAttribute, ret);
 	}
 	else if(obj->getClass()->isSubClass(Class<Proxy>::getClass()))
 	{
-		_NR<ASObject> o=obj->getVariableByMultiname(*name, ASObject::SKIP_IMPL);
+		multiname callPropertyName(NULL);
+		callPropertyName.name_type=multiname::NAME_STRING;
+		callPropertyName.name_s_id=getSys()->getUniqueStringId("callProperty");
+		callPropertyName.ns.push_back(nsNameAndKind(flash_proxy,NAMESPACE));
+		_NR<ASObject> o=obj->getVariableByMultiname(callPropertyName,ASObject::SKIP_IMPL);
+		
 		if(!o.isNull())
 		{
-			o->incRef();
-			multiname callPropertyName(NULL);
-			callPropertyName.name_type=multiname::NAME_STRING;
-			callPropertyName.name_s_id=getSys()->getUniqueStringId("callProperty");
-			callPropertyName.ns.push_back(nsNameAndKind(flash_proxy,NAMESPACE));
-			_NR<ASObject> o=obj->getVariableByMultiname(callPropertyName,ASObject::SKIP_IMPL);
-
-			if(!o.isNull())
-			{
-				assert_and_throw(o->getObjectType()==T_FUNCTION);
-
-				IFunction* f=static_cast<IFunction*>(o.getPtr());
-				//Create a new array
-				ASObject** proxyArgs=g_newa(ASObject*, 1);
-				//Well, I don't how to pass multiname to an as function. I'll just pass the name as a string
-				proxyArgs[0]=Class<ASString>::getInstanceS(getSys()->getStringFromUniqueId(name->name_s_id));
-
-				//We now suppress special handling
-				LOG(LOG_CALLS,_("Proxy::callProperty"));
-				f->incRef();
-				obj->incRef();
-				ASObject* ret=f->call(obj,proxyArgs,1);
-				f->decRef();
-				th->runtime_stack_push(ret);
-
-				obj->decRef();
-				LOG(LOG_CALLS,_("End of calling ") << *name);
-				return;
-			}
-			else
-			{
-				tiny_string objName = obj->getClassName();
-				obj->decRef();
-				throwError<TypeError>(kDescendentsError, objName);
-			}
+			assert_and_throw(o->getObjectType()==T_FUNCTION);
+			
+			IFunction* f=static_cast<IFunction*>(o.getPtr());
+			//Create a new array
+			ASObject** proxyArgs=g_newa(ASObject*, 2);
+			proxyArgs[0]=Class<ASString>::getInstanceS("descendants");
+			ASObject* namearg = Class<ASString>::getInstanceS(name->normalizedName());
+			namearg->setProxyProperty(*name);
+			proxyArgs[1]=namearg;
+			LOG(LOG_ERROR,"Proxy::getDescend:"<<namearg->toDebugString()<<*name);
+
+			//We now suppress special handling
+			LOG(LOG_CALLS,_("Proxy::callProperty"));
+			f->incRef();
+			obj->incRef();
+			ASObject* ret=f->call(obj,proxyArgs,2);
+			f->decRef();
+			th->runtime_stack_push(ret);
+			
+			obj->decRef();
+			LOG(LOG_CALLS,_("End of calling ") << *name);
+			return;
+		}
+		else
+		{
+			tiny_string objName = obj->getClassName();
+			obj->decRef();
+			throwError<TypeError>(kDescendentsError, objName);
 		}
 	}
 	else
@@ -1874,7 +1933,7 @@ void ABCVm::getDescendants(call_context* th, int n)
 		obj->decRef();
 		throwError<TypeError>(kDescendentsError, objName);
 	}
-	XMLList* retObj=Class<XMLList>::getInstanceS(ret);
+	XMLList* retObj=Class<XMLList>::getInstanceS(ret,targetobject,*name);
 	th->runtime_stack_push(retObj);
 	obj->decRef();
 }
@@ -1922,18 +1981,42 @@ ASObject* ABCVm::nextName(ASObject* index, ASObject* obj)
 	ret->incRef();
 	return ret.getPtr();
 }
+std::vector<Class_base*> classesToLinkInterfaces;
+void ABCVm::SetAllClassLinks()
+{
+	for (unsigned int i = 0; i < classesToLinkInterfaces.size(); i++)
+	{
+		Class_base* cls = classesToLinkInterfaces[i];
+		if (!cls)
+			continue;
+		if (ABCVm::newClassRecursiveLink(cls, cls))
+			classesToLinkInterfaces[i] = NULL;
+	}
+}
+void ABCVm::AddClassLinks(Class_base* target)
+{
+	classesToLinkInterfaces.push_back(target);
+}
 
-void ABCVm::newClassRecursiveLink(Class_base* target, Class_base* c)
+bool ABCVm::newClassRecursiveLink(Class_base* target, Class_base* c)
 {
 	if(c->super)
-		newClassRecursiveLink(target, c->super.getPtr());
-
-	const vector<Class_base*>& interfaces=c->getInterfaces();
+	{
+		if (!newClassRecursiveLink(target, c->super.getPtr()))
+			return false;
+	}
+	bool bAllDefined = false;
+	const vector<Class_base*>& interfaces=c->getInterfaces(&bAllDefined);
+	if (!bAllDefined)
+	{
+		return false;
+	}
 	for(unsigned int i=0;i<interfaces.size();i++)
 	{
 		LOG(LOG_CALLS,_("Linking with interface ") << interfaces[i]->class_name);
 		interfaces[i]->linkInterface(target);
 	}
+	return true;
 }
 
 void ABCVm::newClass(call_context* th, int n)
@@ -1947,25 +2030,46 @@ void ABCVm::newClass(call_context* th, int n)
 
 	assert_and_throw(mname->ns.size()==1);
 	QName className(getSys()->getStringFromUniqueId(mname->name_s_id),mname->ns[0].getImpl().name);
-	//Check if this class has been already defined
-	_NR<ApplicationDomain> domain = getCurrentApplicationDomain(th);
-	ASObject* target;
-	ASObject* oldDefinition=domain->getVariableAndTargetByMultiname(*mname, target);
-	if(oldDefinition && oldDefinition->getObjectType()==T_CLASS)
-	{
-		LOG(LOG_CALLS,_("Class ") << className << _(" already defined. Pushing previous definition"));
-		baseClass->decRef();
-		oldDefinition->incRef();
-		th->runtime_stack_push(oldDefinition);
-		return;
-	}
 
-	MemoryAccount* memoryAccount = getSys()->allocateMemoryAccount(className.name);
-	Class_inherit* ret=new (getSys()->unaccountedMemory) Class_inherit(className, memoryAccount);
+	Class_inherit* ret = NULL;
+	auto i = th->context->root->applicationDomain->classesBeingDefined.cbegin();
+	while (i != th->context->root->applicationDomain->classesBeingDefined.cend())
+	{
+		if(i->first->qualifiedString() == mname->qualifiedString())
+		{
+			ret = (Class_inherit*)i->second;
+			ret->incRef();
+			break;
+		}
+		i++;
+	}
 
-	//Add the class to the ones being currently defined in this context
-	th->context->classesBeingDefined.insert(make_pair(mname, ret));
+	if (ret == NULL)
+	{
+		//Check if this class has been already defined
+		_NR<ApplicationDomain> domain = getCurrentApplicationDomain(th);
+		ASObject* target;
+		ASObject* oldDefinition=domain->getVariableAndTargetByMultiname(*mname, target);
+		if(oldDefinition && oldDefinition->getObjectType()==T_CLASS)
+		{
+			LOG(LOG_CALLS,_("Class ") << className << _(" already defined. Pushing previous definition"));
+			baseClass->decRef();
+			oldDefinition->incRef();
+			th->runtime_stack_push(oldDefinition);
+			// ensure that this interface is linked to all previously defined classes implementing this interface
+			if (th->context->instances[n].isInterface())
+				ABCVm::SetAllClassLinks();
+			return;
+		}
+		
+		MemoryAccount* memoryAccount = getSys()->allocateMemoryAccount(className.name);
+		ret=new (getSys()->unaccountedMemory) Class_inherit(className, memoryAccount);
 
+		LOG(LOG_CALLS,"add classes defined:"<<*mname<<" "<<th->context);
+		//Add the class to the ones being currently defined in this context
+		th->context->root->applicationDomain->classesBeingDefined.insert(make_pair(mname, ret));
+	}
+		
 	ret->isFinal = th->context->instances[n].isFinal();
 	ret->isSealed = th->context->instances[n].isSealed();
 
@@ -2036,6 +2140,13 @@ void ABCVm::newClass(call_context* th, int n)
 	if(ret->super)
 		ret->prototype->prevPrototype=ret->super->prototype;
 	ret->addPrototypeGetter();
+	if (constructor->body)
+		ret->constructorprop = _NR<ObjectConstructor>(new_objectConstructor(ret,ret->constructor->length));
+	else
+		ret->constructorprop = _NR<ObjectConstructor>(new_objectConstructor(ret,0));
+	
+	ret->constructorprop->incRef();
+	ret->addConstructorGetter();
 
 	//add implemented interfaces
 	for(unsigned int i=0;i<th->context->instances[n].interface_count;i++)
@@ -2056,9 +2167,16 @@ void ABCVm::newClass(call_context* th, int n)
 	if(!th->context->instances[n].isInterface())
 	{
 		//Link all the interfaces for this class and all the bases
-		newClassRecursiveLink(ret, ret);
+		if (!newClassRecursiveLink(ret, ret))
+		{
+			// remember classes where not all interfaces are defined yet
+			ABCVm::AddClassLinks(ret);
+		}
 	}
-
+	// ensure that this interface is linked to all previously defined classes implementing this interface
+	if (th->context->instances[n].isInterface())
+		ABCVm::SetAllClassLinks();
+	
 	LOG(LOG_CALLS,_("Calling Class init ") << ret);
 	ret->incRef();
 	//Class init functions are called with global as this
@@ -2079,17 +2197,17 @@ void ABCVm::newClass(call_context* th, int n)
 		cinit->decRef();
 
 		//Remove the class to the ones being currently defined in this context
-		th->context->classesBeingDefined.erase(mname);
+		th->context->root->applicationDomain->classesBeingDefined.erase(mname);
 		throw;
 	}
 	assert_and_throw(ret2->is<Undefined>());
 	ret2->decRef();
-	LOG(LOG_CALLS,_("End of Class init ") << ret);
+	LOG(LOG_CALLS,_("End of Class init ") << *mname <<" " <<ret);
 	th->runtime_stack_push(ret);
 	cinit->decRef();
 
 	//Remove the class to the ones being currently defined in this context
-	th->context->classesBeingDefined.erase(mname);
+	th->context->root->applicationDomain->classesBeingDefined.erase(mname);
 }
 
 void ABCVm::swap()
@@ -2188,6 +2306,7 @@ void ABCVm::callImpl(call_context* th, ASObject* f, ASObject* obj, ASObject** ar
 		//we silently ignore calling undefined functions
 		if(f->is<Undefined>())
 		{
+			LOG(LOG_NOT_IMPLEMENTED,"calling undefined function:"<<obj->toDebugString());
 			if(keepReturn)
 				th->runtime_stack_push(f);
 			else
@@ -2264,22 +2383,28 @@ void ABCVm::newArray(call_context* th, int n)
 
 ASObject* ABCVm::esc_xattr(ASObject* o)
 {
-	/* TODO: implement correct escaping according to E4X
-	 * For now we just cut the string at the first \0 byte, which is wrong
-	 * but suppresses more errors */
-	tiny_string t = o->toString();
-	LOG(LOG_NOT_IMPLEMENTED,"esc_xattr on " << t);
+	tiny_string t;
+	if (o->is<XML>())
+		t = o->as<XML>()->toXMLString_internal();
+	else if (o->is<XMLList>())
+		t = o->as<XMLList>()->toXMLString_internal();
+	else
+		t = XML::encodeToXML(o->toString(),true);
 	o->decRef();
-	auto i=t.begin();
-	for(;i!=t.end();++i)
-	{
-		if(*i == '\0')
-			break;
-	}
-	if(i == t.end())
-		return Class<ASString>::getInstanceS(t);
+	return Class<ASString>::getInstanceS(t);
+}
+
+ASObject* ABCVm::esc_xelem(ASObject* o)
+{
+	tiny_string t;
+	if (o->is<XML>())
+		t = o->as<XML>()->toXMLString_internal();
+	else if (o->is<XMLList>())
+		t = o->as<XMLList>()->toXMLString_internal();
 	else
-		return Class<ASString>::getInstanceS(t.substr(0,i));
+		t = XML::encodeToXML(o->toString(),false);
+	o->decRef();
+	return Class<ASString>::getInstanceS(t);
 }
 
 /* This should walk prototype chain of value, trying to find type. See ECMA.
diff --git a/src/scripting/abc_optimizer.cpp b/src/scripting/abc_optimizer.cpp
index c19dd17..2be09f3 100644
--- a/src/scripting/abc_optimizer.cpp
+++ b/src/scripting/abc_optimizer.cpp
@@ -179,7 +179,8 @@ EARLY_BIND_STATUS ABCVm::earlyBindForScopeStack(ostream& out, const SyntheticFun
 				return CANNOT_BIND;
 			}
 
-			const variable* var=it->object->findVariableByMultiname(*name, ASObject::XML_STRICT, it->object->getClass());
+			NS_KIND nskind;
+			const variable* var=it->object->findVariableByMultiname(*name, ASObject::XML_STRICT, it->object->getClass(),nskind);
 			if(var)
 			{
 				found=true;
@@ -964,7 +965,8 @@ void ABCVm::optimizeFunction(SyntheticFunction* function)
 						const Class_base* objType=dynamic_cast<const Class_base*>(baseData.type);
 						if(objType)
 						{
-							const variable* var=objType->findBorrowedGettable(*name);
+							NS_KIND nskind;
+							const variable* var=objType->findBorrowedGettable(*name,nskind);
 							if(var && var->var && var->var->getObjectType()==T_FUNCTION)
 							{
 								SyntheticFunction* calledFunc=dynamic_cast<SyntheticFunction*>(var->var);
diff --git a/src/scripting/abctypes.h b/src/scripting/abctypes.h
index f70280a..0cca5b1 100644
--- a/src/scripting/abctypes.h
+++ b/src/scripting/abctypes.h
@@ -122,8 +122,9 @@ struct multiname_info
 	u30 type_definition;
 	std::vector<u30> param_types;
 	multiname* cached;
-	multiname_info():cached(NULL){}
-	~multiname_info(){delete cached;}
+	multiname* dynamic;
+	multiname_info():cached(NULL),dynamic(NULL){}
+	~multiname_info(){delete cached;if (dynamic) {delete dynamic;};}
 	bool isAttributeName() const;
 };
 
diff --git a/src/scripting/argconv.h b/src/scripting/argconv.h
index 78b51bd..22cce31 100644
--- a/src/scripting/argconv.h
+++ b/src/scripting/argconv.h
@@ -215,15 +215,17 @@ inline ASObject* lightspark::ArgumentConversion<RGB>::toAbstract(const RGB& val)
 	return abstract_ui(val.toUInt());
 }
 
-#define ARG_UNPACK ArgUnpack(args,argslen)
+#define ARG_UNPACK ArgUnpack(args,argslen,false)
+#define ARG_UNPACK_MORE_ALLOWED ArgUnpack(args,argslen,true)
 
 class ArgUnpack
 {
 private:
 	ASObject* const * args;
 	int argslen;
+	bool moreAllowed;
 public:
-	ArgUnpack(ASObject* const * _args, int _argslen) : args(_args), argslen(_argslen) {}
+	ArgUnpack(ASObject* const * _args, int _argslen, bool _moreAllowed) : args(_args), argslen(_argslen), moreAllowed(_moreAllowed) {}
 
 	template<class T> ArgUnpack& operator()(T& v)
 	{
@@ -251,7 +253,7 @@ public:
 	}
 	~ArgUnpack()
 	{
-		if(argslen > 0)
+		if(argslen > 0 && !moreAllowed)
 			LOG(LOG_NOT_IMPLEMENTED,"Not all arguments were unpacked");
 	}
 };
diff --git a/src/scripting/class.cpp b/src/scripting/class.cpp
index 18d9741..6ba15d9 100644
--- a/src/scripting/class.cpp
+++ b/src/scripting/class.cpp
@@ -48,6 +48,13 @@ Function_object* lightspark::new_functionObject(_NR<ASObject> p)
 	return new (c->memoryAccount) Function_object(c, p);
 }
 
+ObjectConstructor* lightspark::new_objectConstructor(Class_base* cls,uint32_t length)
+{
+	return new (cls->memoryAccount) ObjectConstructor(cls, length);
+}
+
+
+
 Class_inherit::Class_inherit(const QName& name, MemoryAccount* m):Class_base(name, m),tag(NULL),bindedToRoot(false)
 {
 	this->incRef(); //create on reference for the classes map
@@ -71,7 +78,6 @@ ASObject* Class_inherit::getInstance(bool construct, ASObject* const* args, cons
 		realClass=this;
 
 	ASObject* ret=NULL;
-	assert_and_throw(!bindedToRoot);
 	if(tag)
 	{
 		ret=tag->instance(realClass);
@@ -172,3 +178,25 @@ ASObject* Class<ASObject>::getInstance(bool construct, ASObject* const* args, co
 		handleConstruction(ret,args,argslen,true);
 	return ret;
 }
+Class<ASObject>* Class<ASObject>::getClass()
+{
+	uint32_t classId=ClassName<ASObject>::id;
+	Class<ASObject>* ret=NULL;
+	Class_base** retAddr=&getSys()->builtinClasses[classId];
+	if(*retAddr==NULL)
+	{
+		//Create the class
+		QName name(ClassName<ASObject>::name,ClassName<ASObject>::ns);
+		MemoryAccount* memoryAccount = getSys()->allocateMemoryAccount(name.name);
+		ret=new (getSys()->unaccountedMemory) Class<ASObject>(name, memoryAccount);
+		ret->incRef();
+		*retAddr=ret;
+		ret->prototype = _MNR(new_objectPrototype());
+		ASObject::sinit(ret);
+		ret->initStandardProps();
+	}
+	else
+		ret=static_cast<Class<ASObject>*>(*retAddr);
+	
+	return ret;
+}
diff --git a/src/scripting/class.h b/src/scripting/class.h
index 3d14643..f98ab08 100644
--- a/src/scripting/class.h
+++ b/src/scripting/class.h
@@ -72,6 +72,7 @@ ASObject* new_asobject();
 Prototype* new_objectPrototype();
 Prototype* new_functionPrototype(Class_base* functionClass, _NR<Prototype> p);
 Function_object* new_functionObject(_NR<ASObject> p);
+ObjectConstructor* new_objectConstructor(Class_base* cls,uint32_t length);
 
 template<class T,std::size_t N>
 struct newWithOptionalClass
@@ -149,13 +150,7 @@ public:
 			ret->prototype = _MNR(new_objectPrototype());
 			T::sinit(ret);
 
-			ret->setDeclaredMethodByQName("toString",AS3,Class<IFunction>::getFunction(Class_base::_toString),NORMAL_METHOD,false);
-			ret->incRef();
-			ret->prototype->setVariableByQName("constructor","",ret,DYNAMIC_TRAIT);
-			if(ret->super)
-				ret->prototype->prevPrototype=ret->super->prototype;
-			ret->addPrototypeGetter();
-			ret->addLengthGetter();
+			ret->initStandardProps();
 		}
 		else
 			ret=static_cast<Class<T>*>(*retAddr);
@@ -241,54 +236,7 @@ public:
 		Class<ASObject>* c=Class<ASObject>::getClass();
 		return c->getInstance(true,NULL,0);
 	}
-	/* This creates a stub class, i.e. a class with given name but without
-	 * any implementation.
-	 */
-	static _R<Class<ASObject>> getStubClass(const QName& name, _R<Class_base> superClass=Class<ASObject>::getRef())
-	{
-		MemoryAccount* memoryAccount = getSys()->allocateMemoryAccount(name.name);
-		Class<ASObject>* ret = new (getSys()->unaccountedMemory) Class<ASObject>(name, memoryAccount);
-
-		ret->setSuper(superClass);
-		ret->prototype = _MNR(new_objectPrototype());
-		ret->prototype->prevPrototype=ret->super->prototype;
-		ret->incRef();
-		ret->prototype->setVariableByQName("constructor","",ret,DYNAMIC_TRAIT);
-		ret->addPrototypeGetter();
-		ret->addLengthGetter();
-
-		ret->setDeclaredMethodByQName("toString",AS3,Class<IFunction>::getFunction(Class_base::_toString),NORMAL_METHOD,false);
-		getSys()->customClasses.insert(ret);
-		ret->incRef();
-		return _MR(ret);
-	}
-	static Class<ASObject>* getClass()
-	{
-		uint32_t classId=ClassName<ASObject>::id;
-		Class<ASObject>* ret=NULL;
-		Class_base** retAddr=&getSys()->builtinClasses[classId];
-		if(*retAddr==NULL)
-		{
-			//Create the class
-			QName name(ClassName<ASObject>::name,ClassName<ASObject>::ns);
-			MemoryAccount* memoryAccount = getSys()->allocateMemoryAccount(name.name);
-			ret=new (getSys()->unaccountedMemory) Class<ASObject>(name, memoryAccount);
-			ret->incRef();
-			*retAddr=ret;
-			ret->prototype = _MNR(new_objectPrototype());
-			ASObject::sinit(ret);
-
-			ret->setDeclaredMethodByQName("toString",AS3,Class<IFunction>::getFunction(Class_base::_toString),NORMAL_METHOD,false);
-			ret->incRef();
-			ret->prototype->setVariableByQName("constructor","",ret,DYNAMIC_TRAIT);
-			ret->addPrototypeGetter();
-			ret->addLengthGetter();
-		}
-		else
-			ret=static_cast<Class<ASObject>*>(*retAddr);
-
-		return ret;
-	}
+	static Class<ASObject>* getClass();
 	static _R<Class<ASObject>> getRef()
 	{
 		Class<ASObject>* ret = getClass();
@@ -331,7 +279,7 @@ void lookupAndLink(Class_base* c, const tiny_string& name, const tiny_string& in
 template<class T>
 class InterfaceClass: public Class_base
 {
-	virtual ~InterfaceClass() {}
+	virtual ~InterfaceClass() { }
 	void buildInstanceTraits(ASObject*) const {}
 	ASObject* getInstance(bool, ASObject* const*, unsigned int, Class_base* realClass)
 	{
@@ -343,7 +291,7 @@ class InterfaceClass: public Class_base
 		assert(argslen == 1);
 		return args[0];
 	}
-	InterfaceClass(const QName& name, MemoryAccount* m):Class_base(name, m) {}
+	InterfaceClass(const QName& name, MemoryAccount* m):Class_base(name, m) { }
 public:
 	static InterfaceClass<T>* getClass()
 	{
@@ -383,9 +331,9 @@ class TemplatedClass : public Class<T>
 private:
 	/* the Template<T>* this class was generated from */
 	const Template_base* templ;
-	std::vector<Type*> types;
+	std::vector<const Type*> types;
 public:
-	TemplatedClass(const QName& name, const std::vector<Type*>& _types, Template_base* _templ, MemoryAccount* m)
+	TemplatedClass(const QName& name, const std::vector<const Type*>& _types, Template_base* _templ, MemoryAccount* m)
 		: Class<T>(name, m), templ(_templ), types(_types)
 	{
 	}
@@ -417,10 +365,14 @@ public:
 		return templ;
 	}
 
-	const std::vector<Type*> getTypes() const
+	std::vector<const Type*> getTypes() const
 	{
 		return types;
 	}
+	void addType(const Type* type)
+	{
+		types.push_back(type);
+	}
 
 	ASObject* coerce(ASObject* o) const
 	{
@@ -429,8 +381,8 @@ public:
 			o->decRef();
 			return getSys()->getNullRef();
 		}
-		else if ((o->is<Vector>() && o->as<Vector>()->sameType(types)) || 
-			 o->is<Null>())
+		else if ((o->is<Vector>() && o->as<Vector>()->sameType(this->class_name)) || 
+				 o->is<Null>())
 		{
 			// Vector.<x> can be coerced to Vector.<y>
 			// only if x and y are the same type
@@ -440,7 +392,7 @@ public:
 		{
 			o->decRef();
 			throwError<TypeError>(kCheckTypeFailedError, o->getClassName(),
-					      Class<T>::getQualifiedClassName());
+								  Class<T>::getQualifiedClassName());
 			return NULL; // not reached
 		}
 	}
@@ -453,7 +405,7 @@ class Template : public Template_base
 public:
 	Template(QName name) : Template_base(name) {};
 
-	QName getQName(const std::vector<Type*>& types)
+	QName getQName(const std::vector<const Type*>& types)
 	{
 		//This is the naming scheme that the ABC compiler uses,
 		//and we need to stay in sync here
@@ -466,7 +418,7 @@ public:
 		return ret;
 	}
 
-	Class_base* applyType(const std::vector<Type*>& types)
+	Class_base* applyType(const std::vector<const Type*>& types)
 	{
 		QName instantiatedQName = getQName(types);
 
@@ -484,21 +436,61 @@ public:
 			ret->addPrototypeGetter();
 		}
 		else
+		{
+			TemplatedClass<T>* tmp = static_cast<TemplatedClass<T>*>(it->second);
+			if (tmp->getTypes().size() == 0)
+				tmp->addType(types[0]);
+			ret= tmp;
+		}
+
+		ret->incRef();
+		return ret;
+	}
+	Class_base* applyTypeByQName(const QName& qname)
+	{
+		const std::vector<const Type*> types;
+		std::map<QName, Class_base*>::iterator it=getSys()->instantiatedTemplates.find(qname);
+		Class<T>* ret=NULL;
+		if(it==getSys()->instantiatedTemplates.end()) //This class is not yet in the map, create it
+		{
+			MemoryAccount* memoryAccount = getSys()->allocateMemoryAccount(qname.name);
+			ret=new (getSys()->unaccountedMemory) TemplatedClass<T>(qname,types,this,memoryAccount);
+			getSys()->instantiatedTemplates.insert(std::make_pair(qname,ret));
+			ret->prototype = _MNR(new_objectPrototype());
+			T::sinit(ret);
+			if(ret->super)
+				ret->prototype->prevPrototype=ret->super->prototype;
+			ret->addPrototypeGetter();
+		}
+		else
 			ret=static_cast<TemplatedClass<T>*>(it->second);
 
 		ret->incRef();
 		return ret;
 	}
 
-	static Ref<Class_base> getTemplateInstance(Type* type)
+	static Ref<Class_base> getTemplateInstance(const Type* type)
 	{
-		std::vector<Type*> t(1,type);
+		std::vector<const Type*> t(1,type);
 		Template<T>* templ=getTemplate();
 		Ref<Class_base> ret=_MR(templ->applyType(t));
 		templ->decRef();
 		return ret;
 	}
 
+	static Ref<Class_base> getTemplateInstance(const QName& qname, ABCContext* context)
+	{
+		Template<T>* templ=getTemplate();
+		Ref<Class_base> ret=_MR(templ->applyTypeByQName(qname));
+		ret->context = context;
+		templ->decRef();
+		return ret;
+	}
+	static T* getInstanceS(const Type* type)
+	{
+		return static_cast<T*>(getTemplateInstance(type).getPtr()->getInstance(true,NULL,0));
+	}
+
 	static Template<T>* getTemplate(const QName& name)
 	{
 		std::map<QName, Template_base*>::iterator it=getSys()->templates.find(name);
diff --git a/src/scripting/flash/accessibility/flashaccessibility.cpp b/src/scripting/flash/accessibility/flashaccessibility.cpp
index ebc460d..4d6a361 100644
--- a/src/scripting/flash/accessibility/flashaccessibility.cpp
+++ b/src/scripting/flash/accessibility/flashaccessibility.cpp
@@ -23,25 +23,37 @@
 
 using namespace lightspark;
 
+AccessibilityProperties::AccessibilityProperties(Class_base* c):
+	ASObject(c), forceSimple(false), noAutoLabeling(false), silent(false)
+{
+}
+
 void AccessibilityProperties::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<ASObject>::getRef());
-	REGISTER_GETTER_SETTER(c,name);
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_SEALED);
+	REGISTER_GETTER_SETTER(c, description);
+	REGISTER_GETTER_SETTER(c, forceSimple);
+	REGISTER_GETTER_SETTER(c, name);
+	REGISTER_GETTER_SETTER(c, noAutoLabeling);
+	REGISTER_GETTER_SETTER(c, shortcut);
+	REGISTER_GETTER_SETTER(c, silent);
 }
 
 ASFUNCTIONBODY(AccessibilityProperties,_constructor)
 {
-	LOG(LOG_NOT_IMPLEMENTED, _("AccessibilityProperties class is unimplemented."));
 	return NULL;
 }
 
-ASFUNCTIONBODY_GETTER_SETTER(AccessibilityProperties,name);
+ASFUNCTIONBODY_GETTER_SETTER(AccessibilityProperties, description);
+ASFUNCTIONBODY_GETTER_SETTER(AccessibilityProperties, forceSimple);
+ASFUNCTIONBODY_GETTER_SETTER(AccessibilityProperties, name);
+ASFUNCTIONBODY_GETTER_SETTER(AccessibilityProperties, noAutoLabeling);
+ASFUNCTIONBODY_GETTER_SETTER(AccessibilityProperties, shortcut);
+ASFUNCTIONBODY_GETTER_SETTER(AccessibilityProperties, silent);
 
 void AccessibilityImplementation::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<ASObject>::getRef());
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_SEALED);
 }
 
 ASFUNCTIONBODY(AccessibilityImplementation,_constructor)
@@ -49,3 +61,19 @@ ASFUNCTIONBODY(AccessibilityImplementation,_constructor)
 	LOG(LOG_NOT_IMPLEMENTED, _("AccessibilityImplementation class is unimplemented."));
 	return NULL;
 }
+
+
+void Accessibility::sinit(Class_base* c)
+{
+	CLASS_SETUP(c, ASObject, _constructorNotInstantiatable, CLASS_FINAL);
+	c->setVariableByQName("active","",abstract_b(false),CONSTANT_TRAIT);
+}
+
+ASFUNCTIONBODY(Accessibility,updateProperties)
+{
+	Accessibility* th=obj->as<Accessibility>();
+	LOG(LOG_NOT_IMPLEMENTED, "Accessibility is not supported.");
+	ARG_UNPACK (th->properties);
+
+	return NULL;
+}
diff --git a/src/scripting/flash/accessibility/flashaccessibility.h b/src/scripting/flash/accessibility/flashaccessibility.h
index 19d00b8..b462e75 100644
--- a/src/scripting/flash/accessibility/flashaccessibility.h
+++ b/src/scripting/flash/accessibility/flashaccessibility.h
@@ -28,9 +28,14 @@ namespace lightspark
 class AccessibilityProperties : public ASObject
 {
 private:
-	ASPROPERTY_GETTER_SETTER(tiny_string,name);
+	ASPROPERTY_GETTER_SETTER(tiny_string, description);
+	ASPROPERTY_GETTER_SETTER(bool, forceSimple);
+	ASPROPERTY_GETTER_SETTER(tiny_string, name);
+	ASPROPERTY_GETTER_SETTER(bool, noAutoLabeling);
+	ASPROPERTY_GETTER_SETTER(tiny_string, shortcut);
+	ASPROPERTY_GETTER_SETTER(bool, silent);
 public:
-	AccessibilityProperties(Class_base* c):ASObject(c){}
+	AccessibilityProperties(Class_base* c);
 	static void sinit(Class_base*);
 	ASFUNCTION(_constructor);
 };
@@ -43,5 +48,15 @@ public:
 	ASFUNCTION(_constructor);
 };
 
+class Accessibility : public ASObject
+{
+private:
+	_NR<AccessibilityProperties> properties;
+public:
+	Accessibility(Class_base* c):ASObject(c),properties(NULL){}
+	static void sinit(Class_base*);
+	ASFUNCTION(updateProperties);
+};
+
 }
 #endif /* SCRIPTING_FLASH_ACCESSIBILITY_FLASHACCESSIBILITY_H */
diff --git a/src/scripting/flash/concurrent/Condition.cpp b/src/scripting/flash/concurrent/Condition.cpp
new file mode 100644
index 0000000..6f49d17
--- /dev/null
+++ b/src/scripting/flash/concurrent/Condition.cpp
@@ -0,0 +1,81 @@
+/**************************************************************************
+    Lightspark, a free flash player implementation
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+**************************************************************************/
+
+#include "scripting/flash/concurrent/Condition.h"
+#include "scripting/flash/errors/flasherrors.h"
+#include "scripting/class.h"
+#include "scripting/argconv.h"
+
+using namespace std;
+using namespace lightspark;
+
+ASCondition::ASCondition(Class_base* c):ASObject(c)
+{
+	
+}
+void ASCondition::sinit(Class_base* c)
+{
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_FINAL);
+	c->setVariableByQName("isSupported","",abstract_b(false),CONSTANT_TRAIT);
+	c->setDeclaredMethodByQName("notify","",Class<IFunction>::getFunction(_notify),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("notifyAll","",Class<IFunction>::getFunction(_notifyAll),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("wait","",Class<IFunction>::getFunction(_wait),NORMAL_METHOD,true);
+	REGISTER_GETTER(c,mutex);
+}
+
+ASFUNCTIONBODY_GETTER(ASCondition,mutex);
+
+ASFUNCTIONBODY(ASCondition,_constructor)
+{
+	ASCondition* th=obj->as<ASCondition>();
+	_NR<ASObject> arg;
+	ARG_UNPACK(arg);
+	if (arg->is<Null>())
+		throwError<ArgumentError>(kNullPointerError);
+	
+	if (!arg->is<ASMutex>())
+		throwError<ArgumentError>(kInvalidArgumentError) ;
+	arg->incRef();
+	th->mutex = _NR<ASMutex>(arg->as<ASMutex>());
+
+	return NULL;
+}
+ASFUNCTIONBODY(ASCondition,_notify)
+{
+	LOG(LOG_NOT_IMPLEMENTED,"condition notify not implemented");
+	ASCondition* th=obj->as<ASCondition>();
+	if (!th->mutex->getLockCount())
+		throwError<ASError>(kConditionCannotNotify) ;
+	return NULL;
+}
+ASFUNCTIONBODY(ASCondition,_notifyAll)
+{
+	LOG(LOG_NOT_IMPLEMENTED,"condition notifyAll not implemented");
+	ASCondition* th=obj->as<ASCondition>();
+	if (!th->mutex->getLockCount())
+		throwError<ASError>(kConditionCannotNotifyAll) ;
+	return NULL;
+}
+ASFUNCTIONBODY(ASCondition,_wait)
+{
+	LOG(LOG_NOT_IMPLEMENTED,"condition wait not implemented");
+	ASCondition* th=obj->as<ASCondition>();
+	if (!th->mutex->getLockCount())
+		throwError<ASError>(kConditionCannotWait) ;
+	return abstract_b(true);
+}
+
diff --git a/src/backends/rtmputils.h b/src/scripting/flash/concurrent/Condition.h
similarity index 66%
copy from src/backends/rtmputils.h
copy to src/scripting/flash/concurrent/Condition.h
index 7e9de51..31498e6 100644
--- a/src/backends/rtmputils.h
+++ b/src/scripting/flash/concurrent/Condition.h
@@ -1,8 +1,6 @@
 /**************************************************************************
     Lightspark, a free flash player implementation
 
-    Copyright (C) 2011-2013  Alessandro Pignotti (a.pignotti at sssup.it)
-
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU Lesser General Public License as published by
     the Free Software Foundation, either version 3 of the License, or
@@ -17,25 +15,27 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 **************************************************************************/
 
-#ifndef BACKENDS_RTMPUTILS_H
-#define BACKENDS_RTMPUTILS_H 1
+#ifndef FLASH_CONCURRENT_CONDITION_H
+#define FLASH_CONCURRENT_CONDITION_H
 
-#include "backends/netutils.h"
+#include "asobject.h"
+#include "scripting/flash/events/flashevents.h"
+#include "scripting/flash/concurrent/Mutex.h"
 
 namespace lightspark
 {
 
-class ILoadable;
-
-class RTMPDownloader: public ThreadedDownloader
+class ASCondition: public ASObject
 {
-private:
-	void execute();
-	void threadAbort();
-	tiny_string stream;
+	ASPROPERTY_GETTER(_NR<ASMutex>,mutex);
 public:
-	RTMPDownloader(const tiny_string& _url, const tiny_string& _stream, ILoadable* o);
+	ASCondition(Class_base* c);
+	static void sinit(Class_base*);
+	ASFUNCTION(_constructor);
+	ASFUNCTION(_notify);
+	ASFUNCTION(_notifyAll);
+	ASFUNCTION(_wait);
 };
 
-};
-#endif /* BACKENDS_RTMPUTILS_H */
+}
+#endif // FLASH_CONCURRENT_CONDITION_H
diff --git a/src/scripting/flash/accessibility/flashaccessibility.cpp b/src/scripting/flash/concurrent/Mutex.cpp
similarity index 53%
copy from src/scripting/flash/accessibility/flashaccessibility.cpp
copy to src/scripting/flash/concurrent/Mutex.cpp
index ebc460d..3dc2902 100644
--- a/src/scripting/flash/accessibility/flashaccessibility.cpp
+++ b/src/scripting/flash/concurrent/Mutex.cpp
@@ -1,8 +1,6 @@
 /**************************************************************************
     Lightspark, a free flash player implementation
 
-    Copyright (C) 2009-2013  Alessandro Pignotti (a.pignotti at sssup.it)
-
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU Lesser General Public License as published by
     the Free Software Foundation, either version 3 of the License, or
@@ -17,35 +15,46 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 **************************************************************************/
 
-#include "scripting/flash/accessibility/flashaccessibility.h"
+#include "scripting/flash/concurrent/Mutex.h"
 #include "scripting/class.h"
 #include "scripting/argconv.h"
 
+using namespace std;
 using namespace lightspark;
 
-void AccessibilityProperties::sinit(Class_base* c)
+ASMutex::ASMutex(Class_base* c):ASObject(c),lockcount(0)
+{
+	
+}
+void ASMutex::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<ASObject>::getRef());
-	REGISTER_GETTER_SETTER(c,name);
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_FINAL);
+	c->setDeclaredMethodByQName("lock","",Class<IFunction>::getFunction(_lock),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("unlock","",Class<IFunction>::getFunction(_unlock),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("tryLock","",Class<IFunction>::getFunction(_trylock),NORMAL_METHOD,true);
 }
 
-ASFUNCTIONBODY(AccessibilityProperties,_constructor)
+ASFUNCTIONBODY(ASMutex,_constructor)
 {
-	LOG(LOG_NOT_IMPLEMENTED, _("AccessibilityProperties class is unimplemented."));
 	return NULL;
 }
-
-ASFUNCTIONBODY_GETTER_SETTER(AccessibilityProperties,name);
-
-void AccessibilityImplementation::sinit(Class_base* c)
+ASFUNCTIONBODY(ASMutex,_lock)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<ASObject>::getRef());
+	ASMutex* th=obj->as<ASMutex>();
+	th->mutex.lock();
+	th->lockcount++;
+	return NULL;
 }
-
-ASFUNCTIONBODY(AccessibilityImplementation,_constructor)
+ASFUNCTIONBODY(ASMutex,_unlock)
 {
-	LOG(LOG_NOT_IMPLEMENTED, _("AccessibilityImplementation class is unimplemented."));
+	ASMutex* th=obj->as<ASMutex>();
+	th->mutex.unlock();
+	th->lockcount--;
 	return NULL;
 }
+ASFUNCTIONBODY(ASMutex,_trylock)
+{
+	ASMutex* th=obj->as<ASMutex>();
+	return abstract_b(th->mutex.trylock());
+}
+
diff --git a/src/backends/rtmputils.h b/src/scripting/flash/concurrent/Mutex.h
similarity index 68%
copy from src/backends/rtmputils.h
copy to src/scripting/flash/concurrent/Mutex.h
index 7e9de51..a642fd9 100644
--- a/src/backends/rtmputils.h
+++ b/src/scripting/flash/concurrent/Mutex.h
@@ -1,8 +1,6 @@
 /**************************************************************************
     Lightspark, a free flash player implementation
 
-    Copyright (C) 2011-2013  Alessandro Pignotti (a.pignotti at sssup.it)
-
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU Lesser General Public License as published by
     the Free Software Foundation, either version 3 of the License, or
@@ -17,25 +15,30 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 **************************************************************************/
 
-#ifndef BACKENDS_RTMPUTILS_H
-#define BACKENDS_RTMPUTILS_H 1
+#ifndef FLASH_CONCURRENT_MUTEX_H
+#define FLASH_CONCURRENT_MUTEX_H
 
-#include "backends/netutils.h"
+#include "asobject.h"
+#include "scripting/flash/events/flashevents.h"
 
 namespace lightspark
 {
 
-class ILoadable;
-
-class RTMPDownloader: public ThreadedDownloader
+class ASMutex: public ASObject
 {
 private:
-	void execute();
-	void threadAbort();
-	tiny_string stream;
+	RecMutex mutex;
+	int lockcount;
+
 public:
-	RTMPDownloader(const tiny_string& _url, const tiny_string& _stream, ILoadable* o);
+	ASMutex(Class_base* c);
+	static void sinit(Class_base*);
+	ASFUNCTION(_constructor);
+	ASFUNCTION(_lock);
+	ASFUNCTION(_unlock);
+	ASFUNCTION(_trylock);
+	int getLockCount() { return lockcount; }
 };
 
-};
-#endif /* BACKENDS_RTMPUTILS_H */
+}
+#endif // FLASH_CONCURRENT_MUTEX_H
diff --git a/src/scripting/flash/desktop/flashdesktop.cpp b/src/scripting/flash/desktop/flashdesktop.cpp
index ebf14e4..4e031da 100644
--- a/src/scripting/flash/desktop/flashdesktop.cpp
+++ b/src/scripting/flash/desktop/flashdesktop.cpp
@@ -27,9 +27,7 @@ using namespace lightspark;
 
 void NativeApplication::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<ASObject>::getRef());
-
+	CLASS_SETUP(c, EventDispatcher, _constructor, CLASS_FINAL | CLASS_SEALED);
 	c->setDeclaredMethodByQName("nativeApplication", "", Class<IFunction>::getFunction(_getNativeApplication), GETTER_METHOD, false);
 	c->setDeclaredMethodByQName("addEventListener", "", Class<IFunction>::getFunction(addEventListener), NORMAL_METHOD, true);
 }
@@ -40,6 +38,7 @@ void NativeApplication::buildTraits(ASObject* o)
 
 ASFUNCTIONBODY(NativeApplication,_constructor)
 {
+	EventDispatcher::_constructor(obj, NULL, 0);
 	return NULL;
 }
 
diff --git a/src/scripting/flash/display/BitmapData.cpp b/src/scripting/flash/display/BitmapData.cpp
index 6adaed3..fa06fc2 100644
--- a/src/scripting/flash/display/BitmapData.cpp
+++ b/src/scripting/flash/display/BitmapData.cpp
@@ -24,6 +24,8 @@
 #include "scripting/flash/geom/flashgeom.h"
 #include "scripting/toplevel/Vector.h"
 #include "scripting/flash/errors/flasherrors.h"
+#include "scripting/flash/utils/ByteArray.h"
+#include "scripting/flash/filters/flashfilters.h"
 #include "backends/rendering_context.h"
 
 using namespace lightspark;
@@ -55,8 +57,7 @@ BitmapData::BitmapData(Class_base* c, uint32_t width, uint32_t height)
 
 void BitmapData::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<ASObject>::getRef());
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_SEALED);
 	c->addImplementedInterface(InterfaceClass<IBitmapDrawable>::getClass());
 	c->setDeclaredMethodByQName("draw","",Class<IFunction>::getFunction(draw),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("dispose","",Class<IFunction>::getFunction(dispose),NORMAL_METHOD,true);
@@ -80,6 +81,9 @@ void BitmapData::sinit(Class_base* c)
 	c->setDeclaredMethodByQName("getVector","",Class<IFunction>::getFunction(getVector),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("setPixels","",Class<IFunction>::getFunction(setPixels),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("setVector","",Class<IFunction>::getFunction(setVector),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("colorTransform","",Class<IFunction>::getFunction(colorTransform),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("compare","",Class<IFunction>::getFunction(compare),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("applyFilter","",Class<IFunction>::getFunction(applyFilter),NORMAL_METHOD,true);
 
 	// properties
 	c->setDeclaredMethodByQName("height","",Class<IFunction>::getFunction(_getHeight),GETTER_METHOD,true);
@@ -111,8 +115,8 @@ void BitmapData::notifyUsers() const
 
 ASFUNCTIONBODY(BitmapData,_constructor)
 {
-	uint32_t width;
-	uint32_t height;
+	int32_t width;
+	int32_t height;
 	bool transparent;
 	uint32_t fillColor;
 	BitmapData* th = obj->as<BitmapData>();
@@ -124,6 +128,10 @@ ASFUNCTIONBODY(BitmapData,_constructor)
 	//If the bitmap is already initialized, just return
 	if(width==0 || height==0 || !th->pixels->isEmpty())
 		return NULL;
+	if(width<0 || height<0)
+		throw Class<ArgumentError>::getInstanceS("invalid height or width", kInvalidArgumentError);
+	if(width>8191 || height>8191)
+		throw Class<ArgumentError>::getInstanceS("invalid height or width", kInvalidArgumentError);
 
 	uint32_t *pixelArray=new uint32_t[width*height];
 	uint32_t c=GUINT32_TO_BE(fillColor); // fromRGB expects big endian data
@@ -561,11 +569,11 @@ ASFUNCTIONBODY(BitmapData,histogram)
 		}
 	}
 
-	Vector *result = Class<Vector>::getInstanceS(Class<Vector>::getClass());
+	Vector *result = Template<Vector>::getInstanceS(Template<Vector>::getTemplateInstance(Class<Number>::getClass()).getPtr());
 	int channelOrder[4] = {2, 1, 0, 3}; // red, green, blue, alpha
 	for (int j=0; j<4; j++)
 	{
-		Vector *histogram = Class<Vector>::getInstanceS(Class<Number>::getClass());
+		Vector *histogram = Template<Vector>::getInstanceS(Class<Number>::getClass());
 		for (int level=0; level<256; level++)
 		{
 			histogram->append(abstract_d(counts[channelOrder[j]][level]));
@@ -654,7 +662,7 @@ ASFUNCTIONBODY(BitmapData,getVector)
 	if (rect.isNull())
 		throwError<TypeError>(kNullPointerError, "rect");
 
-	Vector *result = Class<Vector>::getInstanceS(Class<UInteger>::getClass());
+	Vector *result = Template<Vector>::getInstanceS(Class<UInteger>::getClass());
 	vector<uint32_t> pixelvec = th->pixels->getPixelVector(rect->getRect());
 	vector<uint32_t>::const_iterator it;
 	for (it=pixelvec.begin(); it!=pixelvec.end(); ++it)
@@ -728,3 +736,118 @@ ASFUNCTIONBODY(BitmapData,setVector)
 
 	return NULL;
 }
+
+ASFUNCTIONBODY(BitmapData,colorTransform)
+{
+	BitmapData* th = obj->as<BitmapData>();
+	
+	_NR<Rectangle> inputRect;
+	_NR<ColorTransform> inputColorTransform;
+	ARG_UNPACK (inputRect) (inputColorTransform);
+
+	if (inputRect.isNull())
+		throwError<TypeError>(kNullPointerError, "rect");
+	if (inputColorTransform.isNull())
+		throwError<TypeError>(kNullPointerError, "inputVector");
+
+	RECT rect;
+	th->pixels->clipRect(inputRect->getRect(), rect);
+	
+	vector<uint32_t> pixelvec = th->pixels->getPixelVector(rect);
+
+	unsigned int i = 0;
+	for (int32_t y=rect.Ymin; y<rect.Ymax; y++)
+	{
+		for (int32_t x=rect.Xmin; x<rect.Xmax; x++)
+		{
+
+			uint32_t pixel = pixelvec[i];
+
+			int a, r, g, b;
+			a = ((pixel >> 24 )&0xff) * inputColorTransform->alphaMultiplier + inputColorTransform->alphaOffset;
+			if (a > 255) a = 255;
+			if (a < 0) a = 0;
+			r = ((pixel >> 16 )&0xff) * inputColorTransform->redMultiplier + inputColorTransform->redOffset;
+			if (r > 255) r = 255;
+			if (r < 0) r = 0;
+			g = ((pixel >> 8 )&0xff) * inputColorTransform->greenMultiplier + inputColorTransform->greenOffset;
+			if (g > 255) g = 255;
+			if (g < 0) g = 0;
+			b = ((pixel )&0xff) * inputColorTransform->blueMultiplier + inputColorTransform->blueOffset;
+			if (b > 255) b = 255;
+			if (b < 0) b = 0;
+			
+			pixel = (a<<24) | (r<<16) | (g<<8) | b;
+			
+			th->pixels->setPixel(x, y, pixel, th->transparent);
+			i++;
+		}
+	}
+
+	return NULL;
+}
+ASFUNCTIONBODY(BitmapData,compare)
+{
+	BitmapData* th = obj->as<BitmapData>();
+	
+	_NR<BitmapData> otherBitmapData;
+	ARG_UNPACK (otherBitmapData);
+
+	if (otherBitmapData.isNull())
+		throwError<TypeError>(kNullPointerError, "otherBitmapData");
+
+	if (th->getWidth() != otherBitmapData->getWidth())
+		return abstract_d(-3);
+	if (th->getHeight() != otherBitmapData->getHeight())
+		return abstract_d(-4);
+	RECT rect;
+	rect.Xmin = 0;
+	rect.Xmax = th->getWidth();
+	rect.Ymin = 0;
+	rect.Ymax = th->getHeight();
+	
+	vector<uint32_t> pixelvec = th->pixels->getPixelVector(rect);
+	vector<uint32_t> otherpixelvec = otherBitmapData->pixels->getPixelVector(rect);
+	
+	BitmapData* res = Class<BitmapData>::getInstanceS(rect.Xmax,rect.Ymax);
+	unsigned int i = 0;
+	bool different = false;
+	for (int32_t y=rect.Ymin; y<rect.Ymax; y++)
+	{
+		for (int32_t x=rect.Xmin; x<rect.Xmax; x++)
+		{
+
+			uint32_t pixel = pixelvec[i];
+			uint32_t otherpixel = otherpixelvec[i];
+			if (pixel == otherpixel)
+				res->pixels->setPixel(x, y, 0, true);
+			else if ((pixel & 0x00FFFFFF) == (otherpixel & 0x00FFFFFF))
+			{
+				different = true;
+				res->pixels->setPixel(x, y, ((pixel & 0xFF000000) - (otherpixel & 0xFF000000)) | 0x00FFFFFF , true);
+			}
+			else 
+			{
+				different = true;
+				res->pixels->setPixel(x, y, ((pixel & 0x00FFFFFF) - (otherpixel & 0x00FFFFFF)), true);
+			}
+			i++;
+		}
+	}
+	if (!different)
+		return abstract_d(0);
+	return res;
+}
+
+ASFUNCTIONBODY(BitmapData,applyFilter)
+{
+	BitmapData* th = obj->as<BitmapData>();
+	
+	_NR<BitmapData> sourceBitmapData;
+	_NR<Rectangle> sourceRect;
+	_NR<Point> destPoint;
+	_NR<BitmapFilter> filter;
+	ARG_UNPACK (sourceBitmapData)(sourceRect)(destPoint)(filter);
+	LOG(LOG_NOT_IMPLEMENTED,"BitmapData.applyFilter not implemented");
+	return NULL;
+}
diff --git a/src/scripting/flash/display/BitmapData.h b/src/scripting/flash/display/BitmapData.h
index 89ffd03..9291752 100644
--- a/src/scripting/flash/display/BitmapData.h
+++ b/src/scripting/flash/display/BitmapData.h
@@ -81,6 +81,9 @@ public:
 	ASFUNCTION(getVector);
 	ASFUNCTION(setPixels);
 	ASFUNCTION(setVector);
+	ASFUNCTION(colorTransform);
+	ASFUNCTION(compare);
+	ASFUNCTION(applyFilter);
 };
 
 };
diff --git a/src/scripting/flash/display/DisplayObject.cpp b/src/scripting/flash/display/DisplayObject.cpp
index a4937f1..0e964c0 100644
--- a/src/scripting/flash/display/DisplayObject.cpp
+++ b/src/scripting/flash/display/DisplayObject.cpp
@@ -118,8 +118,7 @@ void DisplayObject::finalize()
 
 void DisplayObject::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<EventDispatcher>::getRef());
+	CLASS_SETUP(c, EventDispatcher, _constructorNotInstantiatable, CLASS_SEALED);
 	c->setDeclaredMethodByQName("loaderInfo","",Class<IFunction>::getFunction(_getLoaderInfo),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("width","",Class<IFunction>::getFunction(_getWidth),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("width","",Class<IFunction>::getFunction(_setWidth),SETTER_METHOD,true);
@@ -142,7 +141,7 @@ void DisplayObject::sinit(Class_base* c)
 	c->setDeclaredMethodByQName("parent","",Class<IFunction>::getFunction(_getParent),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("root","",Class<IFunction>::getFunction(_getRoot),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("blendMode","",Class<IFunction>::getFunction(_getBlendMode),GETTER_METHOD,true);
-	c->setDeclaredMethodByQName("blendMode","",Class<IFunction>::getFunction(undefinedFunction),SETTER_METHOD,true);
+	c->setDeclaredMethodByQName("blendMode","",Class<IFunction>::getFunction(_setBlendMode),SETTER_METHOD,true);
 	c->setDeclaredMethodByQName("scale9Grid","",Class<IFunction>::getFunction(_getScale9Grid),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("scale9Grid","",Class<IFunction>::getFunction(undefinedFunction),SETTER_METHOD,true);
 	c->setDeclaredMethodByQName("stage","",Class<IFunction>::getFunction(_getStage),GETTER_METHOD,true);
@@ -306,7 +305,7 @@ void DisplayObject::extractValuesFromMatrix()
 
 bool DisplayObject::skipRender() const
 {
-	return visible==false || clippedAlpha()==0.0;
+	return visible==false || clippedAlpha()==0.0 || ClipDepth;
 }
 
 void DisplayObject::defaultRender(RenderContext& ctxt) const
@@ -634,14 +633,6 @@ ASFUNCTIONBODY(DisplayObject,_getBounds)
 	return ret;
 }
 
-ASFUNCTIONBODY(DisplayObject,_constructor)
-{
-	//DisplayObject* th=static_cast<DisplayObject*>(obj->implementation);
-	EventDispatcher::_constructor(obj,NULL,0);
-
-	return NULL;
-}
-
 ASFUNCTIONBODY(DisplayObject,_getLoaderInfo)
 {
 	DisplayObject* th=static_cast<DisplayObject*>(obj);
@@ -676,8 +667,36 @@ ASFUNCTIONBODY(DisplayObject,_getScale9Grid)
 
 ASFUNCTIONBODY(DisplayObject,_getBlendMode)
 {
-	//DisplayObject* th=static_cast<DisplayObject*>(obj);
-	return getSys()->getUndefinedRef();
+	DisplayObject* th=static_cast<DisplayObject*>(obj);
+	return Class<ASString>::getInstanceS(th->blendMode);
+}
+ASFUNCTIONBODY(DisplayObject,_setBlendMode)
+{
+	DisplayObject* th=static_cast<DisplayObject*>(obj);
+	tiny_string val;
+	ARG_UNPACK(val);
+
+	if (
+			val != "add" &&
+			val != "alpha" &&
+			val != "darken" &&
+			val != "difference" &&
+			val != "erase" &&
+			val != "hardlight" &&
+			val != "invert" &&
+			val != "invert" &&
+			val != "layer" &&
+			val != "lighten" &&
+			val != "multiply" &&
+			val != "normal" &&
+			val != "overlay" &&
+			val != "screen" &&
+			val != "subtract"
+			)
+			val = "normal";
+	LOG(LOG_NOT_IMPLEMENTED, "blendmode is set but is not respected during drawing:"<<val);
+	th->blendMode = val;
+	return NULL;
 }
 
 ASFUNCTIONBODY(DisplayObject,localToGlobal)
diff --git a/src/scripting/flash/display/DisplayObject.h b/src/scripting/flash/display/DisplayObject.h
index b5ae7f4..1bc2392 100644
--- a/src/scripting/flash/display/DisplayObject.h
+++ b/src/scripting/flash/display/DisplayObject.h
@@ -58,6 +58,7 @@ private:
 	number_t rotation;
 	number_t sx,sy;
 	float alpha;
+	tiny_string blendMode;
 public:
 	UI16_SWF Ratio;
 	UI16_SWF ClipDepth;
@@ -179,7 +180,6 @@ public:
 	number_t getNominalHeight();
 	static void sinit(Class_base* c);
 	static void buildTraits(ASObject* o);
-	ASFUNCTION(_constructor);
 	ASFUNCTION(_getVisible);
 	ASFUNCTION(_setVisible);
 	ASFUNCTION(_getStage);
@@ -207,6 +207,7 @@ public:
 	ASFUNCTION(_getParent);
 	ASFUNCTION(_getRoot);
 	ASFUNCTION(_getBlendMode);
+	ASFUNCTION(_setBlendMode);
 	ASFUNCTION(_getScale9Grid);
 	ASFUNCTION(_setRotation);
 	ASFUNCTION(_getMouseX);
@@ -218,5 +219,5 @@ public:
 	ASFUNCTION(hitTestObject);
 	ASFUNCTION(hitTestPoint);
 };
-};
+}
 #endif /* SCRIPTING_FLASH_DISPLAY_DISPLAYOBJECT_H */
diff --git a/src/scripting/flash/display/Graphics.cpp b/src/scripting/flash/display/Graphics.cpp
new file mode 100644
index 0000000..663c576
--- /dev/null
+++ b/src/scripting/flash/display/Graphics.cpp
@@ -0,0 +1,923 @@
+/**************************************************************************
+    Lightspark, a free flash player implementation
+
+    Copyright (C) 2009-2013  Alessandro Pignotti (a.pignotti at sssup.it)
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+**************************************************************************/
+
+#include "scripting/flash/display/Graphics.h"
+#include "scripting/flash/display/TokenContainer.h"
+#include "scripting/flash/display/BitmapData.h"
+#include "scripting/flash/display/flashdisplay.h"
+#include "scripting/flash/display/IGraphicsData.h"
+#include "scripting/toplevel/Array.h"
+#include "scripting/toplevel/Vector.h"
+#include "scripting/toplevel/Number.h"
+#include "scripting/toplevel/ASString.h"
+#include "scripting/flash/geom/flashgeom.h"
+#include "scripting/argconv.h"
+#include "swf.h"
+
+using namespace std;
+using namespace lightspark;
+
+void Graphics::sinit(Class_base* c)
+{
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_SEALED | CLASS_FINAL);
+	c->setDeclaredMethodByQName("clear","",Class<IFunction>::getFunction(clear),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("copyFrom","",Class<IFunction>::getFunction(copyFrom),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("drawRect","",Class<IFunction>::getFunction(drawRect),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("drawRoundRect","",Class<IFunction>::getFunction(drawRoundRect),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("drawCircle","",Class<IFunction>::getFunction(drawCircle),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("drawEllipse","",Class<IFunction>::getFunction(drawEllipse),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("drawPath","",Class<IFunction>::getFunction(drawPath),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("drawTriangles","",Class<IFunction>::getFunction(drawTriangles),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("drawGraphicsData","",Class<IFunction>::getFunction(drawGraphicsData),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("moveTo","",Class<IFunction>::getFunction(moveTo),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("curveTo","",Class<IFunction>::getFunction(curveTo),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("cubicCurveTo","",Class<IFunction>::getFunction(cubicCurveTo),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("lineTo","",Class<IFunction>::getFunction(lineTo),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("lineBitmapStyle","",Class<IFunction>::getFunction(lineBitmapStyle),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("lineGradientStyle","",Class<IFunction>::getFunction(lineGradientStyle),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("lineStyle","",Class<IFunction>::getFunction(lineStyle),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("beginFill","",Class<IFunction>::getFunction(beginFill),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("beginGradientFill","",Class<IFunction>::getFunction(beginGradientFill),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("beginBitmapFill","",Class<IFunction>::getFunction(beginBitmapFill),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("endFill","",Class<IFunction>::getFunction(endFill),NORMAL_METHOD,true);
+}
+
+void Graphics::buildTraits(ASObject* o)
+{
+}
+
+//TODO: Add spinlock
+void Graphics::checkAndSetScaling()
+{
+	if(owner->scaling != 1.0f)
+	{
+		owner->scaling = 1.0f;
+		owner->tokens.clear();
+	}
+}
+
+ASFUNCTIONBODY(Graphics,_constructor)
+{
+	return NULL;
+}
+
+ASFUNCTIONBODY(Graphics,clear)
+{
+	Graphics* th=static_cast<Graphics*>(obj);
+	th->checkAndSetScaling();
+	th->owner->tokens.clear();
+	th->owner->owner->requestInvalidation(getSys());
+	return NULL;
+}
+
+ASFUNCTIONBODY(Graphics,moveTo)
+{
+	Graphics* th=static_cast<Graphics*>(obj);
+	th->checkAndSetScaling();
+	assert_and_throw(argslen==2);
+
+	int32_t x=args[0]->toInt();
+	int32_t y=args[1]->toInt();
+
+	th->owner->tokens.emplace_back(GeomToken(MOVE, Vector2(x, y)));
+	return NULL;
+}
+
+ASFUNCTIONBODY(Graphics,lineTo)
+{
+	Graphics* th=static_cast<Graphics*>(obj);
+	assert_and_throw(argslen==2);
+	th->checkAndSetScaling();
+
+	int x=args[0]->toInt();
+	int y=args[1]->toInt();
+
+	th->owner->tokens.emplace_back(GeomToken(STRAIGHT, Vector2(x, y)));
+	th->owner->owner->requestInvalidation(getSys());
+
+	return NULL;
+}
+
+ASFUNCTIONBODY(Graphics,curveTo)
+{
+	Graphics* th=static_cast<Graphics*>(obj);
+	assert_and_throw(argslen==4);
+	th->checkAndSetScaling();
+
+	int controlX=args[0]->toInt();
+	int controlY=args[1]->toInt();
+
+	int anchorX=args[2]->toInt();
+	int anchorY=args[3]->toInt();
+
+	th->owner->tokens.emplace_back(GeomToken(CURVE_QUADRATIC,
+	                        Vector2(controlX, controlY),
+	                        Vector2(anchorX, anchorY)));
+	th->owner->owner->requestInvalidation(getSys());
+
+	return NULL;
+}
+
+ASFUNCTIONBODY(Graphics,cubicCurveTo)
+{
+	Graphics* th=static_cast<Graphics*>(obj);
+	assert_and_throw(argslen==6);
+	th->checkAndSetScaling();
+
+	int control1X=args[0]->toInt();
+	int control1Y=args[1]->toInt();
+
+	int control2X=args[2]->toInt();
+	int control2Y=args[3]->toInt();
+
+	int anchorX=args[4]->toInt();
+	int anchorY=args[5]->toInt();
+
+	th->owner->tokens.emplace_back(GeomToken(CURVE_CUBIC,
+	                        Vector2(control1X, control1Y),
+	                        Vector2(control2X, control2Y),
+	                        Vector2(anchorX, anchorY)));
+	th->owner->owner->requestInvalidation(getSys());
+
+	return NULL;
+}
+
+/* KAPPA = 4 * (sqrt2 - 1) / 3
+ * This value was found in a Python prompt:
+ *
+ * >>> 4.0 * (2**0.5 - 1) / 3.0
+ *
+ * Source: http://whizkidtech.redprince.net/bezier/circle/
+ */
+const double KAPPA = 0.55228474983079356;
+
+ASFUNCTIONBODY(Graphics,drawRoundRect)
+{
+	Graphics* th=static_cast<Graphics*>(obj);
+	assert_and_throw(argslen==5 || argslen==6);
+	th->checkAndSetScaling();
+
+	double x=args[0]->toNumber();
+	double y=args[1]->toNumber();
+	double width=args[2]->toNumber();
+	double height=args[3]->toNumber();
+	double ellipseWidth=args[4]->toNumber();
+	double ellipseHeight;
+	if (argslen == 6)
+		ellipseHeight=args[5]->toNumber();
+
+	if (argslen == 5 || std::isnan(ellipseHeight))
+		ellipseHeight=ellipseWidth;
+
+	ellipseHeight /= 2;
+	ellipseWidth  /= 2;
+
+	double kappaW = KAPPA * ellipseWidth;
+	double kappaH = KAPPA * ellipseHeight;
+
+	/*
+	 *    A-----B
+	 *   /       \
+	 *  H         C
+	 *  |         |
+	 *  G         D
+	 *   \       /
+	 *    F-----E
+	 * 
+	 * Flash starts and stops the pen at 'D', so we will too.
+	 */
+
+	// D
+	th->owner->tokens.emplace_back(GeomToken(MOVE, Vector2(x+width, y+height-ellipseHeight)));
+
+	// D -> E
+	th->owner->tokens.emplace_back(GeomToken(CURVE_CUBIC,
+	                        Vector2(x+width, y+height-ellipseHeight+kappaH),
+	                        Vector2(x+width-ellipseWidth+kappaW, y+height),
+	                        Vector2(x+width-ellipseWidth, y+height)));
+
+	// E -> F
+	th->owner->tokens.emplace_back(GeomToken(STRAIGHT, Vector2(x+ellipseWidth, y+height)));
+
+	// F -> G
+	th->owner->tokens.emplace_back(GeomToken(CURVE_CUBIC,
+	                        Vector2(x+ellipseWidth-kappaW, y+height),
+	                        Vector2(x, y+height-kappaH),
+	                        Vector2(x, y+height-ellipseHeight)));
+
+	// G -> H
+	th->owner->tokens.emplace_back(GeomToken(STRAIGHT, Vector2(x, y+ellipseHeight)));
+
+	// H -> A
+	th->owner->tokens.emplace_back(GeomToken(CURVE_CUBIC,
+	                        Vector2(x, y+ellipseHeight-kappaH),
+	                        Vector2(x+ellipseWidth-kappaW, y),
+	                        Vector2(x+ellipseWidth, y)));
+
+	// A -> B
+	th->owner->tokens.emplace_back(GeomToken(STRAIGHT, Vector2(x+width-ellipseWidth, y)));
+
+	// B -> C
+	th->owner->tokens.emplace_back(GeomToken(CURVE_CUBIC,
+	                        Vector2(x+width-ellipseWidth+kappaW, y),
+	                        Vector2(x+width, y+kappaH),
+	                        Vector2(x+width, y+ellipseHeight)));
+
+	// C -> D
+	th->owner->tokens.emplace_back(GeomToken(STRAIGHT, Vector2(x+width, y+height-ellipseHeight)));
+
+	th->owner->owner->requestInvalidation(getSys());
+	
+	return NULL;
+}
+
+ASFUNCTIONBODY(Graphics,drawCircle)
+{
+	Graphics* th=static_cast<Graphics*>(obj);
+	assert_and_throw(argslen==3);
+	th->checkAndSetScaling();
+
+	double x=args[0]->toNumber();
+	double y=args[1]->toNumber();
+	double radius=args[2]->toNumber();
+
+	double kappa = KAPPA*radius;
+
+	// right
+	th->owner->tokens.emplace_back(GeomToken(MOVE, Vector2(x+radius, y)));
+
+	// bottom
+	th->owner->tokens.emplace_back(GeomToken(CURVE_CUBIC,
+	                        Vector2(x+radius, y+kappa ),
+	                        Vector2(x+kappa , y+radius),
+	                        Vector2(x       , y+radius)));
+
+	// left
+	th->owner->tokens.emplace_back(GeomToken(CURVE_CUBIC,
+	                        Vector2(x-kappa , y+radius),
+	                        Vector2(x-radius, y+kappa ),
+	                        Vector2(x-radius, y       )));
+
+	// top
+	th->owner->tokens.emplace_back(GeomToken(CURVE_CUBIC,
+	                        Vector2(x-radius, y-kappa ),
+	                        Vector2(x-kappa , y-radius),
+	                        Vector2(x       , y-radius)));
+
+	// back to right
+	th->owner->tokens.emplace_back(GeomToken(CURVE_CUBIC,
+	                        Vector2(x+kappa , y-radius),
+	                        Vector2(x+radius, y-kappa ),
+	                        Vector2(x+radius, y       )));
+
+	th->owner->owner->requestInvalidation(getSys());
+	
+	return NULL;
+}
+
+ASFUNCTIONBODY(Graphics,drawEllipse)
+{
+	Graphics* th=static_cast<Graphics*>(obj);
+	assert_and_throw(argslen==4);
+	th->checkAndSetScaling();
+
+	double left=args[0]->toNumber();
+	double top=args[1]->toNumber();
+	double width=args[2]->toNumber();
+	double height=args[3]->toNumber();
+
+	double xkappa = KAPPA*width/2;
+	double ykappa = KAPPA*height/2;
+
+	// right
+	th->owner->tokens.emplace_back(GeomToken(MOVE, Vector2(left+width, top+height/2)));
+	
+	// bottom
+	th->owner->tokens.emplace_back(GeomToken(CURVE_CUBIC,
+	                        Vector2(left+width , top+height/2+ykappa),
+	                        Vector2(left+width/2+xkappa, top+height),
+	                        Vector2(left+width/2, top+height)));
+
+	// left
+	th->owner->tokens.emplace_back(GeomToken(CURVE_CUBIC,
+	                        Vector2(left+width/2-xkappa, top+height),
+	                        Vector2(left, top+height/2+ykappa),
+	                        Vector2(left, top+height/2)));
+
+	// top
+	th->owner->tokens.emplace_back(GeomToken(CURVE_CUBIC,
+	                        Vector2(left, top+height/2-ykappa),
+	                        Vector2(left+width/2-xkappa, top),
+	                        Vector2(left+width/2, top)));
+
+	// back to right
+	th->owner->tokens.emplace_back(GeomToken(CURVE_CUBIC,
+	                        Vector2(left+width/2+xkappa, top),
+	                        Vector2(left+width, top+height/2-ykappa),
+	                        Vector2(left+width, top+height/2)));
+
+	th->owner->owner->requestInvalidation(getSys());
+
+	return NULL;
+}
+
+ASFUNCTIONBODY(Graphics,drawRect)
+{
+	Graphics* th=static_cast<Graphics*>(obj);
+	assert_and_throw(argslen==4);
+	th->checkAndSetScaling();
+
+	int x=args[0]->toInt();
+	int y=args[1]->toInt();
+	int width=args[2]->toInt();
+	int height=args[3]->toInt();
+
+	const Vector2 a(x,y);
+	const Vector2 b(x+width,y);
+	const Vector2 c(x+width,y+height);
+	const Vector2 d(x,y+height);
+
+	th->owner->tokens.emplace_back(GeomToken(MOVE, a));
+	th->owner->tokens.emplace_back(GeomToken(STRAIGHT, b));
+	th->owner->tokens.emplace_back(GeomToken(STRAIGHT, c));
+	th->owner->tokens.emplace_back(GeomToken(STRAIGHT, d));
+	th->owner->tokens.emplace_back(GeomToken(STRAIGHT, a));
+	th->owner->owner->requestInvalidation(getSys());
+	
+	return NULL;
+}
+
+ASFUNCTIONBODY(Graphics,drawPath)
+{
+	Graphics* th=static_cast<Graphics*>(obj);
+	th->checkAndSetScaling();
+
+	_NR<Vector> commands;
+	_NR<Vector> data;
+	tiny_string winding;
+	ARG_UNPACK (commands) (data) (winding, "evenOdd");
+
+	if (commands.isNull() || data.isNull())
+		throwError<ArgumentError>(kInvalidParamError);
+
+	pathToTokens(commands, data, winding, th->owner->tokens);
+
+	th->owner->owner->requestInvalidation(getSys());
+
+	return NULL;
+}
+
+void Graphics::pathToTokens(_NR<Vector> commands, _NR<Vector> data,
+			    tiny_string winding, std::vector<GeomToken>& tokens)
+{
+	if (commands.isNull() || data.isNull())
+		return;
+
+	if (winding != "evenOdd")
+		LOG(LOG_NOT_IMPLEMENTED, "Only event-odd winding implemented in Graphics.drawPath");
+
+	_R<Number> zeroRef = _MR(Class<Number>::getInstanceS(0));
+	Number *zero = zeroRef.getPtr();
+
+	int k = 0;
+	for (unsigned int i=0; i<commands->size(); i++)
+	{
+		switch (commands->at(i)->toInt())
+		{
+			case GraphicsPathCommand::MOVE_TO:
+			{
+				number_t x = data->at(k++, zero)->toNumber();
+				number_t y = data->at(k++, zero)->toNumber();
+				tokens.emplace_back(GeomToken(MOVE, Vector2(x, y)));
+				break;
+			}
+
+			case GraphicsPathCommand::LINE_TO:
+			{
+				number_t x = data->at(k++, zero)->toNumber();
+				number_t y = data->at(k++, zero)->toNumber();
+				tokens.emplace_back(GeomToken(STRAIGHT, Vector2(x, y)));
+				break;
+			}
+
+			case GraphicsPathCommand::CURVE_TO:
+			{
+				number_t cx = data->at(k++, zero)->toNumber();
+				number_t cy = data->at(k++, zero)->toNumber();
+				number_t x = data->at(k++, zero)->toNumber();
+				number_t y = data->at(k++, zero)->toNumber();
+				tokens.emplace_back(GeomToken(CURVE_QUADRATIC,
+							      Vector2(cx, cy),
+							      Vector2(x, y)));
+				break;
+			}
+
+			case GraphicsPathCommand::WIDE_MOVE_TO:
+			{
+				k+=2;
+				number_t x = data->at(k++, zero)->toNumber();
+				number_t y = data->at(k++, zero)->toNumber();
+				tokens.emplace_back(GeomToken(MOVE, Vector2(x, y)));
+				break;
+			}
+
+			case GraphicsPathCommand::WIDE_LINE_TO:
+			{
+				k+=2;
+				number_t x = data->at(k++, zero)->toNumber();
+				number_t y = data->at(k++, zero)->toNumber();
+				tokens.emplace_back(GeomToken(STRAIGHT, Vector2(x, y)));
+				break;
+			}
+
+			case GraphicsPathCommand::CUBIC_CURVE_TO:
+			{
+				number_t c1x = data->at(k++, zero)->toNumber();
+				number_t c1y = data->at(k++, zero)->toNumber();
+				number_t c2x = data->at(k++, zero)->toNumber();
+				number_t c2y = data->at(k++, zero)->toNumber();
+				number_t x = data->at(k++, zero)->toNumber();
+				number_t y = data->at(k++, zero)->toNumber();
+				tokens.emplace_back(GeomToken(CURVE_CUBIC,
+							      Vector2(c1x, c1y),
+							      Vector2(c2x, c2y),
+							      Vector2(x, y)));
+				break;
+			}
+
+			case GraphicsPathCommand::NO_OP:
+			default:
+				break;
+		}
+	}
+}
+
+/* Solve for c in the matrix equation
+ *
+ * [ 1 x1 y1 ] [ c[0] ]   [ u1 ]
+ * [ 1 x2 y2 ] [ c[1] ] = [ u2 ]
+ * [ 1 x3 y3 ] [ c[2] ]   [ u3 ]
+ *
+ * The result will be put in the output parameter c.
+ */
+void Graphics::solveVertexMapping(double x1, double y1,
+				  double x2, double y2,
+				  double x3, double y3,
+				  double u1, double u2, double u3,
+				  double c[3])
+{
+	double eps = 1e-15;
+	double det = fabs(x2*y3 + x1*y2 + y1*x3 - y2*x3 - x1*y3 - y1*x2);
+
+	if (det < eps)
+	{
+		// Degenerate matrix
+		c[0] = c[1] = c[2] = 0;
+		return;
+	}
+
+	// Symbolic solution of the equation by Gaussian elimination
+	if (fabs(x1-x2) < eps)
+	{
+		c[2] = (u2-u1)/(y2-y1);
+		c[1] = (u3 - u1 - (y3-y1)*c[2])/(x3-x1);
+		c[0] = u1 - x1*c[1] - y1*c[2];
+	}
+	else
+	{
+		c[2] = ((x2-x1)*(u3-u1) - (x3-x1)*(u2-u1))/((y3-y1)*(x2-x1) - (x3-x1)*(y2-y1));
+		c[1] = (u2 - u1 - (y2-y1)*c[2])/(x2-x1);
+		c[0] = u1 - x1*c[1] - y1*c[2];
+	}
+}
+
+ASFUNCTIONBODY(Graphics,drawTriangles)
+{
+	Graphics* th=static_cast<Graphics*>(obj);
+	th->checkAndSetScaling();
+
+	_NR<Vector> vertices;
+	_NR<Vector> indices;
+	_NR<Vector> uvtData;
+	tiny_string culling;
+	ARG_UNPACK (vertices) (indices, NullRef) (uvtData, NullRef) (culling, "none");
+
+	drawTrianglesToTokens(vertices, indices, uvtData, culling, th->owner->tokens);
+	th->owner->owner->requestInvalidation(getSys());
+
+	return NULL;
+}
+
+void Graphics::drawTrianglesToTokens(_NR<Vector> vertices, _NR<Vector> indices, _NR<Vector> uvtData, tiny_string culling, std::vector<GeomToken>& tokens)
+{
+	if (culling != "none")
+		LOG(LOG_NOT_IMPLEMENTED, "Graphics.drawTriangles doesn't support culling");
+
+	// Validate the parameters
+	if (vertices.isNull())
+		return;
+
+	if ((indices.isNull() && (vertices->size() % 6 != 0)) || 
+	    (!indices.isNull() && (indices->size() % 3 != 0)))
+	{
+		throwError<ArgumentError>(kInvalidParamError);
+	}
+
+	unsigned int numvertices=vertices->size()/2;
+	unsigned int numtriangles;
+	bool has_uvt=false;
+	int uvtElemSize=2;
+	int texturewidth=0;
+	int textureheight=0;
+
+	if (indices.isNull())
+		numtriangles=numvertices/3;
+	else
+		numtriangles=indices->size()/3;
+
+	if (!uvtData.isNull())
+	{
+		if (uvtData->size()==2*numvertices)
+		{
+			has_uvt=true;
+			uvtElemSize=2; /* (u, v) */
+		}
+		else if (uvtData->size()==3*numvertices)
+		{
+			has_uvt=true;
+			uvtElemSize=3; /* (u, v, t), t is ignored */
+			LOG(LOG_NOT_IMPLEMENTED, "Graphics.drawTriangles doesn't support t in uvtData parameter");
+		}
+		else
+		{
+			throwError<ArgumentError>(kInvalidParamError);
+		}
+
+		TokenContainer::getTextureSize(tokens, &texturewidth, &textureheight);
+	}
+
+	// According to testing, drawTriangles first fills the current
+	// path and creates a new path, but keeps the source.
+	tokens.emplace_back(FILL_KEEP_SOURCE);
+
+	if (has_uvt && (texturewidth==0 || textureheight==0))
+		return;
+
+	// Construct the triangles
+	for (unsigned int i=0; i<numtriangles; i++)
+	{
+		double x[3], y[3], u[3]={0}, v[3]={0};
+		for (unsigned int j=0; j<3; j++)
+		{
+			unsigned int vertex;
+			if (indices.isNull())
+				vertex=3*i+j;
+			else
+				vertex=indices->at(3*i+j)->toInt();
+
+			x[j]=vertices->at(2*vertex)->toNumber();
+			y[j]=vertices->at(2*vertex+1)->toNumber();
+
+			if (has_uvt)
+			{
+				u[j]=uvtData->at(vertex*uvtElemSize)->toNumber()*texturewidth;
+				v[j]=uvtData->at(vertex*uvtElemSize+1)->toNumber()*textureheight;
+			}
+		}
+		
+		Vector2 a(x[0], y[0]);
+		Vector2 b(x[1], y[1]);
+		Vector2 c(x[2], y[2]);
+
+		tokens.emplace_back(GeomToken(MOVE, a));
+		tokens.emplace_back(GeomToken(STRAIGHT, b));
+		tokens.emplace_back(GeomToken(STRAIGHT, c));
+		tokens.emplace_back(GeomToken(STRAIGHT, a));
+
+		if (has_uvt)
+		{
+			double t[6];
+
+			// Use the known (x, y) and (u, v)
+			// correspondences to compute a transformation
+			// t from (x, y) space into (u, v) space
+			// (cairo needs the mapping in this
+			// direction).
+			//
+			// u = t[0] + t[1]*x + t[2]*y
+			// v = t[3] + t[4]*x + t[5]*y
+			//
+			// u and v parts can be solved separately.
+			solveVertexMapping(x[0], y[0], x[1], y[1], x[2], y[2],
+					   u[0], u[1], u[2], t);
+			solveVertexMapping(x[0], y[0], x[1], y[1], x[2], y[2],
+					   v[0], v[1], v[2], &t[3]);
+
+			MATRIX m(t[1], t[5], t[4], t[2], t[0], t[3]);
+			tokens.emplace_back(GeomToken(FILL_TRANSFORM_TEXTURE, m));
+		}
+	}
+}
+
+ASFUNCTIONBODY(Graphics,drawGraphicsData)
+{
+	Graphics* th=static_cast<Graphics*>(obj);
+	th->checkAndSetScaling();
+
+	_NR<Vector> graphicsData;
+	ARG_UNPACK(graphicsData);
+
+	for (unsigned int i=0; i<graphicsData->size(); i++)
+	{
+		IGraphicsData *graphElement = dynamic_cast<IGraphicsData *>(graphicsData->at(i));
+		if (!graphElement)
+		{
+			LOG(LOG_ERROR, "Invalid type in Graphics::drawGraphicsData()");
+			continue;
+		}
+
+		graphElement->appendToTokens(th->owner->tokens);
+	}
+
+	th->owner->owner->requestInvalidation(getSys());
+
+	return NULL;
+}
+
+ASFUNCTIONBODY(Graphics,lineStyle)
+{
+	Graphics* th=static_cast<Graphics*>(obj);
+	th->checkAndSetScaling();
+
+	if (argslen == 0)
+	{
+		th->owner->tokens.emplace_back(CLEAR_STROKE);
+		return NULL;
+	}
+	uint32_t color = 0;
+	uint8_t alpha = 255;
+	UI16_SWF thickness = UI16_SWF(imax(args[0]->toNumber() * 20, 0));
+	if (argslen >= 2)
+		color = args[1]->toUInt();
+	if (argslen >= 3)
+		alpha = uint8_t(args[1]->toNumber() * 255);
+
+	// TODO: pixel hinting, scaling, caps, miter, joints
+	
+	LINESTYLE2 style(0xff);
+	style.Color = RGBA(color, alpha);
+	style.Width = thickness;
+	th->owner->tokens.emplace_back(GeomToken(SET_STROKE, style));
+	return NULL;
+}
+
+ASFUNCTIONBODY(Graphics,lineBitmapStyle)
+{
+	Graphics* th=static_cast<Graphics*>(obj);
+	th->checkAndSetScaling();
+
+	_NR<BitmapData> bitmap;
+	_NR<Matrix> matrix;
+	bool repeat, smooth;
+	ARG_UNPACK (bitmap) (matrix, NullRef) (repeat, true) (smooth, false);
+
+	if (bitmap.isNull())
+		return NULL;
+
+	LINESTYLE2 style(0xff);
+	style.Width = th->owner->getCurrentLineWidth();
+	style.HasFillFlag = true;
+	style.FillType = createBitmapFill(bitmap, matrix, repeat, smooth);
+	
+	th->owner->tokens.emplace_back(GeomToken(SET_STROKE, style));
+
+	return NULL;
+}
+
+ASFUNCTIONBODY(Graphics,lineGradientStyle)
+{
+	Graphics* th=static_cast<Graphics*>(obj);
+	th->checkAndSetScaling();
+
+	tiny_string type;
+	_NR<Array> colors;
+	_NR<Array> alphas;
+	_NR<Array> ratios;
+	_NR<Matrix> matrix;
+	tiny_string spreadMethod;
+	tiny_string interpolationMethod;
+	number_t focalPointRatio;
+	ARG_UNPACK (type) (colors) (alphas) (ratios) (matrix, NullRef)
+		(spreadMethod, "pad") (interpolationMethod, "rgb") (focalPointRatio, 0);
+
+	LINESTYLE2 style(0xff);
+	style.Width = th->owner->getCurrentLineWidth();
+	style.HasFillFlag = true;
+	style.FillType = createGradientFill(type, colors, alphas, ratios, matrix,
+					    spreadMethod, interpolationMethod,
+					    focalPointRatio);
+
+	th->owner->tokens.emplace_back(GeomToken(SET_STROKE, style));
+
+	return NULL;
+}
+
+ASFUNCTIONBODY(Graphics,beginGradientFill)
+{
+	Graphics* th=static_cast<Graphics*>(obj);
+	th->checkAndSetScaling();
+
+	tiny_string type;
+	_NR<Array> colors;
+	_NR<Array> alphas;
+	_NR<ASObject> ratiosParam;
+	_NR<Matrix> matrix;
+	tiny_string spreadMethod;
+	tiny_string interpolationMethod;
+	number_t focalPointRatio;
+	ARG_UNPACK (type) (colors) (alphas) (ratiosParam) (matrix, NullRef)
+		(spreadMethod, "pad") (interpolationMethod, "rgb") (focalPointRatio, 0);
+
+	//Work around for bug in YouTube player of July 13 2011
+	if (!ratiosParam->is<Array>())
+		return NULL;
+	if (ratiosParam.isNull())
+		return NULL;
+
+	ratiosParam->incRef();
+	_NR<Array> ratios = _MNR(ratiosParam->as<Array>());
+
+	FILLSTYLE style = createGradientFill(type, colors, alphas, ratios, matrix,
+					     spreadMethod, interpolationMethod,
+					     focalPointRatio);
+	th->owner->tokens.emplace_back(GeomToken(SET_FILL, style));
+
+	return NULL;
+}
+
+FILLSTYLE Graphics::createGradientFill(const tiny_string& type,
+				       _NR<Array> colors,
+				       _NR<Array> alphas,
+				       _NR<Array> ratios,
+				       _NR<Matrix> matrix,
+				       const tiny_string& spreadMethod,
+				       const tiny_string& interpolationMethod,
+				       number_t focalPointRatio)
+{
+	FILLSTYLE style(0xff);
+
+	if (colors.isNull() || alphas.isNull() || ratios.isNull())
+		return style;
+
+	int NumGradient = colors->size();
+	if (NumGradient != (int)alphas->size() || NumGradient != (int)ratios->size())
+		return style;
+
+	if (NumGradient < 1 || NumGradient > 15)
+		return style;
+
+	if(type == "linear")
+		style.FillStyleType=LINEAR_GRADIENT;
+	else if(type == "radial")
+		style.FillStyleType=RADIAL_GRADIENT;
+	else
+		return style;
+
+	// Don't support FOCALGRADIENT for now.
+	GRADIENT grad(0xff);
+	for(int i = 0; i < NumGradient; i ++)
+	{
+		GRADRECORD record(0xff);
+		record.Color = RGBA(colors->at(i)->toUInt(), (int)alphas->at(i)->toNumber()*255);
+		record.Ratio = UI8(ratios->at(i)->toUInt());
+		grad.GradientRecords.push_back(record);
+	}
+
+	if(matrix.isNull())
+	{
+		cairo_matrix_scale(&style.Matrix, 100.0/16384.0, 100.0/16384.0);
+	}
+	else
+	{
+		style.Matrix = matrix->getMATRIX();
+		//Conversion from twips to pixels
+		cairo_matrix_scale(&style.Matrix, 1.0f/20.0f, 1.0f/20.0f);
+	}
+
+	if (spreadMethod == "pad")
+		grad.SpreadMode = 0;
+	else if (spreadMethod == "reflect")
+		grad.SpreadMode = 1;
+	else if (spreadMethod == "repeat")
+		grad.SpreadMode = 2;
+	else
+		grad.SpreadMode = 0; // should not be reached
+
+	if (interpolationMethod == "rgb")
+		grad.InterpolationMode = 0;
+	else if (interpolationMethod == "linearRGB")
+		grad.InterpolationMode = 1;
+	else
+		grad.InterpolationMode = 0; // should not be reached
+
+	style.Gradient = grad;
+	return style;
+}
+
+FILLSTYLE Graphics::createBitmapFill(_R<BitmapData> bitmap, _NR<Matrix> matrix, bool repeat, bool smooth)
+{
+	FILLSTYLE style(0xff);
+	if(repeat && smooth)
+		style.FillStyleType = REPEATING_BITMAP;
+	else if(repeat && !smooth)
+		style.FillStyleType = NON_SMOOTHED_REPEATING_BITMAP;
+	else if(!repeat && smooth)
+		style.FillStyleType = CLIPPED_BITMAP;
+	else
+		style.FillStyleType = NON_SMOOTHED_CLIPPED_BITMAP;
+
+	if(!matrix.isNull())
+		style.Matrix = matrix->getMATRIX();
+
+	style.bitmap = bitmap->getBitmapContainer();
+
+	return style;
+}
+
+FILLSTYLE Graphics::createSolidFill(uint32_t color, uint8_t alpha)
+{
+	FILLSTYLE style(0xff);
+	style.FillStyleType = SOLID_FILL;
+	style.Color = RGBA(color, alpha);
+	return style;
+}
+
+ASFUNCTIONBODY(Graphics,beginBitmapFill)
+{
+	Graphics* th = obj->as<Graphics>();
+	_NR<BitmapData> bitmap;
+	_NR<Matrix> matrix;
+	bool repeat, smooth;
+	ARG_UNPACK (bitmap) (matrix, NullRef) (repeat, true) (smooth, false);
+
+	if(bitmap.isNull())
+		return NULL;
+
+	th->checkAndSetScaling();
+
+	FILLSTYLE style = createBitmapFill(bitmap, matrix, repeat, smooth);
+	th->owner->tokens.emplace_back(GeomToken(SET_FILL, style));
+	return NULL;
+}
+
+ASFUNCTIONBODY(Graphics,beginFill)
+{
+	Graphics* th=static_cast<Graphics*>(obj);
+	th->checkAndSetScaling();
+	uint32_t color=0;
+	uint8_t alpha=255;
+	if(argslen>=1)
+		color=args[0]->toUInt();
+	if(argslen>=2)
+		alpha=(uint8_t(args[1]->toNumber()*0xff));
+	FILLSTYLE style = Graphics::createSolidFill(color, alpha);
+	th->owner->tokens.emplace_back(GeomToken(SET_FILL, style));
+	return NULL;
+}
+
+ASFUNCTIONBODY(Graphics,endFill)
+{
+	Graphics* th=static_cast<Graphics*>(obj);
+	th->checkAndSetScaling();
+	th->owner->tokens.emplace_back(CLEAR_FILL);
+	return NULL;
+}
+
+ASFUNCTIONBODY(Graphics,copyFrom)
+{
+	Graphics* th=static_cast<Graphics*>(obj);
+	_NR<Graphics> source;
+	ARG_UNPACK(source);
+	if (source.isNull())
+		return NULL;
+
+	th->owner->tokens.assign(source->owner->tokens.begin(),
+				 source->owner->tokens.end());
+	return NULL;
+}
diff --git a/src/scripting/flash/display/Graphics.h b/src/scripting/flash/display/Graphics.h
new file mode 100644
index 0000000..50b430a
--- /dev/null
+++ b/src/scripting/flash/display/Graphics.h
@@ -0,0 +1,103 @@
+/**************************************************************************
+    Lightspark, a free flash player implementation
+
+    Copyright (C) 2009-2013  Alessandro Pignotti (a.pignotti at sssup.it)
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+**************************************************************************/
+
+#ifndef SCRIPTING_FLASH_DISPLAY_GRAPHICS_H
+#define SCRIPTING_FLASH_DISPLAY_GRAPHICS_H 1
+
+#include <vector>
+#include "asobject.h"
+#include "backends/geometry.h"
+
+namespace lightspark
+{
+
+class TokenContainer;
+class Array;
+class Matrix;
+class BitmapData;
+class Vector;
+
+/* This objects paints to its owners tokens */
+class Graphics: public ASObject
+{
+private:
+	TokenContainer *const owner;
+	void checkAndSetScaling();
+	static void solveVertexMapping(double x1, double y1,
+				       double x2, double y2,
+				       double x3, double y3,
+				       double u1, double u2, double u3,
+				       double c[3]);
+public:
+	Graphics(Class_base* c):ASObject(c),owner(NULL)
+	{
+//		throw RunTimeException("Cannot instantiate a Graphics object");
+	}
+	Graphics(Class_base* c, TokenContainer* _o)
+		: ASObject(c),owner(_o) {}
+	static void sinit(Class_base* c);
+	static void buildTraits(ASObject* o);
+	static FILLSTYLE createGradientFill(const tiny_string& type,
+					    _NR<Array> colors,
+					    _NR<Array> alphas,
+					    _NR<Array> ratios,
+					    _NR<Matrix> matrix,
+					    const tiny_string& spreadMethod,
+					    const tiny_string& interpolationMethod,
+					    number_t focalPointRatio);
+	static FILLSTYLE createBitmapFill(_R<BitmapData> bitmap,
+					  _NR<Matrix> matrix,
+					  bool repeat,
+					  bool smooth);
+	static FILLSTYLE createSolidFill(uint32_t color, uint8_t alpha);
+	static void pathToTokens(_NR<Vector> commands,
+				 _NR<Vector> data,
+				 tiny_string windings,
+				 std::vector<GeomToken>& tokens);
+	static void drawTrianglesToTokens(_NR<Vector> vertices,
+					  _NR<Vector> indices,
+					  _NR<Vector> uvtData,
+					  tiny_string culling,
+					  std::vector<GeomToken>& tokens);
+	ASFUNCTION(_constructor);
+	ASFUNCTION(lineBitmapStyle);
+	ASFUNCTION(lineGradientStyle);
+	ASFUNCTION(lineStyle);
+	ASFUNCTION(beginFill);
+	ASFUNCTION(beginGradientFill);
+	ASFUNCTION(beginBitmapFill);
+	ASFUNCTION(endFill);
+	ASFUNCTION(drawRect);
+	ASFUNCTION(drawRoundRect);
+	ASFUNCTION(drawCircle);
+	ASFUNCTION(drawEllipse);
+	ASFUNCTION(drawGraphicsData);
+	ASFUNCTION(drawPath);
+	ASFUNCTION(drawTriangles);
+	ASFUNCTION(moveTo);
+	ASFUNCTION(lineTo);
+	ASFUNCTION(curveTo);
+	ASFUNCTION(cubicCurveTo);
+	ASFUNCTION(clear);
+	ASFUNCTION(copyFrom);
+};
+
+};
+
+#endif /* SCRIPTING_FLASH_DISPLAY_GRAPHICS_H */
diff --git a/src/scripting/flash/display/GraphicsBitmapFill.cpp b/src/scripting/flash/display/GraphicsBitmapFill.cpp
new file mode 100644
index 0000000..1f59afa
--- /dev/null
+++ b/src/scripting/flash/display/GraphicsBitmapFill.cpp
@@ -0,0 +1,70 @@
+/**************************************************************************
+    Lightspark, a free flash player implementation
+
+    Copyright (C) 2013  Antti Ajanki (antti.ajanki at iki.fi)
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+**************************************************************************/
+
+#include "scripting/flash/display/GraphicsBitmapFill.h"
+#include "scripting/flash/display/BitmapData.h"
+#include "scripting/flash/display/Graphics.h"
+#include "scripting/flash/geom/flashgeom.h"
+#include "scripting/class.h"
+#include "scripting/argconv.h"
+
+using namespace lightspark;
+
+GraphicsBitmapFill::GraphicsBitmapFill(Class_base* c):
+	ASObject(c), repeat(true), smooth(false)
+{
+}
+
+void GraphicsBitmapFill::sinit(Class_base* c)
+{
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_SEALED | CLASS_FINAL);
+	REGISTER_GETTER_SETTER(c, bitmapData);
+	REGISTER_GETTER_SETTER(c, matrix);
+	REGISTER_GETTER_SETTER(c, repeat);
+	REGISTER_GETTER_SETTER(c, smooth);
+
+	c->addImplementedInterface(InterfaceClass<IGraphicsFill>::getClass());
+	IGraphicsFill::linkTraits(c);
+	c->addImplementedInterface(InterfaceClass<IGraphicsData>::getClass());
+	IGraphicsData::linkTraits(c);
+}
+
+ASFUNCTIONBODY(GraphicsBitmapFill, _constructor)
+{
+	GraphicsBitmapFill* th = obj->as<GraphicsBitmapFill>();
+	ASObject::_constructor(obj,NULL,0);
+	ARG_UNPACK (th->bitmapData, NullRef) (th->matrix, NullRef) (th->repeat, true) (th->smooth, false);
+	return NULL;
+}
+
+ASFUNCTIONBODY_GETTER_SETTER(GraphicsBitmapFill, bitmapData);
+ASFUNCTIONBODY_GETTER_SETTER(GraphicsBitmapFill, matrix);
+ASFUNCTIONBODY_GETTER_SETTER(GraphicsBitmapFill, repeat);
+ASFUNCTIONBODY_GETTER_SETTER(GraphicsBitmapFill, smooth);
+
+FILLSTYLE GraphicsBitmapFill::toFillStyle()
+{
+	return Graphics::createBitmapFill(bitmapData, matrix, repeat, smooth);
+}
+
+void GraphicsBitmapFill::appendToTokens(std::vector<GeomToken>& tokens)
+{
+
+	tokens.emplace_back(GeomToken(SET_FILL, toFillStyle()));
+}
diff --git a/src/scripting/toplevel/UInteger.h b/src/scripting/flash/display/GraphicsBitmapFill.h
similarity index 56%
copy from src/scripting/toplevel/UInteger.h
copy to src/scripting/flash/display/GraphicsBitmapFill.h
index fe0fbcc..effa7f2 100644
--- a/src/scripting/toplevel/UInteger.h
+++ b/src/scripting/flash/display/GraphicsBitmapFill.h
@@ -1,7 +1,7 @@
 /**************************************************************************
     Lightspark, a free flash player implementation
 
-    Copyright (C) 2009-2013  Alessandro Pignotti (a.pignotti at sssup.it)
+    Copyright (C) 2013  Antti Ajanki (antti.ajanki at iki.fi)
 
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU Lesser General Public License as published by
@@ -17,41 +17,33 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 **************************************************************************/
 
-#ifndef SCRIPTING_TOPLEVEL_UINTEGER_H
-#define SCRIPTING_TOPLEVEL_UINTEGER_H 1
-#include "compat.h"
+#ifndef SCRIPTING_FLASH_DISPLAY_GRAPHICSBITMAPFILL_H
+#define SCRIPTING_FLASH_DISPLAY_GRAPHICSBITMAPFILL_H 1
+
 #include "asobject.h"
+#include "scripting/flash/display/IGraphicsFill.h"
+#include "scripting/flash/display/IGraphicsData.h"
 
 namespace lightspark
 {
 
-class UInteger: public ASObject
+class BitmapData;
+class Matrix;
+
+class GraphicsBitmapFill: public ASObject, public IGraphicsFill, public IGraphicsData
 {
-friend ASObject* abstract_ui(uint32_t i);
 public:
-	uint32_t val;
-	UInteger(Class_base* c,uint32_t v=0):ASObject(c),val(v){type=T_UINTEGER;}
-
+	GraphicsBitmapFill(Class_base* c);
 	static void sinit(Class_base* c);
-	tiny_string toString();
-	static tiny_string toString(uint32_t val);
-	int32_t toInt()
-	{
-		return val;
-	}
-	uint32_t toUInt()
-	{
-		return val;
-	}
-	TRISTATE isLess(ASObject* r);
-	bool isEqual(ASObject* o);
 	ASFUNCTION(_constructor);
-	ASFUNCTION(generator);
-	ASFUNCTION(_toString);
-	ASFUNCTION(_valueOf);
-	std::string toDebugString() { return toString()+"ui"; }
-	//CHECK: should this have a special serialization?
+	ASPROPERTY_GETTER_SETTER(_NR<BitmapData>, bitmapData);
+	ASPROPERTY_GETTER_SETTER(_NR<Matrix>, matrix);
+	ASPROPERTY_GETTER_SETTER(bool, repeat);
+	ASPROPERTY_GETTER_SETTER(bool, smooth);
+	FILLSTYLE toFillStyle();
+	void appendToTokens(std::vector<GeomToken>& tokens);
+};
+
 };
 
-}
-#endif /* SCRIPTING_TOPLEVEL_UINTEGER_H */
+#endif /* SCRIPTING_FLASH_DISPLAY_GRAPHICSBITMAPFILL_H */
diff --git a/src/scripting/flash/sensors/flashsensors.cpp b/src/scripting/flash/display/GraphicsEndFill.cpp
similarity index 58%
copy from src/scripting/flash/sensors/flashsensors.cpp
copy to src/scripting/flash/display/GraphicsEndFill.cpp
index bee463b..4c24347 100644
--- a/src/scripting/flash/sensors/flashsensors.cpp
+++ b/src/scripting/flash/display/GraphicsEndFill.cpp
@@ -1,7 +1,7 @@
 /**************************************************************************
     Lightspark, a free flash player implementation
 
-    Copyright (C) 2011-2013  Alessandro Pignotti (a.pignotti at sssup.it)
+    Copyright (C) 2013  Antti Ajanki (antti.ajanki at iki.fi)
 
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU Lesser General Public License as published by
@@ -17,31 +17,31 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 **************************************************************************/
 
-#include <map>
-#include "backends/security.h"
-#include "scripting/abc.h"
-#include "scripting/flash/sensors/flashsensors.h"
+#include "scripting/flash/display/GraphicsEndFill.h"
 #include "scripting/class.h"
-#include "scripting/flash/system/flashsystem.h"
-#include "compat.h"
-#include "backends/audio.h"
 
-using namespace std;
 using namespace lightspark;
 
-Accelerometer::Accelerometer(Class_base* c):ASObject(c) {}
+GraphicsEndFill::GraphicsEndFill(Class_base* c):
+	ASObject(c)
+{
+}
 
-void Accelerometer::sinit(Class_base* c)
+void GraphicsEndFill::sinit(Class_base* c)
 {
-	// properties
-	c->setDeclaredMethodByQName("isSupported", "", Class<IFunction>::getFunction(_isSupported),GETTER_METHOD,false);
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_SEALED | CLASS_FINAL);
+	c->addImplementedInterface(InterfaceClass<IGraphicsFill>::getClass());
+	IGraphicsFill::linkTraits(c);
+	c->addImplementedInterface(InterfaceClass<IGraphicsData>::getClass());
+	IGraphicsData::linkTraits(c);
 }
 
-void Accelerometer::buildTraits(ASObject *o)
+FILLSTYLE GraphicsEndFill::toFillStyle()
 {
+	return FILLSTYLE(0xff);
 }
 
-ASFUNCTIONBODY(Accelerometer,_isSupported)
+void GraphicsEndFill::appendToTokens(std::vector<GeomToken>& tokens)
 {
-	return abstract_b(false);
+	tokens.emplace_back(CLEAR_FILL);
 }
diff --git a/src/backends/rtmputils.h b/src/scripting/flash/display/GraphicsEndFill.h
similarity index 61%
copy from src/backends/rtmputils.h
copy to src/scripting/flash/display/GraphicsEndFill.h
index 7e9de51..b65bf54 100644
--- a/src/backends/rtmputils.h
+++ b/src/scripting/flash/display/GraphicsEndFill.h
@@ -1,7 +1,7 @@
 /**************************************************************************
     Lightspark, a free flash player implementation
 
-    Copyright (C) 2011-2013  Alessandro Pignotti (a.pignotti at sssup.it)
+    Copyright (C) 2013  Antti Ajanki (antti.ajanki at iki.fi)
 
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU Lesser General Public License as published by
@@ -17,25 +17,25 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 **************************************************************************/
 
-#ifndef BACKENDS_RTMPUTILS_H
-#define BACKENDS_RTMPUTILS_H 1
+#ifndef SCRIPTING_FLASH_DISPLAY_GRAPHICSENDFILL_H
+#define SCRIPTING_FLASH_DISPLAY_GRAPHICSENDFILL_H 1
 
-#include "backends/netutils.h"
+#include "asobject.h"
+#include "scripting/flash/display/IGraphicsFill.h"
+#include "scripting/flash/display/IGraphicsData.h"
 
 namespace lightspark
 {
 
-class ILoadable;
-
-class RTMPDownloader: public ThreadedDownloader
+class GraphicsEndFill: public ASObject, public IGraphicsFill, public IGraphicsData
 {
-private:
-	void execute();
-	void threadAbort();
-	tiny_string stream;
 public:
-	RTMPDownloader(const tiny_string& _url, const tiny_string& _stream, ILoadable* o);
+	GraphicsEndFill(Class_base* c);
+	static void sinit(Class_base* c);
+        FILLSTYLE toFillStyle();
+        void appendToTokens(std::vector<GeomToken>& tokens);
 };
 
 };
-#endif /* BACKENDS_RTMPUTILS_H */
+
+#endif /* SCRIPTING_FLASH_DISPLAY_GRAPHICSENDFILL_H */
diff --git a/src/scripting/flash/display/GraphicsGradientFill.cpp b/src/scripting/flash/display/GraphicsGradientFill.cpp
new file mode 100644
index 0000000..3133413
--- /dev/null
+++ b/src/scripting/flash/display/GraphicsGradientFill.cpp
@@ -0,0 +1,96 @@
+/**************************************************************************
+    Lightspark, a free flash player implementation
+
+    Copyright (C) 2013  Antti Ajanki (antti.ajanki at iki.fi)
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+**************************************************************************/
+
+#include "scripting/flash/display/GraphicsGradientFill.h"
+#include "scripting/flash/display/Graphics.h"
+#include "scripting/flash/geom/flashgeom.h"
+#include "scripting/toplevel/toplevel.h"
+#include "scripting/toplevel/Array.h"
+#include "scripting/class.h"
+#include "scripting/argconv.h"
+
+using namespace lightspark;
+
+GraphicsGradientFill::GraphicsGradientFill(Class_base* c):
+	ASObject(c), focalPointRatio(0), interpolationMethod("rgb"),
+	spreadMethod("pad"), type("linear")
+{
+}
+
+void GraphicsGradientFill::sinit(Class_base* c)
+{
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_SEALED | CLASS_FINAL);
+	REGISTER_GETTER_SETTER(c, alphas);
+	REGISTER_GETTER_SETTER(c, colors);
+	REGISTER_GETTER_SETTER(c, focalPointRatio);
+	REGISTER_GETTER_SETTER(c, interpolationMethod);
+	REGISTER_GETTER_SETTER(c, matrix);
+	REGISTER_GETTER_SETTER(c, ratios);
+	REGISTER_GETTER_SETTER(c, spreadMethod);
+	REGISTER_GETTER_SETTER(c, type);
+
+	c->addImplementedInterface(InterfaceClass<IGraphicsFill>::getClass());
+	IGraphicsFill::linkTraits(c);
+	c->addImplementedInterface(InterfaceClass<IGraphicsData>::getClass());
+	IGraphicsData::linkTraits(c);
+}
+
+void GraphicsGradientFill::finalize()
+{
+	ASObject::finalize();
+	alphas.reset();
+	colors.reset();
+	matrix.reset();
+	ratios.reset();
+}
+
+ASFUNCTIONBODY(GraphicsGradientFill, _constructor)
+{
+	GraphicsGradientFill* th = obj->as<GraphicsGradientFill>();
+	ASObject::_constructor(obj,NULL,0);
+	ARG_UNPACK (th->type, "linear")
+		(th->colors, NullRef)
+		(th->alphas, NullRef)
+		(th->ratios, NullRef)
+		(th->matrix, NullRef)
+		(th->spreadMethod, "pad")
+		(th->interpolationMethod, "rgb")
+		(th->focalPointRatio, 0);
+	return NULL;
+}
+
+ASFUNCTIONBODY_GETTER_SETTER(GraphicsGradientFill, alphas);
+ASFUNCTIONBODY_GETTER_SETTER(GraphicsGradientFill, colors);
+ASFUNCTIONBODY_GETTER_SETTER(GraphicsGradientFill, focalPointRatio);
+ASFUNCTIONBODY_GETTER_SETTER(GraphicsGradientFill, interpolationMethod);
+ASFUNCTIONBODY_GETTER_SETTER(GraphicsGradientFill, matrix);
+ASFUNCTIONBODY_GETTER_SETTER(GraphicsGradientFill, ratios);
+ASFUNCTIONBODY_GETTER_SETTER(GraphicsGradientFill, spreadMethod);
+ASFUNCTIONBODY_GETTER_SETTER(GraphicsGradientFill, type);
+
+FILLSTYLE GraphicsGradientFill::toFillStyle()
+{
+	return Graphics::createGradientFill(type, colors, alphas, ratios,
+		matrix, spreadMethod, interpolationMethod, focalPointRatio);
+}
+
+void GraphicsGradientFill::appendToTokens(std::vector<GeomToken>& tokens)
+{
+	tokens.emplace_back(GeomToken(SET_FILL, toFillStyle()));
+}
diff --git a/src/scripting/flash/display/GraphicsGradientFill.h b/src/scripting/flash/display/GraphicsGradientFill.h
new file mode 100644
index 0000000..3cf422c
--- /dev/null
+++ b/src/scripting/flash/display/GraphicsGradientFill.h
@@ -0,0 +1,55 @@
+/**************************************************************************
+    Lightspark, a free flash player implementation
+
+    Copyright (C) 2013  Antti Ajanki (antti.ajanki at iki.fi)
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+**************************************************************************/
+
+#ifndef SCRIPTING_FLASH_DISPLAY_GRAPHICSGRADIENTFILL_H
+#define SCRIPTING_FLASH_DISPLAY_GRAPHICSGRADIENTFILL_H 1
+
+#include "asobject.h"
+#include "tiny_string.h"
+#include "scripting/flash/display/IGraphicsFill.h"
+#include "scripting/flash/display/IGraphicsData.h"
+
+namespace lightspark
+{
+
+class Array;
+class Matrix;
+
+class GraphicsGradientFill: public ASObject, public IGraphicsFill, public IGraphicsData
+{
+public:
+	GraphicsGradientFill(Class_base* c);
+	static void sinit(Class_base* c);
+	void finalize();
+	ASFUNCTION(_constructor);
+	ASPROPERTY_GETTER_SETTER(_NR<Array>, alphas);
+	ASPROPERTY_GETTER_SETTER(_NR<Array>, colors);
+	ASPROPERTY_GETTER_SETTER(number_t, focalPointRatio);
+	ASPROPERTY_GETTER_SETTER(tiny_string, interpolationMethod);
+	ASPROPERTY_GETTER_SETTER(_NR<Matrix>, matrix);
+	ASPROPERTY_GETTER_SETTER(_NR<Array>, ratios);
+	ASPROPERTY_GETTER_SETTER(tiny_string, spreadMethod);
+	ASPROPERTY_GETTER_SETTER(tiny_string, type);
+	FILLSTYLE toFillStyle();
+	void appendToTokens(std::vector<GeomToken>& tokens);
+};
+
+};
+
+#endif /* SCRIPTING_FLASH_DISPLAY_GRAPHICSGRADIENTFILL_H */
diff --git a/src/scripting/flash/display/GraphicsPath.cpp b/src/scripting/flash/display/GraphicsPath.cpp
new file mode 100644
index 0000000..a58482b
--- /dev/null
+++ b/src/scripting/flash/display/GraphicsPath.cpp
@@ -0,0 +1,173 @@
+/**************************************************************************
+    Lightspark, a free flash player implementation
+
+    Copyright (C) 2013  Antti Ajanki (antti.ajanki at iki.fi)
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+**************************************************************************/
+
+#include "scripting/toplevel/Vector.h"
+#include "scripting/flash/display/GraphicsPath.h"
+#include "scripting/flash/display/Graphics.h"
+#include "scripting/argconv.h"
+#include "scripting/class.h"
+
+using namespace lightspark;
+
+GraphicsPath::GraphicsPath(Class_base* c):
+	ASObject(c), winding("evenOdd")
+{
+}
+
+void GraphicsPath::sinit(Class_base* c)
+{
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_SEALED | CLASS_FINAL);
+	REGISTER_GETTER_SETTER(c, commands);
+	REGISTER_GETTER_SETTER(c, data);
+	REGISTER_GETTER_SETTER(c, winding);
+	c->setDeclaredMethodByQName("curveTo","",Class<IFunction>::getFunction(curveTo),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("lineTo","",Class<IFunction>::getFunction(lineTo),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("moveTo","",Class<IFunction>::getFunction(moveTo),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("wideLineTo","",Class<IFunction>::getFunction(wideLineTo),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("wideMoveTo","",Class<IFunction>::getFunction(wideMoveTo),NORMAL_METHOD,true);
+
+	c->addImplementedInterface(InterfaceClass<IGraphicsPath>::getClass());
+	IGraphicsPath::linkTraits(c);
+	c->addImplementedInterface(InterfaceClass<IGraphicsData>::getClass());
+	IGraphicsData::linkTraits(c);
+}
+
+ASFUNCTIONBODY_GETTER_SETTER(GraphicsPath, commands);
+ASFUNCTIONBODY_GETTER_SETTER(GraphicsPath, data);
+ASFUNCTIONBODY_GETTER_SETTER(GraphicsPath, winding);
+
+ASFUNCTIONBODY(GraphicsPath, _constructor)
+{
+	_NR<Vector> commands;
+	_NR<Vector> data;
+	GraphicsPath* th = obj->as<GraphicsPath>();
+	ARG_UNPACK(commands, NullRef)(data, NullRef)(th->winding, "evenOdd");
+
+	ASObject::_constructor(obj,NULL,0);
+
+	if (!commands.isNull())
+		th->commands = commands;
+	if (!data.isNull())
+		th->data = data;
+
+	return NULL;
+}
+
+void GraphicsPath::finalize()
+{
+	ASObject::finalize();
+	commands.reset();
+	data.reset();
+}
+
+void GraphicsPath::ensureValid()
+{
+	if (commands.isNull())
+		commands = _MNR(Template<Vector>::getInstanceS(Class<Integer>::getClass()));
+	if (data.isNull())
+		data = _MNR(Template<Vector>::getInstanceS(Class<Number>::getClass()));
+}
+
+ASFUNCTIONBODY(GraphicsPath, curveTo)
+{
+	GraphicsPath* th=obj->as<GraphicsPath>();
+	number_t cx;
+	number_t cy;
+	number_t ax;
+	number_t ay;
+	ARG_UNPACK (cx) (cy) (ax) (ay);
+
+	th->ensureValid();
+	th->commands->append(abstract_i(GraphicsPathCommand::CURVE_TO));
+	th->data->append(abstract_d(ax));
+	th->data->append(abstract_d(ay));
+	th->data->append(abstract_d(cx));
+	th->data->append(abstract_d(cy));
+
+	return NULL;
+}
+
+ASFUNCTIONBODY(GraphicsPath, lineTo)
+{
+	GraphicsPath* th=obj->as<GraphicsPath>();
+	number_t x;
+	number_t y;
+	ARG_UNPACK (x) (y);
+
+	th->ensureValid();
+	th->commands->append(abstract_i(GraphicsPathCommand::LINE_TO));
+	th->data->append(abstract_d(x));
+	th->data->append(abstract_d(y));
+
+	return NULL;
+}
+
+ASFUNCTIONBODY(GraphicsPath, moveTo)
+{
+	GraphicsPath* th=obj->as<GraphicsPath>();
+	number_t x;
+	number_t y;
+	ARG_UNPACK (x) (y);
+
+	th->ensureValid();
+	th->commands->append(abstract_i(GraphicsPathCommand::MOVE_TO));
+	th->data->append(abstract_d(x));
+	th->data->append(abstract_d(y));
+
+	return NULL;
+}
+
+ASFUNCTIONBODY(GraphicsPath, wideLineTo)
+{
+	GraphicsPath* th=obj->as<GraphicsPath>();
+	number_t x;
+	number_t y;
+	ARG_UNPACK (x) (y);
+
+	th->ensureValid();
+	th->commands->append(abstract_i(GraphicsPathCommand::LINE_TO));
+	th->data->append(abstract_d(0));
+	th->data->append(abstract_d(0));
+	th->data->append(abstract_d(x));
+	th->data->append(abstract_d(y));
+
+	return NULL;
+}
+
+ASFUNCTIONBODY(GraphicsPath, wideMoveTo)
+{
+	GraphicsPath* th=obj->as<GraphicsPath>();
+	number_t x;
+	number_t y;
+	ARG_UNPACK (x) (y);
+
+	th->ensureValid();
+	th->commands->append(abstract_i(GraphicsPathCommand::MOVE_TO));
+	th->data->append(abstract_d(0));
+	th->data->append(abstract_d(0));
+	th->data->append(abstract_d(x));
+	th->data->append(abstract_d(y));
+
+	return NULL;
+}
+
+void GraphicsPath::appendToTokens(std::vector<GeomToken>& tokens)
+{
+	Graphics::pathToTokens(commands, data, winding, tokens);
+}
diff --git a/src/scripting/toplevel/UInteger.h b/src/scripting/flash/display/GraphicsPath.h
similarity index 54%
copy from src/scripting/toplevel/UInteger.h
copy to src/scripting/flash/display/GraphicsPath.h
index fe0fbcc..74bf931 100644
--- a/src/scripting/toplevel/UInteger.h
+++ b/src/scripting/flash/display/GraphicsPath.h
@@ -1,7 +1,7 @@
 /**************************************************************************
     Lightspark, a free flash player implementation
 
-    Copyright (C) 2009-2013  Alessandro Pignotti (a.pignotti at sssup.it)
+    Copyright (C) 2013  Antti Ajanki (antti.ajanki at iki.fi)
 
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU Lesser General Public License as published by
@@ -17,41 +17,39 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 **************************************************************************/
 
-#ifndef SCRIPTING_TOPLEVEL_UINTEGER_H
-#define SCRIPTING_TOPLEVEL_UINTEGER_H 1
-#include "compat.h"
+#ifndef SCRIPTING_FLASH_DISPLAY_GRAPHICSPATH_H
+#define SCRIPTING_FLASH_DISPLAY_GRAPHICSPATH_H 1
+
 #include "asobject.h"
+#include "tiny_string.h"
+#include "scripting/flash/display/IGraphicsPath.h"
+#include "scripting/flash/display/IGraphicsData.h"
 
 namespace lightspark
 {
 
-class UInteger: public ASObject
+class Vector;
+
+class GraphicsPath: public ASObject, public IGraphicsPath, public IGraphicsData
 {
-friend ASObject* abstract_ui(uint32_t i);
+private:
+	void ensureValid();
 public:
-	uint32_t val;
-	UInteger(Class_base* c,uint32_t v=0):ASObject(c),val(v){type=T_UINTEGER;}
-
+	GraphicsPath(Class_base* c);
 	static void sinit(Class_base* c);
-	tiny_string toString();
-	static tiny_string toString(uint32_t val);
-	int32_t toInt()
-	{
-		return val;
-	}
-	uint32_t toUInt()
-	{
-		return val;
-	}
-	TRISTATE isLess(ASObject* r);
-	bool isEqual(ASObject* o);
+	void finalize();
 	ASFUNCTION(_constructor);
-	ASFUNCTION(generator);
-	ASFUNCTION(_toString);
-	ASFUNCTION(_valueOf);
-	std::string toDebugString() { return toString()+"ui"; }
-	//CHECK: should this have a special serialization?
+	ASPROPERTY_GETTER_SETTER(_NR<Vector>, commands);
+	ASPROPERTY_GETTER_SETTER(_NR<Vector>, data);
+	ASPROPERTY_GETTER_SETTER(tiny_string, winding);
+	ASFUNCTION(curveTo);
+	ASFUNCTION(lineTo);
+	ASFUNCTION(moveTo);
+	ASFUNCTION(wideLineTo);
+	ASFUNCTION(wideMoveTo);
+	void appendToTokens(std::vector<GeomToken>& tokens);
+};
+
 };
 
-}
-#endif /* SCRIPTING_TOPLEVEL_UINTEGER_H */
+#endif /* SCRIPTING_FLASH_DISPLAY_GRAPHICSPATH_H */
diff --git a/src/scripting/flash/display/GraphicsShaderFill.cpp b/src/scripting/flash/display/GraphicsShaderFill.cpp
new file mode 100644
index 0000000..4094e3d
--- /dev/null
+++ b/src/scripting/flash/display/GraphicsShaderFill.cpp
@@ -0,0 +1,73 @@
+/**************************************************************************
+    Lightspark, a free flash player implementation
+
+    Copyright (C) 2013  Antti Ajanki (antti.ajanki at iki.fi)
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+**************************************************************************/
+
+#include "scripting/flash/display/GraphicsShaderFill.h"
+#include "scripting/flash/display/flashdisplay.h"
+#include "scripting/flash/geom/flashgeom.h"
+#include "scripting/class.h"
+#include "scripting/argconv.h"
+
+using namespace lightspark;
+
+GraphicsShaderFill::GraphicsShaderFill(Class_base* c):
+	ASObject(c)
+{
+}
+
+void GraphicsShaderFill::sinit(Class_base* c)
+{
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_SEALED | CLASS_FINAL);
+	REGISTER_GETTER_SETTER(c, matrix);
+	REGISTER_GETTER_SETTER(c, shader);
+
+	c->addImplementedInterface(InterfaceClass<IGraphicsFill>::getClass());
+	IGraphicsFill::linkTraits(c);
+	c->addImplementedInterface(InterfaceClass<IGraphicsData>::getClass());
+	IGraphicsData::linkTraits(c);
+}
+
+void GraphicsShaderFill::finalize()
+{
+	ASObject::finalize();
+	matrix.reset();
+	shader.reset();
+}
+
+ASFUNCTIONBODY(GraphicsShaderFill, _constructor)
+{
+	GraphicsShaderFill* th = obj->as<GraphicsShaderFill>();
+	ASObject::_constructor(obj,NULL,0);
+	ARG_UNPACK (th->shader, NullRef) (th->matrix, NullRef);
+	return NULL;
+}
+
+ASFUNCTIONBODY_GETTER_SETTER(GraphicsShaderFill, matrix);
+ASFUNCTIONBODY_GETTER_SETTER(GraphicsShaderFill, shader);
+
+FILLSTYLE GraphicsShaderFill::toFillStyle()
+{
+	LOG(LOG_NOT_IMPLEMENTED, "GraphicsShaderFill::toFillStyle()");
+	return FILLSTYLE(0xff);
+}
+
+void GraphicsShaderFill::appendToTokens(std::vector<GeomToken>& tokens)
+{
+	LOG(LOG_NOT_IMPLEMENTED, "GraphicsShaderFill::appendToTokens()");
+	return;
+}
diff --git a/src/scripting/flash/accessibility/flashaccessibility.h b/src/scripting/flash/display/GraphicsShaderFill.h
similarity index 57%
copy from src/scripting/flash/accessibility/flashaccessibility.h
copy to src/scripting/flash/display/GraphicsShaderFill.h
index 19d00b8..28ed4a6 100644
--- a/src/scripting/flash/accessibility/flashaccessibility.h
+++ b/src/scripting/flash/display/GraphicsShaderFill.h
@@ -1,7 +1,7 @@
 /**************************************************************************
     Lightspark, a free flash player implementation
 
-    Copyright (C) 2009-2013  Alessandro Pignotti (a.pignotti at sssup.it)
+    Copyright (C) 2013  Antti Ajanki (antti.ajanki at iki.fi)
 
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU Lesser General Public License as published by
@@ -17,31 +17,32 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 **************************************************************************/
 
-#ifndef SCRIPTING_FLASH_ACCESSIBILITY_FLASHACCESSIBILITY_H
-#define SCRIPTING_FLASH_ACCESSIBILITY_FLASHACCESSIBILITY_H 1
+#ifndef SCRIPTING_FLASH_DISPLAY_GRAPHICSSHADERFILL_H
+#define SCRIPTING_FLASH_DISPLAY_GRAPHICSSHADERFILL_H 1
 
 #include "asobject.h"
+#include "scripting/flash/display/IGraphicsFill.h"
+#include "scripting/flash/display/IGraphicsData.h"
 
 namespace lightspark
 {
 
-class AccessibilityProperties : public ASObject
+class Matrix;
+class Shader;
+
+class GraphicsShaderFill: public ASObject, public IGraphicsFill, public IGraphicsData
 {
-private:
-	ASPROPERTY_GETTER_SETTER(tiny_string,name);
 public:
-	AccessibilityProperties(Class_base* c):ASObject(c){}
-	static void sinit(Class_base*);
+	GraphicsShaderFill(Class_base* c);
+	static void sinit(Class_base* c);
+	void finalize();
 	ASFUNCTION(_constructor);
+	ASPROPERTY_GETTER_SETTER(_NR<Matrix>, matrix);
+	ASPROPERTY_GETTER_SETTER(_NR<Shader>, shader);
+	FILLSTYLE toFillStyle();
+	void appendToTokens(std::vector<GeomToken>& tokens);
 };
 
-class AccessibilityImplementation : public ASObject
-{
-public:
-	AccessibilityImplementation(Class_base* c):ASObject(c){}
-	static void sinit(Class_base*);
-	ASFUNCTION(_constructor);
 };
 
-}
-#endif /* SCRIPTING_FLASH_ACCESSIBILITY_FLASHACCESSIBILITY_H */
+#endif /* SCRIPTING_FLASH_DISPLAY_GRAPHICSSHADERFILL_H */
diff --git a/src/scripting/flash/display/GraphicsSolidFill.cpp b/src/scripting/flash/display/GraphicsSolidFill.cpp
new file mode 100644
index 0000000..1dcbbc0
--- /dev/null
+++ b/src/scripting/flash/display/GraphicsSolidFill.cpp
@@ -0,0 +1,63 @@
+/**************************************************************************
+    Lightspark, a free flash player implementation
+
+    Copyright (C) 2013  Antti Ajanki (antti.ajanki at iki.fi)
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+**************************************************************************/
+
+#include "scripting/flash/display/GraphicsSolidFill.h"
+#include "scripting/flash/display/Graphics.h"
+#include "scripting/class.h"
+#include "scripting/argconv.h"
+
+using namespace lightspark;
+
+GraphicsSolidFill::GraphicsSolidFill(Class_base* c):
+	ASObject(c), alpha(1.0), color(0)
+{
+}
+
+void GraphicsSolidFill::sinit(Class_base* c)
+{
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_SEALED | CLASS_FINAL);
+	REGISTER_GETTER_SETTER(c, alpha);
+	REGISTER_GETTER_SETTER(c, color);
+
+	c->addImplementedInterface(InterfaceClass<IGraphicsFill>::getClass());
+	IGraphicsFill::linkTraits(c);
+	c->addImplementedInterface(InterfaceClass<IGraphicsData>::getClass());
+	IGraphicsData::linkTraits(c);
+}
+
+ASFUNCTIONBODY(GraphicsSolidFill, _constructor)
+{
+	GraphicsSolidFill* th = obj->as<GraphicsSolidFill>();
+	ASObject::_constructor(obj,NULL,0);
+	ARG_UNPACK (th->color, 0) (th->alpha, 1.0);
+	return NULL;
+}
+
+ASFUNCTIONBODY_GETTER_SETTER(GraphicsSolidFill, alpha);
+ASFUNCTIONBODY_GETTER_SETTER(GraphicsSolidFill, color);
+
+FILLSTYLE GraphicsSolidFill::toFillStyle()
+{
+	return Graphics::createSolidFill(color, static_cast<uint8_t>(255*alpha));
+}
+
+void GraphicsSolidFill::appendToTokens(std::vector<GeomToken>& tokens)
+{
+	tokens.emplace_back(GeomToken(SET_FILL, toFillStyle()));
+}
diff --git a/src/scripting/flash/accessibility/flashaccessibility.h b/src/scripting/flash/display/GraphicsSolidFill.h
similarity index 60%
copy from src/scripting/flash/accessibility/flashaccessibility.h
copy to src/scripting/flash/display/GraphicsSolidFill.h
index 19d00b8..a283dec 100644
--- a/src/scripting/flash/accessibility/flashaccessibility.h
+++ b/src/scripting/flash/display/GraphicsSolidFill.h
@@ -1,7 +1,7 @@
 /**************************************************************************
     Lightspark, a free flash player implementation
 
-    Copyright (C) 2009-2013  Alessandro Pignotti (a.pignotti at sssup.it)
+    Copyright (C) 2013  Antti Ajanki (antti.ajanki at iki.fi)
 
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU Lesser General Public License as published by
@@ -17,31 +17,28 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 **************************************************************************/
 
-#ifndef SCRIPTING_FLASH_ACCESSIBILITY_FLASHACCESSIBILITY_H
-#define SCRIPTING_FLASH_ACCESSIBILITY_FLASHACCESSIBILITY_H 1
+#ifndef SCRIPTING_FLASH_DISPLAY_GRAPHICSSOLIDFILL_H
+#define SCRIPTING_FLASH_DISPLAY_GRAPHICSSOLIDFILL_H 1
 
 #include "asobject.h"
+#include "scripting/flash/display/IGraphicsFill.h"
+#include "scripting/flash/display/IGraphicsData.h"
 
 namespace lightspark
 {
 
-class AccessibilityProperties : public ASObject
+class GraphicsSolidFill: public ASObject, public IGraphicsFill, public IGraphicsData
 {
-private:
-	ASPROPERTY_GETTER_SETTER(tiny_string,name);
 public:
-	AccessibilityProperties(Class_base* c):ASObject(c){}
-	static void sinit(Class_base*);
+	GraphicsSolidFill(Class_base* c);
+	static void sinit(Class_base* c);
 	ASFUNCTION(_constructor);
+	ASPROPERTY_GETTER_SETTER(number_t, alpha);
+	ASPROPERTY_GETTER_SETTER(uint32_t, color);
+	FILLSTYLE toFillStyle();
+	void appendToTokens(std::vector<GeomToken>& tokens);
 };
 
-class AccessibilityImplementation : public ASObject
-{
-public:
-	AccessibilityImplementation(Class_base* c):ASObject(c){}
-	static void sinit(Class_base*);
-	ASFUNCTION(_constructor);
 };
 
-}
-#endif /* SCRIPTING_FLASH_ACCESSIBILITY_FLASHACCESSIBILITY_H */
+#endif /* SCRIPTING_FLASH_DISPLAY_GRAPHICSSOLIDFILL_H */
diff --git a/src/scripting/flash/display/GraphicsStroke.cpp b/src/scripting/flash/display/GraphicsStroke.cpp
new file mode 100644
index 0000000..8858830
--- /dev/null
+++ b/src/scripting/flash/display/GraphicsStroke.cpp
@@ -0,0 +1,109 @@
+/**************************************************************************
+    Lightspark, a free flash player implementation
+
+    Copyright (C) 2013  Antti Ajanki (antti.ajanki at iki.fi)
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+**************************************************************************/
+
+#include <limits>
+#include "scripting/flash/display/GraphicsStroke.h"
+#include "scripting/flash/display/IGraphicsFill.h"
+#include "scripting/class.h"
+#include "scripting/argconv.h"
+#include "swftypes.h"
+
+using namespace lightspark;
+
+GraphicsStroke::GraphicsStroke(Class_base* c):
+	ASObject(c), caps("none"), joints("round"), miterLimit(3.0),
+	pixelHinting(false), scaleMode("normal"),
+	thickness(std::numeric_limits<double>::quiet_NaN())
+{
+}
+
+void GraphicsStroke::sinit(Class_base* c)
+{
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_SEALED | CLASS_FINAL);
+	REGISTER_GETTER_SETTER(c, caps);
+	REGISTER_GETTER_SETTER(c, fill);
+	REGISTER_GETTER_SETTER(c, joints);
+	REGISTER_GETTER_SETTER(c, miterLimit);
+	REGISTER_GETTER_SETTER(c, pixelHinting);
+	REGISTER_GETTER_SETTER(c, scaleMode);
+	REGISTER_GETTER_SETTER(c, thickness);
+
+	c->addImplementedInterface(InterfaceClass<IGraphicsStroke>::getClass());
+	IGraphicsStroke::linkTraits(c);
+	c->addImplementedInterface(InterfaceClass<IGraphicsData>::getClass());
+	IGraphicsData::linkTraits(c);
+}
+
+void GraphicsStroke::finalize()
+{
+	ASObject::finalize();
+	fill.reset();
+}
+
+ASFUNCTIONBODY(GraphicsStroke, _constructor)
+{
+	GraphicsStroke* th = obj->as<GraphicsStroke>();
+	_NR<ASObject> fill;
+	ASObject::_constructor(obj,NULL,0);
+	ARG_UNPACK (th->thickness, std::numeric_limits<double>::quiet_NaN())
+		(th->pixelHinting, false)
+		(th->scaleMode, "normal")
+		(th->caps, "none")
+		(th->joints, "rounds")
+		(th->miterLimit, 3.0)
+		(th->fill, NullRef);
+	th->validateFill(NullRef);
+	return NULL;
+}
+
+ASFUNCTIONBODY_GETTER_SETTER(GraphicsStroke, caps);
+ASFUNCTIONBODY_GETTER_SETTER_CB(GraphicsStroke, fill, validateFill);
+ASFUNCTIONBODY_GETTER_SETTER(GraphicsStroke, joints);
+ASFUNCTIONBODY_GETTER_SETTER(GraphicsStroke, miterLimit);
+ASFUNCTIONBODY_GETTER_SETTER(GraphicsStroke, pixelHinting);
+ASFUNCTIONBODY_GETTER_SETTER(GraphicsStroke, scaleMode);
+ASFUNCTIONBODY_GETTER_SETTER(GraphicsStroke, thickness);
+
+void GraphicsStroke::validateFill(_NR<ASObject> oldValue)
+{
+	if (!fill.isNull() && !fill->is<IGraphicsFill>())
+	{
+		tiny_string wrongClass = fill->getClassName();
+		fill = oldValue;
+		throwError<TypeError>(kCheckTypeFailedError, wrongClass, "IGraphicsFill");
+	}
+}
+
+void GraphicsStroke::appendToTokens(std::vector<GeomToken>& tokens)
+{
+	LINESTYLE2 style(0xff);
+	style.Width = thickness;
+
+	// TODO: pixel hinting, scaling, caps, miter, joints
+
+	if (!fill.isNull())
+	{
+		IGraphicsFill *gfill = dynamic_cast<IGraphicsFill*>(fill.getPtr());
+		assert(gfill);
+		style.HasFillFlag = true;
+		style.FillType = gfill->toFillStyle();
+	}
+
+	tokens.emplace_back(GeomToken(SET_STROKE, style));
+}
diff --git a/src/scripting/toplevel/UInteger.h b/src/scripting/flash/display/GraphicsStroke.h
similarity index 52%
copy from src/scripting/toplevel/UInteger.h
copy to src/scripting/flash/display/GraphicsStroke.h
index fe0fbcc..54eb6fc 100644
--- a/src/scripting/toplevel/UInteger.h
+++ b/src/scripting/flash/display/GraphicsStroke.h
@@ -1,7 +1,7 @@
 /**************************************************************************
     Lightspark, a free flash player implementation
 
-    Copyright (C) 2009-2013  Alessandro Pignotti (a.pignotti at sssup.it)
+    Copyright (C) 2013  Antti Ajanki (antti.ajanki at iki.fi)
 
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU Lesser General Public License as published by
@@ -17,41 +17,35 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 **************************************************************************/
 
-#ifndef SCRIPTING_TOPLEVEL_UINTEGER_H
-#define SCRIPTING_TOPLEVEL_UINTEGER_H 1
-#include "compat.h"
+#ifndef SCRIPTING_FLASH_DISPLAY_GRAPHICSSTROKE_H
+#define SCRIPTING_FLASH_DISPLAY_GRAPHICSSTROKE_H 1
+
 #include "asobject.h"
+#include "scripting/flash/display/IGraphicsStroke.h"
+#include "scripting/flash/display/IGraphicsData.h"
 
 namespace lightspark
 {
 
-class UInteger: public ASObject
+class GraphicsStroke: public ASObject, public IGraphicsStroke, public IGraphicsData
 {
-friend ASObject* abstract_ui(uint32_t i);
+protected:
+	void validateFill(_NR<ASObject> oldValue);
 public:
-	uint32_t val;
-	UInteger(Class_base* c,uint32_t v=0):ASObject(c),val(v){type=T_UINTEGER;}
-
+	GraphicsStroke(Class_base* c);
 	static void sinit(Class_base* c);
-	tiny_string toString();
-	static tiny_string toString(uint32_t val);
-	int32_t toInt()
-	{
-		return val;
-	}
-	uint32_t toUInt()
-	{
-		return val;
-	}
-	TRISTATE isLess(ASObject* r);
-	bool isEqual(ASObject* o);
+	void finalize();
 	ASFUNCTION(_constructor);
-	ASFUNCTION(generator);
-	ASFUNCTION(_toString);
-	ASFUNCTION(_valueOf);
-	std::string toDebugString() { return toString()+"ui"; }
-	//CHECK: should this have a special serialization?
+	ASPROPERTY_GETTER_SETTER(tiny_string, caps);
+	ASPROPERTY_GETTER_SETTER(_NR<ASObject>, fill); // really IGraphicsFill
+	ASPROPERTY_GETTER_SETTER(tiny_string, joints);
+	ASPROPERTY_GETTER_SETTER(number_t, miterLimit);
+	ASPROPERTY_GETTER_SETTER(bool, pixelHinting);
+	ASPROPERTY_GETTER_SETTER(tiny_string, scaleMode);
+	ASPROPERTY_GETTER_SETTER(number_t, thickness);
+	void appendToTokens(std::vector<GeomToken>& tokens);
+};
+
 };
 
-}
-#endif /* SCRIPTING_TOPLEVEL_UINTEGER_H */
+#endif /* SCRIPTING_FLASH_DISPLAY_GRAPHICSSTROKE_H */
diff --git a/src/scripting/flash/display/GraphicsTrianglePath.cpp b/src/scripting/flash/display/GraphicsTrianglePath.cpp
new file mode 100644
index 0000000..faa44cb
--- /dev/null
+++ b/src/scripting/flash/display/GraphicsTrianglePath.cpp
@@ -0,0 +1,74 @@
+/**************************************************************************
+    Lightspark, a free flash player implementation
+
+    Copyright (C) 2013  Antti Ajanki (antti.ajanki at iki.fi)
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+**************************************************************************/
+
+#include "scripting/flash/display/GraphicsTrianglePath.h"
+#include "scripting/flash/display/Graphics.h"
+#include "scripting/toplevel/Vector.h"
+#include "scripting/class.h"
+#include "scripting/argconv.h"
+
+using namespace lightspark;
+
+GraphicsTrianglePath::GraphicsTrianglePath(Class_base* c):
+	ASObject(c), culling("none")
+{
+}
+
+void GraphicsTrianglePath::sinit(Class_base* c)
+{
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_SEALED | CLASS_FINAL);
+	REGISTER_GETTER_SETTER(c, culling);
+	REGISTER_GETTER_SETTER(c, indices);
+	REGISTER_GETTER_SETTER(c, uvtData);
+	REGISTER_GETTER_SETTER(c, vertices);
+
+	c->addImplementedInterface(InterfaceClass<IGraphicsPath>::getClass());
+	IGraphicsPath::linkTraits(c);
+	c->addImplementedInterface(InterfaceClass<IGraphicsData>::getClass());
+	IGraphicsData::linkTraits(c);
+}
+
+void GraphicsTrianglePath::finalize()
+{
+	ASObject::finalize();
+	indices.reset();
+	uvtData.reset();
+	vertices.reset();
+}
+
+ASFUNCTIONBODY(GraphicsTrianglePath, _constructor)
+{
+	GraphicsTrianglePath* th = obj->as<GraphicsTrianglePath>();
+	ASObject::_constructor(obj,NULL,0);
+	ARG_UNPACK (th->vertices, NullRef)
+		(th->indices, NullRef)
+		(th->uvtData, NullRef)
+		(th->culling, "none");
+	return NULL;
+}
+
+ASFUNCTIONBODY_GETTER_SETTER(GraphicsTrianglePath, culling);
+ASFUNCTIONBODY_GETTER_SETTER(GraphicsTrianglePath, indices);
+ASFUNCTIONBODY_GETTER_SETTER(GraphicsTrianglePath, uvtData);
+ASFUNCTIONBODY_GETTER_SETTER(GraphicsTrianglePath, vertices);
+
+void GraphicsTrianglePath::appendToTokens(std::vector<GeomToken>& tokens)
+{
+	Graphics::drawTrianglesToTokens(vertices, indices, uvtData, culling, tokens);
+}
diff --git a/src/scripting/toplevel/UInteger.h b/src/scripting/flash/display/GraphicsTrianglePath.h
similarity index 56%
copy from src/scripting/toplevel/UInteger.h
copy to src/scripting/flash/display/GraphicsTrianglePath.h
index fe0fbcc..5e30e9e 100644
--- a/src/scripting/toplevel/UInteger.h
+++ b/src/scripting/flash/display/GraphicsTrianglePath.h
@@ -1,7 +1,7 @@
 /**************************************************************************
     Lightspark, a free flash player implementation
 
-    Copyright (C) 2009-2013  Alessandro Pignotti (a.pignotti at sssup.it)
+    Copyright (C) 2013  Antti Ajanki (antti.ajanki at iki.fi)
 
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU Lesser General Public License as published by
@@ -17,41 +17,32 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 **************************************************************************/
 
-#ifndef SCRIPTING_TOPLEVEL_UINTEGER_H
-#define SCRIPTING_TOPLEVEL_UINTEGER_H 1
-#include "compat.h"
+#ifndef SCRIPTING_FLASH_DISPLAY_GRAPHICSTRIANGLEPATH_H
+#define SCRIPTING_FLASH_DISPLAY_GRAPHICSTRIANGLEPATH_H 1
+
 #include "asobject.h"
+#include "scripting/flash/display/IGraphicsPath.h"
+#include "scripting/flash/display/IGraphicsData.h"
 
 namespace lightspark
 {
 
-class UInteger: public ASObject
+class Vector;
+
+class GraphicsTrianglePath: public ASObject, public IGraphicsPath, public IGraphicsData
 {
-friend ASObject* abstract_ui(uint32_t i);
 public:
-	uint32_t val;
-	UInteger(Class_base* c,uint32_t v=0):ASObject(c),val(v){type=T_UINTEGER;}
-
+	GraphicsTrianglePath(Class_base* c);
 	static void sinit(Class_base* c);
-	tiny_string toString();
-	static tiny_string toString(uint32_t val);
-	int32_t toInt()
-	{
-		return val;
-	}
-	uint32_t toUInt()
-	{
-		return val;
-	}
-	TRISTATE isLess(ASObject* r);
-	bool isEqual(ASObject* o);
+	void finalize();
 	ASFUNCTION(_constructor);
-	ASFUNCTION(generator);
-	ASFUNCTION(_toString);
-	ASFUNCTION(_valueOf);
-	std::string toDebugString() { return toString()+"ui"; }
-	//CHECK: should this have a special serialization?
+	ASPROPERTY_GETTER_SETTER(tiny_string, culling);
+	ASPROPERTY_GETTER_SETTER(_NR<Vector>, indices);
+	ASPROPERTY_GETTER_SETTER(_NR<Vector>, uvtData);
+	ASPROPERTY_GETTER_SETTER(_NR<Vector>, vertices);
+	void appendToTokens(std::vector<GeomToken>& tokens);
+};
+
 };
 
-}
-#endif /* SCRIPTING_TOPLEVEL_UINTEGER_H */
+#endif /* SCRIPTING_FLASH_DISPLAY_GRAPHICSTRIANGLEPATH_H */
diff --git a/src/backends/rtmputils.h b/src/scripting/flash/display/IGraphicsData.h
similarity index 64%
copy from src/backends/rtmputils.h
copy to src/scripting/flash/display/IGraphicsData.h
index 7e9de51..480527b 100644
--- a/src/backends/rtmputils.h
+++ b/src/scripting/flash/display/IGraphicsData.h
@@ -1,7 +1,7 @@
 /**************************************************************************
     Lightspark, a free flash player implementation
 
-    Copyright (C) 2011-2013  Alessandro Pignotti (a.pignotti at sssup.it)
+    Copyright (C) 2013  Antti Ajanki (antti.ajanki at iki.fi)
 
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU Lesser General Public License as published by
@@ -17,25 +17,26 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 **************************************************************************/
 
-#ifndef BACKENDS_RTMPUTILS_H
-#define BACKENDS_RTMPUTILS_H 1
+#ifndef SCRIPTING_FLASH_DISPLAY_IGRAPHICSDATA_H
+#define SCRIPTING_FLASH_DISPLAY_IGRAPHICSDATA_H 1
 
-#include "backends/netutils.h"
+#include <vector>
+#include "backends/geometry.h"
 
 namespace lightspark
 {
 
-class ILoadable;
+class Class_base;
 
-class RTMPDownloader: public ThreadedDownloader
+class IGraphicsData
 {
-private:
-	void execute();
-	void threadAbort();
-	tiny_string stream;
+protected:
+	virtual ~IGraphicsData() {}
 public:
-	RTMPDownloader(const tiny_string& _url, const tiny_string& _stream, ILoadable* o);
+	static void linkTraits(Class_base* c) {};
+	// Appends GeomTokens for drawing this object into tokens
+	virtual void appendToTokens(std::vector<GeomToken>& tokens) = 0;
 };
 
 };
-#endif /* BACKENDS_RTMPUTILS_H */
+#endif /* SCRIPTING_FLASH_DISPLAY_IGRAPHICSDATA_H */
diff --git a/src/backends/rtmputils.h b/src/scripting/flash/display/IGraphicsFill.h
similarity index 69%
copy from src/backends/rtmputils.h
copy to src/scripting/flash/display/IGraphicsFill.h
index 7e9de51..b3d4d18 100644
--- a/src/backends/rtmputils.h
+++ b/src/scripting/flash/display/IGraphicsFill.h
@@ -1,7 +1,7 @@
 /**************************************************************************
     Lightspark, a free flash player implementation
 
-    Copyright (C) 2011-2013  Alessandro Pignotti (a.pignotti at sssup.it)
+    Copyright (C) 2013  Antti Ajanki (antti.ajanki at iki.fi)
 
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU Lesser General Public License as published by
@@ -17,25 +17,24 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 **************************************************************************/
 
-#ifndef BACKENDS_RTMPUTILS_H
-#define BACKENDS_RTMPUTILS_H 1
+#ifndef SCRIPTING_FLASH_DISPLAY_IGRAPHICSFILL_H
+#define SCRIPTING_FLASH_DISPLAY_IGRAPHICSFILL_H 1
 
-#include "backends/netutils.h"
+#include "swftypes.h"
 
 namespace lightspark
 {
 
-class ILoadable;
+class Class_base;
 
-class RTMPDownloader: public ThreadedDownloader
+class IGraphicsFill
 {
-private:
-	void execute();
-	void threadAbort();
-	tiny_string stream;
+protected:
+	virtual ~IGraphicsFill() {}
 public:
-	RTMPDownloader(const tiny_string& _url, const tiny_string& _stream, ILoadable* o);
+	static void linkTraits(Class_base* c) {};
+	virtual FILLSTYLE toFillStyle() = 0;
 };
 
 };
-#endif /* BACKENDS_RTMPUTILS_H */
+#endif /* SCRIPTING_FLASH_DISPLAY_IGRAPHICSFILL_H */
diff --git a/src/backends/rtmputils.h b/src/scripting/flash/display/IGraphicsPath.h
similarity index 69%
copy from src/backends/rtmputils.h
copy to src/scripting/flash/display/IGraphicsPath.h
index 7e9de51..93da267 100644
--- a/src/backends/rtmputils.h
+++ b/src/scripting/flash/display/IGraphicsPath.h
@@ -1,7 +1,7 @@
 /**************************************************************************
     Lightspark, a free flash player implementation
 
-    Copyright (C) 2011-2013  Alessandro Pignotti (a.pignotti at sssup.it)
+    Copyright (C) 2013  Antti Ajanki (antti.ajanki at iki.fi)
 
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU Lesser General Public License as published by
@@ -17,25 +17,19 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 **************************************************************************/
 
-#ifndef BACKENDS_RTMPUTILS_H
-#define BACKENDS_RTMPUTILS_H 1
-
-#include "backends/netutils.h"
+#ifndef SCRIPTING_FLASH_DISPLAY_IGRAPHICSPATH_H
+#define SCRIPTING_FLASH_DISPLAY_IGRAPHICSPATH_H 1
 
 namespace lightspark
 {
 
-class ILoadable;
+class Class_base;
 
-class RTMPDownloader: public ThreadedDownloader
+class IGraphicsPath
 {
-private:
-	void execute();
-	void threadAbort();
-	tiny_string stream;
 public:
-	RTMPDownloader(const tiny_string& _url, const tiny_string& _stream, ILoadable* o);
+	static void linkTraits(Class_base* c) {};
 };
 
 };
-#endif /* BACKENDS_RTMPUTILS_H */
+#endif /* SCRIPTING_FLASH_DISPLAY_IGRAPHICSPATH_H */
diff --git a/src/backends/rtmputils.h b/src/scripting/flash/display/IGraphicsStroke.h
similarity index 69%
copy from src/backends/rtmputils.h
copy to src/scripting/flash/display/IGraphicsStroke.h
index 7e9de51..f11c2ba 100644
--- a/src/backends/rtmputils.h
+++ b/src/scripting/flash/display/IGraphicsStroke.h
@@ -1,7 +1,7 @@
 /**************************************************************************
     Lightspark, a free flash player implementation
 
-    Copyright (C) 2011-2013  Alessandro Pignotti (a.pignotti at sssup.it)
+    Copyright (C) 2013  Antti Ajanki (antti.ajanki at iki.fi)
 
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU Lesser General Public License as published by
@@ -17,25 +17,19 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 **************************************************************************/
 
-#ifndef BACKENDS_RTMPUTILS_H
-#define BACKENDS_RTMPUTILS_H 1
-
-#include "backends/netutils.h"
+#ifndef SCRIPTING_FLASH_DISPLAY_IGRAPHICSSTROKE_H
+#define SCRIPTING_FLASH_DISPLAY_IGRAPHICSSTROKE_H 1
 
 namespace lightspark
 {
 
-class ILoadable;
+class Class_base;
 
-class RTMPDownloader: public ThreadedDownloader
+class IGraphicsStroke
 {
-private:
-	void execute();
-	void threadAbort();
-	tiny_string stream;
 public:
-	RTMPDownloader(const tiny_string& _url, const tiny_string& _stream, ILoadable* o);
+	static void linkTraits(Class_base* c) {};
 };
 
 };
-#endif /* BACKENDS_RTMPUTILS_H */
+#endif /* SCRIPTING_FLASH_DISPLAY_IGRAPHICSSTROKE_H */
diff --git a/src/scripting/flash/display/TokenContainer.cpp b/src/scripting/flash/display/TokenContainer.cpp
index d1ad664..e20c286 100644
--- a/src/scripting/flash/display/TokenContainer.cpp
+++ b/src/scripting/flash/display/TokenContainer.cpp
@@ -230,17 +230,16 @@ bool TokenContainer::boundsRect(number_t& xmin, number_t& xmax, number_t& ymin,
 }
 
 /* Find the size of the active texture (bitmap set by the latest SET_FILL). */
-void TokenContainer::getTextureSize(int *width, int *height) const
+void TokenContainer::getTextureSize(std::vector<GeomToken>& tokens, int *width, int *height)
 {
 	*width=0;
 	*height=0;
 
-	unsigned int len=tokens.size();
-	for(unsigned int i=0;i<len;i++)
+	for(int i=tokens.size()-1;i>=0;i--)
 	{
-		const FILLSTYLE& style=tokens[len-i-1].fillStyle;
+		const FILLSTYLE& style=tokens[i].fillStyle;
 		const FILL_STYLE_TYPE& fstype=style.FillStyleType;
-		if(tokens[len-i-1].type==SET_FILL && 
+		if(tokens[i].type==SET_FILL && 
 		   (fstype==REPEATING_BITMAP ||
 		    fstype==NON_SMOOTHED_REPEATING_BITMAP ||
 		    fstype==CLIPPED_BITMAP ||
@@ -255,3 +254,17 @@ void TokenContainer::getTextureSize(int *width, int *height) const
 		}
 	}
 }
+
+/* Return the width of the latest SET_STROKE */
+uint16_t TokenContainer::getCurrentLineWidth() const
+{
+	for(int i=tokens.size()-1;i>=0;i--)
+	{
+		if(tokens[i].type==SET_STROKE)
+		{
+			return tokens[i].lineStyle.Width;
+		}
+	}
+
+	return 0;
+}
diff --git a/src/scripting/flash/display/TokenContainer.h b/src/scripting/flash/display/TokenContainer.h
index 5fdb7b8..fbfe13d 100644
--- a/src/scripting/flash/display/TokenContainer.h
+++ b/src/scripting/flash/display/TokenContainer.h
@@ -24,6 +24,7 @@
 #include "backends/geometry.h"
 #include "backends/graphics.h"
 #include "scripting/flash/display/DisplayObject.h"
+#include "scripting/flash/display/Graphics.h"
 
 namespace lightspark
 {
@@ -49,7 +50,8 @@ public:
 	static void FromShaperecordListToShapeVector(const std::vector<SHAPERECORD>& shapeRecords,
 					 tokensVector& tokens, const std::list<FILLSTYLE>& fillStyles,
 					 const MATRIX& matrix = MATRIX());
-	void getTextureSize(int *width, int *height) const;
+	static void getTextureSize(std::vector<GeomToken>& tokens, int *width, int *height);
+	uint16_t getCurrentLineWidth() const;
 	float scaling;
 protected:
 	TokenContainer(DisplayObject* _o);
diff --git a/src/scripting/flash/display/flashdisplay.cpp b/src/scripting/flash/display/flashdisplay.cpp
index 1fa9722..ac23bc4 100644
--- a/src/scripting/flash/display/flashdisplay.cpp
+++ b/src/scripting/flash/display/flashdisplay.cpp
@@ -22,6 +22,7 @@
 #include "backends/security.h"
 #include "scripting/abc.h"
 #include "scripting/flash/display/flashdisplay.h"
+#include "scripting/flash/display/Graphics.h"
 #include "swf.h"
 #include "scripting/flash/geom/flashgeom.h"
 #include "scripting/flash/system/flashsystem.h"
@@ -53,41 +54,45 @@ std::ostream& lightspark::operator<<(std::ostream& s, const DisplayObject& r)
 LoaderInfo::LoaderInfo(Class_base* c):EventDispatcher(c),applicationDomain(NullRef),securityDomain(NullRef),
 	contentType("application/x-shockwave-flash"),
 	bytesLoaded(0),bytesTotal(0),sharedEvents(NullRef),
-	loader(NullRef),loadStatus(STARTED),actionScriptVersion(3),childAllowsParent(true)
+	loader(NullRef),bytesData(NullRef),loadStatus(STARTED),actionScriptVersion(3),swfVersion(0),childAllowsParent(true),uncaughtErrorEvents(NullRef)
 {
 }
 
 LoaderInfo::LoaderInfo(Class_base* c, _R<Loader> l):EventDispatcher(c),applicationDomain(NullRef),securityDomain(NullRef),
 	contentType("application/x-shockwave-flash"),
 	bytesLoaded(0),bytesTotal(0),sharedEvents(NullRef),
-	loader(l),loadStatus(STARTED),actionScriptVersion(3),childAllowsParent(true)
+	loader(l),bytesData(NullRef),loadStatus(STARTED),actionScriptVersion(3),swfVersion(0),childAllowsParent(true),uncaughtErrorEvents(NullRef)
 {
 }
 
 void LoaderInfo::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<EventDispatcher>::getRef());
+	CLASS_SETUP(c, EventDispatcher, _constructor, CLASS_SEALED);
 	c->setDeclaredMethodByQName("loaderURL","",Class<IFunction>::getFunction(_getLoaderURL),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("loader","",Class<IFunction>::getFunction(_getLoader),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("content","",Class<IFunction>::getFunction(_getContent),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("url","",Class<IFunction>::getFunction(_getURL),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("bytesLoaded","",Class<IFunction>::getFunction(_getBytesLoaded),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("bytesTotal","",Class<IFunction>::getFunction(_getBytesTotal),GETTER_METHOD,true);
+	c->setDeclaredMethodByQName("bytes","",Class<IFunction>::getFunction(_getBytes),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("applicationDomain","",Class<IFunction>::getFunction(_getApplicationDomain),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("sharedEvents","",Class<IFunction>::getFunction(_getSharedEvents),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("width","",Class<IFunction>::getFunction(_getWidth),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("height","",Class<IFunction>::getFunction(_getHeight),GETTER_METHOD,true);
 	REGISTER_GETTER(c,parameters);
 	REGISTER_GETTER(c,actionScriptVersion);
+	REGISTER_GETTER(c,swfVersion);
 	REGISTER_GETTER(c,childAllowsParent);
 	REGISTER_GETTER(c,contentType);
+	REGISTER_GETTER(c,uncaughtErrorEvents);
 }
 
 ASFUNCTIONBODY_GETTER(LoaderInfo,parameters);
 ASFUNCTIONBODY_GETTER(LoaderInfo,actionScriptVersion);
 ASFUNCTIONBODY_GETTER(LoaderInfo,childAllowsParent);
 ASFUNCTIONBODY_GETTER(LoaderInfo,contentType);
+ASFUNCTIONBODY_GETTER(LoaderInfo,swfVersion);
+ASFUNCTIONBODY_GETTER(LoaderInfo,uncaughtErrorEvents);
 
 void LoaderInfo::buildTraits(ASObject* o)
 {
@@ -101,6 +106,7 @@ void LoaderInfo::finalize()
 	applicationDomain.reset();
 	securityDomain.reset();
 	waitedObject.reset();
+	bytesData.reset();
 }
 
 void LoaderInfo::resetState()
@@ -108,6 +114,8 @@ void LoaderInfo::resetState()
 	SpinlockLocker l(spinlock);
 	bytesLoaded=0;
 	bytesTotal=0;
+	if(!bytesData.isNull())
+		bytesData->setLength(0);
 	loadStatus=STARTED;
 }
 
@@ -187,6 +195,7 @@ ASFUNCTIONBODY(LoaderInfo,_constructor)
 	EventDispatcher::_constructor(obj,NULL,0);
 	th->sharedEvents=_MR(Class<EventDispatcher>::getInstanceS());
 	th->parameters = _MR(Class<ASObject>::getInstanceS());
+	th->uncaughtErrorEvents = _MR(Class<UncaughtErrorEvents>::getInstanceS());
 	return NULL;
 }
 
@@ -243,6 +252,17 @@ ASFUNCTIONBODY(LoaderInfo,_getBytesTotal)
 	return abstract_i(th->bytesTotal);
 }
 
+ASFUNCTIONBODY(LoaderInfo,_getBytes)
+{
+	LoaderInfo* th=static_cast<LoaderInfo*>(obj);
+	if (th->bytesData.isNull())
+		th->bytesData = _NR<ByteArray>(Class<ByteArray>::getInstanceS());
+	if (!th->loader->getContent().isNull())
+		th->bytesData->writeObject(th->loader->getContent().getPtr());
+
+	return th->bytesData.getPtr();
+}
+
 ASFUNCTIONBODY(LoaderInfo,_getApplicationDomain)
 {
 	LoaderInfo* th=static_cast<LoaderInfo*>(obj);
@@ -296,19 +316,27 @@ void LoaderThread::execute()
 	streambuf *sbuf = 0;
 	if(source==URL)
 	{
-		if(!createDownloader(false, loaderInfo, loaderInfo.getPtr(), false))
+		_R<MemoryStreamCache> cache(_MR(new MemoryStreamCache));
+		if(!createDownloader(cache, loaderInfo, loaderInfo.getPtr(), false))
 			return;
 
-		downloader->waitForData(); //Wait for some data, making sure our check for failure is working
-		if(downloader->hasFailed()) //Check to see if the download failed for some reason
+		sbuf = cache->createReader();
+		
+		// Wait for some data, making sure our check for failure is working
+		sbuf->sgetc(); // peek one byte
+		if(downloader->getRequestStatus() == 204) // empty answer
+			return;
+
+		if(cache->hasFailed()) //Check to see if the download failed for some reason
 		{
 			LOG(LOG_ERROR, "Loader::execute(): Download of URL failed: " << url);
 			getVm()->addEvent(loaderInfo,_MR(Class<IOErrorEvent>::getInstanceS()));
+			getVm()->addEvent(loader,_MR(Class<IOErrorEvent>::getInstanceS()));
+			delete sbuf;
 			// downloader will be deleted in jobFence
 			return;
 		}
 		getVm()->addEvent(loaderInfo,_MR(Class<Event>::getInstanceS("open")));
-		sbuf=downloader;
 	}
 	else if(source==BYTES)
 	{
@@ -324,19 +352,15 @@ void LoaderThread::execute()
 	ParseThread local_pt(s,loaderInfo->applicationDomain,loaderInfo->securityDomain,loader.getPtr(),url.getParsedURL());
 	local_pt.execute();
 
-	// Delete the bytes container (downloader or bytes_buf)
+	// Delete the bytes container (cache reader or bytes_buf)
+	delete sbuf;
+	sbuf = NULL;
 	if (source==URL) {
 		//Acquire the lock to ensure consistency in threadAbort
 		SpinlockLocker l(downloaderLock);
 		if(downloader)
 			getSys()->downloadManager->destroy(downloader);
 		downloader=NULL;
-		sbuf = NULL;
-	}
-	else if (source==BYTES)
-	{
-		delete sbuf;
-		sbuf = NULL;
 	}
 
 	bytes.reset();
@@ -356,6 +380,7 @@ ASFUNCTIONBODY(Loader,_constructor)
 	Loader* th=static_cast<Loader*>(obj);
 	DisplayObjectContainer::_constructor(obj,NULL,0);
 	th->contentLoaderInfo->setLoaderURL(getSys()->mainClip->getOrigin().getParsedURL());
+	th->uncaughtErrorEvents = _MR(Class<UncaughtErrorEvents>::getInstanceS());
 	return NULL;
 }
 
@@ -402,12 +427,21 @@ ASFUNCTIONBODY(Loader,load)
 	//Check if a security domain has been manually set
 	_NR<SecurityDomain> secDomain;
 	_NR<SecurityDomain> curSecDomain=ABCVm::getCurrentSecurityDomain(getVm()->currentCallContext);
-	if(!context.isNull() && !context->securityDomain.isNull())
+	if(!context.isNull())
 	{
-		//The passed domain must be the current one. See Loader::load specs.
-		if(context->securityDomain!=curSecDomain)
-			throw Class<SecurityError>::getInstanceS("SecurityError: securityDomain must be current one");
-		secDomain=curSecDomain;
+		if (!context->securityDomain.isNull())
+		{
+			//The passed domain must be the current one. See Loader::load specs.
+			if(context->securityDomain!=curSecDomain)
+				throw Class<SecurityError>::getInstanceS("SecurityError: securityDomain must be current one");
+			secDomain=curSecDomain;
+		}
+
+		bool sameDomain = (secDomain == curSecDomain);
+		th->allowCodeImport = !sameDomain || context->getAllowCodeImport();
+
+		if (!context->parameters.isNull())
+			th->contentLoaderInfo->setParameters(context->parameters);
 	}
 	//Default is to create a child ApplicationDomain if the file is in the same security context
 	//otherwise create a child of the system domain. If the security domain is different
@@ -443,6 +477,19 @@ ASFUNCTIONBODY(Loader,load)
 	SecurityManager::checkURLStaticAndThrow(th->url, ~(SecurityManager::LOCAL_WITH_FILE),
 		SecurityManager::LOCAL_WITH_FILE | SecurityManager::LOCAL_TRUSTED, true);
 
+	if (!context.isNull() && context->getCheckPolicyFile())
+	{
+		//TODO: this should be async as it could block if invoked from ExternalInterface
+		SecurityManager::EVALUATIONRESULT evaluationResult;
+		evaluationResult = getSys()->securityManager->evaluatePoliciesURL(th->url, true);
+		if(evaluationResult == SecurityManager::NA_CROSSDOMAIN_POLICY)
+		{
+			// should this dispatch SecurityErrorEvent instead of throwing?
+			throw Class<SecurityError>::getInstanceS(
+				"SecurityError: connection to domain not allowed by securityManager");
+		}
+	}
+
 	th->incRef();
 	r->incRef();
 	LoaderThread *thread=new LoaderThread(_MR(r), _MR(th));
@@ -473,6 +520,11 @@ ASFUNCTIONBODY(Loader,loadBytes)
 	_NR<SecurityDomain> curSecDomain=ABCVm::getCurrentSecurityDomain(getVm()->currentCallContext);
 	th->contentLoaderInfo->securityDomain = curSecDomain;
 
+	th->allowCodeImport = context.isNull() || context->getAllowCodeImport();
+
+	if (!context.isNull() && !context->parameters.isNull())
+		th->contentLoaderInfo->setParameters(context->parameters);
+
 	if(bytes->getLength()!=0)
 	{
 		th->incRef();
@@ -492,6 +544,22 @@ ASFUNCTIONBODY(Loader,_unload)
 	th->unload();
 	return NULL;
 }
+ASFUNCTIONBODY(Loader,_unloadAndStop)
+{
+	Loader* th=static_cast<Loader*>(obj);
+	th->unload();
+	LOG(LOG_NOT_IMPLEMENTED,"unloadAndStop does not execute any stopping actions");
+	/* TODO: (taken from specs)
+	Sounds are stopped.
+	Stage event listeners are removed.
+	Event listeners for enterFrame, frameConstructed, exitFrame, activate and deactivate are removed.
+	Timers are stopped.
+	Camera and Microphone instances are detached
+	Movie clips are stopped.
+	*/
+
+	return NULL;
+}
 
 void Loader::unload()
 {
@@ -526,7 +594,7 @@ void Loader::finalize()
 	contentLoaderInfo.reset();
 }
 
-Loader::Loader(Class_base* c):DisplayObjectContainer(c),content(NullRef),contentLoaderInfo(NullRef),loaded(false)
+Loader::Loader(Class_base* c):DisplayObjectContainer(c),content(NullRef),contentLoaderInfo(NullRef),loaded(false), allowCodeImport(true),uncaughtErrorEvents(NullRef)
 {
 	incRef();
 	contentLoaderInfo=_MR(Class<LoaderInfo>::getInstanceS(_MR(this)));
@@ -538,16 +606,19 @@ Loader::~Loader()
 
 void Loader::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<DisplayObjectContainer>::getRef());
+	CLASS_SETUP(c, DisplayObjectContainer, _constructor, CLASS_SEALED);
 	c->setDeclaredMethodByQName("contentLoaderInfo","",Class<IFunction>::getFunction(_getContentLoaderInfo),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("content","",Class<IFunction>::getFunction(_getContent),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("close","",Class<IFunction>::getFunction(close),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("loadBytes","",Class<IFunction>::getFunction(loadBytes),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("load","",Class<IFunction>::getFunction(load),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("unload","",Class<IFunction>::getFunction(_unload),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("unloadAndStop","",Class<IFunction>::getFunction(_unloadAndStop),NORMAL_METHOD,true);
+	REGISTER_GETTER(c,uncaughtErrorEvents);
 }
 
+ASFUNCTIONBODY_GETTER(Loader,uncaughtErrorEvents);
+
 void Loader::threadFinished(IThreadJob* finishedJob)
 {
 	SpinlockLocker l(spinlock);
@@ -590,8 +661,7 @@ void Sprite::finalize()
 
 void Sprite::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<DisplayObjectContainer>::getRef());
+	CLASS_SETUP(c, DisplayObjectContainer, _constructor, CLASS_SEALED);
 	c->setDeclaredMethodByQName("graphics","",Class<IFunction>::getFunction(_getGraphics),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("startDrag","",Class<IFunction>::getFunction(_startDrag),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("stopDrag","",Class<IFunction>::getFunction(_stopDrag),NORMAL_METHOD,true);
@@ -849,8 +919,7 @@ FrameLabel::FrameLabel(Class_base* c, const FrameLabel_data& data):ASObject(c),F
 
 void FrameLabel::sinit(Class_base* c)
 {
-	c->setConstructor(NULL);
-	c->setSuper(Class<ASObject>::getRef());
+	CLASS_SETUP_NO_CONSTRUCTOR(c, ASObject, CLASS_SEALED | CLASS_FINAL);
 	c->setDeclaredMethodByQName("frame","",Class<IFunction>::getFunction(_getFrame),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("name","",Class<IFunction>::getFunction(_getName),GETTER_METHOD,true);
 }
@@ -906,8 +975,7 @@ Scene::Scene(Class_base* c, const Scene_data& data, uint32_t _numFrames):ASObjec
 
 void Scene::sinit(Class_base* c)
 {
-	c->setConstructor(NULL);
-	c->setSuper(Class<ASObject>::getRef());
+	CLASS_SETUP_NO_CONSTRUCTOR(c, ASObject, CLASS_SEALED | CLASS_FINAL);
 	c->setDeclaredMethodByQName("labels","",Class<IFunction>::getFunction(_getLabels),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("name","",Class<IFunction>::getFunction(_getName),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("numFrames","",Class<IFunction>::getFunction(_getNumFrames),GETTER_METHOD,true);
@@ -999,8 +1067,7 @@ void FrameContainer::addFrameLabel(uint32_t frame, const tiny_string& label)
 
 void MovieClip::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<Sprite>::getRef());
+	CLASS_SETUP(c, Sprite, _constructor, CLASS_DYNAMIC_NOT_FINAL);
 	c->setDeclaredMethodByQName("currentFrame","",Class<IFunction>::getFunction(_getCurrentFrame),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("totalFrames","",Class<IFunction>::getFunction(_getTotalFrames),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("framesLoaded","",Class<IFunction>::getFunction(_getFramesLoaded),GETTER_METHOD,true);
@@ -1013,6 +1080,7 @@ void MovieClip::sinit(Class_base* c)
 	c->setDeclaredMethodByQName("play","",Class<IFunction>::getFunction(play),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("gotoAndStop","",Class<IFunction>::getFunction(gotoAndStop),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("gotoAndPlay","",Class<IFunction>::getFunction(gotoAndPlay),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("prevFrame","",Class<IFunction>::getFunction(prevFrame),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("nextFrame","",Class<IFunction>::getFunction(nextFrame),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("addFrameScript","",Class<IFunction>::getFunction(addFrameScript),NORMAL_METHOD,true);
 	REGISTER_GETTER_SETTER(c, enabled);
@@ -1164,7 +1232,7 @@ ASObject* MovieClip::gotoAnd(ASObject* const* args, const unsigned int argslen,
 	{
 		uint32_t dest=getFrameIdByLabel(args[0]->toString(), sceneName);
 		if(dest==FRAME_NOT_FOUND)
-			throw Class<ArgumentError>::getInstanceS("gotoAndPlay/Stop: label not found");
+			throwError<ArgumentError>(kInvalidArgumentError,stop ? "gotoAndStop: label not found" : "gotoAndPlay: label not found");
 
 		next_FP = dest;
 	}
@@ -1179,7 +1247,7 @@ ASObject* MovieClip::gotoAnd(ASObject* const* args, const unsigned int argslen,
 		{
 			LOG(LOG_ERROR, next_FP << "= next_FP >= state.max_FP = " << getFramesLoaded());
 			/* spec says we should throw an error, but then YT breaks */
-			//throw Class<ArgumentError>::getInstanceS("gotoAndPlay/Stop: frame not found");
+			//throwError<ArgumentError>(kInvalidArgumentError,stop ? "gotoAndStop: frame not found" : "gotoAndPlay: frame not found");
 			next_FP = getFramesLoaded()-1;
 		}
 	}
@@ -1211,6 +1279,15 @@ ASFUNCTIONBODY(MovieClip,nextFrame)
 	return NULL;
 }
 
+ASFUNCTIONBODY(MovieClip,prevFrame)
+{
+	MovieClip* th=static_cast<MovieClip*>(obj);
+	assert_and_throw(th->state.FP<th->getFramesLoaded());
+	th->state.next_FP = th->state.FP-1;
+	th->state.explicit_FP=true;
+	return NULL;
+}
+
 ASFUNCTIONBODY(MovieClip,_getFramesLoaded)
 {
 	MovieClip* th=static_cast<MovieClip*>(obj);
@@ -1345,8 +1422,7 @@ void MovieClip::addScene(uint32_t sceneNo, uint32_t startframe, const tiny_strin
 
 void DisplayObjectContainer::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<InteractiveObject>::getRef());
+	CLASS_SETUP(c, InteractiveObject, _constructor, CLASS_SEALED);
 	c->setDeclaredMethodByQName("numChildren","",Class<IFunction>::getFunction(_getNumChildren),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("getChildIndex","",Class<IFunction>::getFunction(_getChildIndex),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("setChildIndex","",Class<IFunction>::getFunction(_setChildIndex),NORMAL_METHOD,true);
@@ -1513,8 +1589,7 @@ void InteractiveObject::buildTraits(ASObject* o)
 
 void InteractiveObject::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<DisplayObject>::getRef());
+	CLASS_SETUP(c, DisplayObject, _constructor, CLASS_SEALED);
 	c->setDeclaredMethodByQName("mouseEnabled","",Class<IFunction>::getFunction(_setMouseEnabled),SETTER_METHOD,true);
 	c->setDeclaredMethodByQName("mouseEnabled","",Class<IFunction>::getFunction(_getMouseEnabled),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("doubleClickEnabled","",Class<IFunction>::getFunction(_setDoubleClickEnabled),SETTER_METHOD,true);
@@ -1522,11 +1597,13 @@ void InteractiveObject::sinit(Class_base* c)
 	REGISTER_GETTER_SETTER(c, contextMenu);
 	REGISTER_GETTER_SETTER(c, tabEnabled);
 	REGISTER_GETTER_SETTER(c, tabIndex);
+	REGISTER_GETTER_SETTER(c, focusRect);
 }
 
 ASFUNCTIONBODY_GETTER_SETTER(InteractiveObject, contextMenu);
 ASFUNCTIONBODY_GETTER_SETTER(InteractiveObject, tabEnabled);
 ASFUNCTIONBODY_GETTER_SETTER(InteractiveObject, tabIndex);
+ASFUNCTIONBODY_GETTER_SETTER(InteractiveObject, focusRect); // stub
 
 void DisplayObjectContainer::dumpDisplayList(unsigned int level)
 {
@@ -1677,12 +1754,11 @@ ASFUNCTIONBODY(DisplayObjectContainer,contains)
 	DisplayObjectContainer* th=static_cast<DisplayObjectContainer*>(obj);
 	assert_and_throw(argslen==1);
 	if(args[0]->getObjectType() == T_CLASS)
-	{
 		return abstract_b(false);
-	}
-	//Validate object type
-	assert_and_throw(args[0] && args[0]->getClass() && 
-		args[0]->getClass()->isSubClass(Class<DisplayObject>::getClass()));
+	if (!args[0]->getClass())
+		return abstract_b(false);
+	if (!args[0]->getClass()->isSubClass(Class<DisplayObject>::getClass()))
+		return abstract_b(false);
 
 	//Cast to object
 	DisplayObject* d=static_cast<DisplayObject*>(args[0]);
@@ -1958,8 +2034,7 @@ void Shape::finalize()
 
 void Shape::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<DisplayObject>::getRef());
+	CLASS_SETUP(c, DisplayObject, _constructor, CLASS_SEALED);
 	c->setDeclaredMethodByQName("graphics","",Class<IFunction>::getFunction(_getGraphics),GETTER_METHOD,true);
 }
 
@@ -1984,8 +2059,9 @@ ASFUNCTIONBODY(Shape,_getGraphics)
 
 void MorphShape::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<DisplayObject>::getRef());
+	// FIXME: should use _constructorNotInstantiatable but then
+	// DefineMorphShapeTag::instance breaks
+	CLASS_SETUP_NO_CONSTRUCTOR(c, DisplayObject, CLASS_SEALED | CLASS_FINAL);
 }
 
 void MorphShape::buildTraits(ASObject* o)
@@ -1993,12 +2069,6 @@ void MorphShape::buildTraits(ASObject* o)
 	//No traits
 }
 
-ASFUNCTIONBODY(MorphShape,_constructor)
-{
-	DisplayObject::_constructor(obj,NULL,0);
-	return NULL;
-}
-
 bool MorphShape::boundsRect(number_t& xmin, number_t& xmax, number_t& ymin, number_t& ymax) const
 {
 	LOG(LOG_NOT_IMPLEMENTED, "MorphShape::boundsRect is a stub");
@@ -2012,8 +2082,12 @@ _NR<DisplayObject> MorphShape::hitTestImpl(_NR<DisplayObject> last, number_t x,
 
 void Stage::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<DisplayObjectContainer>::getRef());
+	CLASS_SETUP(c, DisplayObjectContainer, _constructor, CLASS_SEALED);
+	c->setDeclaredMethodByQName("allowFullScreen","",Class<IFunction>::getFunction(_getAllowFullScreen),GETTER_METHOD,true);
+	c->setDeclaredMethodByQName("allowFullScreenInteractive","",Class<IFunction>::getFunction(_getAllowFullScreenInteractive),GETTER_METHOD,true);
+	c->setDeclaredMethodByQName("colorCorrectionSupport","",Class<IFunction>::getFunction(_getColorCorrectionSupport),GETTER_METHOD,true);
+	c->setDeclaredMethodByQName("fullScreenHeight","",Class<IFunction>::getFunction(_getStageHeight),GETTER_METHOD,true);
+	c->setDeclaredMethodByQName("fullScreenWidth","",Class<IFunction>::getFunction(_getStageWidth),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("stageWidth","",Class<IFunction>::getFunction(_getStageWidth),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("stageWidth","",Class<IFunction>::getFunction(undefinedFunction),SETTER_METHOD,true);
 	c->setDeclaredMethodByQName("stageHeight","",Class<IFunction>::getFunction(_getStageHeight),GETTER_METHOD,true);
@@ -2026,23 +2100,65 @@ void Stage::sinit(Class_base* c)
 	c->setDeclaredMethodByQName("stageVideos","",Class<IFunction>::getFunction(_getStageVideos),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("focus","",Class<IFunction>::getFunction(_getFocus),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("focus","",Class<IFunction>::getFunction(_setFocus),SETTER_METHOD,true);
+	c->setDeclaredMethodByQName("frameRate","",Class<IFunction>::getFunction(_getFrameRate),GETTER_METHOD,true);
+	c->setDeclaredMethodByQName("frameRate","",Class<IFunction>::getFunction(_setFrameRate),SETTER_METHOD,true);
 	// override the setter from DisplayObjectContainer
 	c->setDeclaredMethodByQName("tabChildren","",Class<IFunction>::getFunction(_setTabChildren),SETTER_METHOD,true);
+	c->setDeclaredMethodByQName("wmodeGPU","",Class<IFunction>::getFunction(_getWmodeGPU),GETTER_METHOD,true);
+	c->setDeclaredMethodByQName("invalidate","",Class<IFunction>::getFunction(_invalidate),NORMAL_METHOD,true);
+	REGISTER_GETTER_SETTER(c,align);
+	REGISTER_GETTER_SETTER(c,colorCorrection);
 	REGISTER_GETTER_SETTER(c,displayState);
+	REGISTER_GETTER_SETTER(c,fullScreenSourceRect);
+	REGISTER_GETTER_SETTER(c,showDefaultContextMenu);
+	REGISTER_GETTER_SETTER(c,quality);
+	REGISTER_GETTER_SETTER(c,stageFocusRect);
 }
 
+ASFUNCTIONBODY_GETTER_SETTER_CB(Stage,align,onAlign);
+ASFUNCTIONBODY_GETTER_SETTER_CB(Stage,colorCorrection,onColorCorrection);
+ASFUNCTIONBODY_GETTER_SETTER_CB(Stage,displayState,onDisplayState);
+ASFUNCTIONBODY_GETTER_SETTER(Stage,showDefaultContextMenu);  // stub
+ASFUNCTIONBODY_GETTER_SETTER_CB(Stage,fullScreenSourceRect,onFullScreenSourceRect);
+ASFUNCTIONBODY_GETTER_SETTER(Stage,quality);
+ASFUNCTIONBODY_GETTER_SETTER(Stage,stageFocusRect);  // stub
+
 void Stage::onDisplayState(const tiny_string&)
 {
-	LOG(LOG_NOT_IMPLEMENTED,"Stage.displayState = " << displayState);
+	if (displayState != "normal")
+		LOG(LOG_NOT_IMPLEMENTED,"Stage.displayState = " << displayState);
+	displayState = "normal"; // until fullscreen support is implemented
 }
 
-ASFUNCTIONBODY_GETTER_SETTER_CB(Stage,displayState,onDisplayState);
+void Stage::onAlign(const tiny_string& /*oldValue*/)
+{
+	LOG(LOG_NOT_IMPLEMENTED, "Stage.align = " << align);
+}
+
+void Stage::onColorCorrection(const tiny_string& oldValue)
+{
+	if (colorCorrection != "default" && 
+	    colorCorrection != "on" && 
+	    colorCorrection != "off")
+	{
+		colorCorrection = oldValue;
+		throwError<ArgumentError>(kInvalidEnumError, "colorCorrection");
+	}
+}
+
+void Stage::onFullScreenSourceRect(_NR<Rectangle> /*oldValue*/)
+{
+	LOG(LOG_NOT_IMPLEMENTED, "Stage.fullScreenSourceRect");
+	fullScreenSourceRect.reset();
+}
 
 void Stage::buildTraits(ASObject* o)
 {
 }
 
-Stage::Stage(Class_base* c):DisplayObjectContainer(c)
+Stage::Stage(Class_base* c):
+	DisplayObjectContainer(c), colorCorrection("default"),
+	showDefaultContextMenu(true), quality("high")
 {
 	onStage = true;
 }
@@ -2152,7 +2268,7 @@ ASFUNCTIONBODY(Stage,_setScaleMode)
 ASFUNCTIONBODY(Stage,_getStageVideos)
 {
 	LOG(LOG_NOT_IMPLEMENTED, "Accelerated rendering through StageVideo not implemented, SWF should fall back to Video");
-	return Class<Vector>::getInstanceS(Class<StageVideo>::getClass());
+	return Template<Vector>::getInstanceS(Class<StageVideo>::getClass());
 }
 
 _NR<InteractiveObject> Stage::getFocusTarget()
@@ -2207,665 +2323,94 @@ ASFUNCTIONBODY(Stage,_setTabChildren)
 	return NULL;
 }
 
-void Graphics::sinit(Class_base* c)
-{
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setDeclaredMethodByQName("clear","",Class<IFunction>::getFunction(clear),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("copyFrom","",Class<IFunction>::getFunction(copyFrom),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("drawRect","",Class<IFunction>::getFunction(drawRect),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("drawRoundRect","",Class<IFunction>::getFunction(drawRoundRect),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("drawCircle","",Class<IFunction>::getFunction(drawCircle),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("drawTriangles","",Class<IFunction>::getFunction(drawTriangles),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("moveTo","",Class<IFunction>::getFunction(moveTo),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("curveTo","",Class<IFunction>::getFunction(curveTo),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("cubicCurveTo","",Class<IFunction>::getFunction(cubicCurveTo),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("lineTo","",Class<IFunction>::getFunction(lineTo),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("lineStyle","",Class<IFunction>::getFunction(lineStyle),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("beginFill","",Class<IFunction>::getFunction(beginFill),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("beginGradientFill","",Class<IFunction>::getFunction(beginGradientFill),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("beginBitmapFill","",Class<IFunction>::getFunction(beginBitmapFill),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("endFill","",Class<IFunction>::getFunction(endFill),NORMAL_METHOD,true);
-}
-
-void Graphics::buildTraits(ASObject* o)
-{
-}
-
-ASFUNCTIONBODY(Graphics,_constructor)
-{
-	return NULL;
-}
-
-ASFUNCTIONBODY(Graphics,clear)
-{
-	Graphics* th=static_cast<Graphics*>(obj);
-	th->checkAndSetScaling();
-	th->owner->tokens.clear();
-	th->owner->owner->requestInvalidation(getSys());
-	return NULL;
-}
-
-ASFUNCTIONBODY(Graphics,moveTo)
-{
-	Graphics* th=static_cast<Graphics*>(obj);
-	th->checkAndSetScaling();
-	assert_and_throw(argslen==2);
-
-	th->curX=args[0]->toInt();
-	th->curY=args[1]->toInt();
-
-	th->owner->tokens.emplace_back(GeomToken(MOVE, Vector2(th->curX, th->curY)));
-	return NULL;
-}
-
-ASFUNCTIONBODY(Graphics,lineTo)
-{
-	Graphics* th=static_cast<Graphics*>(obj);
-	assert_and_throw(argslen==2);
-	th->checkAndSetScaling();
-
-	int x=args[0]->toInt();
-	int y=args[1]->toInt();
-
-	th->owner->tokens.emplace_back(GeomToken(STRAIGHT, Vector2(x, y)));
-	th->owner->owner->requestInvalidation(getSys());
-
-	th->curX=x;
-	th->curY=y;
-	return NULL;
-}
-
-ASFUNCTIONBODY(Graphics,curveTo)
-{
-	Graphics* th=static_cast<Graphics*>(obj);
-	assert_and_throw(argslen==4);
-	th->checkAndSetScaling();
-
-	int controlX=args[0]->toInt();
-	int controlY=args[1]->toInt();
-
-	int anchorX=args[2]->toInt();
-	int anchorY=args[3]->toInt();
-
-	th->owner->tokens.emplace_back(GeomToken(CURVE_QUADRATIC,
-	                        Vector2(controlX, controlY),
-	                        Vector2(anchorX, anchorY)));
-	th->owner->owner->requestInvalidation(getSys());
-
-	th->curX=anchorX;
-	th->curY=anchorY;
-	return NULL;
-}
-
-ASFUNCTIONBODY(Graphics,cubicCurveTo)
-{
-	Graphics* th=static_cast<Graphics*>(obj);
-	assert_and_throw(argslen==6);
-	th->checkAndSetScaling();
-
-	int control1X=args[0]->toInt();
-	int control1Y=args[1]->toInt();
-
-	int control2X=args[2]->toInt();
-	int control2Y=args[3]->toInt();
-
-	int anchorX=args[4]->toInt();
-	int anchorY=args[5]->toInt();
-
-	th->owner->tokens.emplace_back(GeomToken(CURVE_CUBIC,
-	                        Vector2(control1X, control1Y),
-	                        Vector2(control2X, control2Y),
-	                        Vector2(anchorX, anchorY)));
-	th->owner->owner->requestInvalidation(getSys());
-
-	th->curX=anchorX;
-	th->curY=anchorY;
-	return NULL;
-}
-
-/* KAPPA = 4 * (sqrt2 - 1) / 3
- * This value was found in a Python prompt:
- *
- * >>> 4.0 * (2**0.5 - 1) / 3.0
- *
- * Source: http://whizkidtech.redprince.net/bezier/circle/
- */
-const double KAPPA = 0.55228474983079356;
-
-ASFUNCTIONBODY(Graphics,drawRoundRect)
-{
-	Graphics* th=static_cast<Graphics*>(obj);
-	assert_and_throw(argslen==5 || argslen==6);
-	th->checkAndSetScaling();
-
-	double x=args[0]->toNumber();
-	double y=args[1]->toNumber();
-	double width=args[2]->toNumber();
-	double height=args[3]->toNumber();
-	double ellipseWidth=args[4]->toNumber();
-	double ellipseHeight;
-	if (argslen == 6)
-		ellipseHeight=args[5]->toNumber();
-
-	if (argslen == 5 || std::isnan(ellipseHeight))
-		ellipseHeight=ellipseWidth;
-
-	ellipseHeight /= 2;
-	ellipseWidth  /= 2;
-
-	double kappaW = KAPPA * ellipseWidth;
-	double kappaH = KAPPA * ellipseHeight;
-
-	/*
-	 *    A-----B
-	 *   /       \
-	 *  H         C
-	 *  |         |
-	 *  G         D
-	 *   \       /
-	 *    F-----E
-	 * 
-	 * Flash starts and stops the pen at 'D', so we will too.
-	 */
-
-	// D
-	th->owner->tokens.emplace_back(GeomToken(MOVE, Vector2(x+width, y+height-ellipseHeight)));
-
-	// D -> E
-	th->owner->tokens.emplace_back(GeomToken(CURVE_CUBIC,
-	                        Vector2(x+width, y+height-ellipseHeight+kappaH),
-	                        Vector2(x+width-ellipseWidth+kappaW, y+height),
-	                        Vector2(x+width-ellipseWidth, y+height)));
-
-	// E -> F
-	th->owner->tokens.emplace_back(GeomToken(STRAIGHT, Vector2(x+ellipseWidth, y+height)));
-
-	// F -> G
-	th->owner->tokens.emplace_back(GeomToken(CURVE_CUBIC,
-	                        Vector2(x+ellipseWidth-kappaW, y+height),
-	                        Vector2(x, y+height-kappaH),
-	                        Vector2(x, y+height-ellipseHeight)));
-
-	// G -> H
-	th->owner->tokens.emplace_back(GeomToken(STRAIGHT, Vector2(x, y+ellipseHeight)));
-
-	// H -> A
-	th->owner->tokens.emplace_back(GeomToken(CURVE_CUBIC,
-	                        Vector2(x, y+ellipseHeight-kappaH),
-	                        Vector2(x+ellipseWidth-kappaW, y),
-	                        Vector2(x+ellipseWidth, y)));
-
-	// A -> B
-	th->owner->tokens.emplace_back(GeomToken(STRAIGHT, Vector2(x+width-ellipseWidth, y)));
-
-	// B -> C
-	th->owner->tokens.emplace_back(GeomToken(CURVE_CUBIC,
-	                        Vector2(x+width-ellipseWidth+kappaW, y),
-	                        Vector2(x+width, y+kappaH),
-	                        Vector2(x+width, y+ellipseHeight)));
-
-	// C -> D
-	th->owner->tokens.emplace_back(GeomToken(STRAIGHT, Vector2(x+width, y+height-ellipseHeight)));
-
-	th->owner->owner->requestInvalidation(getSys());
-	
-	return NULL;
-}
-
-ASFUNCTIONBODY(Graphics,drawCircle)
-{
-	Graphics* th=static_cast<Graphics*>(obj);
-	assert_and_throw(argslen==3);
-	th->checkAndSetScaling();
-
-	double x=args[0]->toNumber();
-	double y=args[1]->toNumber();
-	double radius=args[2]->toNumber();
-
-	double kappa = KAPPA*radius;
-
-	// right
-	th->owner->tokens.emplace_back(GeomToken(MOVE, Vector2(x+radius, y)));
-
-	// bottom
-	th->owner->tokens.emplace_back(GeomToken(CURVE_CUBIC,
-	                        Vector2(x+radius, y+kappa ),
-	                        Vector2(x+kappa , y+radius),
-	                        Vector2(x       , y+radius)));
-
-	// left
-	th->owner->tokens.emplace_back(GeomToken(CURVE_CUBIC,
-	                        Vector2(x-kappa , y+radius),
-	                        Vector2(x-radius, y+kappa ),
-	                        Vector2(x-radius, y       )));
-
-	// top
-	th->owner->tokens.emplace_back(GeomToken(CURVE_CUBIC,
-	                        Vector2(x-radius, y-kappa ),
-	                        Vector2(x-kappa , y-radius),
-	                        Vector2(x       , y-radius)));
-
-	// back to right
-	th->owner->tokens.emplace_back(GeomToken(CURVE_CUBIC,
-	                        Vector2(x+kappa , y-radius),
-	                        Vector2(x+radius, y-kappa ),
-	                        Vector2(x+radius, y       )));
-
-	th->owner->owner->requestInvalidation(getSys());
-	
-	return NULL;
-}
-
-ASFUNCTIONBODY(Graphics,drawRect)
+ASFUNCTIONBODY(Stage,_getFrameRate)
 {
-	Graphics* th=static_cast<Graphics*>(obj);
-	assert_and_throw(argslen==4);
-	th->checkAndSetScaling();
-
-	int x=args[0]->toInt();
-	int y=args[1]->toInt();
-	int width=args[2]->toInt();
-	int height=args[3]->toInt();
-
-	const Vector2 a(x,y);
-	const Vector2 b(x+width,y);
-	const Vector2 c(x+width,y+height);
-	const Vector2 d(x,y+height);
-
-	th->owner->tokens.emplace_back(GeomToken(MOVE, a));
-	th->owner->tokens.emplace_back(GeomToken(STRAIGHT, b));
-	th->owner->tokens.emplace_back(GeomToken(STRAIGHT, c));
-	th->owner->tokens.emplace_back(GeomToken(STRAIGHT, d));
-	th->owner->tokens.emplace_back(GeomToken(STRAIGHT, a));
-	th->owner->owner->requestInvalidation(getSys());
-	
-	return NULL;
-}
-
-/* Solve for c in the matrix equation
- *
- * [ 1 x1 y1 ] [ c[0] ]   [ u1 ]
- * [ 1 x2 y2 ] [ c[1] ] = [ u2 ]
- * [ 1 x3 y3 ] [ c[2] ]   [ u3 ]
- *
- * The result will be put in the output parameter c.
- */
-void Graphics::solveVertexMapping(double x1, double y1,
-				  double x2, double y2,
-				  double x3, double y3,
-				  double u1, double u2, double u3,
-				  double c[3])
-{
-	double eps = 1e-15;
-	double det = fabs(x2*y3 + x1*y2 + y1*x3 - y2*x3 - x1*y3 - y1*x2);
-
-	if (det < eps)
-	{
-		// Degenerate matrix
-		c[0] = c[1] = c[2] = 0;
-		return;
-	}
-
-	// Symbolic solution of the equation by Gaussian elimination
-	if (fabs(x1-x2) < eps)
-	{
-		c[2] = (u2-u1)/(y2-y1);
-		c[1] = (u3 - u1 - (y3-y1)*c[2])/(x3-x1);
-		c[0] = u1 - x1*c[1] - y1*c[2];
-	}
+	Stage* th=obj->as<Stage>();
+	_NR<RootMovieClip> root = th->getRoot();
+	if (root.isNull())
+		return abstract_d(getSys()->mainClip->getFrameRate());
 	else
-	{
-		c[2] = ((x2-x1)*(u3-u1) - (x3-x1)*(u2-u1))/((y3-y1)*(x2-x1) - (x3-x1)*(y2-y1));
-		c[1] = (u2 - u1 - (y2-y1)*c[2])/(x2-x1);
-		c[0] = u1 - x1*c[1] - y1*c[2];
-	}
+		return abstract_d(root->getFrameRate());
 }
 
-ASFUNCTIONBODY(Graphics,drawTriangles)
+ASFUNCTIONBODY(Stage,_setFrameRate)
 {
-	Graphics* th=static_cast<Graphics*>(obj);
-	_NR<Vector> vertices;
-	_NR<Vector> indices;
-	_NR<Vector> uvtData;
-	tiny_string culling;
-	ARG_UNPACK (vertices) (indices, NullRef) (uvtData, NullRef) (culling, "none");
-
-	if (culling != "none")
-		LOG(LOG_NOT_IMPLEMENTED, "Graphics.drawTriangles doesn't support culling");
-
-	// Validate the parameters
-	if ((indices.isNull() && (vertices->size() % 6 != 0)) || 
-	    (!indices.isNull() && (indices->size() % 3 != 0)))
-	{
-		throwError<ArgumentError>(kInvalidParamError);
-	}
-
-	unsigned int numvertices=vertices->size()/2;
-	unsigned int numtriangles;
-	bool has_uvt=false;
-	int uvtElemSize=2;
-	int texturewidth=0;
-	int textureheight=0;
-
-	if (indices.isNull())
-		numtriangles=numvertices/3;
-	else
-		numtriangles=indices->size()/3;
-
-	if (!uvtData.isNull())
-	{
-		if (uvtData->size()==2*numvertices)
-		{
-			has_uvt=true;
-			uvtElemSize=2; /* (u, v) */
-		}
-		else if (uvtData->size()==3*numvertices)
-		{
-			has_uvt=true;
-			uvtElemSize=3; /* (u, v, t), t is ignored */
-			LOG(LOG_NOT_IMPLEMENTED, "Graphics.drawTriangles doesn't support t in uvtData parameter");
-		}
-		else
-		{
-			throwError<ArgumentError>(kInvalidParamError);
-		}
-
-		th->owner->getTextureSize(&texturewidth, &textureheight);
-	}
-
-	// According to testing, drawTriangles first fills the current
-	// path and creates a new path, but keeps the source.
-	th->owner->tokens.emplace_back(FILL_KEEP_SOURCE);
-
-	if (has_uvt && (texturewidth==0 || textureheight==0))
-		return NULL;
-
-	// Construct the triangles
-	for (unsigned int i=0; i<numtriangles; i++)
-	{
-		double x[3], y[3], u[3]={0}, v[3]={0};
-		for (unsigned int j=0; j<3; j++)
-		{
-			unsigned int vertex;
-			if (indices.isNull())
-				vertex=3*i+j;
-			else
-				vertex=indices->at(3*i+j)->toInt();
-
-			x[j]=vertices->at(2*vertex)->toNumber();
-			y[j]=vertices->at(2*vertex+1)->toNumber();
-
-			if (has_uvt)
-			{
-				u[j]=uvtData->at(vertex*uvtElemSize)->toNumber()*texturewidth;
-				v[j]=uvtData->at(vertex*uvtElemSize+1)->toNumber()*textureheight;
-			}
-		}
-		
-		Vector2 a(x[0], y[0]);
-		Vector2 b(x[1], y[1]);
-		Vector2 c(x[2], y[2]);
-
-		th->owner->tokens.emplace_back(GeomToken(MOVE, a));
-		th->owner->tokens.emplace_back(GeomToken(STRAIGHT, b));
-		th->owner->tokens.emplace_back(GeomToken(STRAIGHT, c));
-		th->owner->tokens.emplace_back(GeomToken(STRAIGHT, a));
-
-		if (has_uvt)
-		{
-			double t[6];
-
-			// Use the known (x, y) and (u, v)
-			// correspondences to compute a transformation
-			// t from (x, y) space into (u, v) space
-			// (cairo needs the mapping in this
-			// direction).
-			//
-			// u = t[0] + t[1]*x + t[2]*y
-			// v = t[3] + t[4]*x + t[5]*y
-			//
-			// u and v parts can be solved separately.
-			th->solveVertexMapping(x[0], y[0], x[1], y[1], x[2], y[2],
-					       u[0], u[1], u[2], t);
-			th->solveVertexMapping(x[0], y[0], x[1], y[1], x[2], y[2],
-					       v[0], v[1], v[2], &t[3]);
-
-			MATRIX m(t[1], t[5], t[4], t[2], t[0], t[3]);
-			th->owner->tokens.emplace_back(GeomToken(FILL_TRANSFORM_TEXTURE, m));
-		}
-	}
-	
-	th->owner->owner->requestInvalidation(getSys());
-
+	Stage* th=obj->as<Stage>();
+	number_t frameRate;
+	ARG_UNPACK(frameRate);
+	_NR<RootMovieClip> root = th->getRoot();
+	if (!root.isNull())
+		root->setFrameRate(frameRate);
 	return NULL;
 }
 
-ASFUNCTIONBODY(Graphics,lineStyle)
+ASFUNCTIONBODY(Stage,_getAllowFullScreen)
 {
-	Graphics* th=static_cast<Graphics*>(obj);
-	th->checkAndSetScaling();
-
-	if (argslen == 0)
-	{
-		th->owner->tokens.emplace_back(CLEAR_STROKE);
-		return NULL;
-	}
-	uint32_t color = 0;
-	uint8_t alpha = 255;
-	UI16_SWF thickness = UI16_SWF(imax(args[0]->toNumber() * 20, 0));
-	if (argslen >= 2)
-		color = args[1]->toUInt();
-	if (argslen >= 3)
-		alpha = uint8_t(args[1]->toNumber() * 255);
-
-	// TODO: pixel hinting, scaling, caps, miter, joints
-	
-	LINESTYLE2 style(0xff);
-	style.Color = RGBA(color, alpha);
-	style.Width = thickness;
-	th->owner->tokens.emplace_back(GeomToken(SET_STROKE, style));
-	return NULL;
+	return abstract_b(false); // until fullscreen support is implemented
 }
 
-ASFUNCTIONBODY(Graphics,beginGradientFill)
+ASFUNCTIONBODY(Stage,_getAllowFullScreenInteractive)
 {
-	Graphics* th=static_cast<Graphics*>(obj);
-	assert_and_throw(argslen>=4);
-	th->checkAndSetScaling();
-
-	FILLSTYLE style(0xff);
-
-	assert_and_throw(args[1]->getObjectType()==T_ARRAY);
-	Array* colors=Class<Array>::cast(args[1]);
-
-	assert_and_throw(args[2]->getObjectType()==T_ARRAY);
-	Array* alphas=Class<Array>::cast(args[2]);
-
-	//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();
-	if (NumGradient != (int)alphas->size() || NumGradient != (int)ratios->size())
-		return NULL;
-
-	if (NumGradient < 1 || NumGradient > 15)
-		return NULL;
-
-	const tiny_string& type=args[0]->toString();
-
-	if(type == "linear")
-		style.FillStyleType=LINEAR_GRADIENT;
-	else if(type == "radial")
-		style.FillStyleType=RADIAL_GRADIENT;
-	else
-		return NULL;
-
-	// Don't support FOCALGRADIENT for now.
-	GRADIENT grad(0xff);
-	for(int i = 0; i < NumGradient; i ++)
-	{
-		GRADRECORD record(0xff);
-		record.Color = RGBA(colors->at(i)->toUInt(), (int)alphas->at(i)->toNumber()*255);
-		record.Ratio = UI8(ratios->at(i)->toUInt());
-		grad.GradientRecords.push_back(record);
-	}
-
-	if(argslen > 4 && args[4]->getClass()==Class<Matrix>::getClass())
-	{
-		style.Matrix = static_cast<Matrix*>(args[4])->getMATRIX();
-		//Conversion from twips to pixels
-		cairo_matrix_scale(&style.Matrix, 1.0f/20.0f, 1.0f/20.0f);
-	}
-	else
-	{
-		cairo_matrix_scale(&style.Matrix, 100.0/16384.0, 100.0/16384.0);
-	}
-
-	if(argslen > 5)
-	{
-		const tiny_string& spread=args[5]->toString();
-		if (spread == "pad")
-			grad.SpreadMode = 0;
-		else if (spread == "reflect")
-			grad.SpreadMode = 1;
-		else if (spread == "repeat")
-			grad.SpreadMode = 2;
-	}
-	else
-	{
-		//default is pad
-		grad.SpreadMode = 0;
-	}
-
-
-	if(argslen > 6)
-	{
-		const tiny_string& interp=args[6]->toString();
-		if (interp == "rgb")
-			grad.InterpolationMode = 0;
-		else if (interp == "linearRGB")
-			grad.InterpolationMode = 1;
-	}
-	else
-	{
-		//default is rgb
-		grad.InterpolationMode = 0;
-	}
-
-	style.Gradient = grad;
-	th->owner->tokens.emplace_back(GeomToken(SET_FILL, style));
-	return NULL;
+	return abstract_b(false);
 }
 
-ASFUNCTIONBODY(Graphics,beginBitmapFill)
+ASFUNCTIONBODY(Stage,_getColorCorrectionSupport)
 {
-	Graphics* th = obj->as<Graphics>();
-	_NR<BitmapData> bitmap;
-	_NR<Matrix> matrix;
-	bool repeat, smooth;
-	ARG_UNPACK (bitmap) (matrix, NullRef) (repeat, true) (smooth, false);
-
-	if(bitmap.isNull())
-		return NULL;
-
-	th->checkAndSetScaling();
-	FILLSTYLE style(0xff);
-	if(repeat && smooth)
-		style.FillStyleType = REPEATING_BITMAP;
-	else if(repeat && !smooth)
-		style.FillStyleType = NON_SMOOTHED_REPEATING_BITMAP;
-	else if(!repeat && smooth)
-		style.FillStyleType = CLIPPED_BITMAP;
-	else
-		style.FillStyleType = NON_SMOOTHED_CLIPPED_BITMAP;
-
-	if(!matrix.isNull())
-		style.Matrix = matrix->getMATRIX();
-
-	style.bitmap = bitmap->getBitmapContainer();
-	th->owner->tokens.emplace_back(GeomToken(SET_FILL, style));
-	return NULL;
+	return abstract_b(false); // until color correction is implemented
 }
 
-ASFUNCTIONBODY(Graphics,beginFill)
+ASFUNCTIONBODY(Stage,_getWmodeGPU)
 {
-	Graphics* th=static_cast<Graphics*>(obj);
-	th->checkAndSetScaling();
-	uint32_t color=0;
-	uint8_t alpha=255;
-	if(argslen>=1)
-		color=args[0]->toUInt();
-	if(argslen>=2)
-		alpha=(uint8_t(args[1]->toNumber()*0xff));
-	FILLSTYLE style(0xff);
-	style.FillStyleType = SOLID_FILL;
-	style.Color         = RGBA(color, alpha);
-	th->owner->tokens.emplace_back(GeomToken(SET_FILL, style));
-	return NULL;
+	return abstract_b(false);
 }
-
-ASFUNCTIONBODY(Graphics,endFill)
+ASFUNCTIONBODY(Stage,_invalidate)
 {
-	Graphics* th=static_cast<Graphics*>(obj);
-	th->checkAndSetScaling();
-	th->owner->tokens.emplace_back(CLEAR_FILL);
+	LOG(LOG_NOT_IMPLEMENTED,"invalidate not implemented yet");
+	// TODO this crashes lightspark
+	//Stage* th=obj->as<Stage>();
+	//_R<FlushInvalidationQueueEvent> event=_MR(new (getSys()->unaccountedMemory) FlushInvalidationQueueEvent());
+	//getVm()->addEvent(_MR(th),event);
 	return NULL;
 }
 
-ASFUNCTIONBODY(Graphics,copyFrom)
-{
-	Graphics* th=static_cast<Graphics*>(obj);
-	_NR<Graphics> source;
-	ARG_UNPACK(source);
-	if (source.isNull())
-		return NULL;
-
-	th->owner->tokens.assign(source->owner->tokens.begin(),
-				 source->owner->tokens.end());
-	return NULL;
-}
-
-void LineScaleMode::sinit(Class_base* c)
-{
-	c->setConstructor(NULL);
-	c->setVariableByQName("HORIZONTAL","",Class<ASString>::getInstanceS("horizontal"),DECLARED_TRAIT);
-	c->setVariableByQName("NONE","",Class<ASString>::getInstanceS("none"),DECLARED_TRAIT);
-	c->setVariableByQName("NORMAL","",Class<ASString>::getInstanceS("normal"),DECLARED_TRAIT);
-	c->setVariableByQName("VERTICAL","",Class<ASString>::getInstanceS("vertical"),DECLARED_TRAIT);
-}
 
 void StageScaleMode::sinit(Class_base* c)
 {
-	c->setConstructor(NULL);
-	c->setVariableByQName("EXACT_FIT","",Class<ASString>::getInstanceS("exactFit"),DECLARED_TRAIT);
-	c->setVariableByQName("NO_BORDER","",Class<ASString>::getInstanceS("noBorder"),DECLARED_TRAIT);
-	c->setVariableByQName("NO_SCALE","",Class<ASString>::getInstanceS("noScale"),DECLARED_TRAIT);
-	c->setVariableByQName("SHOW_ALL","",Class<ASString>::getInstanceS("showAll"),DECLARED_TRAIT);
+	CLASS_SETUP_NO_CONSTRUCTOR(c, ASObject, CLASS_SEALED | CLASS_FINAL);
+	c->setVariableByQName("EXACT_FIT","",Class<ASString>::getInstanceS("exactFit"),CONSTANT_TRAIT);
+	c->setVariableByQName("NO_BORDER","",Class<ASString>::getInstanceS("noBorder"),CONSTANT_TRAIT);
+	c->setVariableByQName("NO_SCALE","",Class<ASString>::getInstanceS("noScale"),CONSTANT_TRAIT);
+	c->setVariableByQName("SHOW_ALL","",Class<ASString>::getInstanceS("showAll"),CONSTANT_TRAIT);
 }
 
 void StageAlign::sinit(Class_base* c)
 {
-	c->setConstructor(NULL);
-	c->setVariableByQName("TOP_LEFT","",Class<ASString>::getInstanceS("TL"),DECLARED_TRAIT);
+	CLASS_SETUP_NO_CONSTRUCTOR(c, ASObject, CLASS_SEALED | CLASS_FINAL);
+	c->setVariableByQName("BOTTOM","",Class<ASString>::getInstanceS("B"),CONSTANT_TRAIT);
+	c->setVariableByQName("BOTTOM_LEFT","",Class<ASString>::getInstanceS("BL"),CONSTANT_TRAIT);
+	c->setVariableByQName("BOTTOM_RIGHT","",Class<ASString>::getInstanceS("BR"),CONSTANT_TRAIT);
+	c->setVariableByQName("LEFT","",Class<ASString>::getInstanceS("L"),CONSTANT_TRAIT);
+	c->setVariableByQName("RIGHT","",Class<ASString>::getInstanceS("R"),CONSTANT_TRAIT);
+	c->setVariableByQName("TOP","",Class<ASString>::getInstanceS("T"),CONSTANT_TRAIT);
+	c->setVariableByQName("TOP_LEFT","",Class<ASString>::getInstanceS("TL"),CONSTANT_TRAIT);
+	c->setVariableByQName("TOP_RIGHT","",Class<ASString>::getInstanceS("TR"),CONSTANT_TRAIT);
 }
 
 void StageQuality::sinit(Class_base* c)
 {
-	c->setConstructor(NULL);
-	c->setVariableByQName("BEST","",Class<ASString>::getInstanceS("best"),DECLARED_TRAIT);
-	c->setVariableByQName("HIGH","",Class<ASString>::getInstanceS("high"),DECLARED_TRAIT);
-	c->setVariableByQName("LOW","",Class<ASString>::getInstanceS("low"),DECLARED_TRAIT);
-	c->setVariableByQName("MEDIUM","",Class<ASString>::getInstanceS("medium"),DECLARED_TRAIT);
+	CLASS_SETUP_NO_CONSTRUCTOR(c, ASObject, CLASS_SEALED | CLASS_FINAL);
+	c->setVariableByQName("BEST","",Class<ASString>::getInstanceS("best"),CONSTANT_TRAIT);
+	c->setVariableByQName("HIGH","",Class<ASString>::getInstanceS("high"),CONSTANT_TRAIT);
+	c->setVariableByQName("LOW","",Class<ASString>::getInstanceS("low"),CONSTANT_TRAIT);
+	c->setVariableByQName("MEDIUM","",Class<ASString>::getInstanceS("medium"),CONSTANT_TRAIT);
 }
 
 void StageDisplayState::sinit(Class_base* c)
 {
-	c->setConstructor(NULL);
-	c->setVariableByQName("FULL_SCREEN","",Class<ASString>::getInstanceS("fullScreen"),DECLARED_TRAIT);
-	c->setVariableByQName("NORMAL","",Class<ASString>::getInstanceS("normal"),DECLARED_TRAIT);
+	CLASS_SETUP_NO_CONSTRUCTOR(c, ASObject, CLASS_SEALED | CLASS_FINAL);
+	c->setVariableByQName("FULL_SCREEN","",Class<ASString>::getInstanceS("fullScreen"),CONSTANT_TRAIT);
+	c->setVariableByQName("FULL_SCREEN_INTERACTIVE","",Class<ASString>::getInstanceS("fullScreenInteractive"),CONSTANT_TRAIT);
+	c->setVariableByQName("NORMAL","",Class<ASString>::getInstanceS("normal"),CONSTANT_TRAIT);
 }
 
 Bitmap::Bitmap(Class_base* c, _NR<LoaderInfo> li, std::istream *s, FILE_TYPE type):
@@ -2934,8 +2479,7 @@ void Bitmap::finalize()
 
 void Bitmap::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<DisplayObject>::getRef());
+	CLASS_SETUP(c, DisplayObject, _constructor, CLASS_SEALED);
 	REGISTER_GETTER_SETTER(c,bitmapData);
 	REGISTER_GETTER_SETTER(c,smoothing);
 }
@@ -3027,8 +2571,7 @@ IntSize Bitmap::getBitmapSize() const
 
 void SimpleButton::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<InteractiveObject>::getRef());
+	CLASS_SETUP(c, InteractiveObject, _constructor, CLASS_SEALED);
 	c->setDeclaredMethodByQName("upState","",Class<IFunction>::getFunction(_getUpState),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("upState","",Class<IFunction>::getFunction(_setUpState),SETTER_METHOD,true);
 	c->setDeclaredMethodByQName("downState","",Class<IFunction>::getFunction(_getDownState),GETTER_METHOD,true);
@@ -3039,6 +2582,8 @@ void SimpleButton::sinit(Class_base* c)
 	c->setDeclaredMethodByQName("hitTestState","",Class<IFunction>::getFunction(_setHitTestState),SETTER_METHOD,true);
 	c->setDeclaredMethodByQName("enabled","",Class<IFunction>::getFunction(_getEnabled),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("enabled","",Class<IFunction>::getFunction(_setEnabled),SETTER_METHOD,true);
+	c->setDeclaredMethodByQName("useHandCursor","",Class<IFunction>::getFunction(_getUseHandCursor),GETTER_METHOD,true);
+	c->setDeclaredMethodByQName("useHandCursor","",Class<IFunction>::getFunction(_setUseHandCursor),SETTER_METHOD,true);
 }
 
 void SimpleButton::buildTraits(ASObject* o)
@@ -3273,43 +2818,62 @@ ASFUNCTIONBODY(SimpleButton,_getUseHandCursor)
 
 void GradientType::sinit(Class_base* c)
 {
-	c->setConstructor(NULL);
-	c->setVariableByQName("LINEAR","",Class<ASString>::getInstanceS("linear"),DECLARED_TRAIT);
-	c->setVariableByQName("RADIAL","",Class<ASString>::getInstanceS("radial"),DECLARED_TRAIT);
+	CLASS_SETUP_NO_CONSTRUCTOR(c, ASObject, CLASS_SEALED | CLASS_FINAL);
+	c->setVariableByQName("LINEAR","",Class<ASString>::getInstanceS("linear"),CONSTANT_TRAIT);
+	c->setVariableByQName("RADIAL","",Class<ASString>::getInstanceS("radial"),CONSTANT_TRAIT);
 }
 
 void BlendMode::sinit(Class_base* c)
 {
-	c->setConstructor(NULL);
-	c->setVariableByQName("ADD","",Class<ASString>::getInstanceS("add"),DECLARED_TRAIT);
-	c->setVariableByQName("ALPHA","",Class<ASString>::getInstanceS("alpha"),DECLARED_TRAIT);
-	c->setVariableByQName("DARKEN","",Class<ASString>::getInstanceS("darken"),DECLARED_TRAIT);
-	c->setVariableByQName("DIFFERENCE","",Class<ASString>::getInstanceS("difference"),DECLARED_TRAIT);
-	c->setVariableByQName("ERASE","",Class<ASString>::getInstanceS("erase"),DECLARED_TRAIT);
-	c->setVariableByQName("HARDLIGHT","",Class<ASString>::getInstanceS("hardlight"),DECLARED_TRAIT);
-	c->setVariableByQName("INVERT","",Class<ASString>::getInstanceS("invert"),DECLARED_TRAIT);
-	c->setVariableByQName("LAYER","",Class<ASString>::getInstanceS("layer"),DECLARED_TRAIT);
-	c->setVariableByQName("LIGHTEN","",Class<ASString>::getInstanceS("lighten"),DECLARED_TRAIT);
-	c->setVariableByQName("MULTIPLY","",Class<ASString>::getInstanceS("multiply"),DECLARED_TRAIT);
-	c->setVariableByQName("NORMAL","",Class<ASString>::getInstanceS("normal"),DECLARED_TRAIT);
-	c->setVariableByQName("OVERLAY","",Class<ASString>::getInstanceS("overlay"),DECLARED_TRAIT);
-	c->setVariableByQName("SCREEN","",Class<ASString>::getInstanceS("screen"),DECLARED_TRAIT);
-	c->setVariableByQName("SUBSTRACT","",Class<ASString>::getInstanceS("substract"),DECLARED_TRAIT);
+	CLASS_SETUP_NO_CONSTRUCTOR(c, ASObject, CLASS_SEALED | CLASS_FINAL);
+	c->setVariableByQName("ADD","",Class<ASString>::getInstanceS("add"),CONSTANT_TRAIT);
+	c->setVariableByQName("ALPHA","",Class<ASString>::getInstanceS("alpha"),CONSTANT_TRAIT);
+	c->setVariableByQName("DARKEN","",Class<ASString>::getInstanceS("darken"),CONSTANT_TRAIT);
+	c->setVariableByQName("DIFFERENCE","",Class<ASString>::getInstanceS("difference"),CONSTANT_TRAIT);
+	c->setVariableByQName("ERASE","",Class<ASString>::getInstanceS("erase"),CONSTANT_TRAIT);
+	c->setVariableByQName("HARDLIGHT","",Class<ASString>::getInstanceS("hardlight"),CONSTANT_TRAIT);
+	c->setVariableByQName("INVERT","",Class<ASString>::getInstanceS("invert"),CONSTANT_TRAIT);
+	c->setVariableByQName("LAYER","",Class<ASString>::getInstanceS("layer"),CONSTANT_TRAIT);
+	c->setVariableByQName("LIGHTEN","",Class<ASString>::getInstanceS("lighten"),CONSTANT_TRAIT);
+	c->setVariableByQName("MULTIPLY","",Class<ASString>::getInstanceS("multiply"),CONSTANT_TRAIT);
+	c->setVariableByQName("NORMAL","",Class<ASString>::getInstanceS("normal"),CONSTANT_TRAIT);
+	c->setVariableByQName("OVERLAY","",Class<ASString>::getInstanceS("overlay"),CONSTANT_TRAIT);
+	c->setVariableByQName("SCREEN","",Class<ASString>::getInstanceS("screen"),CONSTANT_TRAIT);
+	c->setVariableByQName("SUBTRACT","",Class<ASString>::getInstanceS("subtract"),CONSTANT_TRAIT);
 }
 
 void SpreadMethod::sinit(Class_base* c)
 {
-	c->setConstructor(NULL);
-	c->setVariableByQName("PAD","",Class<ASString>::getInstanceS("pad"),DECLARED_TRAIT);
-	c->setVariableByQName("REFLECT","",Class<ASString>::getInstanceS("reflect"),DECLARED_TRAIT);
-	c->setVariableByQName("REPEAT","",Class<ASString>::getInstanceS("repeat"),DECLARED_TRAIT);
+	CLASS_SETUP_NO_CONSTRUCTOR(c, ASObject, CLASS_SEALED | CLASS_FINAL);
+	c->setVariableByQName("PAD","",Class<ASString>::getInstanceS("pad"),CONSTANT_TRAIT);
+	c->setVariableByQName("REFLECT","",Class<ASString>::getInstanceS("reflect"),CONSTANT_TRAIT);
+	c->setVariableByQName("REPEAT","",Class<ASString>::getInstanceS("repeat"),CONSTANT_TRAIT);
 }
 
 void InterpolationMethod::sinit(Class_base* c)
 {
-	c->setConstructor(NULL);
-	c->setVariableByQName("RGB","",Class<ASString>::getInstanceS("rgb"),DECLARED_TRAIT);
-	c->setVariableByQName("LINEAR_RGB","",Class<ASString>::getInstanceS("linearRGB"),DECLARED_TRAIT);
+	CLASS_SETUP_NO_CONSTRUCTOR(c, ASObject, CLASS_SEALED | CLASS_FINAL);
+	c->setVariableByQName("RGB","",Class<ASString>::getInstanceS("rgb"),CONSTANT_TRAIT);
+	c->setVariableByQName("LINEAR_RGB","",Class<ASString>::getInstanceS("linearRGB"),CONSTANT_TRAIT);
+}
+
+void GraphicsPathCommand::sinit(Class_base* c)
+{
+	CLASS_SETUP_NO_CONSTRUCTOR(c, ASObject, CLASS_SEALED | CLASS_FINAL);
+	c->setVariableByQName("CUBIC_CURVE_TO","",abstract_i(6),CONSTANT_TRAIT);
+	c->setVariableByQName("CURVE_TO","",abstract_i(3),CONSTANT_TRAIT);
+	c->setVariableByQName("LINE_TO","",abstract_i(2),CONSTANT_TRAIT);
+	c->setVariableByQName("MOVE_TO","",abstract_i(1),CONSTANT_TRAIT);
+	c->setVariableByQName("NO_OP","",abstract_i(0),CONSTANT_TRAIT);
+	c->setVariableByQName("WIDE_LINE_TO","",abstract_i(5),CONSTANT_TRAIT);
+	c->setVariableByQName("WIDE_MOVE_TO","",abstract_i(4),CONSTANT_TRAIT);
+}
+
+void GraphicsPathWinding::sinit(Class_base* c)
+{
+	CLASS_SETUP_NO_CONSTRUCTOR(c, ASObject, CLASS_SEALED | CLASS_FINAL);
+	c->setVariableByQName("EVEN_ODD","",Class<ASString>::getInstanceS("evenOdd"),CONSTANT_TRAIT);
+	c->setVariableByQName("NON_ZERO","",Class<ASString>::getInstanceS("nonZero"),CONSTANT_TRAIT);
 }
 
 /* Go through the hierarchy and add all
@@ -3456,8 +3020,7 @@ void MovieClip::constructionComplete()
 
 void AVM1Movie::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<DisplayObject>::getRef());
+	CLASS_SETUP(c, DisplayObject, _constructor, CLASS_SEALED);
 }
 
 void AVM1Movie::buildTraits(ASObject* o)
@@ -3473,8 +3036,7 @@ ASFUNCTIONBODY(AVM1Movie,_constructor)
 
 void Shader::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<ASObject>::getRef());
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_SEALED);
 }
 
 ASFUNCTIONBODY(Shader,_constructor)
@@ -3485,12 +3047,11 @@ ASFUNCTIONBODY(Shader,_constructor)
 
 void BitmapDataChannel::sinit(Class_base* c)
 {
-	c->setConstructor(NULL);
-	c->setSuper(Class<ASObject>::getRef());
-	c->setVariableByQName("ALPHA","",abstract_ui(8),DECLARED_TRAIT);
-	c->setVariableByQName("BLUE","",abstract_ui(4),DECLARED_TRAIT);
-	c->setVariableByQName("GREEN","",abstract_ui(2),DECLARED_TRAIT);
-	c->setVariableByQName("RED","",abstract_ui(1),DECLARED_TRAIT);
+	CLASS_SETUP_NO_CONSTRUCTOR(c, ASObject, CLASS_SEALED | CLASS_FINAL);
+	c->setVariableByQName("ALPHA","",abstract_ui(8),CONSTANT_TRAIT);
+	c->setVariableByQName("BLUE","",abstract_ui(4),CONSTANT_TRAIT);
+	c->setVariableByQName("GREEN","",abstract_ui(2),CONSTANT_TRAIT);
+	c->setVariableByQName("RED","",abstract_ui(1),CONSTANT_TRAIT);
 }
 
 unsigned int BitmapDataChannel::channelShift(uint32_t channelConstant)
@@ -3515,3 +3076,12 @@ unsigned int BitmapDataChannel::channelShift(uint32_t channelConstant)
 
 	return shift;
 }
+
+void LineScaleMode::sinit(Class_base* c)
+{
+	CLASS_SETUP_NO_CONSTRUCTOR(c, ASObject, CLASS_SEALED | CLASS_FINAL);
+	c->setVariableByQName("HORIZONTAL","",Class<ASString>::getInstanceS("horizontal"),CONSTANT_TRAIT);
+	c->setVariableByQName("NONE","",Class<ASString>::getInstanceS("none"),CONSTANT_TRAIT);
+	c->setVariableByQName("NORMAL","",Class<ASString>::getInstanceS("normal"),CONSTANT_TRAIT);
+	c->setVariableByQName("VERTICAL","",Class<ASString>::getInstanceS("vertical"),CONSTANT_TRAIT);
+}
diff --git a/src/scripting/flash/display/flashdisplay.h b/src/scripting/flash/display/flashdisplay.h
index 451821e..8a9f24f 100644
--- a/src/scripting/flash/display/flashdisplay.h
+++ b/src/scripting/flash/display/flashdisplay.h
@@ -31,6 +31,7 @@
 #include "backends/netutils.h"
 #include "scripting/flash/display/DisplayObject.h"
 #include "scripting/flash/display/TokenContainer.h"
+#include "scripting/flash/ui/ContextMenu.h"
 
 namespace lightspark
 {
@@ -43,6 +44,10 @@ class RenderContext;
 class ApplicationDomain;
 class SecurityDomain;
 class BitmapData;
+class Matrix;
+class Vector;
+class Graphics;
+class Rectangle;
 
 class InteractiveObject: public DisplayObject
 {
@@ -61,9 +66,10 @@ protected:
 	~InteractiveObject();
 public:
 	InteractiveObject(Class_base* c);
-	ASPROPERTY_GETTER_SETTER(_NR<ASObject>,contextMenu); // TOOD: should be NativeMenu
+	ASPROPERTY_GETTER_SETTER(_NR<ContextMenu>,contextMenu); // TOOD: should be NativeMenu
 	ASPROPERTY_GETTER_SETTER(bool,tabEnabled);
 	ASPROPERTY_GETTER_SETTER(int32_t,tabIndex);
+	ASPROPERTY_GETTER_SETTER(_NR<ASObject>,focusRect);
 	ASFUNCTION(_constructor);
 	ASFUNCTION(_setMouseEnabled);
 	ASFUNCTION(_getMouseEnabled);
@@ -171,55 +177,6 @@ public:
 	ASFUNCTION(_setUseHandCursor);
 };
 
-/* This objects paints to its owners tokens */
-class Graphics: public ASObject
-{
-private:
-	int curX, curY;
-	TokenContainer *const owner;
-	//TODO: Add spinlock
-	void checkAndSetScaling()
-	{
-		if(owner->scaling != 1.0f)
-		{
-			owner->scaling = 1.0f;
-			owner->tokens.clear();
-			assert(curX == 0 && curY == 0);
-		}
-	}
-	static void solveVertexMapping(double x1, double y1,
-				       double x2, double y2,
-				       double x3, double y3,
-				       double u1, double u2, double u3,
-				       double c[3]);
-public:
-	Graphics(Class_base* c):ASObject(c),curX(0),curY(0),owner(NULL)
-	{
-		throw RunTimeException("Cannot instantiate a Graphics object");
-	}
-	Graphics(Class_base* c, TokenContainer* _o)
-		: ASObject(c),curX(0),curY(0),owner(_o) {}
-	static void sinit(Class_base* c);
-	static void buildTraits(ASObject* o);
-	ASFUNCTION(_constructor);
-	ASFUNCTION(lineStyle);
-	ASFUNCTION(beginFill);
-	ASFUNCTION(beginGradientFill);
-	ASFUNCTION(beginBitmapFill);
-	ASFUNCTION(endFill);
-	ASFUNCTION(drawRect);
-	ASFUNCTION(drawRoundRect);
-	ASFUNCTION(drawCircle);
-	ASFUNCTION(drawTriangles);
-	ASFUNCTION(moveTo);
-	ASFUNCTION(lineTo);
-	ASFUNCTION(curveTo);
-	ASFUNCTION(cubicCurveTo);
-	ASFUNCTION(clear);
-	ASFUNCTION(copyFrom);
-};
-
-
 class Shape: public DisplayObject, public TokenContainer
 {
 protected:
@@ -253,7 +210,6 @@ public:
 	MorphShape(Class_base* c):DisplayObject(c){}
 	static void sinit(Class_base* c);
 	static void buildTraits(ASObject* o);
-	ASFUNCTION(_constructor);
 };
 
 class Loader;
@@ -272,6 +228,7 @@ private:
 	tiny_string loaderURL;
 	_NR<EventDispatcher> sharedEvents;
 	_NR<Loader> loader;
+	_NR<ByteArray> bytesData;
 	/*
 	 * waitedObject is the object we are supposed to wait,
 	 * it's necessary when multiple loads are invoked on
@@ -290,18 +247,20 @@ private:
 	void sendInit();
 public:
 	ASPROPERTY_GETTER(uint32_t,actionScriptVersion);
+	ASPROPERTY_GETTER(uint32_t,swfVersion);
 	ASPROPERTY_GETTER(bool, childAllowsParent);
+	ASPROPERTY_GETTER(_NR<UncaughtErrorEvents>,uncaughtErrorEvents);
 	LoaderInfo(Class_base* c);
 	LoaderInfo(Class_base* c, _R<Loader> l);
 	void finalize();
 	static void sinit(Class_base* c);
 	static void buildTraits(ASObject* o);
 	ASFUNCTION(_constructor);
-	ASFUNCTION(addEventListener);
 	ASFUNCTION(_getLoaderURL);
 	ASFUNCTION(_getURL);
 	ASFUNCTION(_getBytesLoaded);
 	ASFUNCTION(_getBytesTotal);
+	ASFUNCTION(_getBytes);
 	ASFUNCTION(_getApplicationDomain);
 	ASFUNCTION(_getLoader);
 	ASFUNCTION(_getContent);
@@ -318,6 +277,7 @@ public:
 	void setBytesLoaded(uint32_t b);
 	void setURL(const tiny_string& _url, bool setParameters=true);
 	void setLoaderURL(const tiny_string& _url) { loaderURL=_url; }
+	void setParameters(_NR<ASObject> p) { parameters = p; }
 	void resetState();
 };
 
@@ -349,6 +309,7 @@ private:
 	_NR<LoaderInfo> contentLoaderInfo;
 	void unload();
 	bool loaded;
+	bool allowCodeImport;
 public:
 	Loader(Class_base* c);
 	~Loader();
@@ -361,8 +322,10 @@ public:
 	ASFUNCTION(load);
 	ASFUNCTION(loadBytes);
 	ASFUNCTION(_unload);
+	ASFUNCTION(_unloadAndStop);
 	ASFUNCTION(_getContentLoaderInfo);
 	ASFUNCTION(_getContent);
+	ASPROPERTY_GETTER(_NR<UncaughtErrorEvents>,uncaughtErrorEvents);
 	int getDepth() const
 	{
 		return 0;
@@ -370,6 +333,7 @@ public:
 	void setContent(_R<DisplayObject> o);
 	_NR<DisplayObject> getContent() { return content; }
 	_R<LoaderInfo> getContentLoaderInfo() { return contentLoaderInfo; }
+	bool allowLoadingSWF() { return allowCodeImport; };
 };
 
 class Sprite: public DisplayObjectContainer, public TokenContainer
@@ -528,6 +492,7 @@ public:
 	ASFUNCTION(play);
 	ASFUNCTION(gotoAndStop);
 	ASFUNCTION(gotoAndPlay);
+	ASFUNCTION(prevFrame);
 	ASFUNCTION(nextFrame);
 	ASFUNCTION(_getCurrentFrame);
 	ASFUNCTION(_getCurrentFrameLabel);
@@ -550,6 +515,9 @@ private:
 	uint32_t internalGetHeight() const;
 	uint32_t internalGetWidth() const;
 	void onDisplayState(const tiny_string&);
+	void onAlign(const tiny_string&);
+	void onColorCorrection(const tiny_string&);
+	void onFullScreenSourceRect(_NR<Rectangle>);
 	// Keyboard focus object is accessed from the VM thread (AS
 	// code) and the input thread and is protected focusSpinlock
 	Spinlock focusSpinlock;
@@ -564,6 +532,9 @@ public:
 	_NR<InteractiveObject> getFocusTarget();
 	void setFocusTarget(_NR<InteractiveObject> focus);
 	ASFUNCTION(_constructor);
+	ASFUNCTION(_getAllowFullScreen);
+	ASFUNCTION(_getAllowFullScreenInteractive);
+	ASFUNCTION(_getColorCorrectionSupport);
 	ASFUNCTION(_getStageWidth);
 	ASFUNCTION(_getStageHeight);
 	ASFUNCTION(_getScaleMode);
@@ -573,7 +544,17 @@ public:
 	ASFUNCTION(_getFocus);
 	ASFUNCTION(_setFocus);
 	ASFUNCTION(_setTabChildren);
+	ASFUNCTION(_getFrameRate);
+	ASFUNCTION(_setFrameRate);
+	ASFUNCTION(_getWmodeGPU);
+	ASFUNCTION(_invalidate);
+	ASPROPERTY_GETTER_SETTER(tiny_string,align);
+	ASPROPERTY_GETTER_SETTER(tiny_string,colorCorrection);
 	ASPROPERTY_GETTER_SETTER(tiny_string,displayState);
+	ASPROPERTY_GETTER_SETTER(_NR<Rectangle>,fullScreenSourceRect);
+	ASPROPERTY_GETTER_SETTER(bool,showDefaultContextMenu);
+	ASPROPERTY_GETTER_SETTER(tiny_string,quality);
+	ASPROPERTY_GETTER_SETTER(bool,stageFocusRect);
 };
 
 class StageScaleMode: public ASObject
@@ -645,6 +626,22 @@ public:
 	static void sinit(Class_base* c);
 };
 
+class GraphicsPathCommand: public ASObject
+{
+public:
+	enum {NO_OP=0, MOVE_TO, LINE_TO, CURVE_TO, WIDE_MOVE_TO, WIDE_LINE_TO, CUBIC_CURVE_TO};
+	GraphicsPathCommand(Class_base* c):ASObject(c){}
+	static void sinit(Class_base* c);
+};
+
+class GraphicsPathWinding: public ASObject
+{
+public:
+	GraphicsPathWinding(Class_base* c):ASObject(c){}
+	static void sinit(Class_base* c);
+
+};
+
 class IntSize
 {
 public:
diff --git a/src/scripting/flash/errors/flasherrors.cpp b/src/scripting/flash/errors/flasherrors.cpp
index 81c0a83..087f5a1 100644
--- a/src/scripting/flash/errors/flasherrors.cpp
+++ b/src/scripting/flash/errors/flasherrors.cpp
@@ -32,8 +32,7 @@ ASFUNCTIONBODY(IOError,_constructor)
 
 void IOError::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<ASError>::getRef());
+	CLASS_SETUP(c, ASError, _constructor, CLASS_DYNAMIC_NOT_FINAL);
 }
 
 void IOError::buildTraits(ASObject* o)
@@ -49,8 +48,7 @@ ASFUNCTIONBODY(EOFError,_constructor)
 
 void EOFError::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<IOError>::getRef());
+	CLASS_SETUP(c, IOError, _constructor, CLASS_DYNAMIC_NOT_FINAL);
 }
 
 void EOFError::buildTraits(ASObject* o)
@@ -66,8 +64,7 @@ ASFUNCTIONBODY(IllegalOperationError,_constructor)
 
 void IllegalOperationError::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<ASError>::getRef());
+	CLASS_SETUP(c, ASError, _constructor, CLASS_DYNAMIC_NOT_FINAL);
 }
 
 void IllegalOperationError::buildTraits(ASObject* o)
@@ -85,8 +82,7 @@ ASFUNCTIONBODY(InvalidSWFError,_constructor)
 
 void InvalidSWFError::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<ASError>::getRef());
+	CLASS_SETUP(c, ASError, _constructor, CLASS_DYNAMIC_NOT_FINAL);
 }
 
 void InvalidSWFError::buildTraits(ASObject* o)
@@ -102,8 +98,7 @@ ASFUNCTIONBODY(MemoryError,_constructor)
 
 void MemoryError::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<ASError>::getRef());
+	CLASS_SETUP(c, ASError, _constructor, CLASS_DYNAMIC_NOT_FINAL);
 }
 
 void MemoryError::buildTraits(ASObject* o)
@@ -119,8 +114,7 @@ ASFUNCTIONBODY(ScriptTimeoutError,_constructor)
 
 void ScriptTimeoutError::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<ASError>::getRef());
+	CLASS_SETUP(c, ASError, _constructor, CLASS_DYNAMIC_NOT_FINAL);
 }
 
 void ScriptTimeoutError::buildTraits(ASObject* o)
@@ -136,8 +130,7 @@ ASFUNCTIONBODY(StackOverflowError,_constructor)
 
 void StackOverflowError::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<ASError>::getRef());
+	CLASS_SETUP(c, ASError, _constructor, CLASS_DYNAMIC_NOT_FINAL);
 }
 
 void StackOverflowError::buildTraits(ASObject* o)
diff --git a/src/scripting/flash/events/flashevents.cpp b/src/scripting/flash/events/flashevents.cpp
index 6f99dfd..5495dd7 100644
--- a/src/scripting/flash/events/flashevents.cpp
+++ b/src/scripting/flash/events/flashevents.cpp
@@ -49,9 +49,7 @@ void Event::finalize()
 
 void Event::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<ASObject>::getRef());
-
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_SEALED);
 	c->setVariableByQName("ACTIVATE","",Class<ASString>::getInstanceS("activate"),DECLARED_TRAIT);
 	c->setVariableByQName("ADDED","",Class<ASString>::getInstanceS("added"),DECLARED_TRAIT);
 	c->setVariableByQName("ADDED_TO_STAGE","",Class<ASString>::getInstanceS("addedToStage"),DECLARED_TRAIT);
@@ -189,8 +187,7 @@ ASFUNCTIONBODY(Event,clone)
 
 void EventPhase::sinit(Class_base* c)
 {
-	c->setConstructor(NULL);
-	c->setSuper(Class<ASObject>::getRef());
+	CLASS_SETUP_NO_CONSTRUCTOR(c, ASObject, CLASS_SEALED | CLASS_FINAL);
 	c->setVariableByQName("CAPTURING_PHASE","",abstract_i(CAPTURING_PHASE),DECLARED_TRAIT);
 	c->setVariableByQName("BUBBLING_PHASE","",abstract_i(BUBBLING_PHASE),DECLARED_TRAIT);
 	c->setVariableByQName("AT_TARGET","",abstract_i(AT_TARGET),DECLARED_TRAIT);
@@ -201,10 +198,8 @@ FocusEvent::FocusEvent(Class_base* c):Event(c, "focusEvent")
 }
 
 void FocusEvent::sinit(Class_base* c)
-{
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<Event>::getRef());
-
+{	
+	CLASS_SETUP(c, Event, _constructor, CLASS_SEALED);
 	c->setVariableByQName("FOCUS_IN","",Class<ASString>::getInstanceS("focusIn"),DECLARED_TRAIT);
 	c->setVariableByQName("FOCUS_OUT","",Class<ASString>::getInstanceS("focusOut"),DECLARED_TRAIT);
 	c->setVariableByQName("MOUSE_FOCUS_CHANGE","",Class<ASString>::getInstanceS("mouseFocusChange"),DECLARED_TRAIT);
@@ -249,9 +244,7 @@ Event* ProgressEvent::cloneImpl() const
 
 void ProgressEvent::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<Event>::getRef());
-
+	CLASS_SETUP(c, Event, _constructor, CLASS_SEALED);
 	c->setVariableByQName("PROGRESS","",Class<ASString>::getInstanceS("progress"),DECLARED_TRAIT);
 	REGISTER_GETTER_SETTER(c,bytesLoaded);
 	REGISTER_GETTER_SETTER(c,bytesTotal);
@@ -279,18 +272,14 @@ ASFUNCTIONBODY(ProgressEvent,_constructor)
 
 void TimerEvent::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<Event>::getRef());
-
+	CLASS_SETUP(c, Event, _constructor, CLASS_SEALED);
 	c->setVariableByQName("TIMER","",Class<ASString>::getInstanceS("timer"),DECLARED_TRAIT);
 	c->setVariableByQName("TIMER_COMPLETE","",Class<ASString>::getInstanceS("timerComplete"),DECLARED_TRAIT);
 }
 
 void MouseEvent::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<Event>::getRef());
-
+	CLASS_SETUP(c, Event, _constructor, CLASS_SEALED);
 	c->setVariableByQName("CLICK","",Class<ASString>::getInstanceS("click"),DECLARED_TRAIT);
 	c->setVariableByQName("DOUBLE_CLICK","",Class<ASString>::getInstanceS("doubleClick"),DECLARED_TRAIT);
 	c->setVariableByQName("MOUSE_DOWN","",Class<ASString>::getInstanceS("mouseDown"),DECLARED_TRAIT);
@@ -302,6 +291,7 @@ void MouseEvent::sinit(Class_base* c)
 	c->setVariableByQName("RIGHT_CLICK","",Class<ASString>::getInstanceS("rightClick"),DECLARED_TRAIT);
 	c->setVariableByQName("ROLL_OVER","",Class<ASString>::getInstanceS("rollOver"),DECLARED_TRAIT);
 	c->setVariableByQName("ROLL_OUT","",Class<ASString>::getInstanceS("rollOut"),DECLARED_TRAIT);
+	c->setDeclaredMethodByQName("updateAfterEvent","",Class<IFunction>::getFunction(updateAfterEvent),NORMAL_METHOD,true);
 
 	REGISTER_GETTER(c,relatedObject);
 	REGISTER_GETTER(c,stageX);
@@ -454,6 +444,11 @@ ASFUNCTIONBODY(MouseEvent,_setter_shiftKey)
 	th->modifiers |= GDK_SHIFT_MASK;
 	return NULL;
 }
+ASFUNCTIONBODY(MouseEvent,updateAfterEvent)
+{
+	LOG(LOG_NOT_IMPLEMENTED,"MouseEvent::updateAfterEvent not implemented");
+	return NULL;
+}
 
 void MouseEvent::buildTraits(ASObject* o)
 {
@@ -488,9 +483,7 @@ IOErrorEvent::IOErrorEvent(Class_base* c) : ErrorEvent(c, "ioError")
 
 void IOErrorEvent::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<ErrorEvent>::getRef());
-
+	CLASS_SETUP(c, ErrorEvent, _constructor, CLASS_SEALED);
 	c->setVariableByQName("DISK_ERROR","",Class<ASString>::getInstanceS("diskError"),DECLARED_TRAIT);
 	c->setVariableByQName("IO_ERROR","",Class<ASString>::getInstanceS("ioError"),DECLARED_TRAIT);
 	c->setVariableByQName("NETWORK_ERROR","",Class<ASString>::getInstanceS("networkError"),DECLARED_TRAIT);
@@ -510,9 +503,8 @@ void EventDispatcher::finalize()
 
 void EventDispatcher::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_SEALED);
 	c->addImplementedInterface(InterfaceClass<IEventDispatcher>::getClass());
-	c->setSuper(Class<ASObject>::getRef());
 
 	c->setDeclaredMethodByQName("addEventListener","",Class<IFunction>::getFunction(addEventListener),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("hasEventListener","",Class<IFunction>::getFunction(_hasEventListener),NORMAL_METHOD,true);
@@ -564,18 +556,12 @@ ASFUNCTIONBODY(EventDispatcher,addEventListener)
 		Locker l(th->handlersMutex);
 		//Search if any listener is already registered for the event
 		list<listener>& listeners=th->handlers[eventName];
-		if(find(listeners.begin(),listeners.end(),make_pair(f,useCapture))!=listeners.end())
-		{
-			LOG(LOG_CALLS,_("Weird event reregistration"));
-			return NULL;
-		}
 		f->incRef();
 		const listener newListener(_MR(f), priority, useCapture);
 		//Ordered insertion
 		list<listener>::iterator insertionPoint=upper_bound(listeners.begin(),listeners.end(),newListener);
 		listeners.insert(insertionPoint,newListener);
 	}
-
 	return NULL;
 }
 
@@ -642,7 +628,6 @@ ASFUNCTIONBODY(EventDispatcher,dispatchEvent)
 
 	args[0]->incRef();
 	_R<Event> e=_MR(Class<Event>::cast(args[0]));
-	assert_and_throw(e->type!="");
 
 	// Must call the AS getter, because the getter may have been
 	// overridden
@@ -731,7 +716,6 @@ bool EventDispatcher::hasEventListener(const tiny_string& eventName)
 
 NetStatusEvent::NetStatusEvent(Class_base* cb, const tiny_string& level, const tiny_string& code):Event(cb, "netStatus")
 {
-	//The object has been initialized internally
 	ASObject* info=Class<ASObject>::getInstanceS();
 	info->setVariableByQName("level","",Class<ASString>::getInstanceS(level),DECLARED_TRAIT);
 	info->setVariableByQName("code","",Class<ASString>::getInstanceS(code),DECLARED_TRAIT);
@@ -740,9 +724,7 @@ NetStatusEvent::NetStatusEvent(Class_base* cb, const tiny_string& level, const t
 
 void NetStatusEvent::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<Event>::getRef());
-
+	CLASS_SETUP(c, Event, _constructor, CLASS_SEALED);
 	c->setVariableByQName("NET_STATUS","",Class<ASString>::getInstanceS("netStatus"),DECLARED_TRAIT);
 }
 
@@ -769,7 +751,12 @@ ASFUNCTIONBODY(NetStatusEvent,_constructor)
 		//Uninitialized info
 		info=getSys()->getNullRef();
 	}
-	obj->setVariableByQName("info","",info,DECLARED_TRAIT);
+	multiname infoName(NULL);
+	infoName.name_type=multiname::NAME_STRING;
+	infoName.name_s_id=getSys()->getUniqueStringId("info");
+	infoName.ns.push_back(nsNameAndKind("",NAMESPACE));
+	infoName.isAttribute = false;
+	obj->setVariableByMultiname(infoName, info, CONST_NOT_ALLOWED);
 	return NULL;
 }
 
@@ -800,9 +787,7 @@ FullScreenEvent::FullScreenEvent(Class_base* c):Event(c, "fullScreenEvent")
 
 void FullScreenEvent::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<Event>::getRef());
-
+	CLASS_SETUP(c, Event, _constructor, CLASS_SEALED);
 	c->setVariableByQName("FULL_SCREEN","",Class<ASString>::getInstanceS("fullScreen"),DECLARED_TRAIT);
 }
 
@@ -820,9 +805,7 @@ KeyboardEvent::KeyboardEvent(Class_base* c, tiny_string _type, uint32_t _charcod
 
 void KeyboardEvent::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<Event>::getRef());
-
+	CLASS_SETUP(c, Event, _constructor, CLASS_SEALED);
 	REGISTER_GETTER_SETTER(c, altKey);
 	REGISTER_GETTER_SETTER(c, charCode);
 	REGISTER_GETTER_SETTER(c, commandKey);
@@ -959,11 +942,8 @@ TextEvent::TextEvent(Class_base* c,const tiny_string& t):Event(c,t)
 
 void TextEvent::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<Event>::getRef());
-
+	CLASS_SETUP(c, Event, _constructor, CLASS_SEALED);
 	c->setVariableByQName("TEXT_INPUT","",Class<ASString>::getInstanceS("textInput"),DECLARED_TRAIT);
-
 	REGISTER_GETTER_SETTER(c,text);
 }
 
@@ -985,9 +965,7 @@ ErrorEvent::ErrorEvent(Class_base* c, const tiny_string& t, const std::string& e
 
 void ErrorEvent::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<TextEvent>::getRef());
-
+	CLASS_SETUP(c, TextEvent, _constructor, CLASS_SEALED);
 	c->setVariableByQName("ERROR","",Class<ASString>::getInstanceS("error"),DECLARED_TRAIT);
 }
 
@@ -1008,9 +986,7 @@ SecurityErrorEvent::SecurityErrorEvent(Class_base* c, const std::string& e):Erro
 
 void SecurityErrorEvent::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<ErrorEvent>::getRef());
-
+	CLASS_SETUP(c, ErrorEvent, _constructor, CLASS_SEALED);
 	c->setVariableByQName("SECURITY_ERROR","",Class<ASString>::getInstanceS("securityError"),DECLARED_TRAIT);
 }
 
@@ -1020,9 +996,7 @@ AsyncErrorEvent::AsyncErrorEvent(Class_base* c):ErrorEvent(c, "asyncError")
 
 void AsyncErrorEvent::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<ErrorEvent>::getRef());
-
+	CLASS_SETUP(c, ErrorEvent, _constructor, CLASS_SEALED);
 	c->setVariableByQName("ASYNC_ERROR","",Class<ASString>::getInstanceS("asyncError"),DECLARED_TRAIT);
 }
 
@@ -1033,6 +1007,24 @@ ASFUNCTIONBODY(AsyncErrorEvent,_constructor)
 	return NULL;
 }
 
+
+UncaughtErrorEvent::UncaughtErrorEvent(Class_base* c):ErrorEvent(c, "uncaughtError")
+{
+}
+
+void UncaughtErrorEvent::sinit(Class_base* c)
+{
+	CLASS_SETUP(c, ErrorEvent, _constructor, CLASS_SEALED);
+	c->setVariableByQName("UNCAUGHT_ERROR","",Class<ASString>::getInstanceS("uncaughtError"),DECLARED_TRAIT);
+}
+
+ASFUNCTIONBODY(UncaughtErrorEvent,_constructor)
+{
+	uint32_t baseClassArgs=imin(argslen,4);
+	ErrorEvent::_constructor(obj,args,baseClassArgs);
+	return NULL;
+}
+
 ABCContextInitEvent::ABCContextInitEvent(ABCContext* c, bool l):Event(NULL, "ABCContextInitEvent"),context(c),lazy(l)
 {
 }
@@ -1043,9 +1035,7 @@ ShutdownEvent::ShutdownEvent():Event(NULL, "shutdownEvent")
 
 void HTTPStatusEvent::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<Event>::getRef());
-
+	CLASS_SETUP(c, Event, _constructor, CLASS_SEALED);
 	c->setVariableByQName("HTTP_STATUS","",Class<ASString>::getInstanceS("httpStatus"),DECLARED_TRAIT);
 }
 
@@ -1109,18 +1099,14 @@ void ParseRPCMessageEvent::finalize()
 
 void StatusEvent::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<Event>::getRef());
-
+	CLASS_SETUP(c, Event, _constructor, CLASS_SEALED);
 	/* TODO: dispatch this event */
 	c->setVariableByQName("STATUS","",Class<ASString>::getInstanceS("status"),DECLARED_TRAIT);
 }
 
 void DataEvent::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<TextEvent>::getRef());
-
+	CLASS_SETUP(c, TextEvent, _constructor, CLASS_SEALED);
 	/* TODO: dispatch this event */
 	c->setVariableByQName("DATA","",Class<ASString>::getInstanceS("data"),DECLARED_TRAIT);
 	/* TODO: dispatch this event */
@@ -1160,9 +1146,7 @@ Event* DataEvent::cloneImpl() const
 
 void InvokeEvent::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<Event>::getRef());
-
+	CLASS_SETUP(c, Event, _constructor, CLASS_SEALED);
 	c->setVariableByQName("INVOKE","",Class<ASString>::getInstanceS("invoke"),DECLARED_TRAIT);
 }
 
@@ -1179,9 +1163,7 @@ DRMErrorEvent::DRMErrorEvent(Class_base* c) : ErrorEvent(c, "drmAuthenticate")
 
 void DRMErrorEvent::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<ErrorEvent>::getRef());
-
+	CLASS_SETUP(c, ErrorEvent, _constructor, CLASS_SEALED);
 	c->setVariableByQName("DRM_ERROR","",Class<ASString>::getInstanceS("drmError"),DECLARED_TRAIT);
 	c->setVariableByQName("DRM_LOAD_DEVICEID_ERROR","",Class<ASString>::getInstanceS("drmLoadDeviceIdError"),DECLARED_TRAIT);
 }
@@ -1201,9 +1183,7 @@ DRMStatusEvent::DRMStatusEvent(Class_base* c) : Event(c, "drmAuthenticate")
 
 void DRMStatusEvent::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<Event>::getRef());
-
+	CLASS_SETUP(c, Event, _constructor, CLASS_SEALED);
 	c->setVariableByQName("DRM_STATUS","",Class<ASString>::getInstanceS("drmStatus"),DECLARED_TRAIT);
 }
 
@@ -1216,18 +1196,59 @@ ASFUNCTIONBODY(DRMStatusEvent,_constructor)
 	return NULL;
 }
 
+VideoEvent::VideoEvent(Class_base* c)
+  : Event(c, "renderState"),status("unavailable")
+{
+}
+
+void VideoEvent::sinit(Class_base* c)
+{
+	CLASS_SETUP(c, Event, _constructor, CLASS_SEALED);
+	c->setVariableByQName("RENDER_STATE","",Class<ASString>::getInstanceS("renderState"),CONSTANT_TRAIT);
+	c->setVariableByQName("RENDER_STATUS_ACCELERATED","",Class<ASString>::getInstanceS("accelerated"),CONSTANT_TRAIT);
+	c->setVariableByQName("RENDER_STATUS_SOFTWARE","",Class<ASString>::getInstanceS("software"),CONSTANT_TRAIT);
+	c->setVariableByQName("RENDER_STATUS_UNAVAILABLE","",Class<ASString>::getInstanceS("unavailable"),CONSTANT_TRAIT);
+	REGISTER_GETTER(c,status);
+}
+
+ASFUNCTIONBODY(VideoEvent,_constructor)
+{
+	uint32_t baseClassArgs=imin(argslen,3);
+	Event::_constructor(obj,args,baseClassArgs);
+
+	VideoEvent* th=static_cast<VideoEvent*>(obj);
+	if(argslen>=4)
+	{
+		th->status=args[3]->toString();
+	}
+
+	return NULL;
+}
+
+Event* VideoEvent::cloneImpl() const
+{
+	VideoEvent *clone;
+	clone = Class<VideoEvent>::getInstanceS();
+	clone->status = status;
+	// Event
+	clone->type = type;
+	clone->bubbles = bubbles;
+	clone->cancelable = cancelable;
+	return clone;
+}
+
+ASFUNCTIONBODY_GETTER(VideoEvent,status);
+
+
 StageVideoEvent::StageVideoEvent(Class_base* c)
-  : Event(c, "renderState")
+  : Event(c, "renderState"),status("unavailable")
 {
 }
 
 void StageVideoEvent::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<Event>::getRef());
-	
-	c->setVariableByQName("RENDER_STATE","",Class<ASString>::getInstanceS("renderState"),DECLARED_TRAIT);
-
+	CLASS_SETUP(c, Event, _constructor, CLASS_SEALED);
+	c->setVariableByQName("RENDER_STATE","",Class<ASString>::getInstanceS("renderState"),CONSTANT_TRAIT);
 	REGISTER_GETTER(c,colorSpace);
 	REGISTER_GETTER(c,status);
 }
@@ -1273,6 +1294,7 @@ StageVideoAvailabilityEvent::StageVideoAvailabilityEvent(Class_base* c)
 
 void StageVideoAvailabilityEvent::sinit(Class_base* c)
 {
+	CLASS_SETUP_NO_CONSTRUCTOR(c, Event, CLASS_SEALED);
 	c->setVariableByQName("STAGE_VIDEO_AVAILABILITY","",Class<ASString>::getInstanceS("stageVideoAvailability"),DECLARED_TRAIT);
 	REGISTER_GETTER(c, availability);
 }
@@ -1304,3 +1326,63 @@ Event* StageVideoAvailabilityEvent::cloneImpl() const
 }
 
 ASFUNCTIONBODY_GETTER(StageVideoAvailabilityEvent,availability);
+
+void ContextMenuEvent::sinit(Class_base* c)
+{
+	CLASS_SETUP(c, Event, _constructor, CLASS_SEALED);
+	c->setVariableByQName("MENU_ITEM_SELECT","",Class<ASString>::getInstanceS("menuItemSelect"),DECLARED_TRAIT);
+	c->setVariableByQName("MENU_SELECT","",Class<ASString>::getInstanceS("menuSelect"),DECLARED_TRAIT);
+}
+
+
+void TouchEvent::sinit(Class_base* c)
+{
+	CLASS_SETUP(c, Event, _constructor, CLASS_SEALED);
+	c->setVariableByQName("TOUCH_BEGIN","",Class<ASString>::getInstanceS("touchBegin"),DECLARED_TRAIT);
+	c->setVariableByQName("TOUCH_END","",Class<ASString>::getInstanceS("touchEnd"),DECLARED_TRAIT);
+	c->setVariableByQName("TOUCH_MOVE","",Class<ASString>::getInstanceS("touchMove"),DECLARED_TRAIT);
+	c->setVariableByQName("TOUCH_OUT","",Class<ASString>::getInstanceS("touchOut"),DECLARED_TRAIT);
+	c->setVariableByQName("TOUCH_OVER","",Class<ASString>::getInstanceS("touchOver"),DECLARED_TRAIT);
+	c->setVariableByQName("TOUCH_ROLL_OUT","",Class<ASString>::getInstanceS("touchRollOut"),DECLARED_TRAIT);
+	c->setVariableByQName("TOUCH_ROLL_OVER","",Class<ASString>::getInstanceS("touchRollOver"),DECLARED_TRAIT);
+	c->setVariableByQName("TOUCH_TAP","",Class<ASString>::getInstanceS("touchTap"),DECLARED_TRAIT);
+}
+
+void GestureEvent::sinit(Class_base* c)
+{
+	CLASS_SETUP(c, Event, _constructor, CLASS_SEALED);
+	c->setVariableByQName("GESTURE_TWO_FINGER_TAP","",Class<ASString>::getInstanceS("gestureTwoFingerTap"),DECLARED_TRAIT);
+}
+
+void PressAndTapGestureEvent::sinit(Class_base* c)
+{
+	CLASS_SETUP(c, GestureEvent, _constructor, CLASS_SEALED);
+	c->setVariableByQName("GESTURE_PRESS_AND_TAP","",Class<ASString>::getInstanceS("gesturePressAndTap"),DECLARED_TRAIT);
+}
+
+void TransformGestureEvent::sinit(Class_base* c)
+{
+	CLASS_SETUP(c, GestureEvent, _constructor, CLASS_SEALED);
+	c->setVariableByQName("GESTURE_PAN","",Class<ASString>::getInstanceS("gesturePan"),DECLARED_TRAIT);
+	c->setVariableByQName("GESTURE_ROTATE","",Class<ASString>::getInstanceS("gestureRotate"),DECLARED_TRAIT);
+	c->setVariableByQName("GESTURE_SWIPE","",Class<ASString>::getInstanceS("gestureSwipe"),DECLARED_TRAIT);
+	c->setVariableByQName("GESTURE_ZOOM","",Class<ASString>::getInstanceS("gestureZoom"),DECLARED_TRAIT);
+}
+
+UncaughtErrorEvents::UncaughtErrorEvents(Class_base* c):
+	EventDispatcher(c)
+{
+}
+
+void UncaughtErrorEvents::sinit(Class_base* c)
+{
+	CLASS_SETUP(c, EventDispatcher, _constructor, CLASS_SEALED);
+}
+
+ASFUNCTIONBODY(UncaughtErrorEvents, _constructor)
+{
+	EventDispatcher::_constructor(obj, NULL, 0);
+	UncaughtErrorEvents* th=Class<UncaughtErrorEvents>::cast(obj);
+	LOG(LOG_NOT_IMPLEMENTED,"UncaughtErrorEvents is not implemented");
+	return NULL;
+}
diff --git a/src/scripting/flash/events/flashevents.h b/src/scripting/flash/events/flashevents.h
index 2c3cdfc..fd71e15 100644
--- a/src/scripting/flash/events/flashevents.h
+++ b/src/scripting/flash/events/flashevents.h
@@ -145,8 +145,7 @@ class NetStatusEvent: public Event
 private:
 	virtual Event* cloneImpl() const;
 public:
-	NetStatusEvent(Class_base* c):Event(c, "netStatus"){}
-	NetStatusEvent(Class_base* cb, const tiny_string& l, const tiny_string& c);
+	NetStatusEvent(Class_base* cb, const tiny_string& l="", const tiny_string& c="");
 	static void sinit(Class_base*);
 	static void buildTraits(ASObject* o)
 	{
@@ -223,6 +222,18 @@ public:
 	ASFUNCTION(_constructor);
 };
 
+class UncaughtErrorEvent: public ErrorEvent
+{
+public:
+	UncaughtErrorEvent(Class_base* c);
+	static void sinit(Class_base*);
+	static void buildTraits(ASObject* o)
+	{
+	}
+	ASFUNCTION(_constructor);
+};
+
+
 class ProgressEvent: public Event
 {
 private:
@@ -273,7 +284,8 @@ public:
 	ASFUNCTION_GETTER_SETTER(shiftKey);
 	ASPROPERTY_GETTER(number_t,stageX);
 	ASPROPERTY_GETTER(number_t,stageY);
-	ASPROPERTY_GETTER(_NR<InteractiveObject>,relatedObject);	
+	ASPROPERTY_GETTER(_NR<InteractiveObject>,relatedObject);
+	ASFUNCTION(updateAfterEvent);
 };
 
 class InvokeEvent: public Event
@@ -494,6 +506,17 @@ public:
 	ASFUNCTION(_constructor);
 };
 
+class VideoEvent: public Event
+{
+private:
+	Event* cloneImpl() const;
+public:
+	VideoEvent(Class_base* c);
+	static void sinit(Class_base*);
+	ASFUNCTION(_constructor);
+	ASPROPERTY_GETTER(tiny_string,status);
+};
+
 class StageVideoEvent: public Event
 {
 private:
@@ -517,5 +540,52 @@ public:
 	ASPROPERTY_GETTER(tiny_string,availability);
 };
 
+class ContextMenuEvent: public Event
+{
+public:
+	ContextMenuEvent(Class_base* c) : Event(c, "ContextMenuEvent") {}
+	static void sinit(Class_base*);
+	static void buildTraits(ASObject* o) {}
 };
+
+class TouchEvent: public Event
+{
+public:
+	TouchEvent(Class_base* c) : Event(c, "TouchEvent") {}
+	static void sinit(Class_base*);
+	static void buildTraits(ASObject* o) {}
+};
+
+class GestureEvent: public Event
+{
+public:
+	GestureEvent(Class_base* c, const tiny_string& t = "GestureEvent") : Event(c, t) {}
+	static void sinit(Class_base*);
+	static void buildTraits(ASObject* o) {}
+};
+
+class PressAndTapGestureEvent: public GestureEvent
+{
+public:
+	PressAndTapGestureEvent(Class_base* c) : GestureEvent(c, "PressAndTapGestureEvent") {}
+	static void sinit(Class_base*);
+	static void buildTraits(ASObject* o) {}
+};
+class TransformGestureEvent: public GestureEvent
+{
+public:
+	TransformGestureEvent(Class_base* c) : GestureEvent(c, "TransformGestureEvent") {}
+	static void sinit(Class_base*);
+	static void buildTraits(ASObject* o) {}
+};
+
+class UncaughtErrorEvents: public EventDispatcher
+{
+public:
+	UncaughtErrorEvents(Class_base* c);
+	static void sinit(Class_base*);
+	ASFUNCTION(_constructor);
+};
+
+}
 #endif /* SCRIPTING_FLASH_EVENTS_FLASHEVENTS_H */
diff --git a/src/scripting/flash/external/ExternalInterface.cpp b/src/scripting/flash/external/ExternalInterface.cpp
index 7cc2130..bb7b3c0 100644
--- a/src/scripting/flash/external/ExternalInterface.cpp
+++ b/src/scripting/flash/external/ExternalInterface.cpp
@@ -26,7 +26,7 @@ using namespace lightspark;
 
 void ExternalInterface::sinit(Class_base* c)
 {
-	c->setConstructor(NULL);
+	CLASS_SETUP_NO_CONSTRUCTOR(c, ASObject, CLASS_SEALED | CLASS_FINAL);
 	c->setDeclaredMethodByQName("available","",Class<IFunction>::getFunction(_getAvailable),GETTER_METHOD,false);
 	c->setDeclaredMethodByQName("objectID","",Class<IFunction>::getFunction(_getObjectID),GETTER_METHOD,false);
 	c->setDeclaredMethodByQName("marshallExceptions","",Class<IFunction>::getFunction(_getMarshallExceptions),GETTER_METHOD,false);
@@ -73,7 +73,8 @@ ASFUNCTIONBODY(ExternalInterface, _setMarshallExceptions)
 ASFUNCTIONBODY(ExternalInterface,addCallback)
 {
 	if(getSys()->extScriptObject == NULL)
-		throw Class<ASError>::getInstanceS("Container doesn't support callbacks");
+		return abstract_b(false);
+//		throw Class<ASError>::getInstanceS("Container doesn't support callbacks");
 
 	assert_and_throw(argslen == 2);
 
@@ -90,7 +91,8 @@ ASFUNCTIONBODY(ExternalInterface,addCallback)
 ASFUNCTIONBODY(ExternalInterface,call)
 {
 	if(getSys()->extScriptObject == NULL)
-		throw Class<ASError>::getInstanceS("Container doesn't support callbacks");
+		return getSys()->getNullRef();
+//		throw Class<ASError>::getInstanceS("Container doesn't support callbacks");
 
 	assert_and_throw(argslen >= 1);
 	const tiny_string& arg0=args[0]->toString();
diff --git a/src/scripting/flash/sensors/flashsensors.cpp b/src/scripting/flash/filesystem/flashfilesystem.cpp
similarity index 60%
copy from src/scripting/flash/sensors/flashsensors.cpp
copy to src/scripting/flash/filesystem/flashfilesystem.cpp
index bee463b..1106815 100644
--- a/src/scripting/flash/sensors/flashsensors.cpp
+++ b/src/scripting/flash/filesystem/flashfilesystem.cpp
@@ -1,7 +1,7 @@
 /**************************************************************************
     Lightspark, a free flash player implementation
 
-    Copyright (C) 2011-2013  Alessandro Pignotti (a.pignotti at sssup.it)
+    Copyright (C) 2009-2013  Alessandro Pignotti (a.pignotti at sssup.it)
 
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU Lesser General Public License as published by
@@ -17,31 +17,26 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 **************************************************************************/
 
-#include <map>
-#include "backends/security.h"
+#include "scripting/flash/filesystem/flashfilesystem.h"
 #include "scripting/abc.h"
-#include "scripting/flash/sensors/flashsensors.h"
-#include "scripting/class.h"
-#include "scripting/flash/system/flashsystem.h"
+#include "scripting/argconv.h"
 #include "compat.h"
-#include "backends/audio.h"
 
-using namespace std;
 using namespace lightspark;
 
-Accelerometer::Accelerometer(Class_base* c):ASObject(c) {}
-
-void Accelerometer::sinit(Class_base* c)
+FileStream::FileStream(Class_base* c):
+	EventDispatcher(c)
 {
-	// properties
-	c->setDeclaredMethodByQName("isSupported", "", Class<IFunction>::getFunction(_isSupported),GETTER_METHOD,false);
 }
 
-void Accelerometer::buildTraits(ASObject *o)
+void FileStream::sinit(Class_base* c)
 {
+	CLASS_SETUP(c, EventDispatcher, _constructor, CLASS_SEALED);
 }
-
-ASFUNCTIONBODY(Accelerometer,_isSupported)
+ASFUNCTIONBODY(FileStream, _constructor)
 {
-	return abstract_b(false);
+	EventDispatcher::_constructor(obj, NULL, 0);
+	FileStream* th=Class<FileStream>::cast(obj);
+	LOG(LOG_NOT_IMPLEMENTED,"FileStream is not implemented");
+	return NULL;
 }
diff --git a/src/scripting/flash/accessibility/flashaccessibility.h b/src/scripting/flash/filesystem/flashfilesystem.h
similarity index 67%
copy from src/scripting/flash/accessibility/flashaccessibility.h
copy to src/scripting/flash/filesystem/flashfilesystem.h
index 19d00b8..41df839 100644
--- a/src/scripting/flash/accessibility/flashaccessibility.h
+++ b/src/scripting/flash/filesystem/flashfilesystem.h
@@ -17,31 +17,25 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 **************************************************************************/
 
-#ifndef SCRIPTING_FLASH_ACCESSIBILITY_FLASHACCESSIBILITY_H
-#define SCRIPTING_FLASH_ACCESSIBILITY_FLASHACCESSIBILITY_H 1
+#ifndef SCRIPTING_FLASH_FILESYSTEM_FLASHFILESYSTEM_H
+#define SCRIPTING_FLASH_PRINTING_FLASHFILESYSTEM_H 1
 
+#include "compat.h"
 #include "asobject.h"
+#include "scripting/flash/events/flashevents.h"
 
 namespace lightspark
 {
 
-class AccessibilityProperties : public ASObject
+class FileStream: public EventDispatcher
 {
-private:
-	ASPROPERTY_GETTER_SETTER(tiny_string,name);
 public:
-	AccessibilityProperties(Class_base* c):ASObject(c){}
+	FileStream(Class_base* c);
 	static void sinit(Class_base*);
 	ASFUNCTION(_constructor);
+	ASPROPERTY_GETTER(bool,isSupported);
 };
 
-class AccessibilityImplementation : public ASObject
-{
-public:
-	AccessibilityImplementation(Class_base* c):ASObject(c){}
-	static void sinit(Class_base*);
-	ASFUNCTION(_constructor);
-};
 
 }
-#endif /* SCRIPTING_FLASH_ACCESSIBILITY_FLASHACCESSIBILITY_H */
+#endif /* SCRIPTING_FLASH_FILESYSTEM_FLASHFILESYSTEM_H */
diff --git a/src/scripting/flash/filters/flashfilters.cpp b/src/scripting/flash/filters/flashfilters.cpp
index 9d70fc1..d230db4 100644
--- a/src/scripting/flash/filters/flashfilters.cpp
+++ b/src/scripting/flash/filters/flashfilters.cpp
@@ -19,14 +19,14 @@
 
 #include "scripting/flash/filters/flashfilters.h"
 #include "scripting/class.h"
+#include "scripting/argconv.h"
 
 using namespace std;
 using namespace lightspark;
 
 void BitmapFilter::sinit(Class_base* c)
 {
-	c->setConstructor(NULL);
-	c->setSuper(Class<ASObject>::getRef());
+	CLASS_SETUP(c, ASObject, _constructorNotInstantiatable, CLASS_SEALED);
 	c->setDeclaredMethodByQName("clone","",Class<IFunction>::getFunction(clone),NORMAL_METHOD,true);
 }
 
@@ -41,24 +41,325 @@ ASFUNCTIONBODY(BitmapFilter,clone)
 	return th->cloneImpl();
 }
 
+GlowFilter::GlowFilter(Class_base* c):
+	BitmapFilter(c), alpha(1.0), blurX(6.0), blurY(6.0), color(0xFF0000),
+	inner(false), knockout(false), quality(1), strength(2.0)
+{
+}
+
 void GlowFilter::sinit(Class_base* c)
 {
-	c->setConstructor(NULL);
-	c->setSuper(Class<BitmapFilter>::getRef());
+	CLASS_SETUP(c, BitmapFilter, _constructor, CLASS_SEALED | CLASS_FINAL);
+	REGISTER_GETTER_SETTER(c, alpha);
+	REGISTER_GETTER_SETTER(c, blurX);
+	REGISTER_GETTER_SETTER(c, blurY);
+	REGISTER_GETTER_SETTER(c, color);
+	REGISTER_GETTER_SETTER(c, inner);
+	REGISTER_GETTER_SETTER(c, knockout);
+	REGISTER_GETTER_SETTER(c, quality);
+	REGISTER_GETTER_SETTER(c, strength);
+}
+
+ASFUNCTIONBODY_GETTER_SETTER(GlowFilter, alpha);
+ASFUNCTIONBODY_GETTER_SETTER(GlowFilter, blurX);
+ASFUNCTIONBODY_GETTER_SETTER(GlowFilter, blurY);
+ASFUNCTIONBODY_GETTER_SETTER(GlowFilter, color);
+ASFUNCTIONBODY_GETTER_SETTER(GlowFilter, inner);
+ASFUNCTIONBODY_GETTER_SETTER(GlowFilter, knockout);
+ASFUNCTIONBODY_GETTER_SETTER(GlowFilter, quality);
+ASFUNCTIONBODY_GETTER_SETTER(GlowFilter, strength);
+
+ASFUNCTIONBODY(GlowFilter, _constructor)
+{
+	GlowFilter *th = obj->as<GlowFilter>();
+	ARG_UNPACK (th->color, 0xFF0000)
+		(th->alpha, 1.0)
+		(th->blurX, 6.0)
+		(th->blurY, 6.0)
+		(th->strength, 2.0)
+		(th->quality, 1)
+		(th->inner, false)
+		(th->knockout, false);
+	return NULL;
 }
 
-GlowFilter* GlowFilter::cloneImpl() const
+BitmapFilter* GlowFilter::cloneImpl() const
+{
+	GlowFilter *cloned = Class<GlowFilter>::getInstanceS();
+	cloned->alpha = alpha;
+	cloned->blurX = blurX;
+	cloned->blurY = blurY;
+	cloned->color = color;
+	cloned->inner = inner;
+	cloned->knockout = knockout;
+	cloned->quality = quality;
+	cloned->strength = strength;
+	return cloned;
+}
+
+DropShadowFilter::DropShadowFilter(Class_base* c):
+	BitmapFilter(c), alpha(1.0), angle(45), blurX(4.0), blurY(4.0),
+	color(0), distance(4.0), hideObject(false), inner(false),
+	knockout(false), quality(1), strength(1.0)
 {
-	return Class<GlowFilter>::getInstanceS();
 }
 
 void DropShadowFilter::sinit(Class_base* c)
 {
-	c->setConstructor(NULL);
-	c->setSuper(Class<BitmapFilter>::getRef());
+	CLASS_SETUP(c, BitmapFilter, _constructor, CLASS_SEALED | CLASS_FINAL);
+	REGISTER_GETTER_SETTER(c, alpha);
+	REGISTER_GETTER_SETTER(c, angle);
+	REGISTER_GETTER_SETTER(c, blurX);
+	REGISTER_GETTER_SETTER(c, blurY);
+	REGISTER_GETTER_SETTER(c, color);
+	REGISTER_GETTER_SETTER(c, distance);
+	REGISTER_GETTER_SETTER(c, hideObject);
+	REGISTER_GETTER_SETTER(c, inner);
+	REGISTER_GETTER_SETTER(c, knockout);
+	REGISTER_GETTER_SETTER(c, quality);
+	REGISTER_GETTER_SETTER(c, strength);
+}
+
+ASFUNCTIONBODY_GETTER_SETTER(DropShadowFilter, alpha);
+ASFUNCTIONBODY_GETTER_SETTER(DropShadowFilter, angle);
+ASFUNCTIONBODY_GETTER_SETTER(DropShadowFilter, blurX);
+ASFUNCTIONBODY_GETTER_SETTER(DropShadowFilter, blurY);
+ASFUNCTIONBODY_GETTER_SETTER(DropShadowFilter, color);
+ASFUNCTIONBODY_GETTER_SETTER(DropShadowFilter, distance);
+ASFUNCTIONBODY_GETTER_SETTER(DropShadowFilter, hideObject);
+ASFUNCTIONBODY_GETTER_SETTER(DropShadowFilter, inner);
+ASFUNCTIONBODY_GETTER_SETTER(DropShadowFilter, knockout);
+ASFUNCTIONBODY_GETTER_SETTER(DropShadowFilter, quality);
+ASFUNCTIONBODY_GETTER_SETTER(DropShadowFilter, strength);
+
+ASFUNCTIONBODY(DropShadowFilter, _constructor)
+{
+	DropShadowFilter *th = obj->as<DropShadowFilter>();
+	ARG_UNPACK (th->distance, 4.0)
+		(th->angle, 45)
+		(th->color, 0)
+		(th->alpha, 1.0)
+		(th->blurX, 4.0)
+		(th->blurY, 4.0)
+		(th->strength, 1.0)
+		(th->quality, 1)
+		(th->inner, false)
+		(th->knockout, false)
+		(th->hideObject, false);
+	return NULL;
+}
+
+BitmapFilter* DropShadowFilter::cloneImpl() const
+{
+	DropShadowFilter *cloned = Class<DropShadowFilter>::getInstanceS();
+	cloned->alpha = alpha;
+	cloned->angle = angle;
+	cloned->blurX = blurX;
+	cloned->blurY = blurY;
+	cloned->color = color;
+	cloned->distance = distance;
+	cloned->hideObject = hideObject;
+	cloned->inner = inner;
+	cloned->knockout = knockout;
+	cloned->quality = quality;
+	cloned->strength = strength;
+	return cloned;
+}
+
+GradientGlowFilter::GradientGlowFilter(Class_base* c):
+	BitmapFilter(c)
+{
+}
+
+void GradientGlowFilter::sinit(Class_base* c)
+{
+	CLASS_SETUP(c, BitmapFilter, _constructor, CLASS_SEALED | CLASS_FINAL);
+}
+
+ASFUNCTIONBODY(GradientGlowFilter, _constructor)
+{
+	GradientGlowFilter *th = obj->as<GradientGlowFilter>();
+	LOG(LOG_NOT_IMPLEMENTED,"GradientGlowFilter is not implemented");
+	return NULL;
+}
+
+BitmapFilter* GradientGlowFilter::cloneImpl() const
+{
+	GradientGlowFilter *cloned = Class<GradientGlowFilter>::getInstanceS();
+	return cloned;
+}
+
+BevelFilter::BevelFilter(Class_base* c):
+	BitmapFilter(c)
+{
+}
+
+void BevelFilter::sinit(Class_base* c)
+{
+	CLASS_SETUP(c, BitmapFilter, _constructor, CLASS_SEALED | CLASS_FINAL);
+}
+
+ASFUNCTIONBODY(BevelFilter, _constructor)
+{
+	BevelFilter *th = obj->as<BevelFilter>();
+	LOG(LOG_NOT_IMPLEMENTED,"GradientGlowFilter is not implemented");
+	return NULL;
+}
+
+BitmapFilter* BevelFilter::cloneImpl() const
+{
+	BevelFilter *cloned = Class<BevelFilter>::getInstanceS();
+	return cloned;
+}
+ColorMatrixFilter::ColorMatrixFilter(Class_base* c):
+	BitmapFilter(c),matrix(NULL)
+{
+}
+
+void ColorMatrixFilter::sinit(Class_base* c)
+{
+	CLASS_SETUP(c, BitmapFilter, _constructor, CLASS_SEALED | CLASS_FINAL);
+	REGISTER_GETTER_SETTER(c, matrix);
+}
+
+ASFUNCTIONBODY_GETTER_SETTER(ColorMatrixFilter, matrix);
+
+ASFUNCTIONBODY(ColorMatrixFilter, _constructor)
+{
+	ColorMatrixFilter *th = obj->as<ColorMatrixFilter>();
+	ARG_UNPACK(th->matrix,NullRef);
+	return NULL;
+}
+
+BitmapFilter* ColorMatrixFilter::cloneImpl() const
+{
+	ColorMatrixFilter *cloned = Class<ColorMatrixFilter>::getInstanceS();
+	if (!matrix.isNull())
+	{
+		matrix->incRef();
+		cloned->matrix = matrix;
+	}
+	return cloned;
+}
+BlurFilter::BlurFilter(Class_base* c):
+	BitmapFilter(c)
+{
+}
+
+void BlurFilter::sinit(Class_base* c)
+{
+	CLASS_SETUP(c, BitmapFilter, _constructor, CLASS_SEALED | CLASS_FINAL);
+}
+
+ASFUNCTIONBODY(BlurFilter, _constructor)
+{
+	BlurFilter *th = obj->as<BlurFilter>();
+	LOG(LOG_NOT_IMPLEMENTED,"BlurFilter is not implemented");
+	return NULL;
+}
+
+BitmapFilter* BlurFilter::cloneImpl() const
+{
+	BlurFilter *cloned = Class<BlurFilter>::getInstanceS();
+	return cloned;
+}
+
+ConvolutionFilter::ConvolutionFilter(Class_base* c):
+	BitmapFilter(c)
+{
+}
+
+void ConvolutionFilter::sinit(Class_base* c)
+{
+	CLASS_SETUP(c, BitmapFilter, _constructor, CLASS_SEALED | CLASS_FINAL);
+}
+
+ASFUNCTIONBODY(ConvolutionFilter, _constructor)
+{
+	ConvolutionFilter *th = obj->as<ConvolutionFilter>();
+	LOG(LOG_NOT_IMPLEMENTED,"ConvolutionFilter is not implemented");
+	return NULL;
+}
+
+BitmapFilter* ConvolutionFilter::cloneImpl() const
+{
+	ConvolutionFilter *cloned = Class<ConvolutionFilter>::getInstanceS();
+	return cloned;
+}
+
+DisplacementMapFilter::DisplacementMapFilter(Class_base* c):
+	BitmapFilter(c)
+{
+}
+
+void DisplacementMapFilter::sinit(Class_base* c)
+{
+	CLASS_SETUP(c, BitmapFilter, _constructor, CLASS_SEALED | CLASS_FINAL);
+}
+
+ASFUNCTIONBODY(DisplacementMapFilter, _constructor)
+{
+	DisplacementMapFilter *th = obj->as<DisplacementMapFilter>();
+	LOG(LOG_NOT_IMPLEMENTED,"DisplacementMapFilter is not implemented");
+	return NULL;
+}
+
+BitmapFilter* DisplacementMapFilter::cloneImpl() const
+{
+	DisplacementMapFilter *cloned = Class<DisplacementMapFilter>::getInstanceS();
+	return cloned;
+}
+
+GradientBevelFilter::GradientBevelFilter(Class_base* c):
+	BitmapFilter(c)
+{
+}
+
+void GradientBevelFilter::sinit(Class_base* c)
+{
+	CLASS_SETUP(c, BitmapFilter, _constructor, CLASS_SEALED | CLASS_FINAL);
+}
+
+ASFUNCTIONBODY(GradientBevelFilter, _constructor)
+{
+	GradientBevelFilter *th = obj->as<GradientBevelFilter>();
+	LOG(LOG_NOT_IMPLEMENTED,"GradientBevelFilter is not implemented");
+	return NULL;
+}
+
+BitmapFilter* GradientBevelFilter::cloneImpl() const
+{
+	GradientBevelFilter *cloned = Class<GradientBevelFilter>::getInstanceS();
+	return cloned;
+}
+
+ShaderFilter::ShaderFilter(Class_base* c):
+	BitmapFilter(c)
+{
+}
+
+void ShaderFilter::sinit(Class_base* c)
+{
+	CLASS_SETUP(c, BitmapFilter, _constructor, CLASS_SEALED | CLASS_FINAL);
+}
+
+ASFUNCTIONBODY(ShaderFilter, _constructor)
+{
+	ShaderFilter *th = obj->as<ShaderFilter>();
+	LOG(LOG_NOT_IMPLEMENTED,"ShaderFilter is not implemented");
+	return NULL;
+}
+
+BitmapFilter* ShaderFilter::cloneImpl() const
+{
+	ShaderFilter *cloned = Class<ShaderFilter>::getInstanceS();
+	return cloned;
 }
 
-DropShadowFilter* DropShadowFilter::cloneImpl() const
+void BitmapFilterQuality::sinit(Class_base* c)
 {
-	return Class<DropShadowFilter>::getInstanceS();
+	CLASS_SETUP(c, ASObject, _constructorNotInstantiatable, CLASS_SEALED | CLASS_FINAL);
+	c->setVariableByQName("HIGH","",abstract_i(3),DECLARED_TRAIT);
+	c->setVariableByQName("LOW","",abstract_i(1),DECLARED_TRAIT);
+	c->setVariableByQName("MEDIUM","",abstract_i(3),DECLARED_TRAIT);
 }
diff --git a/src/scripting/flash/filters/flashfilters.h b/src/scripting/flash/filters/flashfilters.h
index 2004b94..f81e73d 100644
--- a/src/scripting/flash/filters/flashfilters.h
+++ b/src/scripting/flash/filters/flashfilters.h
@@ -40,21 +40,124 @@ public:
 class GlowFilter: public BitmapFilter
 {
 private:
-	virtual GlowFilter* cloneImpl() const;
+	ASPROPERTY_GETTER_SETTER(number_t, alpha);
+	ASPROPERTY_GETTER_SETTER(number_t, blurX);
+	ASPROPERTY_GETTER_SETTER(number_t, blurY);
+	ASPROPERTY_GETTER_SETTER(uint32_t, color);
+	ASPROPERTY_GETTER_SETTER(bool, inner);
+	ASPROPERTY_GETTER_SETTER(bool, knockout);
+	ASPROPERTY_GETTER_SETTER(int32_t, quality);
+	ASPROPERTY_GETTER_SETTER(number_t, strength);
+	virtual BitmapFilter* cloneImpl() const;
 public:
-	GlowFilter(Class_base* c):BitmapFilter(c){}
+	GlowFilter(Class_base* c);
 	static void sinit(Class_base* c);
 //	static void buildTraits(ASObject* o);
+	ASFUNCTION(_constructor);
 };
 
 class DropShadowFilter: public BitmapFilter
 {
 private:
-	virtual DropShadowFilter* cloneImpl() const;
+	ASPROPERTY_GETTER_SETTER(number_t, alpha);
+	ASPROPERTY_GETTER_SETTER(number_t, angle);
+	ASPROPERTY_GETTER_SETTER(number_t, blurX);
+	ASPROPERTY_GETTER_SETTER(number_t, blurY);
+	ASPROPERTY_GETTER_SETTER(uint32_t, color);
+	ASPROPERTY_GETTER_SETTER(number_t, distance);
+	ASPROPERTY_GETTER_SETTER(bool, hideObject);
+	ASPROPERTY_GETTER_SETTER(bool, inner);
+	ASPROPERTY_GETTER_SETTER(bool, knockout);
+	ASPROPERTY_GETTER_SETTER(int32_t, quality);
+	ASPROPERTY_GETTER_SETTER(number_t, strength);
+	virtual BitmapFilter* cloneImpl() const;
 public:
-	DropShadowFilter(Class_base* c):BitmapFilter(c){}
+	DropShadowFilter(Class_base* c);
 	static void sinit(Class_base* c);
 //	static void buildTraits(ASObject* o);
+	ASFUNCTION(_constructor);
+};
+
+class GradientGlowFilter: public BitmapFilter
+{
+private:
+	virtual BitmapFilter* cloneImpl() const;
+public:
+	GradientGlowFilter(Class_base* c);
+	static void sinit(Class_base* c);
+	ASFUNCTION(_constructor);
+};
+
+class BevelFilter: public BitmapFilter
+{
+private:
+	virtual BitmapFilter* cloneImpl() const;
+public:
+	BevelFilter(Class_base* c);
+	static void sinit(Class_base* c);
+	ASFUNCTION(_constructor);
+};
+class ColorMatrixFilter: public BitmapFilter
+{
+private:
+	virtual BitmapFilter* cloneImpl() const;
+public:
+	ColorMatrixFilter(Class_base* c);
+	static void sinit(Class_base* c);
+	ASFUNCTION(_constructor);
+	ASPROPERTY_GETTER_SETTER(_NR<Array>, matrix);
+};
+class BlurFilter: public BitmapFilter
+{
+private:
+	virtual BitmapFilter* cloneImpl() const;
+public:
+	BlurFilter(Class_base* c);
+	static void sinit(Class_base* c);
+	ASFUNCTION(_constructor);
+};
+class ConvolutionFilter: public BitmapFilter
+{
+private:
+	virtual BitmapFilter* cloneImpl() const;
+public:
+	ConvolutionFilter(Class_base* c);
+	static void sinit(Class_base* c);
+	ASFUNCTION(_constructor);
+};
+class DisplacementMapFilter: public BitmapFilter
+{
+private:
+	virtual BitmapFilter* cloneImpl() const;
+public:
+	DisplacementMapFilter(Class_base* c);
+	static void sinit(Class_base* c);
+	ASFUNCTION(_constructor);
+};
+class GradientBevelFilter: public BitmapFilter
+{
+private:
+	virtual BitmapFilter* cloneImpl() const;
+public:
+	GradientBevelFilter(Class_base* c);
+	static void sinit(Class_base* c);
+	ASFUNCTION(_constructor);
+};
+class ShaderFilter: public BitmapFilter
+{
+private:
+	virtual BitmapFilter* cloneImpl() const;
+public:
+	ShaderFilter(Class_base* c);
+	static void sinit(Class_base* c);
+	ASFUNCTION(_constructor);
+};
+
+class BitmapFilterQuality: public ASObject
+{
+public:
+	BitmapFilterQuality(Class_base* c):ASObject(c) {}
+	static void sinit(Class_base* c);
 };
 
 };
diff --git a/src/scripting/flash/geom/flashgeom.cpp b/src/scripting/flash/geom/flashgeom.cpp
index 4d7f12b..8d93cd9 100644
--- a/src/scripting/flash/geom/flashgeom.cpp
+++ b/src/scripting/flash/geom/flashgeom.cpp
@@ -26,7 +26,7 @@ using namespace std;
 
 void Rectangle::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_SEALED);
 	IFunction* gleft=Class<IFunction>::getFunction(_getLeft);
 	c->setDeclaredMethodByQName("left","",gleft,GETTER_METHOD,true);
 	gleft->incRef();
@@ -490,7 +490,7 @@ ColorTransform::ColorTransform(Class_base* c, const CXFORMWITHALPHA& cx)
 
 void ColorTransform::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_SEALED);
 
 	// properties
 	c->setDeclaredMethodByQName("color","",Class<IFunction>::getFunction(getColor),GETTER_METHOD,true);
@@ -582,7 +582,6 @@ ASFUNCTIONBODY(ColorTransform,setColor)
 
 ASFUNCTIONBODY(ColorTransform,getColor)
 {
-	assert_and_throw(argslen==1);
 	ColorTransform* th=static_cast<ColorTransform*>(obj);
 
 	int ao, ro, go, bo;
@@ -738,7 +737,7 @@ ASFUNCTIONBODY(ColorTransform,_toString)
 
 void Point::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_SEALED);
 	c->setDeclaredMethodByQName("x","",Class<IFunction>::getFunction(_getX),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("y","",Class<IFunction>::getFunction(_getY),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("length","",Class<IFunction>::getFunction(_getlength),GETTER_METHOD,true);
@@ -930,12 +929,13 @@ void Transform::finalize()
 
 void Transform::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_SEALED);
 	c->setDeclaredMethodByQName("colorTransform","",Class<IFunction>::getFunction(_getColorTransform),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("colorTransform","",Class<IFunction>::getFunction(_setColorTransform),SETTER_METHOD,true);
 	c->setDeclaredMethodByQName("matrix","",Class<IFunction>::getFunction(_setMatrix),SETTER_METHOD,true);
 	c->setDeclaredMethodByQName("matrix","",Class<IFunction>::getFunction(_getMatrix),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("matrix","",Class<IFunction>::getFunction(_setMatrix),SETTER_METHOD,true);
+	c->setDeclaredMethodByQName("concatenatedMatrix","",Class<IFunction>::getFunction(_getConcatenatedMatrix),GETTER_METHOD,true);
 }
 
 ASFUNCTIONBODY(Transform,_constructor)
@@ -985,6 +985,13 @@ ASFUNCTIONBODY(Transform,_setColorTransform)
 	return NULL;
 }
 
+ASFUNCTIONBODY(Transform,_getConcatenatedMatrix)
+{
+	Transform* th=Class<Transform>::cast(obj);
+	LOG(LOG_NOT_IMPLEMENTED,"contcatenatedMAtrix not implemented");
+	return Class<Matrix>::getInstanceS();
+}
+
 void Transform::buildTraits(ASObject* o)
 {
 }
@@ -999,7 +1006,7 @@ Matrix::Matrix(Class_base* c, const MATRIX& m):ASObject(c),matrix(m)
 
 void Matrix::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_SEALED);
 	
 	//Properties
 	c->setDeclaredMethodByQName("a","",Class<IFunction>::getFunction(_get_a),GETTER_METHOD,true);
@@ -1318,7 +1325,7 @@ ASFUNCTIONBODY(Matrix,deltaTransformPoint)
 
 void Vector3D::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_SEALED);
 
 	// constants
 	Vector3D* tx = new (c->memoryAccount) Vector3D(c);
@@ -1705,3 +1712,28 @@ ASFUNCTIONBODY(Vector3D,subtract)
 
 	return ret;
 }
+
+
+void Matrix3D::sinit(Class_base* c)
+{
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_SEALED);
+}
+
+ASFUNCTIONBODY(Matrix3D,_constructor)
+{
+	Matrix3D * th=static_cast<Matrix3D*>(obj);
+	LOG(LOG_NOT_IMPLEMENTED,"Matrix3D is not implemented");
+	return NULL;
+}
+
+void PerspectiveProjection::sinit(Class_base* c)
+{
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_SEALED);
+}
+
+ASFUNCTIONBODY(PerspectiveProjection,_constructor)
+{
+	PerspectiveProjection * th=static_cast<PerspectiveProjection*>(obj);
+	LOG(LOG_NOT_IMPLEMENTED,"PerspectiveProjection is not implemented");
+	return NULL;
+}
diff --git a/src/scripting/flash/geom/flashgeom.h b/src/scripting/flash/geom/flashgeom.h
index 1ca359a..31dd8e8 100644
--- a/src/scripting/flash/geom/flashgeom.h
+++ b/src/scripting/flash/geom/flashgeom.h
@@ -107,7 +107,8 @@ public:
 
 class ColorTransform: public ASObject
 {
-private:
+friend class BitmapData;
+protected:
 	number_t redMultiplier,greenMultiplier,blueMultiplier,alphaMultiplier;
 	number_t redOffset,greenOffset,blueOffset,alphaOffset;
 public:
@@ -184,6 +185,7 @@ public:
 	ASFUNCTION(_set_ty);
 };
 
+class DisplayObject;
 class Transform: public ASObject
 {
 private:
@@ -199,6 +201,8 @@ public:
 	ASFUNCTION(_setColorTransform);
 	ASFUNCTION(_getMatrix);
 	ASFUNCTION(_setMatrix);
+	ASFUNCTION(_getConcatenatedMatrix);
+	
 };
 
 class Vector3D: public ASObject
@@ -243,5 +247,22 @@ public:
 	ASFUNCTION(_toString);
 };
 
+class Matrix3D: public ASObject
+{
+public:
+	Matrix3D(Class_base* c):ASObject(c){}
+	static void sinit(Class_base* c);
+	
+	ASFUNCTION(_constructor);
 };
+class PerspectiveProjection: public ASObject
+{
+public:
+	PerspectiveProjection(Class_base* c):ASObject(c){}
+	static void sinit(Class_base* c);
+	
+	ASFUNCTION(_constructor);
+};
+
+}
 #endif /* SCRIPTING_FLASH_FLASHGEOM_H */
diff --git a/src/scripting/flash/media/flashmedia.cpp b/src/scripting/flash/media/flashmedia.cpp
index 3caaa55..f78cb52 100644
--- a/src/scripting/flash/media/flashmedia.cpp
+++ b/src/scripting/flash/media/flashmedia.cpp
@@ -24,6 +24,7 @@
 #include <iostream>
 #include "backends/audio.h"
 #include "backends/rendering.h"
+#include "backends/streamcache.h"
 #include "scripting/argconv.h"
 
 using namespace lightspark;
@@ -31,8 +32,7 @@ using namespace std;
 
 void SoundTransform::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<ASObject>::getRef());
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_SEALED | CLASS_FINAL);
 	REGISTER_GETTER_SETTER(c,volume);
 	REGISTER_GETTER_SETTER(c,pan);
 }
@@ -55,8 +55,7 @@ ASFUNCTIONBODY(SoundTransform,_constructor)
 
 void Video::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<DisplayObject>::getRef());
+	CLASS_SETUP(c, DisplayObject, _constructor, CLASS_SEALED);
 	c->setDeclaredMethodByQName("videoWidth","",Class<IFunction>::getFunction(_getVideoWidth),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("videoHeight","",Class<IFunction>::getFunction(_getVideoHeight),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("width","",Class<IFunction>::getFunction(Video::_getWidth),GETTER_METHOD,true);
@@ -64,8 +63,14 @@ void Video::sinit(Class_base* c)
 	c->setDeclaredMethodByQName("height","",Class<IFunction>::getFunction(Video::_getHeight),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("height","",Class<IFunction>::getFunction(Video::_setHeight),SETTER_METHOD,true);
 	c->setDeclaredMethodByQName("attachNetStream","",Class<IFunction>::getFunction(attachNetStream),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("clear","",Class<IFunction>::getFunction(clear),NORMAL_METHOD,true);
+	REGISTER_GETTER_SETTER(c, deblocking);
+	REGISTER_GETTER_SETTER(c, smoothing);
 }
 
+ASFUNCTIONBODY_GETTER_SETTER(Video, deblocking);
+ASFUNCTIONBODY_GETTER_SETTER(Video, smoothing);
+
 void Video::buildTraits(ASObject* o)
 {
 }
@@ -77,7 +82,8 @@ void Video::finalize()
 }
 
 Video::Video(Class_base* c, uint32_t w, uint32_t h)
-	: DisplayObject(c),width(w),height(h),videoWidth(0),videoHeight(0),initialized(false),netStream(NullRef)
+	: DisplayObject(c),width(w),height(h),videoWidth(0),videoHeight(0),
+	  initialized(false),netStream(NullRef),deblocking(0),smoothing(false)
 {
 }
 
@@ -204,6 +210,11 @@ ASFUNCTIONBODY(Video,attachNetStream)
 	th->netStream=_MR(Class<NetStream>::cast(args[0]));
 	return NULL;
 }
+ASFUNCTIONBODY(Video,clear)
+{
+	LOG(LOG_NOT_IMPLEMENTED,"clear is not implemented");
+	return NULL;
+}
 
 _NR<DisplayObject> Video::hitTestImpl(_NR<DisplayObject> last, number_t x, number_t y, DisplayObject::HIT_TYPE type)
 {
@@ -215,7 +226,16 @@ _NR<DisplayObject> Video::hitTestImpl(_NR<DisplayObject> last, number_t x, numbe
 }
 
 Sound::Sound(Class_base* c)
- :EventDispatcher(c),downloader(NULL),soundChannelCreated(false),bytesLoaded(0),bytesTotal(0),length(60*1000)
+	:EventDispatcher(c),downloader(NULL),soundData(new MemoryStreamCache),
+	 container(true),format(CODEC_NONE, 0, 0),bytesLoaded(0),bytesTotal(0),length(60*1000)
+{
+}
+
+Sound::Sound(Class_base* c, _R<StreamCache> data, AudioFormat _format)
+	:EventDispatcher(c),downloader(NULL),soundData(data),
+	 container(false),format(_format),
+	 bytesLoaded(soundData->getReceivedLength()),
+	 bytesTotal(soundData->getReceivedLength()),length(60*1000)
 {
 }
 
@@ -227,8 +247,7 @@ Sound::~Sound()
 
 void Sound::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<EventDispatcher>::getRef());
+	CLASS_SETUP(c, EventDispatcher, _constructor, CLASS_SEALED);
 	c->setDeclaredMethodByQName("load","",Class<IFunction>::getFunction(load),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("play","",Class<IFunction>::getFunction(play),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("close","",Class<IFunction>::getFunction(close),NORMAL_METHOD,true);
@@ -261,6 +280,9 @@ ASFUNCTIONBODY(Sound,load)
 	th->url = urlRequest->getRequestURL();
 	urlRequest->getPostData(th->postData);
 
+	_R<StreamCache> c(_MR(new MemoryStreamCache()));
+	th->soundData = c;
+
 	if(!th->url.isValid())
 	{
 		//Notify an error during loading
@@ -275,13 +297,13 @@ ASFUNCTIONBODY(Sound,load)
 	{
 		//This is a GET request
 		//Use disk cache our downloaded files
-		th->downloader=getSys()->downloadManager->download(th->url, true, th);
+		th->downloader=getSys()->downloadManager->download(th->url, th->soundData, th);
 	}
 	else
 	{
 		list<tiny_string> headers=urlRequest->getHeaders();
-		th->downloader=getSys()->downloadManager->downloadWithData(th->url, th->postData,
-				headers, th);
+		th->downloader=getSys()->downloadManager->downloadWithData(th->url,
+				th->soundData, th->postData, headers, th);
 		//Clean up the postData for the next load
 		th->postData.clear();
 	}
@@ -302,19 +324,11 @@ ASFUNCTIONBODY(Sound,play)
 	if(startTime!=0)
 		LOG(LOG_NOT_IMPLEMENTED,"startTime not supported in Sound::play");
 
-	if (!th->soundChannelCreated)
-	{
-		th->soundChannelCreated = true;
-		th->incRef();
-		return Class<SoundChannel>::getInstanceS(th->downloader, _MNR(th));
-	}
+	th->incRef();
+	if (th->container)
+		return Class<SoundChannel>::getInstanceS(th->soundData);
 	else
-	{
-		LOG(LOG_NOT_IMPLEMENTED,"Sound::play called more than once");
-		// should return a new independent SoundChannel for
-		// the same downloaded data
-		return getSys()->getUndefinedRef();
-	}
+		return Class<SoundChannel>::getInstanceS(th->soundData, th->format);
 }
 
 ASFUNCTIONBODY(Sound,close)
@@ -352,8 +366,7 @@ ASFUNCTIONBODY_GETTER(Sound,length);
 
 void SoundLoaderContext::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<ASObject>::getRef());
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_SEALED);
 	REGISTER_GETTER_SETTER(c,bufferTime);
 	REGISTER_GETTER_SETTER(c,checkPolicyFile);
 }
@@ -374,10 +387,11 @@ ASFUNCTIONBODY(SoundLoaderContext,_constructor)
 ASFUNCTIONBODY_GETTER_SETTER(SoundLoaderContext,bufferTime);
 ASFUNCTIONBODY_GETTER_SETTER(SoundLoaderContext,checkPolicyFile);
 
-SoundChannel::SoundChannel(Class_base* c, std::streambuf *s, _NR<Sound> _owner)
-  : EventDispatcher(c),stream(s),owner(_owner),stopped(false),audioDecoder(NULL),audioStream(NULL),position(0)
+SoundChannel::SoundChannel(Class_base* c, _NR<StreamCache> _stream, AudioFormat _format)
+: EventDispatcher(c),stream(_stream),stopped(false),audioDecoder(NULL),audioStream(NULL),
+  format(_format),position(0),soundTransform(_MR(Class<SoundTransform>::getInstanceS()))
 {
-	if(s)
+	if (!stream.isNull())
 	{
 		// Start playback
 		incRef();
@@ -392,19 +406,35 @@ SoundChannel::~SoundChannel()
 
 void SoundChannel::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<EventDispatcher>::getRef());
+	CLASS_SETUP(c, EventDispatcher, _constructor, CLASS_SEALED | CLASS_FINAL);
 	c->setDeclaredMethodByQName("stop","",Class<IFunction>::getFunction(stop),NORMAL_METHOD,true);
 
 	REGISTER_GETTER(c,position);
+	REGISTER_GETTER_SETTER(c,soundTransform);
 }
 
 ASFUNCTIONBODY_GETTER(SoundChannel,position);
+ASFUNCTIONBODY_GETTER_SETTER_CB(SoundChannel,soundTransform,validateSoundTransform);
 
 void SoundChannel::buildTraits(ASObject* o)
 {
 }
 
+void SoundChannel::finalize()
+{
+	EventDispatcher::finalize();
+	soundTransform.reset();
+}
+
+void SoundChannel::validateSoundTransform(_NR<SoundTransform> oldValue)
+{
+	if (soundTransform.isNull())
+	{
+		soundTransform = oldValue;
+		throwError<TypeError>(kNullPointerError, "soundTransform");
+	}
+}
+
 ASFUNCTIONBODY(SoundChannel, _constructor)
 {
 	EventDispatcher::_constructor(obj, NULL, 0);
@@ -421,7 +451,18 @@ ASFUNCTIONBODY(SoundChannel, stop)
 
 void SoundChannel::execute()
 {
-	stream.exceptions ( istream::eofbit | istream::failbit | istream::badbit );
+	if (format.codec == CODEC_NONE)
+		playStream();
+	else
+		playRaw();
+}
+
+void SoundChannel::playStream()
+{
+	assert(!stream.isNull());
+	std::streambuf *sbuf = stream->createReader();
+	istream s(sbuf);
+	s.exceptions ( istream::eofbit | istream::failbit | istream::badbit );
 
 	bool waitForFlush=true;
 	StreamDecoder* streamDecoder=NULL;
@@ -429,7 +470,7 @@ void SoundChannel::execute()
 	try
 	{
 #ifdef ENABLE_LIBAVCODEC
-		streamDecoder=new FFMpegStreamDecoder(stream);
+		streamDecoder=new FFMpegStreamDecoder(s);
 		if(!streamDecoder->isValid())
 			threadAbort();
 
@@ -486,6 +527,45 @@ void SoundChannel::execute()
 		audioStream=NULL;
 	}
 	delete streamDecoder;
+	delete sbuf;
+
+	if (!ACQUIRE_READ(stopped))
+	{
+		incRef();
+		getVm()->addEvent(_MR(this),_MR(Class<Event>::getInstanceS("soundComplete")));
+	}
+}
+
+void SoundChannel::playRaw()
+{
+	assert(!stream.isNull());
+	FFMpegAudioDecoder *decoder = new FFMpegAudioDecoder(format.codec,
+							     format.sampleRate,
+							     format.channels,
+							     true);
+	if (!decoder)
+		return;
+	if(!getSys()->audioManager->pluginLoaded())
+		return;
+
+	AudioStream *audioStream = NULL;
+	std::streambuf *sbuf = stream->createReader();
+	istream stream(sbuf);
+	do
+	{
+		decoder->decodeStreamSomePackets(stream, 0);
+		if (decoder->isValid())
+			audioStream=getSys()->audioManager->createStreamPlugin(decoder);
+	}
+	while (!ACQUIRE_READ(stopped) && !stream.eof() && !stream.fail() && !stream.bad());
+
+	decoder->setFlushing();
+	decoder->waitFlushed();
+	sleep(1);
+	
+	delete audioStream;
+	delete decoder;
+	delete sbuf;
 
 	if (!ACQUIRE_READ(stopped))
 	{
@@ -513,8 +593,7 @@ void SoundChannel::threadAbort()
 
 void StageVideo::sinit(Class_base *c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<EventDispatcher>::getRef());
+	CLASS_SETUP(c, EventDispatcher, _constructor, CLASS_SEALED);
 }
 
 ASFUNCTIONBODY(StageVideo,_constructor)
@@ -525,14 +604,14 @@ ASFUNCTIONBODY(StageVideo,_constructor)
 
 void StageVideoAvailability::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_SEALED | CLASS_FINAL);
 	c->setVariableByQName("AVAILABLE","",Class<ASString>::getInstanceS("available"),DECLARED_TRAIT);
 	c->setVariableByQName("UNAVAILABLE","",Class<ASString>::getInstanceS("unavailable"),DECLARED_TRAIT);
 }
 
 void VideoStatus::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_SEALED | CLASS_FINAL);
 	c->setVariableByQName("ACCELERATED","",Class<ASString>::getInstanceS("accelerated"),DECLARED_TRAIT);
 	c->setVariableByQName("SOFTWARE","",Class<ASString>::getInstanceS("software"),DECLARED_TRAIT);
 	c->setVariableByQName("UNAVAILABLE","",Class<ASString>::getInstanceS("unavailable"),DECLARED_TRAIT);
diff --git a/src/scripting/flash/media/flashmedia.h b/src/scripting/flash/media/flashmedia.h
index b7a2841..5397764 100644
--- a/src/scripting/flash/media/flashmedia.h
+++ b/src/scripting/flash/media/flashmedia.h
@@ -34,6 +34,16 @@ namespace lightspark
 
 class AudioDecoder;
 class NetStream;
+class StreamCache;
+
+class AudioFormat
+{
+public:
+	AudioFormat(LS_AUDIO_CODEC co, int sr, int ch):codec(co),sampleRate(sr),channels(ch) {}
+	LS_AUDIO_CODEC codec;
+	int sampleRate;
+	int channels;
+};
 
 class Sound: public EventDispatcher, public ILoadable
 {
@@ -41,7 +51,12 @@ private:
 	URLInfo url;
 	std::vector<uint8_t> postData;
 	Downloader* downloader;
-	bool soundChannelCreated;
+	_R<StreamCache> soundData;
+	// If container is true, audio format is parsed from
+	// soundData. If container is false, soundData is raw samples
+	// and format is defined by format member.
+	bool container;
+	AudioFormat format;
 	ASPROPERTY_GETTER(uint32_t,bytesLoaded);
 	ASPROPERTY_GETTER(uint32_t,bytesTotal);
 	ASPROPERTY_GETTER(number_t,length);
@@ -50,6 +65,7 @@ private:
 	void setBytesLoaded(uint32_t b);
 public:
 	Sound(Class_base* c);
+	Sound(Class_base* c, _R<StreamCache> soundData, AudioFormat format);
 	~Sound();
 	static void sinit(Class_base*);
 	static void buildTraits(ASObject* o);
@@ -72,20 +88,23 @@ public:
 class SoundChannel : public EventDispatcher, public IThreadJob
 {
 private:
-	std::istream stream;
-	// owner keeps reference to the Sound object that owns the
-	// streambuf. TODO: ugly, get rid of this
-	_NR<Sound> owner;
+        _NR<StreamCache> stream;
 	Mutex mutex;
 	ACQUIRE_RELEASE_FLAG(stopped);
 	AudioDecoder* audioDecoder;
 	AudioStream* audioStream;
+	AudioFormat format;
 	ASPROPERTY_GETTER_SETTER(uint32_t,position);
+	ASPROPERTY_GETTER_SETTER(_NR<SoundTransform>,soundTransform);
+	void validateSoundTransform(_NR<SoundTransform>);
+	void playStream();
+	void playRaw();
 public:
-	SoundChannel(Class_base* c, std::streambuf *s=NULL, _NR<Sound> owner=NullRef);
+	SoundChannel(Class_base* c, _NR<StreamCache> stream=NullRef, AudioFormat format=AudioFormat(CODEC_NONE,0,0));
 	~SoundChannel();
 	static void sinit(Class_base* c);
 	static void buildTraits(ASObject* o);
+	void finalize();
 	ASFUNCTION(_constructor);
 	ASFUNCTION(stop);
 
@@ -103,6 +122,8 @@ private:
 	mutable uint32_t videoWidth, videoHeight;
 	bool initialized;
 	_NR<NetStream> netStream;
+	ASPROPERTY_GETTER_SETTER(int32_t, deblocking);
+	ASPROPERTY_GETTER_SETTER(bool, smoothing);
 public:
 	Video(Class_base* c, uint32_t w=320, uint32_t h=240);
 	void finalize();
@@ -117,6 +138,7 @@ public:
 	ASFUNCTION(_getHeight);
 	ASFUNCTION(_setHeight);
 	ASFUNCTION(attachNetStream);
+	ASFUNCTION(clear);
 	void renderImpl(RenderContext& ctxt) const;
 	bool boundsRect(number_t& xmin, number_t& xmax, number_t& ymin, number_t& ymax) const;
 	_NR<DisplayObject> hitTestImpl(_NR<DisplayObject> last, number_t x, number_t y, DisplayObject::HIT_TYPE type);
diff --git a/src/scripting/flash/accessibility/flashaccessibility.cpp b/src/scripting/flash/net/NetStreamPlayOptions.cpp
similarity index 50%
copy from src/scripting/flash/accessibility/flashaccessibility.cpp
copy to src/scripting/flash/net/NetStreamPlayOptions.cpp
index ebc460d..86ba82c 100644
--- a/src/scripting/flash/accessibility/flashaccessibility.cpp
+++ b/src/scripting/flash/net/NetStreamPlayOptions.cpp
@@ -1,8 +1,6 @@
 /**************************************************************************
     Lightspark, a free flash player implementation
 
-    Copyright (C) 2009-2013  Alessandro Pignotti (a.pignotti at sssup.it)
-
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU Lesser General Public License as published by
     the Free Software Foundation, either version 3 of the License, or
@@ -17,35 +15,38 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 **************************************************************************/
 
-#include "scripting/flash/accessibility/flashaccessibility.h"
+#include "scripting/flash/net/NetStreamPlayOptions.h"
 #include "scripting/class.h"
 #include "scripting/argconv.h"
 
+using namespace std;
 using namespace lightspark;
 
-void AccessibilityProperties::sinit(Class_base* c)
+NetStreamPlayOptions::NetStreamPlayOptions(Class_base* c):EventDispatcher(c),len(-1),offset(-1),start(-2)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<ASObject>::getRef());
-	REGISTER_GETTER_SETTER(c,name);
+	
 }
-
-ASFUNCTIONBODY(AccessibilityProperties,_constructor)
+void NetStreamPlayOptions::sinit(Class_base* c)
 {
-	LOG(LOG_NOT_IMPLEMENTED, _("AccessibilityProperties class is unimplemented."));
-	return NULL;
+	CLASS_SETUP(c, EventDispatcher, _constructor, CLASS_DYNAMIC_NOT_FINAL);
+	REGISTER_GETTER_SETTER(c,len);
+	REGISTER_GETTER_SETTER(c,offset);
+	REGISTER_GETTER_SETTER(c,oldStreamName);
+	REGISTER_GETTER_SETTER(c,start);
+	REGISTER_GETTER_SETTER(c,streamName);
+	REGISTER_GETTER_SETTER(c,transition);
 }
 
-ASFUNCTIONBODY_GETTER_SETTER(AccessibilityProperties,name);
+ASFUNCTIONBODY_GETTER_SETTER(NetStreamPlayOptions,len);
+ASFUNCTIONBODY_GETTER_SETTER(NetStreamPlayOptions,offset);
+ASFUNCTIONBODY_GETTER_SETTER(NetStreamPlayOptions,oldStreamName);
+ASFUNCTIONBODY_GETTER_SETTER(NetStreamPlayOptions,start);
+ASFUNCTIONBODY_GETTER_SETTER(NetStreamPlayOptions,streamName);
+ASFUNCTIONBODY_GETTER_SETTER(NetStreamPlayOptions,transition);
 
-void AccessibilityImplementation::sinit(Class_base* c)
+ASFUNCTIONBODY(NetStreamPlayOptions,_constructor)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<ASObject>::getRef());
-}
-
-ASFUNCTIONBODY(AccessibilityImplementation,_constructor)
-{
-	LOG(LOG_NOT_IMPLEMENTED, _("AccessibilityImplementation class is unimplemented."));
+	EventDispatcher::_constructor(obj, NULL, 0);
 	return NULL;
 }
+
diff --git a/src/scripting/flash/sensors/flashsensors.h b/src/scripting/flash/net/NetStreamPlayOptions.h
similarity index 64%
copy from src/scripting/flash/sensors/flashsensors.h
copy to src/scripting/flash/net/NetStreamPlayOptions.h
index 9f9ef19..8330d2a 100644
--- a/src/scripting/flash/sensors/flashsensors.h
+++ b/src/scripting/flash/net/NetStreamPlayOptions.h
@@ -1,8 +1,6 @@
 /**************************************************************************
     Lightspark, a free flash player implementation
 
-    Copyright (C) 2011-2013  Alessandro Pignotti (a.pignotti at sssup.it)
-
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU Lesser General Public License as published by
     the Free Software Foundation, either version 3 of the License, or
@@ -17,25 +15,29 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 **************************************************************************/
 
-#ifndef SCRIPTING_FLASH_SENSORS_FLASHSENSORS_H
-#define SCRIPTING_FLASH_SENSORS_FLASHSENSORS_H 1
+#ifndef NETSTREAMPLAYOPTIONS_H
+#define NETSTREAMPLAYOPTIONS_H
 
-#include "compat.h"
 #include "asobject.h"
 #include "scripting/flash/events/flashevents.h"
-#include "thread_pool.h"
-#include "backends/netutils.h"
-#include "timer.h"
-#include "backends/interfaces/audio/IAudioPlugin.h"
 
 namespace lightspark
 {
-class Accelerometer: public ASObject {
-	public:
-		Accelerometer(Class_base* c);
-		static void sinit(Class_base* c);
-		static void buildTraits(ASObject* o);
-		ASFUNCTION(_isSupported);
+
+class NetStreamPlayOptions: public EventDispatcher
+{
+private:
+	ASPROPERTY_GETTER_SETTER(number_t,len);
+	ASPROPERTY_GETTER_SETTER(number_t,offset);
+	ASPROPERTY_GETTER_SETTER(tiny_string,oldStreamName);
+	ASPROPERTY_GETTER_SETTER(number_t,start);
+	ASPROPERTY_GETTER_SETTER(tiny_string,streamName);
+	ASPROPERTY_GETTER_SETTER(tiny_string,transition);
+public:
+	NetStreamPlayOptions(Class_base* c);
+	static void sinit(Class_base*);
+	ASFUNCTION(_constructor);
 };
+
 }
-#endif /* SCRIPTING_FLASH_SENSORS_FLASHSENSORS_H */
+#endif // NETSTREAMPLAYOPTIONS_H
diff --git a/src/scripting/flash/accessibility/flashaccessibility.cpp b/src/scripting/flash/net/NetStreamPlayTransitions.cpp
similarity index 51%
copy from src/scripting/flash/accessibility/flashaccessibility.cpp
copy to src/scripting/flash/net/NetStreamPlayTransitions.cpp
index ebc460d..7b23154 100644
--- a/src/scripting/flash/accessibility/flashaccessibility.cpp
+++ b/src/scripting/flash/net/NetStreamPlayTransitions.cpp
@@ -1,8 +1,6 @@
 /**************************************************************************
     Lightspark, a free flash player implementation
 
-    Copyright (C) 2009-2013  Alessandro Pignotti (a.pignotti at sssup.it)
-
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU Lesser General Public License as published by
     the Free Software Foundation, either version 3 of the License, or
@@ -16,36 +14,27 @@
     You should have received a copy of the GNU Lesser General Public License
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 **************************************************************************/
-
-#include "scripting/flash/accessibility/flashaccessibility.h"
+#include "scripting/flash/net/NetStreamPlayTransitions.h"
 #include "scripting/class.h"
 #include "scripting/argconv.h"
 
+using namespace std;
 using namespace lightspark;
 
-void AccessibilityProperties::sinit(Class_base* c)
-{
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<ASObject>::getRef());
-	REGISTER_GETTER_SETTER(c,name);
-}
-
-ASFUNCTIONBODY(AccessibilityProperties,_constructor)
+NetStreamPlayTransitions::NetStreamPlayTransitions(Class_base* c):ASObject(c)
 {
-	LOG(LOG_NOT_IMPLEMENTED, _("AccessibilityProperties class is unimplemented."));
-	return NULL;
+	
 }
 
-ASFUNCTIONBODY_GETTER_SETTER(AccessibilityProperties,name);
-
-void AccessibilityImplementation::sinit(Class_base* c)
+void NetStreamPlayTransitions::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<ASObject>::getRef());
+	CLASS_SETUP(c, ASObject, NULL, CLASS_FINAL);
+	c->setVariableByQName("APPEND","",Class<ASString>::getInstanceS("append"),CONSTANT_TRAIT);
+	c->setVariableByQName("APPEND_AND_WAIT","",Class<ASString>::getInstanceS("appendAndWait"),CONSTANT_TRAIT);
+	c->setVariableByQName("RESET","",Class<ASString>::getInstanceS("reset"),CONSTANT_TRAIT);
+	c->setVariableByQName("RESUME","",Class<ASString>::getInstanceS("resume"),CONSTANT_TRAIT);
+	c->setVariableByQName("STOP","",Class<ASString>::getInstanceS("stop"),CONSTANT_TRAIT);
+	c->setVariableByQName("SWAP","",Class<ASString>::getInstanceS("swap"),CONSTANT_TRAIT);
+	c->setVariableByQName("SWITCH","",Class<ASString>::getInstanceS("switch"),CONSTANT_TRAIT);
 }
 
-ASFUNCTIONBODY(AccessibilityImplementation,_constructor)
-{
-	LOG(LOG_NOT_IMPLEMENTED, _("AccessibilityImplementation class is unimplemented."));
-	return NULL;
-}
diff --git a/src/backends/rtmputils.h b/src/scripting/flash/net/NetStreamPlayTransitions.h
similarity index 68%
copy from src/backends/rtmputils.h
copy to src/scripting/flash/net/NetStreamPlayTransitions.h
index 7e9de51..428d87b 100644
--- a/src/backends/rtmputils.h
+++ b/src/scripting/flash/net/NetStreamPlayTransitions.h
@@ -1,8 +1,6 @@
 /**************************************************************************
     Lightspark, a free flash player implementation
 
-    Copyright (C) 2011-2013  Alessandro Pignotti (a.pignotti at sssup.it)
-
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU Lesser General Public License as published by
     the Free Software Foundation, either version 3 of the License, or
@@ -16,26 +14,20 @@
     You should have received a copy of the GNU Lesser General Public License
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 **************************************************************************/
+#ifndef NETSTREAMPLAYTRANSITIONS_H
+#define NETSTREAMPLAYTRANSITIONS_H
 
-#ifndef BACKENDS_RTMPUTILS_H
-#define BACKENDS_RTMPUTILS_H 1
-
-#include "backends/netutils.h"
+#include "asobject.h"
 
 namespace lightspark
 {
 
-class ILoadable;
-
-class RTMPDownloader: public ThreadedDownloader
+class NetStreamPlayTransitions: public ASObject
 {
-private:
-	void execute();
-	void threadAbort();
-	tiny_string stream;
 public:
-	RTMPDownloader(const tiny_string& _url, const tiny_string& _stream, ILoadable* o);
+	NetStreamPlayTransitions(Class_base* c);
+	static void sinit(Class_base*);
 };
 
-};
-#endif /* BACKENDS_RTMPUTILS_H */
+}
+#endif // NETSTREAMPLAYTRANSITIONS_H
diff --git a/src/scripting/flash/net/URLRequestHeader.cpp b/src/scripting/flash/net/URLRequestHeader.cpp
index cee832c..4bd97d6 100644
--- a/src/scripting/flash/net/URLRequestHeader.cpp
+++ b/src/scripting/flash/net/URLRequestHeader.cpp
@@ -10,8 +10,7 @@ URLRequestHeader::URLRequestHeader(Class_base* c) : ASObject(c)
 
 void URLRequestHeader::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<ASObject>::getRef());
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_FINAL | CLASS_SEALED);
 	REGISTER_GETTER_SETTER(c,name);
 	REGISTER_GETTER_SETTER(c,value);
 }
diff --git a/src/scripting/flash/net/URLStream.cpp b/src/scripting/flash/net/URLStream.cpp
index 1d3594a..3702865 100644
--- a/src/scripting/flash/net/URLStream.cpp
+++ b/src/scripting/flash/net/URLStream.cpp
@@ -43,17 +43,19 @@ void URLStreamThread::execute()
 
 	//TODO: support httpStatus, progress events
 
-	if(!createDownloader(false, loader))
+	_R<MemoryStreamCache> cache(_MR(new MemoryStreamCache));
+	if(!createDownloader(cache, loader))
 		return;
 
 	bool success=false;
 	if(!downloader->hasFailed())
 	{
 		getVm()->addEvent(loader,_MR(Class<Event>::getInstanceS("open")));
-		downloader->waitForTermination();
+		cache->waitForTermination();
 		if(!downloader->hasFailed() && !threadAborting)
 		{
-			istream s(downloader);
+			std::streambuf *sbuf = cache->createReader();
+			istream s(sbuf);
 			uint8_t* buf=new uint8_t[downloader->getLength()];
 			//TODO: avoid this useless copy
 			s.read((char*)buf,downloader->getLength());
@@ -61,6 +63,7 @@ void URLStreamThread::execute()
 			data->acquireBuffer(buf,downloader->getLength());
 			//The buffers must not be deleted, it's now handled by the ByteArray instance
 			success=true;
+			delete sbuf;
 		}
 	}
 
@@ -86,8 +89,7 @@ void URLStreamThread::execute()
 
 void URLStream::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<EventDispatcher>::getRef());
+	CLASS_SETUP(c, EventDispatcher, _constructor, CLASS_SEALED);
 	c->setDeclaredMethodByQName("load","",Class<IFunction>::getFunction(load),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("close","",Class<IFunction>::getFunction(close),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("load","",Class<IFunction>::getFunction(load),NORMAL_METHOD,true);
diff --git a/src/scripting/flash/net/URLStream.h b/src/scripting/flash/net/URLStream.h
index 3497f6f..1e7af44 100644
--- a/src/scripting/flash/net/URLStream.h
+++ b/src/scripting/flash/net/URLStream.h
@@ -23,6 +23,7 @@
 #include "compat.h"
 #include "asobject.h"
 #include "scripting/flash/events/flashevents.h"
+#include "scripting/flash/utils/ByteArray.h"
 #include "thread_pool.h"
 #include "backends/netutils.h"
 
diff --git a/src/scripting/flash/net/XMLSocket.cpp b/src/scripting/flash/net/XMLSocket.cpp
index 273ce00..8fe5abd 100644
--- a/src/scripting/flash/net/XMLSocket.cpp
+++ b/src/scripting/flash/net/XMLSocket.cpp
@@ -172,8 +172,7 @@ XMLSocket::~XMLSocket()
 
 void XMLSocket::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<EventDispatcher>::getRef());
+	CLASS_SETUP(c, EventDispatcher, _constructor, CLASS_SEALED);
 	c->setDeclaredMethodByQName("close","",Class<IFunction>::getFunction(_close),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("connect","",Class<IFunction>::getFunction(_connect),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("send","",Class<IFunction>::getFunction(_send),NORMAL_METHOD,true);
diff --git a/src/scripting/flash/net/flashnet.cpp b/src/scripting/flash/net/flashnet.cpp
index 7b268bc..695db78 100644
--- a/src/scripting/flash/net/flashnet.cpp
+++ b/src/scripting/flash/net/flashnet.cpp
@@ -29,6 +29,7 @@
 #include "backends/audio.h"
 #include "backends/builtindecoder.h"
 #include "backends/rendering.h"
+#include "backends/streamcache.h"
 #include "scripting/argconv.h"
 
 using namespace std;
@@ -41,14 +42,15 @@ URLRequest::URLRequest(Class_base* c):ASObject(c),method(GET),contentType("appli
 
 void URLRequest::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<ASObject>::getRef());
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_FINAL | CLASS_SEALED);
 	c->setDeclaredMethodByQName("url","",Class<IFunction>::getFunction(_setURL),SETTER_METHOD,true);
 	c->setDeclaredMethodByQName("url","",Class<IFunction>::getFunction(_getURL),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("method","",Class<IFunction>::getFunction(_setMethod),SETTER_METHOD,true);
 	c->setDeclaredMethodByQName("method","",Class<IFunction>::getFunction(_getMethod),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("data","",Class<IFunction>::getFunction(_setData),SETTER_METHOD,true);
 	c->setDeclaredMethodByQName("data","",Class<IFunction>::getFunction(_getData),GETTER_METHOD,true);
+	c->setDeclaredMethodByQName("digest","",Class<IFunction>::getFunction(_setDigest),SETTER_METHOD,true);
+	c->setDeclaredMethodByQName("digest","",Class<IFunction>::getFunction(_getDigest),GETTER_METHOD,true);
 	REGISTER_GETTER_SETTER(c,contentType);
 	REGISTER_GETTER_SETTER(c,requestHeaders);
 }
@@ -283,12 +285,51 @@ ASFUNCTIONBODY(URLRequest,_setData)
 	return NULL;
 }
 
+ASFUNCTIONBODY(URLRequest,_getDigest)
+{
+	URLRequest* th=obj->as<URLRequest>();
+	if (th->digest.empty())
+		return getSys()->getNullRef();
+	else
+		return Class<ASString>::getInstanceS(th->digest);
+}
+
+ASFUNCTIONBODY(URLRequest,_setDigest)
+{
+	URLRequest* th=obj->as<URLRequest>();
+	tiny_string value;
+	ARG_UNPACK(value);
+
+	int numHexChars = 0;
+	bool validChars = true;
+	for (CharIterator it=value.begin(); it!=value.end(); ++it)
+	{
+		if (((*it >= 'A') && (*it <= 'F')) ||
+		    ((*it >= 'a') && (*it <= 'f')) ||
+		    ((*it >= '0') && (*it <= '9')))
+		{
+			numHexChars++;
+		}
+		else
+		{
+			validChars = false;
+			break;
+		}
+	}
+
+	if (!validChars || numHexChars != 64)
+		throw Class<ArgumentError>::getInstanceS("An invalid digest was supplied", 2034);
+
+	th->digest = value;
+	return NULL;
+}
+
 ASFUNCTIONBODY_GETTER_SETTER(URLRequest,contentType);
 ASFUNCTIONBODY_GETTER_SETTER(URLRequest,requestHeaders);
 
 void URLRequestMethod::sinit(Class_base* c)
 {
-	c->setSuper(Class<ASObject>::getRef());
+	CLASS_SETUP_NO_CONSTRUCTOR(c, ASObject, CLASS_FINAL | CLASS_SEALED);
 	c->setVariableByQName("GET","",Class<ASString>::getInstanceS("GET"),DECLARED_TRAIT);
 	c->setVariableByQName("POST","",Class<ASString>::getInstanceS("POST"),DECLARED_TRAIT);
 }
@@ -304,7 +345,8 @@ void URLLoaderThread::execute()
 
 	//TODO: support httpStatus, progress events
 
-	if(!createDownloader(false, loader, loader.getPtr()))
+	_R<MemoryStreamCache> cache(_MR(new MemoryStreamCache));
+	if(!createDownloader(cache, loader, loader.getPtr()))
 		return;
 
 	_NR<ASObject> data;
@@ -312,10 +354,12 @@ void URLLoaderThread::execute()
 	if(!downloader->hasFailed())
 	{
 		getVm()->addEvent(loader,_MR(Class<Event>::getInstanceS("open")));
-		downloader->waitForTermination();
+
+		cache->waitForTermination();
 		if(!downloader->hasFailed() && !threadAborting)
 		{
-			istream s(downloader);
+			std::streambuf *sbuf = cache->createReader();
+			istream s(sbuf);
 			uint8_t* buf=new uint8_t[downloader->getLength()+1];
 			//TODO: avoid this useless copy
 			s.read((char*)buf,downloader->getLength());
@@ -344,6 +388,7 @@ void URLLoaderThread::execute()
 				assert(false && "invalid dataFormat");
 			}
 
+			delete sbuf;
 			success=true;
 		}
 	}
@@ -381,8 +426,7 @@ void URLLoader::finalize()
 
 void URLLoader::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<EventDispatcher>::getRef());
+	CLASS_SETUP(c, EventDispatcher, _constructor, CLASS_SEALED);
 	c->setDeclaredMethodByQName("dataFormat","",Class<IFunction>::getFunction(_getDataFormat),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("data","",Class<IFunction>::getFunction(_getData),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("data","",Class<IFunction>::getFunction(_setData),SETTER_METHOD,true);
@@ -539,12 +583,19 @@ ASFUNCTIONBODY(URLLoader,_setDataFormat)
 
 void URLLoaderDataFormat::sinit(Class_base* c)
 {
-	c->setSuper(Class<ASObject>::getRef());
+	CLASS_SETUP(c, ASObject, _constructorNotInstantiatable, CLASS_FINAL | CLASS_SEALED);
 	c->setVariableByQName("VARIABLES","",Class<ASString>::getInstanceS("variables"),DECLARED_TRAIT);
 	c->setVariableByQName("TEXT","",Class<ASString>::getInstanceS("text"),DECLARED_TRAIT);
 	c->setVariableByQName("BINARY","",Class<ASString>::getInstanceS("binary"),DECLARED_TRAIT);
 }
 
+void SharedObjectFlushStatus::sinit(Class_base* c)
+{
+	CLASS_SETUP_NO_CONSTRUCTOR(c, ASObject, CLASS_FINAL);
+	c->setVariableByQName("FLUSHED","",Class<ASString>::getInstanceS("flushed"),DECLARED_TRAIT);
+	c->setVariableByQName("PENDING","",Class<ASString>::getInstanceS("pending"),DECLARED_TRAIT);
+}
+
 SharedObject::SharedObject(Class_base* c):EventDispatcher(c)
 {
 	data=_MR(new_asobject());
@@ -552,10 +603,12 @@ SharedObject::SharedObject(Class_base* c):EventDispatcher(c)
 
 void SharedObject::sinit(Class_base* c)
 {
-	c->setSuper(Class<EventDispatcher>::getRef());
+	// TODO: Use _constructorNotInstantiatable after getLocal is
+	// implemented
+	CLASS_SETUP_NO_CONSTRUCTOR(c, EventDispatcher, CLASS_SEALED);
 	c->setDeclaredMethodByQName("getLocal","",Class<IFunction>::getFunction(getLocal),NORMAL_METHOD,false);
 	REGISTER_GETTER(c,data);
-};
+}
 
 ASFUNCTIONBODY_GETTER(SharedObject,data);
 
@@ -567,20 +620,21 @@ ASFUNCTIONBODY(SharedObject,getLocal)
 
 void ObjectEncoding::sinit(Class_base* c)
 {
-	c->setSuper(Class<ASObject>::getRef());
+	CLASS_SETUP(c, ASObject, _constructorNotInstantiatable, CLASS_FINAL | CLASS_SEALED);
 	c->setVariableByQName("AMF0","",abstract_i(AMF0),DECLARED_TRAIT);
 	c->setVariableByQName("AMF3","",abstract_i(AMF3),DECLARED_TRAIT);
 	c->setVariableByQName("DEFAULT","",abstract_i(DEFAULT),DECLARED_TRAIT);
 };
 
-NetConnection::NetConnection(Class_base* c):EventDispatcher(c),_connected(false),downloader(NULL),messageCount(0)
+NetConnection::NetConnection(Class_base* c):
+	EventDispatcher(c),_connected(false),downloader(NULL),messageCount(0),
+	proxyType(PT_NONE)
 {
 }
 
 void NetConnection::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<EventDispatcher>::getRef());
+	CLASS_SETUP(c, EventDispatcher, _constructor, CLASS_SEALED);
 	c->setDeclaredMethodByQName("connect","",Class<IFunction>::getFunction(connect),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("call","",Class<IFunction>::getFunction(call),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("connected","",Class<IFunction>::getFunction(_getConnected),GETTER_METHOD,true);
@@ -590,7 +644,10 @@ void NetConnection::sinit(Class_base* c)
 	c->setDeclaredMethodByQName("objectEncoding","",Class<IFunction>::getFunction(_getObjectEncoding),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("objectEncoding","",Class<IFunction>::getFunction(_setObjectEncoding),SETTER_METHOD,true);
 	c->setDeclaredMethodByQName("protocol","",Class<IFunction>::getFunction(_getProtocol),GETTER_METHOD,true);
+	c->setDeclaredMethodByQName("proxyType","",Class<IFunction>::getFunction(_getProxyType),GETTER_METHOD,true);
+	c->setDeclaredMethodByQName("proxyType","",Class<IFunction>::getFunction(_setProxyType),SETTER_METHOD,true);
 	c->setDeclaredMethodByQName("uri","",Class<IFunction>::getFunction(_getURI),GETTER_METHOD,true);
+	c->setDeclaredMethodByQName("close","",Class<IFunction>::getFunction(close),GETTER_METHOD,true);
 	REGISTER_GETTER_SETTER(c,client);
 }
 
@@ -607,6 +664,7 @@ void NetConnection::finalize()
 
 ASFUNCTIONBODY(NetConnection, _constructor)
 {
+	EventDispatcher::_constructor(obj, NULL, 0);
 	NetConnection* th=Class<NetConnection>::cast(obj);
 	th->objectEncoding = getSys()->staticNetConnectionDefaultObjectEncoding;
 	return NULL;
@@ -683,22 +741,25 @@ void NetConnection::execute()
 	assert(!messageData.empty());
 	std::list<tiny_string> headers;
 	headers.push_back("Content-Type: application/x-amf");
-	downloader=getSys()->downloadManager->downloadWithData(uri, messageData,
-			headers, NULL);
+	_R<MemoryStreamCache> cache(_MR(new MemoryStreamCache));
+	downloader=getSys()->downloadManager->downloadWithData(uri, cache,
+			messageData, headers, NULL);
 	//Get the whole answer
-	downloader->waitForTermination();
-	if(downloader->hasFailed()) //Check to see if the download failed for some reason
+	cache->waitForTermination();
+	if(cache->hasFailed()) //Check to see if the download failed for some reason
 	{
 		LOG(LOG_ERROR, "NetConnection::execute(): Download of URL failed: " << uri);
 //		getVm()->addEvent(contentLoaderInfo,_MR(Class<IOErrorEvent>::getInstanceS()));
 		getSys()->downloadManager->destroy(downloader);
 		return;
 	}
-	istream s(downloader);
+	std::streambuf *sbuf = cache->createReader();
+	istream s(sbuf);
 	_R<ByteArray> message=_MR(Class<ByteArray>::getInstanceS());
 	uint8_t* buf=message->getBuffer(downloader->getLength(), true);
 	s.read((char*)buf,downloader->getLength());
 	//Download is done, destroy it
+	delete sbuf;
 	{
 		//Acquire the lock to ensure consistency in threadAbort
 		SpinlockLocker l(downloaderLock);
@@ -743,7 +804,9 @@ ASFUNCTIONBODY(NetConnection,connect)
 	//bool isRPC = false;
 
 	//Null argument means local file or web server, the spec only mentions NULL, but youtube uses UNDEFINED, so supporting that too.
-	if(args[0]->getObjectType()==T_NULL || args[0]->getObjectType()==T_UNDEFINED)
+	if(args[0]->getObjectType()==T_NULL || 
+			args[0]->getObjectType()==T_UNDEFINED ||
+			!args[0]->isConstructed())
 	{
 		th->_connected = false;
 		isNull = true;
@@ -798,6 +861,14 @@ ASFUNCTIONBODY(NetConnection,_getConnected)
 	return abstract_b(th->_connected);
 }
 
+ASFUNCTIONBODY(NetConnection,_getConnectedProxyType)
+{
+	NetConnection* th=Class<NetConnection>::cast(obj);
+	if (!th->_connected)
+		throw Class<ArgumentError>::getInstanceS("NetConnection object must be connected.", 2126);
+	return Class<ASString>::getInstanceS("none");
+}
+
 ASFUNCTIONBODY(NetConnection,_getDefaultObjectEncoding)
 {
 	return abstract_i(getSys()->staticNetConnectionDefaultObjectEncoding);
@@ -847,6 +918,59 @@ ASFUNCTIONBODY(NetConnection,_getProtocol)
 		throw Class<ArgumentError>::getInstanceS("get NetConnection.protocol before connect");
 }
 
+ASFUNCTIONBODY(NetConnection,_getProxyType)
+{
+	NetConnection* th=Class<NetConnection>::cast(obj);
+	tiny_string name;
+	switch(th->proxyType)
+	{
+		case PT_NONE:
+			name = "NONE";
+			break;
+		case PT_HTTP:
+			name = "HTTP";
+			break;
+		case PT_CONNECT_ONLY:
+			name = "CONNECTOnly";
+			break;
+		case PT_CONNECT:
+			name = "CONNECT";
+			break;
+		case PT_BEST:
+			name = "best";
+			break;
+		default:
+			assert(false && "Invalid proxy type");
+			name = "";
+			break;
+	}
+	return Class<ASString>::getInstanceS(name);
+}
+
+ASFUNCTIONBODY(NetConnection,_setProxyType)
+{
+	NetConnection* th=Class<NetConnection>::cast(obj);
+	tiny_string value;
+	ARG_UNPACK(value);
+	if (value == "NONE")
+		th->proxyType = PT_NONE;
+	else if (value == "HTTP")
+		th->proxyType = PT_HTTP;
+	else if (value == "CONNECTOnly")
+		th->proxyType = PT_CONNECT_ONLY;
+	else if (value == "CONNECT")
+		th->proxyType = PT_CONNECT;
+	else if (value == "best")
+		th->proxyType = PT_BEST;
+	else
+		throwError<ArgumentError>(kInvalidEnumError, "proxyType");
+
+	if (th->proxyType != PT_NONE)
+		LOG(LOG_NOT_IMPLEMENTED, "Unimplemented proxy type " << value);
+
+	return NULL;
+}
+
 ASFUNCTIONBODY(NetConnection,_getURI)
 {
 	NetConnection* th=Class<NetConnection>::cast(obj);
@@ -859,8 +983,28 @@ ASFUNCTIONBODY(NetConnection,_getURI)
 	}
 }
 
+ASFUNCTIONBODY(NetConnection,close)
+{
+	NetConnection* th=Class<NetConnection>::cast(obj);
+	if(th->_connected)
+	{
+		th->threadAbort();
+		th->_connected = false;
+	}
+	return NULL;
+}
+
 ASFUNCTIONBODY_GETTER_SETTER(NetConnection, client);
 
+void NetStreamAppendBytesAction::sinit(Class_base* c)
+{
+	CLASS_SETUP_NO_CONSTRUCTOR(c, ASObject, CLASS_FINAL);
+	c->setVariableByQName("END_SEQUENCE","",Class<ASString>::getInstanceS("endSequence"),CONSTANT_TRAIT);
+	c->setVariableByQName("RESET_BEGIN","",Class<ASString>::getInstanceS("resetBegin"),CONSTANT_TRAIT);
+	c->setVariableByQName("RESET_SEEK","",Class<ASString>::getInstanceS("resetSeek"),CONSTANT_TRAIT);
+}
+
+
 NetStream::NetStream(Class_base* c):EventDispatcher(c),tickStarted(false),paused(false),closed(true),
 	streamTime(0),frameRate(0),connection(),downloader(NULL),videoDecoder(NULL),
 	audioDecoder(NULL),audioStream(NULL),
@@ -888,8 +1032,7 @@ NetStream::~NetStream()
 
 void NetStream::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<EventDispatcher>::getRef());
+	CLASS_SETUP(c, EventDispatcher, _constructor, CLASS_SEALED);
 	c->setVariableByQName("CONNECT_TO_FMS","",Class<ASString>::getInstanceS("connectToFMS"),DECLARED_TRAIT);
 	c->setVariableByQName("DIRECT_CONNECTIONS","",Class<ASString>::getInstanceS("directConnections"),DECLARED_TRAIT);
 	c->setDeclaredMethodByQName("play","",Class<IFunction>::getFunction(play),NORMAL_METHOD,true);
@@ -906,6 +1049,9 @@ void NetStream::sinit(Class_base* c)
 	c->setDeclaredMethodByQName("client","",Class<IFunction>::getFunction(_setClient),SETTER_METHOD,true);
 	c->setDeclaredMethodByQName("checkPolicyFile","",Class<IFunction>::getFunction(_getCheckPolicyFile),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("checkPolicyFile","",Class<IFunction>::getFunction(_setCheckPolicyFile),SETTER_METHOD,true);
+	c->setDeclaredMethodByQName("attach","",Class<IFunction>::getFunction(attach),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("appendBytes","",Class<IFunction>::getFunction(appendBytes),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("appendBytesAction","",Class<IFunction>::getFunction(appendBytesAction),NORMAL_METHOD,true);
 	REGISTER_GETTER(c, backBufferLength);
 	REGISTER_GETTER_SETTER(c, backBufferTime);
 	REGISTER_GETTER(c, bufferLength);
@@ -969,40 +1115,31 @@ ASFUNCTIONBODY(NetStream,_setCheckPolicyFile)
 
 ASFUNCTIONBODY(NetStream,_constructor)
 {
-	obj->incRef();
-	_R<NetStream> th=_MR(Class<NetStream>::cast(obj));
+	EventDispatcher::_constructor(obj, NULL, 0);
+	NetStream* th=obj->as<NetStream>();
 
 	LOG(LOG_CALLS,_("NetStream constructor"));
-	assert_and_throw(argslen>=1 && argslen <=2);
-	assert_and_throw(args[0]->getClass()==Class<NetConnection>::getClass());
+	tiny_string value;
+	_NR<NetConnection> netConnection;
 
-	args[0]->incRef();
-	_R<NetConnection> netConnection = _MR(Class<NetConnection>::cast(args[0]));
-	if(argslen == 2)
-	{
-		if(args[1]->getObjectType() == T_STRING)
-		{
-			tiny_string value = Class<ASString>::cast(args[1])->toString();
-			if(value == "directConnections")
-				th->peerID = DIRECT_CONNECTIONS;
-			else
-				th->peerID = CONNECT_TO_FMS;
-		}
-		else if(args[1]->getObjectType() == T_NULL)
-			th->peerID = CONNECT_TO_FMS;
-		else
-			throw Class<ArgumentError>::getInstanceS("NetStream constructor: peerID");
-	}
+	ARG_UNPACK(netConnection)(value, "connectToFMS");
+
+	if(value == "directConnections")
+		th->peerID = DIRECT_CONNECTIONS;
+	else
+		th->peerID = CONNECT_TO_FMS;
 
-	th->client = th;
+	th->incRef();
+	netConnection->incRef();
 	th->connection=netConnection;
+	th->client = _NR<ASObject>(th);
 
 	return NULL;
 }
 
 ASFUNCTIONBODY(NetStream,play)
 {
-	NetStream* th=Class<NetStream>::cast(obj);
+	NetStream* th=obj->as<NetStream>();
 
 	//Make sure the stream is restarted properly
 	if(th->closed)
@@ -1013,8 +1150,10 @@ ASFUNCTIONBODY(NetStream,play)
 	//Reset the paused states
 	th->paused = false;
 //	th->audioPaused = false;
-	assert(!th->connection.isNull());
 
+	if (th->connection.isNull())
+		throwError<ASError>(0,"not connected");
+	
 	if(th->connection->uri.getProtocol()=="http")
 	{
 		//Remoting connection used, this should not happen
@@ -1070,9 +1209,8 @@ ASFUNCTIONBODY(NetStream,play)
 	}
 	else //The URL is valid so we can start the download and add ourself as a job
 	{
-		//Cahe the download only if it is not RTMP based
-		bool cached=!th->url.isRTMP();
-		th->downloader=getSys()->downloadManager->download(th->url, cached, NULL);
+		StreamCache *cache = new FileStreamCache;
+		th->downloader=getSys()->downloadManager->download(th->url, _MR(cache), NULL);
 		th->streamTime=0;
 		//To be decreffed in jobFence
 		th->incRef();
@@ -1149,6 +1287,35 @@ ASFUNCTIONBODY(NetStream,close)
 ASFUNCTIONBODY(NetStream,seek)
 {
 	//NetStream* th=Class<NetStream>::cast(obj);
+	LOG(LOG_NOT_IMPLEMENTED,"NetStream.seek is not implemented yet");
+	assert_and_throw(argslen == 1);
+	return NULL;
+}
+
+ASFUNCTIONBODY(NetStream,attach)
+{
+	NetStream* th=obj->as<NetStream>();
+	_NR<NetConnection> netConnection;
+	ARG_UNPACK(netConnection);
+
+	netConnection->incRef();
+	th->connection=netConnection;
+	return NULL;
+}
+ASFUNCTIONBODY(NetStream,appendBytes)
+{
+	NetStream* th=Class<NetStream>::cast(obj);
+	_NR<ByteArray> bytearray;
+	ARG_UNPACK(bytearray);
+	
+	if(!bytearray.isNull())
+		th->downloader->append(bytearray->getBuffer(bytearray->getLength(),false),bytearray->getLength());
+	return NULL;
+}
+ASFUNCTIONBODY(NetStream,appendBytesAction)
+{
+	//NetStream* th=Class<NetStream>::cast(obj);
+	LOG(LOG_NOT_IMPLEMENTED,"NetStream.appendBytesAction is not implemented yet");
 	assert_and_throw(argslen == 1);
 	return NULL;
 }
@@ -1232,7 +1399,8 @@ void NetStream::execute()
 
 	//The downloader hasn't failed yet at this point
 
-	istream s(downloader);
+	std::streambuf *sbuf = downloader->getCache()->createReader();
+	istream s(sbuf);
 	s.exceptions(istream::goodbit);
 
 	ThreadProfile* profile=getSys()->allocateProfiler(RGB(0,0,200));
@@ -1307,6 +1475,7 @@ void NetStream::execute()
 	}
 	catch(JobTerminationException& e)
 	{
+		LOG(LOG_ERROR, "JobTerminationException in NetStream ");
 		waitForFlush=false;
 	}
 	catch(exception& e)
@@ -1349,6 +1518,7 @@ void NetStream::execute()
 		audioStream=NULL;
 	}
 	delete streamDecoder;
+	delete sbuf;
 }
 
 void NetStream::threadAbort()
@@ -1605,8 +1775,7 @@ void URLVariables::decode(const tiny_string& s)
 
 void URLVariables::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<ASObject>::getRef());
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_DYNAMIC_NOT_FINAL);
 	c->setDeclaredMethodByQName("decode","",Class<IFunction>::getFunction(decode),NORMAL_METHOD,true);
 	c->prototype->setVariableByQName("toString","",Class<IFunction>::getFunction(_toString),DYNAMIC_TRAIT);
 }
@@ -1734,12 +1903,7 @@ ASFUNCTIONBODY(lightspark,sendToURL)
 	//TODO: should we disallow accessing local files in a directory above 
 	//the current one like we do with NetStream.play?
 
-	vector<uint8_t> postData;
-	urlRequest->getPostData(postData);
-	assert_and_throw(postData.empty());
-
-	//Don't cache our downloaded files
-	Downloader* downloader=getSys()->downloadManager->download(url, false, NULL);
+	Downloader* downloader=getSys()->downloadManager->download(url, _MR(new MemoryStreamCache), NULL);
 	//TODO: make the download asynchronous instead of waiting for an unused response
 	downloader->waitForTermination();
 	getSys()->downloadManager->destroy(downloader);
@@ -1783,8 +1947,7 @@ ASFUNCTIONBODY(lightspark,navigateToURL)
 
 void Responder::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<ASObject>::getRef());
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_SEALED);
 	c->setDeclaredMethodByQName("onResult","",Class<IFunction>::getFunction(onResult),NORMAL_METHOD,true);
 }
 
@@ -1820,6 +1983,90 @@ ASFUNCTIONBODY(Responder, onResult)
 	return NULL;
 }
 
+LocalConnection::LocalConnection(Class_base* c):
+	EventDispatcher(c),isSupported(false)
+{
+}
+
+void LocalConnection::sinit(Class_base* c)
+{
+	CLASS_SETUP(c, EventDispatcher, _constructor, CLASS_SEALED);
+	c->setDeclaredMethodByQName("allowDomain","",Class<IFunction>::getFunction(allowDomain),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("allowInsecureDomain","",Class<IFunction>::getFunction(allowInsecureDomain),NORMAL_METHOD,true);
+	REGISTER_GETTER(c,isSupported);
+}
+ASFUNCTIONBODY_GETTER(LocalConnection, isSupported);
+
+ASFUNCTIONBODY(LocalConnection, _constructor)
+{
+	EventDispatcher::_constructor(obj, NULL, 0);
+	LocalConnection* th=Class<LocalConnection>::cast(obj);
+	LOG(LOG_NOT_IMPLEMENTED,"LocalConnection is not implemented");
+	return NULL;
+}
+ASFUNCTIONBODY(LocalConnection, allowDomain)
+{
+	LocalConnection* th=Class<LocalConnection>::cast(obj);
+	LOG(LOG_NOT_IMPLEMENTED,"LocalConnection::allowDomain is not implemented");
+	return NULL;
+}
+ASFUNCTIONBODY(LocalConnection, allowInsecureDomain)
+{
+	EventDispatcher::_constructor(obj, NULL, 0);
+	LocalConnection* th=Class<LocalConnection>::cast(obj);
+	LOG(LOG_NOT_IMPLEMENTED,"LocalConnection::allowInsecureDomain is not implemented");
+	return NULL;
+}
+
+NetGroup::NetGroup(Class_base* c):
+	EventDispatcher(c)
+{
+}
+
+void NetGroup::sinit(Class_base* c)
+{
+	CLASS_SETUP(c, EventDispatcher, _constructor, CLASS_SEALED);
+}
+
+ASFUNCTIONBODY(NetGroup, _constructor)
+{
+	EventDispatcher::_constructor(obj, NULL, 0);
+	NetGroup* th=Class<NetGroup>::cast(obj);
+	LOG(LOG_NOT_IMPLEMENTED,"NetGroup is not implemented");
+	return NULL;
+}
+
+
+ASSocket::ASSocket(Class_base* c):
+	EventDispatcher(c)
+{
+}
+
+void ASSocket::sinit(Class_base* c)
+{
+	CLASS_SETUP(c, EventDispatcher, _constructor, CLASS_SEALED);
+}
+
+ASFUNCTIONBODY(ASSocket, _constructor)
+{
+	EventDispatcher::_constructor(obj, NULL, 0);
+	ASSocket* th=Class<ASSocket>::cast(obj);
+	LOG(LOG_NOT_IMPLEMENTED,"ASSocket is not implemented");
+	return NULL;
+}
+
+DRMManager::DRMManager(Class_base* c):
+	EventDispatcher(c),isSupported(false)
+{
+}
+
+void DRMManager::sinit(Class_base* c)
+{
+	CLASS_SETUP(c, EventDispatcher, _constructorNotInstantiatable, CLASS_SEALED);
+	REGISTER_GETTER(c,isSupported);
+}
+ASFUNCTIONBODY_GETTER(DRMManager, isSupported);
+
 ASFUNCTIONBODY(lightspark,registerClassAlias)
 {
 	assert_and_throw(argslen==2 && args[0]->getObjectType()==T_STRING && args[1]->getObjectType()==T_CLASS);
diff --git a/src/scripting/flash/net/flashnet.h b/src/scripting/flash/net/flashnet.h
index 0ab5b27..9274c15 100644
--- a/src/scripting/flash/net/flashnet.h
+++ b/src/scripting/flash/net/flashnet.h
@@ -39,6 +39,7 @@ private:
 	METHOD method;
 	tiny_string url;
 	_NR<ASObject> data;
+	tiny_string digest;
 	tiny_string validatedContentType() const;
 	tiny_string getContentTypeHeader() const;
 	void validateHeaderName(const tiny_string& headerName) const;
@@ -56,6 +57,8 @@ public:
 	ASFUNCTION(_setMethod);
 	ASFUNCTION(_setData);
 	ASFUNCTION(_getData);
+	ASFUNCTION(_getDigest);
+	ASFUNCTION(_setDigest);
 	URLInfo getRequestURL() const;
 	std::list<tiny_string> getHeaders() const;
 	void getPostData(std::vector<uint8_t>& data) const;
@@ -91,6 +94,14 @@ public:
 	static void sinit(Class_base*);
 };
 
+
+class SharedObjectFlushStatus: public ASObject
+{
+public:
+	SharedObjectFlushStatus(Class_base* c):ASObject(c){}
+	static void sinit(Class_base*);
+};
+
 class SharedObject: public EventDispatcher
 {
 public:
@@ -165,6 +176,7 @@ class NetConnection: public EventDispatcher, public IThreadJob
 {
 friend class NetStream;
 private:
+	enum PROXY_TYPE { PT_NONE, PT_HTTP, PT_CONNECT_ONLY, PT_CONNECT, PT_BEST };
 	//Indicates whether the application is connected to a server through a persistent RMTP connection/HTTP server with Flash Remoting
 	bool _connected;
 	tiny_string protocol;
@@ -178,6 +190,7 @@ private:
 	uint32_t messageCount;
 	//The connection is to a flash media server
 	ObjectEncoding::ENCODING objectEncoding;
+	PROXY_TYPE proxyType;
 	//IThreadJob interface
 	void execute();
 	void threadAbort();
@@ -191,15 +204,27 @@ public:
 	ASFUNCTION(connect);
 	ASFUNCTION(call);
 	ASFUNCTION(_getConnected);
+	ASFUNCTION(_getConnectedProxyType);
 	ASFUNCTION(_getDefaultObjectEncoding);
 	ASFUNCTION(_setDefaultObjectEncoding);
 	ASFUNCTION(_getObjectEncoding);
 	ASFUNCTION(_setObjectEncoding);
 	ASFUNCTION(_getProtocol);
+	ASFUNCTION(_getProxyType);
+	ASFUNCTION(_setProxyType);
 	ASFUNCTION(_getURI);
+	ASFUNCTION(close);
 	ASPROPERTY_GETTER_SETTER(NullableRef<ASObject>,client);
 };
 
+class NetStreamAppendBytesAction: public ASObject
+{
+public:
+	NetStreamAppendBytesAction(Class_base* c):ASObject(c){}
+	static void sinit(Class_base*);
+};
+
+
 class SoundTransform;
 class NetStream: public EventDispatcher, public IThreadJob, public ITickJob
 {
@@ -264,6 +289,9 @@ public:
 	ASFUNCTION(_setClient);
 	ASFUNCTION(_getCheckPolicyFile);
 	ASFUNCTION(_setCheckPolicyFile);
+	ASFUNCTION(attach);
+	ASFUNCTION(appendBytes);
+	ASFUNCTION(appendBytesAction);
 	ASPROPERTY_GETTER(number_t, backBufferLength);
 	ASPROPERTY_GETTER_SETTER(number_t, backBufferTime);
 	ASPROPERTY_GETTER(number_t, bufferLength);
@@ -334,11 +362,46 @@ public:
 	void unlock();
 };
 
+class LocalConnection: public EventDispatcher
+{
+public:
+	LocalConnection(Class_base* c);
+	static void sinit(Class_base*);
+	ASFUNCTION(_constructor);
+	ASPROPERTY_GETTER(bool,isSupported);
+	ASFUNCTION(allowDomain);
+	ASFUNCTION(allowInsecureDomain);
+};
+
+class NetGroup: public EventDispatcher
+{
+public:
+	NetGroup(Class_base* c);
+	static void sinit(Class_base*);
+	ASFUNCTION(_constructor);
+};
+
+class ASSocket: public EventDispatcher, IDataInput, IDataOutput
+{
+public:
+	ASSocket(Class_base* c);
+	static void sinit(Class_base*);
+	ASFUNCTION(_constructor);
+};
+
+class DRMManager: public EventDispatcher
+{
+public:
+	DRMManager(Class_base* c);
+	static void sinit(Class_base*);
+	ASPROPERTY_GETTER(bool,isSupported);
+};
+
 ASObject* navigateToURL(ASObject* obj,ASObject* const* args, const unsigned int argslen);
 ASObject* sendToURL(ASObject* obj,ASObject* const* args, const unsigned int argslen);
 ASObject* registerClassAlias(ASObject* obj,ASObject* const* args, const unsigned int argslen);
 ASObject* getClassByAlias(ASObject* obj,ASObject* const* args, const unsigned int argslen);
 
-};
+}
 
 #endif /* SCRIPTING_FLASH_NET_FLASHNET_H */
diff --git a/src/scripting/flash/printing/flashprinting.cpp b/src/scripting/flash/printing/flashprinting.cpp
new file mode 100644
index 0000000..2d46b4b
--- /dev/null
+++ b/src/scripting/flash/printing/flashprinting.cpp
@@ -0,0 +1,69 @@
+/**************************************************************************
+    Lightspark, a free flash player implementation
+
+    Copyright (C) 2009-2013  Alessandro Pignotti (a.pignotti at sssup.it)
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+**************************************************************************/
+
+#include "scripting/flash/printing/flashprinting.h"
+#include "scripting/abc.h"
+#include "scripting/argconv.h"
+#include "compat.h"
+
+using namespace lightspark;
+
+PrintJob::PrintJob(Class_base* c):
+	EventDispatcher(c),isSupported(false)
+{
+}
+
+void PrintJob::sinit(Class_base* c)
+{
+	CLASS_SETUP(c, EventDispatcher, _constructor, CLASS_SEALED);
+	REGISTER_GETTER(c,isSupported);
+}
+ASFUNCTIONBODY_GETTER(PrintJob, isSupported);
+
+ASFUNCTIONBODY(PrintJob, _constructor)
+{
+	EventDispatcher::_constructor(obj, NULL, 0);
+	PrintJob* th=Class<PrintJob>::cast(obj);
+	LOG(LOG_NOT_IMPLEMENTED,"PrintJob is not implemented");
+	return NULL;
+}
+
+PrintJobOptions::PrintJobOptions(Class_base* c):
+	ASObject(c)
+{
+}
+
+void PrintJobOptions::sinit(Class_base* c)
+{
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_SEALED);
+}
+
+ASFUNCTIONBODY(PrintJobOptions, _constructor)
+{
+	PrintJobOptions* th=Class<PrintJobOptions>::cast(obj);
+	LOG(LOG_NOT_IMPLEMENTED,"PrintJobOptions is not implemented");
+	return NULL;
+}
+
+void PrintJobOrientation::sinit(Class_base* c)
+{
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_SEALED| CLASS_FINAL);
+	c->setVariableByQName("LANDSCAPE","",Class<ASString>::getInstanceS("landscape"),CONSTANT_TRAIT);
+	c->setVariableByQName("PORTRAIT","",Class<ASString>::getInstanceS("portrait"),CONSTANT_TRAIT);
+}
diff --git a/src/scripting/flash/accessibility/flashaccessibility.h b/src/scripting/flash/printing/flashprinting.h
similarity index 67%
copy from src/scripting/flash/accessibility/flashaccessibility.h
copy to src/scripting/flash/printing/flashprinting.h
index 19d00b8..9932183 100644
--- a/src/scripting/flash/accessibility/flashaccessibility.h
+++ b/src/scripting/flash/printing/flashprinting.h
@@ -17,31 +17,40 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 **************************************************************************/
 
-#ifndef SCRIPTING_FLASH_ACCESSIBILITY_FLASHACCESSIBILITY_H
-#define SCRIPTING_FLASH_ACCESSIBILITY_FLASHACCESSIBILITY_H 1
+#ifndef SCRIPTING_FLASH_PRINTING_FLASHPRINTING_H
+#define SCRIPTING_FLASH_PRINTING_FLASHPRINTING_H 1
 
+#include "compat.h"
 #include "asobject.h"
+#include "scripting/flash/events/flashevents.h"
 
 namespace lightspark
 {
 
-class AccessibilityProperties : public ASObject
+class PrintJob: public EventDispatcher
 {
-private:
-	ASPROPERTY_GETTER_SETTER(tiny_string,name);
 public:
-	AccessibilityProperties(Class_base* c):ASObject(c){}
+	PrintJob(Class_base* c);
 	static void sinit(Class_base*);
 	ASFUNCTION(_constructor);
+	ASPROPERTY_GETTER(bool,isSupported);
 };
 
-class AccessibilityImplementation : public ASObject
+class PrintJobOptions: public ASObject
 {
 public:
-	AccessibilityImplementation(Class_base* c):ASObject(c){}
+	PrintJobOptions(Class_base* c);
 	static void sinit(Class_base*);
 	ASFUNCTION(_constructor);
 };
 
+class PrintJobOrientation: public ASObject
+{
+public:
+	PrintJobOrientation(Class_base* c) : ASObject(c) {}
+	static void sinit(Class_base*);
+};
+
+
 }
-#endif /* SCRIPTING_FLASH_ACCESSIBILITY_FLASHACCESSIBILITY_H */
+#endif /* SCRIPTING_FLASH_PRINTING_FLASHPRINTING_H */
diff --git a/src/scripting/flash/sensors/flashsensors.cpp b/src/scripting/flash/sensors/flashsensors.cpp
index bee463b..3d4587f 100644
--- a/src/scripting/flash/sensors/flashsensors.cpp
+++ b/src/scripting/flash/sensors/flashsensors.cpp
@@ -29,10 +29,11 @@
 using namespace std;
 using namespace lightspark;
 
-Accelerometer::Accelerometer(Class_base* c):ASObject(c) {}
+Accelerometer::Accelerometer(Class_base* c):EventDispatcher(c) {}
 
 void Accelerometer::sinit(Class_base* c)
 {
+	CLASS_SETUP_NO_CONSTRUCTOR(c, EventDispatcher, CLASS_SEALED);
 	// properties
 	c->setDeclaredMethodByQName("isSupported", "", Class<IFunction>::getFunction(_isSupported),GETTER_METHOD,false);
 }
diff --git a/src/scripting/flash/sensors/flashsensors.h b/src/scripting/flash/sensors/flashsensors.h
index 9f9ef19..760c476 100644
--- a/src/scripting/flash/sensors/flashsensors.h
+++ b/src/scripting/flash/sensors/flashsensors.h
@@ -30,7 +30,7 @@
 
 namespace lightspark
 {
-class Accelerometer: public ASObject {
+class Accelerometer: public EventDispatcher {
 	public:
 		Accelerometer(Class_base* c);
 		static void sinit(Class_base* c);
diff --git a/src/scripting/flash/system/flashsystem.cpp b/src/scripting/flash/system/flashsystem.cpp
index 26701f6..6c5224b 100644
--- a/src/scripting/flash/system/flashsystem.cpp
+++ b/src/scripting/flash/system/flashsystem.cpp
@@ -43,6 +43,7 @@ const char* Capabilities::MANUFACTURER = "Adobe Linux";
 
 void Capabilities::sinit(Class_base* c)
 {
+	CLASS_SETUP(c, ASObject, _constructorNotInstantiatable, CLASS_SEALED | CLASS_FINAL);
 	c->setDeclaredMethodByQName("language","",Class<IFunction>::getFunction(_getLanguage),GETTER_METHOD,false);
 	c->setDeclaredMethodByQName("playerType","",Class<IFunction>::getFunction(_getPlayerType),GETTER_METHOD,false);
 	c->setDeclaredMethodByQName("version","",Class<IFunction>::getFunction(_getVersion),GETTER_METHOD,false);
@@ -55,6 +56,8 @@ void Capabilities::sinit(Class_base* c)
 	c->setDeclaredMethodByQName("serverString","",Class<IFunction>::getFunction(_getServerString),GETTER_METHOD,false);
 	c->setDeclaredMethodByQName("screenResolutionX","",Class<IFunction>::getFunction(_getScreenResolutionX),GETTER_METHOD,false);
 	c->setDeclaredMethodByQName("screenResolutionY","",Class<IFunction>::getFunction(_getScreenResolutionY),GETTER_METHOD,false);
+	c->setDeclaredMethodByQName("hasAccessibility","",Class<IFunction>::getFunction(_getHasAccessibility),GETTER_METHOD,false);
+	
 }
 
 ASFUNCTIONBODY(Capabilities,_getPlayerType)
@@ -105,8 +108,56 @@ ASFUNCTIONBODY(Capabilities,_getVersion)
 
 ASFUNCTIONBODY(Capabilities,_getServerString)
 {
-	LOG(LOG_NOT_IMPLEMENTED, "Capabilities.serverString is not implemented");
-	return Class<ASString>::getInstanceS("");
+	LOG(LOG_NOT_IMPLEMENTED,"Capabilities: not all capabilities are reported in ServerString");
+	tiny_string res = "A=t&SA=t&SV=t&MP3=t&OS=Linux&PT=PlugIn&L=en&TLS=t";
+	res +="&V=";
+	res += EMULATED_VERSION;
+	res +="&M=";
+	res += MANUFACTURER;
+
+	GdkScreen*  screen = gdk_screen_get_default();
+	gint width = gdk_screen_get_width (screen);
+	gint height = gdk_screen_get_height (screen);
+	char buf[40];
+	snprintf(buf,40,"&R=%ix%i",width,height);
+	res += buf;
+
+	/*
+	avHardwareDisable	AVD
+	hasAccessibility	ACC
+	hasAudio	A
+	hasAudioEncoder	AE
+	hasEmbeddedVideo	EV
+	hasIME	IME
+	hasMP3	MP3
+	hasPrinting	PR
+	hasScreenBroadcast	SB
+	hasScreenPlayback	SP
+	hasStreamingAudio	SA
+	hasStreamingVideo	SV
+	hasTLS	TLS
+	hasVideoEncoder	VE
+	isDebugger	DEB
+	language	L
+	localFileReadDisable	LFD
+	manufacturer	M
+	maxLevelIDC	ML
+	os	OS
+	pixelAspectRatio	AR
+	playerType	PT
+	screenColor	COL
+	screenDPI	DP
+	screenResolutionX	R
+	screenResolutionY	R
+	version	V
+	supports Dolby Digital audio	DD
+	supports Dolby Digital Plus audio	DDP
+	supports DTS audio	DTS
+	supports DTS Express audio	DTE
+	supports DTS-HD High Resolution Audio	DTH
+	supports DTS-HD Master Audio	DTM
+	*/
+	return Class<ASString>::getInstanceS(res);
 }
 ASFUNCTIONBODY(Capabilities,_getScreenResolutionX)
 {
@@ -120,14 +171,21 @@ ASFUNCTIONBODY(Capabilities,_getScreenResolutionY)
 	gint height = gdk_screen_get_height (screen);
 	return abstract_d(height);
 }
+ASFUNCTIONBODY(Capabilities,_getHasAccessibility)
+{
+	LOG(LOG_NOT_IMPLEMENTED,"hasAccessibility always returns false");
+	return abstract_b(false);
+}
 
-ApplicationDomain::ApplicationDomain(Class_base* c, _NR<ApplicationDomain> p):ASObject(c),parentDomain(p)
+#define MIN_DOMAIN_MEMORY_LIMIT 1024
+ApplicationDomain::ApplicationDomain(Class_base* c, _NR<ApplicationDomain> p):ASObject(c),domainMemory(Class<ByteArray>::getInstanceS()),parentDomain(p)
 {
+	domainMemory->setLength(MIN_DOMAIN_MEMORY_LIMIT);
 }
 
 void ApplicationDomain::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_SEALED | CLASS_FINAL);
 	//Static
 	c->setDeclaredMethodByQName("currentDomain","",Class<IFunction>::getFunction(_getCurrentDomain),GETTER_METHOD,false);
 	c->setDeclaredMethodByQName("MIN_DOMAIN_MEMORY_LENGTH","",Class<IFunction>::getFunction(_getMinDomainMemoryLength),GETTER_METHOD,false);
@@ -171,7 +229,7 @@ ASFUNCTIONBODY(ApplicationDomain,_constructor)
 
 ASFUNCTIONBODY(ApplicationDomain,_getMinDomainMemoryLength)
 {
-	return abstract_ui(1024);
+	return abstract_ui(MIN_DOMAIN_MEMORY_LIMIT);
 }
 
 ASFUNCTIONBODY(ApplicationDomain,_getCurrentDomain)
@@ -229,7 +287,8 @@ ASFUNCTIONBODY(ApplicationDomain,getDefinition)
 	LOG(LOG_CALLS,_("Looking for definition of ") << name);
 	ASObject* target;
 	ASObject* o=th->getVariableAndTargetByMultiname(name,target);
-	assert_and_throw(o);
+	if(o == NULL)
+		throwError<ReferenceError>(kClassNotFoundError,name.normalizedName());
 
 	//TODO: specs says that also namespaces and function may be returned
 	assert_and_throw(o->getObjectType()==T_CLASS);
@@ -329,10 +388,20 @@ ASObject* ApplicationDomain::getVariableByMultinameOpportunistic(const multiname
 	return NULL;
 }
 
+LoaderContext::LoaderContext(Class_base* c):
+	ASObject(c),allowCodeImport(true),checkPolicyFile(false)
+{
+}
+
 void LoaderContext::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_SEALED);
+	c->setDeclaredMethodByQName("allowLoadBytesCodeExecution","",Class<IFunction>::getFunction(_getter_allowCodeImport),GETTER_METHOD,false);
+	c->setDeclaredMethodByQName("allowLoadBytesCodeExecution","",Class<IFunction>::getFunction(_setter_allowCodeImport),SETTER_METHOD,false);
+	REGISTER_GETTER_SETTER(c, allowCodeImport);
 	REGISTER_GETTER_SETTER(c, applicationDomain);
+	REGISTER_GETTER_SETTER(c, checkPolicyFile);
+	REGISTER_GETTER_SETTER(c, parameters);
 	REGISTER_GETTER_SETTER(c, securityDomain);
 }
 
@@ -346,22 +415,31 @@ void LoaderContext::finalize()
 ASFUNCTIONBODY(LoaderContext,_constructor)
 {
 	LoaderContext* th=Class<LoaderContext>::cast(obj);
-	bool checkPolicy;
-	_NR<ApplicationDomain> appDomain;
-	_NR<SecurityDomain> secDomain;
-	ARG_UNPACK (checkPolicy, false) (appDomain, NullRef) (secDomain, NullRef);
-	//TODO: Support checkPolicyFile
-	th->applicationDomain=appDomain;
-	th->securityDomain=secDomain;
+	ARG_UNPACK (th->checkPolicyFile, false)
+		(th->applicationDomain, NullRef)
+		(th->securityDomain, NullRef);
 	return NULL;
 }
 
+ASFUNCTIONBODY_GETTER_SETTER(LoaderContext, allowCodeImport);
 ASFUNCTIONBODY_GETTER_SETTER(LoaderContext, applicationDomain);
+ASFUNCTIONBODY_GETTER_SETTER(LoaderContext, checkPolicyFile);
+ASFUNCTIONBODY_GETTER_SETTER(LoaderContext, parameters);
 ASFUNCTIONBODY_GETTER_SETTER(LoaderContext, securityDomain);
 
+bool LoaderContext::getCheckPolicyFile()
+{
+	return checkPolicyFile;
+}
+
+bool LoaderContext::getAllowCodeImport()
+{
+	return allowCodeImport;
+}
+
 void SecurityDomain::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_SEALED);
 	//Static
 	c->setDeclaredMethodByQName("currentDomain","",Class<IFunction>::getFunction(_getCurrentDomain),GETTER_METHOD,false);
 }
@@ -384,8 +462,8 @@ ASFUNCTIONBODY(SecurityDomain,_getCurrentDomain)
 
 void Security::sinit(Class_base* c)
 {
+	CLASS_SETUP(c, ASObject, _constructorNotInstantiatable, CLASS_SEALED | CLASS_FINAL);
 	//Fully static class
-	c->setConstructor(NULL);
 	c->setDeclaredMethodByQName("exactSettings","",Class<IFunction>::getFunction(_getExactSettings),GETTER_METHOD,false);
 	c->setDeclaredMethodByQName("exactSettings","",Class<IFunction>::getFunction(_setExactSettings),SETTER_METHOD,false);
 	c->setDeclaredMethodByQName("sandboxType","",Class<IFunction>::getFunction(_getSandboxType),GETTER_METHOD,false);
@@ -401,6 +479,7 @@ void Security::sinit(Class_base* c)
 	c->setDeclaredMethodByQName("allowInsecureDomain","",Class<IFunction>::getFunction(allowInsecureDomain),NORMAL_METHOD,false);
 	c->setDeclaredMethodByQName("loadPolicyFile","",Class<IFunction>::getFunction(loadPolicyFile),NORMAL_METHOD,false);
 	c->setDeclaredMethodByQName("showSettings","",Class<IFunction>::getFunction(showSettings),NORMAL_METHOD,false);
+	c->setDeclaredMethodByQName("pageDomain","",Class<IFunction>::getFunction(pageDomain),GETTER_METHOD,false);
 
 	getSys()->securityManager->setExactSettings(true, false);
 }
@@ -461,6 +540,12 @@ ASFUNCTIONBODY(Security, showSettings)
 	return NULL;
 }
 
+ASFUNCTIONBODY(Security, pageDomain)
+{
+	tiny_string s = getSys()->mainClip->getBaseURL().getProtocol()+"://"+getSys()->mainClip->getBaseURL().getHostname();
+	return Class<ASString>::getInstanceS(s);
+}
+
 ASFUNCTIONBODY(lightspark, fscommand)
 {
 	assert_and_throw(argslen >= 1 && argslen <= 2);
@@ -476,6 +561,7 @@ ASFUNCTIONBODY(lightspark, fscommand)
 
 void System::sinit(Class_base* c)
 {
+	CLASS_SETUP(c, ASObject, _constructorNotInstantiatable, CLASS_SEALED | CLASS_FINAL);
 	c->setDeclaredMethodByQName("totalMemory","",Class<IFunction>::getFunction(totalMemory),GETTER_METHOD,false);
 }
 
@@ -483,5 +569,24 @@ void System::sinit(Class_base* c)
 ASFUNCTIONBODY(System,totalMemory)
 {
 	LOG(LOG_NOT_IMPLEMENTED, "System.totalMemory not implemented");
-	return abstract_d(0);
+	return abstract_d(1024);
+}
+
+ASWorker::ASWorker(Class_base* c):
+	EventDispatcher(c)
+{
+	LOG(LOG_NOT_IMPLEMENTED, "Worker not implemented");
 }
+
+void ASWorker::sinit(Class_base* c)
+{
+	CLASS_SETUP(c, EventDispatcher, _constructorNotInstantiatable, CLASS_SEALED | CLASS_FINAL);
+	c->setDeclaredMethodByQName("current","",Class<IFunction>::getFunction(_getCurrent),GETTER_METHOD,false);
+}
+ASFUNCTIONBODY(ASWorker,_getCurrent)
+{
+	LOG(LOG_NOT_IMPLEMENTED, "Worker not implemented");
+	return getSys()->getUndefinedRef();
+}
+
+
diff --git a/src/scripting/flash/system/flashsystem.h b/src/scripting/flash/system/flashsystem.h
index cf86063..5c6a948 100644
--- a/src/scripting/flash/system/flashsystem.h
+++ b/src/scripting/flash/system/flashsystem.h
@@ -22,7 +22,9 @@
 
 #include "compat.h"
 #include "asobject.h"
-#include "scripting/flash/utils/flashutils.h"
+#include "scripting/flash/utils/ByteArray.h"
+#include "scripting/toplevel/toplevel.h"
+#include "scripting/flash/events/flashevents.h"
 
 namespace lightspark
 {
@@ -48,6 +50,7 @@ public:
 	ASFUNCTION(_getServerString);
 	ASFUNCTION(_getScreenResolutionX);
 	ASFUNCTION(_getScreenResolutionY);
+	ASFUNCTION(_getHasAccessibility);
 };
 
 class ApplicationDomain: public ASObject
@@ -57,6 +60,8 @@ private:
 public:
 	ApplicationDomain(Class_base* c, _NR<ApplicationDomain> p=NullRef);
 	void finalize();
+	std::map<const multiname*, Class_base*> classesBeingDefined;
+
 	static void sinit(Class_base* c);
 	static void buildTraits(ASObject* o);
 	void registerGlobalScope(Global* scope);
@@ -102,12 +107,17 @@ public:
 class LoaderContext: public ASObject
 {
 public:
-	LoaderContext(Class_base* c):ASObject(c){};
+	LoaderContext(Class_base* c);
 	static void sinit(Class_base* c);
 	ASFUNCTION(_constructor);
+	ASPROPERTY_GETTER_SETTER(bool, allowCodeImport);
 	ASPROPERTY_GETTER_SETTER(_NR<ApplicationDomain>, applicationDomain);
+	ASPROPERTY_GETTER_SETTER(bool, checkPolicyFile);
+	ASPROPERTY_GETTER_SETTER(_NR<ASObject>, parameters);
 	ASPROPERTY_GETTER_SETTER(_NR<SecurityDomain>, securityDomain);
 	void finalize();
+	bool getAllowCodeImport();
+	bool getCheckPolicyFile();
 };
 
 class SecurityDomain: public ASObject
@@ -132,6 +142,7 @@ public:
 	ASFUNCTION(allowInsecureDomain);
 	ASFUNCTION(loadPolicyFile);
 	ASFUNCTION(showSettings);
+	ASFUNCTION(pageDomain);
 };
 
 ASObject* fscommand(ASObject* obj,ASObject* const* args, const unsigned int argslen);
@@ -143,6 +154,13 @@ public:
 	static void sinit(Class_base* c);
 	ASFUNCTION(totalMemory);
 };
-
+class ASWorker: public EventDispatcher
+{
+public:
+	ASWorker(Class_base* c);
+	static void sinit(Class_base*);
+	ASFUNCTION(_getCurrent);
 };
+
+}
 #endif /* SCRIPTING_FLASH_SYSTEM_FLASHSYSTEM_H */
diff --git a/src/scripting/flash/text/flashtext.cpp b/src/scripting/flash/text/flashtext.cpp
index e9420ba..829447e 100644
--- a/src/scripting/flash/text/flashtext.cpp
+++ b/src/scripting/flash/text/flashtext.cpp
@@ -33,16 +33,14 @@ using namespace lightspark;
 
 void lightspark::AntiAliasType::sinit(Class_base* c)
 {
-	c->setConstructor(NULL);
+	CLASS_SETUP_NO_CONSTRUCTOR(c, ASObject, CLASS_FINAL | CLASS_SEALED);
 	c->setVariableByQName("ADVANCED","",Class<ASString>::getInstanceS("advanced"),DECLARED_TRAIT);
 	c->setVariableByQName("NORMAL","",Class<ASString>::getInstanceS("normal"),DECLARED_TRAIT);
 }
 
 void ASFont::sinit(Class_base* c)
 {
-//	c->constructor=Class<IFunction>::getFunction(_constructor);
-	//c->setConstructor(NULL);
-	c->setSuper(Class<ASObject>::getRef());
+	CLASS_SETUP_NO_CONSTRUCTOR(c, ASObject, CLASS_SEALED);
 	c->setDeclaredMethodByQName("enumerateFonts","",Class<IFunction>::getFunction(enumerateFonts),NORMAL_METHOD,false);
 	c->setDeclaredMethodByQName("registerFont","",Class<IFunction>::getFunction(registerFont),NORMAL_METHOD,false);
 
@@ -93,60 +91,123 @@ ASFUNCTIONBODY(ASFont,registerFont)
 }
 
 TextField::TextField(Class_base* c, const TextData& textData, bool _selectable, bool readOnly)
-	: InteractiveObject(c), TextData(textData), type(READ_ONLY), 
-	  mouseWheelEnabled(true), selectable(_selectable)
+	: InteractiveObject(c), TextData(textData), type(ET_READ_ONLY), 
+	  antiAliasType(AA_NORMAL), gridFitType(GF_PIXEL),
+	  textInteractionMode(TI_NORMAL), alwaysShowSelection(false),
+	  caretIndex(0), condenseWhite(false), displayAsPassword(false),
+	  embedFonts(false), maxChars(0), mouseWheelEnabled(true),
+	  selectable(_selectable), selectionBeginIndex(0), selectionEndIndex(0),
+	  sharpness(0), thickness(0), useRichTextClipboard(false)
 {
 	if (!readOnly)
 	{
-		type = EDITABLE;
+		type = ET_EDITABLE;
 		tabEnabled = true;
 	}
 }
 
 void TextField::sinit(Class_base* c)
 {
-	c->setConstructor(NULL);
-	c->setSuper(Class<InteractiveObject>::getRef());
-	c->setDeclaredMethodByQName("width","",Class<IFunction>::getFunction(TextField::_getWidth),GETTER_METHOD,true);
-	c->setDeclaredMethodByQName("width","",Class<IFunction>::getFunction(TextField::_setWidth),SETTER_METHOD,true);
+	CLASS_SETUP_NO_CONSTRUCTOR(c, InteractiveObject, CLASS_SEALED);
+
+	// methods
+	c->setDeclaredMethodByQName("appendText","",Class<IFunction>::getFunction(TextField:: appendText),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("getTextFormat","",Class<IFunction>::getFunction(_getTextFormat),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("setTextFormat","",Class<IFunction>::getFunction(_setTextFormat),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("getLineIndexAtPoint","",Class<IFunction>::getFunction(_getLineIndexAtPoint),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("getLineIndexOfChar","",Class<IFunction>::getFunction(_getLineIndexOfChar),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("getLineLength","",Class<IFunction>::getFunction(_getLineLength),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("getLineMetrics","",Class<IFunction>::getFunction(_getLineMetrics),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("getLineOffset","",Class<IFunction>::getFunction(_getLineOffset),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("getLineText","",Class<IFunction>::getFunction(_getLineText),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("replaceSelectedText","",Class<IFunction>::getFunction(_replaceSelectedText),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("replaceText","",Class<IFunction>::getFunction(_replaceText),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("setSelection","",Class<IFunction>::getFunction(_setSelection),NORMAL_METHOD,true);
+
+	// properties
+	c->setDeclaredMethodByQName("antiAliasType","",Class<IFunction>::getFunction(TextField::_getAntiAliasType),GETTER_METHOD,true);
+	c->setDeclaredMethodByQName("antiAliasType","",Class<IFunction>::getFunction(TextField::_setAntiAliasType),SETTER_METHOD,true);
+	c->setDeclaredMethodByQName("autoSize","",Class<IFunction>::getFunction(TextField::_setAutoSize),SETTER_METHOD,true);
+	c->setDeclaredMethodByQName("autoSize","",Class<IFunction>::getFunction(TextField::_getAutoSize),GETTER_METHOD,true);
+	c->setDeclaredMethodByQName("defaultTextFormat","",Class<IFunction>::getFunction(TextField::_getDefaultTextFormat),GETTER_METHOD,true);
+	c->setDeclaredMethodByQName("defaultTextFormat","",Class<IFunction>::getFunction(TextField::_setDefaultTextFormat),SETTER_METHOD,true);
+	c->setDeclaredMethodByQName("gridFitType","",Class<IFunction>::getFunction(TextField::_getGridFitType),GETTER_METHOD,true);
+	c->setDeclaredMethodByQName("gridFitType","",Class<IFunction>::getFunction(TextField::_setGridFitType),SETTER_METHOD,true);
 	c->setDeclaredMethodByQName("height","",Class<IFunction>::getFunction(TextField::_getHeight),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("height","",Class<IFunction>::getFunction(TextField::_setHeight),SETTER_METHOD,true);
 	c->setDeclaredMethodByQName("htmlText","",Class<IFunction>::getFunction(TextField::_getHtmlText),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("htmlText","",Class<IFunction>::getFunction(TextField::_setHtmlText),SETTER_METHOD,true);
-	c->setDeclaredMethodByQName("textHeight","",Class<IFunction>::getFunction(TextField::_getTextHeight),GETTER_METHOD,true);
-	c->setDeclaredMethodByQName("textWidth","",Class<IFunction>::getFunction(TextField::_getTextWidth),GETTER_METHOD,true);
+	c->setDeclaredMethodByQName("length","",Class<IFunction>::getFunction(TextField::_getLength),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("text","",Class<IFunction>::getFunction(TextField::_getText),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("text","",Class<IFunction>::getFunction(TextField::_setText),SETTER_METHOD,true);
+	c->setDeclaredMethodByQName("textHeight","",Class<IFunction>::getFunction(TextField::_getTextHeight),GETTER_METHOD,true);
+	c->setDeclaredMethodByQName("textWidth","",Class<IFunction>::getFunction(TextField::_getTextWidth),GETTER_METHOD,true);
+	c->setDeclaredMethodByQName("width","",Class<IFunction>::getFunction(TextField::_getWidth),GETTER_METHOD,true);
+	c->setDeclaredMethodByQName("width","",Class<IFunction>::getFunction(TextField::_setWidth),SETTER_METHOD,true);
 	c->setDeclaredMethodByQName("wordWrap","",Class<IFunction>::getFunction(TextField::_setWordWrap),SETTER_METHOD,true);
 	c->setDeclaredMethodByQName("wordWrap","",Class<IFunction>::getFunction(TextField::_getWordWrap),GETTER_METHOD,true);
-	c->setDeclaredMethodByQName("autoSize","",Class<IFunction>::getFunction(TextField::_setAutoSize),SETTER_METHOD,true);
-	c->setDeclaredMethodByQName("autoSize","",Class<IFunction>::getFunction(TextField::_getAutoSize),GETTER_METHOD,true);
-	c->setDeclaredMethodByQName("appendText","",Class<IFunction>::getFunction(TextField:: appendText),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("getTextFormat","",Class<IFunction>::getFunction(_getTextFormat),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("setTextFormat","",Class<IFunction>::getFunction(_setTextFormat),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("getLineMetrics","",Class<IFunction>::getFunction(_getLineMetrics),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("defaultTextFormat","",Class<IFunction>::getFunction(TextField::_getDefaultTextFormat),GETTER_METHOD,true);
-	c->setDeclaredMethodByQName("defaultTextFormat","",Class<IFunction>::getFunction(TextField::_setDefaultTextFormat),SETTER_METHOD,true);
-
+	c->setDeclaredMethodByQName("numLines","",Class<IFunction>::getFunction(TextField::_getNumLines),GETTER_METHOD,true);
+	c->setDeclaredMethodByQName("maxScrollH","",Class<IFunction>::getFunction(TextField::_getMaxScrollH),GETTER_METHOD,true);
+	c->setDeclaredMethodByQName("maxScrollV","",Class<IFunction>::getFunction(TextField::_getMaxScrollV),GETTER_METHOD,true);
+	c->setDeclaredMethodByQName("bottomScrollV","",Class<IFunction>::getFunction(TextField::_getBottomScrollV),GETTER_METHOD,true);
+	c->setDeclaredMethodByQName("restrict","",Class<IFunction>::getFunction(TextField::_getRestrict),GETTER_METHOD,true);
+	c->setDeclaredMethodByQName("restrict","",Class<IFunction>::getFunction(TextField::_setRestrict),SETTER_METHOD,true);
+	c->setDeclaredMethodByQName("textInteractionMode","",Class<IFunction>::getFunction(TextField::_getTextInteractionMode),GETTER_METHOD,true);
+
+	REGISTER_GETTER_SETTER(c, alwaysShowSelection);
 	REGISTER_GETTER_SETTER(c, background);
 	REGISTER_GETTER_SETTER(c, backgroundColor);
 	REGISTER_GETTER_SETTER(c, border);
 	REGISTER_GETTER_SETTER(c, borderColor);
+	REGISTER_GETTER(c, caretIndex);
+	REGISTER_GETTER_SETTER(c, condenseWhite);
+	REGISTER_GETTER_SETTER(c, displayAsPassword);
+	REGISTER_GETTER_SETTER(c, embedFonts);
+	REGISTER_GETTER_SETTER(c, maxChars);
 	REGISTER_GETTER_SETTER(c, multiline);
 	REGISTER_GETTER_SETTER(c, mouseWheelEnabled);
+	REGISTER_GETTER_SETTER(c, scrollH);
+	REGISTER_GETTER_SETTER(c, scrollV);
 	REGISTER_GETTER_SETTER(c, selectable);
+	REGISTER_GETTER(c, selectionBeginIndex);
+	REGISTER_GETTER(c, selectionEndIndex);
+	REGISTER_GETTER_SETTER(c, sharpness);
+	REGISTER_GETTER_SETTER(c, styleSheet);
 	REGISTER_GETTER_SETTER(c, textColor);
+	REGISTER_GETTER_SETTER(c, thickness);
 	REGISTER_GETTER_SETTER(c, type);
+	REGISTER_GETTER_SETTER(c, useRichTextClipboard);
 }
 
+ASFUNCTIONBODY_GETTER_SETTER(TextField, alwaysShowSelection); // stub
 ASFUNCTIONBODY_GETTER_SETTER(TextField, background);
 ASFUNCTIONBODY_GETTER_SETTER(TextField, backgroundColor);
 ASFUNCTIONBODY_GETTER_SETTER(TextField, border);
 ASFUNCTIONBODY_GETTER_SETTER(TextField, borderColor);
+ASFUNCTIONBODY_GETTER(TextField, caretIndex);
+ASFUNCTIONBODY_GETTER_SETTER(TextField, condenseWhite);
+ASFUNCTIONBODY_GETTER_SETTER(TextField, displayAsPassword); // stub
+ASFUNCTIONBODY_GETTER_SETTER(TextField, embedFonts); // stub
+ASFUNCTIONBODY_GETTER_SETTER(TextField, maxChars); // stub
 ASFUNCTIONBODY_GETTER_SETTER(TextField, multiline);
-ASFUNCTIONBODY_GETTER_SETTER(TextField, mouseWheelEnabled);
-ASFUNCTIONBODY_GETTER_SETTER(TextField, selectable);
+ASFUNCTIONBODY_GETTER_SETTER(TextField, mouseWheelEnabled); // stub
+ASFUNCTIONBODY_GETTER_SETTER_CB(TextField, scrollH, validateScrollH);
+ASFUNCTIONBODY_GETTER_SETTER_CB(TextField, scrollV, validateScrollV);
+ASFUNCTIONBODY_GETTER_SETTER(TextField, selectable); // stub
+ASFUNCTIONBODY_GETTER(TextField, selectionBeginIndex);
+ASFUNCTIONBODY_GETTER(TextField, selectionEndIndex);
+ASFUNCTIONBODY_GETTER_SETTER_CB(TextField, sharpness, validateSharpness); // stub
+ASFUNCTIONBODY_GETTER_SETTER(TextField, styleSheet); // stub
 ASFUNCTIONBODY_GETTER_SETTER(TextField, textColor);
+ASFUNCTIONBODY_GETTER_SETTER_CB(TextField, thickness, validateThickness); // stub
+ASFUNCTIONBODY_GETTER_SETTER(TextField, useRichTextClipboard); // stub
+
+void TextField::finalize()
+{
+	ASObject::finalize();
+	restrictChars.reset();
+	styleSheet.reset();
+}
 
 void TextField::buildTraits(ASObject* o)
 {
@@ -167,7 +228,10 @@ _NR<DisplayObject> TextField::hitTestImpl(_NR<DisplayObject> last, number_t x, n
 	number_t xmin,xmax,ymin,ymax;
 	boundsRect(xmin,xmax,ymin,ymax);
 	if( xmin <= x && x <= xmax && ymin <= y && y <= ymax && isHittable(type))
-		return last;
+	{
+		incRef();
+		return _MNR(this);
+	}
 	else
 		return NullRef;
 }
@@ -181,8 +245,8 @@ ASFUNCTIONBODY(TextField,_getWordWrap)
 ASFUNCTIONBODY(TextField,_setWordWrap)
 {
 	TextField* th=Class<TextField>::cast(obj);
-	assert_and_throw(argslen==1);
-	th->wordWrap=Boolean_concrete(args[0]);
+	ARG_UNPACK(th->wordWrap);
+	th->setSizeAndPositionFromAutoSize();
 	if(th->onStage)
 		th->requestInvalidation(getSys());
 	return NULL;
@@ -208,23 +272,59 @@ ASFUNCTIONBODY(TextField,_getAutoSize)
 ASFUNCTIONBODY(TextField,_setAutoSize)
 {
 	TextField* th=Class<TextField>::cast(obj);
-	assert_and_throw(argslen==1);
-	tiny_string temp = args[0]->toString();
-	if(temp == "none")
-		th->autoSize = AS_NONE;//TODO: take care of corner cases : what to do with sizes when changing the autoSize
-	else if (temp == "left")
-		th->autoSize = AS_LEFT;
-	else if (temp == "right")
-		th->autoSize = AS_RIGHT;
-	else if (temp == "center")
-		th->autoSize = AS_CENTER;
+	tiny_string autoSizeString;
+	ARG_UNPACK(autoSizeString);
+
+	AUTO_SIZE newAutoSize = AS_NONE;
+	if(autoSizeString == "none")
+		newAutoSize = AS_NONE;
+	else if (autoSizeString == "left")
+		newAutoSize = AS_LEFT;
+	else if (autoSizeString == "right")
+		newAutoSize = AS_RIGHT;
+	else if (autoSizeString == "center")
+		newAutoSize = AS_CENTER;
 	else
-		throw Class<ArgumentError>::getInstanceS("Wrong argument in TextField.autoSize");
-	if(th->onStage)
-		th->requestInvalidation(getSys());//TODO:check if there was any change
+		throwError<ArgumentError>(kInvalidEnumError, "autoSize");
+
+	if (th->autoSize != newAutoSize)
+	{
+		th->autoSize = newAutoSize;
+		th->setSizeAndPositionFromAutoSize();
+		if(th->onStage)
+			th->requestInvalidation(getSys());
+	}
+
 	return NULL;
 }
 
+void TextField::setSizeAndPositionFromAutoSize()
+{
+	if (autoSize == AS_NONE)
+		return;
+
+	height = textHeight;
+	if (!wordWrap && width < textWidth)
+	{
+		if (autoSize == AS_RIGHT)
+		{
+			number_t oldX = getXY().x;
+			setX(oldX+width-textWidth);
+			width = textWidth;
+		}
+		else if (autoSize == AS_CENTER)
+		{
+			number_t oldX = getXY().x;
+			setX(oldX + width/2 - textWidth/2);
+			width = textWidth;
+		}
+		else // AS_LEFT, because AS_NONE was handled before
+		{
+			width = textWidth;
+		}
+	}
+}
+
 ASFUNCTIONBODY(TextField,_getWidth)
 {
 	TextField* th=Class<TextField>::cast(obj);
@@ -383,7 +483,7 @@ ASFUNCTIONBODY(TextField,_setDefaultTextFormat)
 ASFUNCTIONBODY(TextField, _getter_type)
 {
 	TextField* th=Class<TextField>::cast(obj);
-	if (th->type == READ_ONLY)
+	if (th->type == ET_READ_ONLY)
 		return Class<ASString>::getInstanceS("dynamic");
 	else
 		return Class<ASString>::getInstanceS("input");
@@ -397,19 +497,370 @@ ASFUNCTIONBODY(TextField, _setter_type)
 	ARG_UNPACK(value);
 
 	if (value == "dynamic")
-		th->type = READ_ONLY;
+		th->type = ET_READ_ONLY;
 	else if (value == "input")
-		th->type = EDITABLE;
+		th->type = ET_EDITABLE;
 	else
 		throwError<ArgumentError>(kInvalidEnumError, "type");
 
 	return NULL;
 }
 
+ASFUNCTIONBODY(TextField,_getLineIndexAtPoint)
+{
+	TextField* th=Class<TextField>::cast(obj);
+	number_t x;
+	number_t y;
+	ARG_UNPACK(x) (y);
+
+	std::vector<LineData> lines = CairoPangoRenderer::getLineData(*th);
+	std::vector<LineData>::const_iterator it;
+	int i;
+	for (i=0, it=lines.begin(); it!=lines.end(); ++i, ++it)
+	{
+		if (x > it->extents.Xmin && x <= it->extents.Xmax &&
+		    y > it->extents.Ymin && y <= it->extents.Ymax)
+			return abstract_i(i);
+	}
+
+	return abstract_i(-1);
+}
+
+ASFUNCTIONBODY(TextField,_getLineIndexOfChar)
+{
+	TextField* th=Class<TextField>::cast(obj);
+	int32_t charIndex;
+	ARG_UNPACK(charIndex);
+
+	if (charIndex < 0)
+		return abstract_i(-1);
+
+	std::vector<LineData> lines = CairoPangoRenderer::getLineData(*th);
+	std::vector<LineData>::const_iterator it;
+	int i;
+	for (i=0, it=lines.begin(); it!=lines.end(); ++i, ++it)
+	{
+		if (charIndex >= it->firstCharOffset &&
+		    charIndex < it->firstCharOffset + it->length)
+			return abstract_i(i);
+	}
+
+	// testing shows that returns -1 on invalid index instead of
+	// throwing RangeError
+	return abstract_i(-1);
+}
+
+ASFUNCTIONBODY(TextField,_getLineLength)
+{
+	TextField* th=Class<TextField>::cast(obj);
+	int32_t  lineIndex;
+	ARG_UNPACK(lineIndex);
+
+	std::vector<LineData> lines = CairoPangoRenderer::getLineData(*th);
+	if (lineIndex < 0 || lineIndex >= (int32_t)lines.size())
+		throwError<RangeError>(kParamRangeError);
+
+	return abstract_i(lines[lineIndex].length);
+}
+
 ASFUNCTIONBODY(TextField,_getLineMetrics)
 {
-	LOG(LOG_NOT_IMPLEMENTED, "TextField.getLineMetrics() returns bogus values");
-	return Class<TextLineMetrics>::getInstanceS(19, 280, 14, 11, 3.5, 0);
+	TextField* th=Class<TextField>::cast(obj);
+	int32_t  lineIndex;
+	ARG_UNPACK(lineIndex);
+
+	std::vector<LineData> lines = CairoPangoRenderer::getLineData(*th);
+	if (lineIndex < 0 || lineIndex >= (int32_t)lines.size())
+		throwError<RangeError>(kParamRangeError);
+
+	return Class<TextLineMetrics>::getInstanceS(
+		lines[lineIndex].indent,
+		lines[lineIndex].extents.Xmax - lines[lineIndex].extents.Xmin,
+		lines[lineIndex].extents.Ymax - lines[lineIndex].extents.Ymin,
+		lines[lineIndex].ascent,
+		lines[lineIndex].descent,
+		lines[lineIndex].leading);
+}
+
+ASFUNCTIONBODY(TextField,_getLineOffset)
+{
+	TextField* th=Class<TextField>::cast(obj);
+	int32_t  lineIndex;
+	ARG_UNPACK(lineIndex);
+
+	std::vector<LineData> lines = CairoPangoRenderer::getLineData(*th);
+	if (lineIndex < 0 || lineIndex >= (int32_t)lines.size())
+		throwError<RangeError>(kParamRangeError);
+
+	return abstract_i(lines[lineIndex].firstCharOffset);
+}
+
+ASFUNCTIONBODY(TextField,_getLineText)
+{
+	TextField* th=Class<TextField>::cast(obj);
+	int32_t  lineIndex;
+	ARG_UNPACK(lineIndex);
+
+	std::vector<LineData> lines = CairoPangoRenderer::getLineData(*th);
+	if (lineIndex < 0 || lineIndex >= (int32_t)lines.size())
+		throwError<RangeError>(kParamRangeError);
+
+	tiny_string substr = th->text.substr(lines[lineIndex].firstCharOffset,
+					     lines[lineIndex].length);
+	return Class<ASString>::getInstanceS(substr);
+}
+
+ASFUNCTIONBODY(TextField,_getAntiAliasType)
+{
+	TextField* th=Class<TextField>::cast(obj);
+	if (th->antiAliasType == AA_NORMAL)
+		return Class<ASString>::getInstanceS("normal");
+	else
+		return Class<ASString>::getInstanceS("advanced");
+}
+
+ASFUNCTIONBODY(TextField,_setAntiAliasType)
+{
+	TextField* th=Class<TextField>::cast(obj);
+	tiny_string value;
+	ARG_UNPACK(value);
+
+	if (value == "advanced")
+	{
+		th->antiAliasType = AA_ADVANCED;
+		LOG(LOG_NOT_IMPLEMENTED, "TextField advanced antiAliasType not implemented");
+	}
+	else
+		th->antiAliasType = AA_NORMAL;
+
+
+	return NULL;
+}
+
+ASFUNCTIONBODY(TextField,_getGridFitType)
+{
+	TextField* th=Class<TextField>::cast(obj);
+	if (th->gridFitType == GF_NONE)
+		return Class<ASString>::getInstanceS("none");
+	else if (th->gridFitType == GF_PIXEL)
+		return Class<ASString>::getInstanceS("pixel");
+	else
+		return Class<ASString>::getInstanceS("subpixel");
+}
+
+ASFUNCTIONBODY(TextField,_setGridFitType)
+{
+	TextField* th=Class<TextField>::cast(obj);
+	tiny_string value;
+	ARG_UNPACK(value);
+
+	if (value == "none")
+		th->gridFitType = GF_NONE;
+	else if (value == "pixel")
+		th->gridFitType = GF_PIXEL;
+	else
+		th->gridFitType = GF_SUBPIXEL;
+
+	LOG(LOG_NOT_IMPLEMENTED, "TextField gridFitType not implemented");
+
+	return NULL;
+}
+
+ASFUNCTIONBODY(TextField,_getLength)
+{
+	TextField* th=Class<TextField>::cast(obj);
+	return abstract_i(th->text.numChars());
+}
+
+ASFUNCTIONBODY(TextField,_getNumLines)
+{
+	TextField* th=Class<TextField>::cast(obj);
+	return abstract_i(CairoPangoRenderer::getLineData(*th).size());
+}
+
+ASFUNCTIONBODY(TextField,_getMaxScrollH)
+{
+	TextField* th=Class<TextField>::cast(obj);
+	return abstract_i(th->getMaxScrollH());
+}
+
+ASFUNCTIONBODY(TextField,_getMaxScrollV)
+{
+	TextField* th=Class<TextField>::cast(obj);
+	return abstract_i(th->getMaxScrollV());
+}
+
+ASFUNCTIONBODY(TextField,_getBottomScrollV)
+{
+	TextField* th=Class<TextField>::cast(obj);
+	std::vector<LineData> lines = CairoPangoRenderer::getLineData(*th);
+	for (unsigned int k=0; k<lines.size()-1; k++)
+	{
+		if (lines[k+1].extents.Ymin >= (int)th->height)
+			return abstract_i(k + 1);
+	}
+
+	return abstract_i(lines.size() + 1);
+}
+
+ASFUNCTIONBODY(TextField,_getRestrict)
+{
+	TextField* th=Class<TextField>::cast(obj);
+	if (th->restrictChars.isNull())
+		return NULL;
+	else
+	{
+		th->restrictChars->incRef();
+		return th->restrictChars.getPtr();
+	}
+}
+
+ASFUNCTIONBODY(TextField,_setRestrict)
+{
+	TextField* th=Class<TextField>::cast(obj);
+	ARG_UNPACK(th->restrictChars);
+	if (!th->restrictChars.isNull())
+		LOG(LOG_NOT_IMPLEMENTED, "TextField restrict property");
+	return NULL;
+}
+
+ASFUNCTIONBODY(TextField,_getTextInteractionMode)
+{
+	TextField* th=Class<TextField>::cast(obj);
+	if (th->textInteractionMode == TI_NORMAL)
+		return Class<ASString>::getInstanceS("normal");
+	else
+		return Class<ASString>::getInstanceS("selection");
+}
+
+ASFUNCTIONBODY(TextField,_setSelection)
+{
+	TextField* th=Class<TextField>::cast(obj);
+	ARG_UNPACK(th->selectionBeginIndex) (th->selectionEndIndex);
+
+	if (th->selectionBeginIndex < 0)
+		th->selectionBeginIndex = 0;
+
+	if (th->selectionEndIndex >= (int32_t)th->text.numChars())
+		th->selectionEndIndex = th->text.numChars()-1;
+
+	if (th->selectionBeginIndex > th->selectionEndIndex)
+		th->selectionBeginIndex = th->selectionEndIndex;
+
+	if (th->selectionBeginIndex == th->selectionEndIndex)
+		th->caretIndex = th->selectionBeginIndex;
+
+	LOG(LOG_NOT_IMPLEMENTED, "TextField selection will not be rendered");
+
+	return NULL;
+}
+
+ASFUNCTIONBODY(TextField,_replaceSelectedText)
+{
+	TextField* th=Class<TextField>::cast(obj);
+	tiny_string newText;
+	ARG_UNPACK(newText);
+	th->replaceText(th->selectionBeginIndex, th->selectionEndIndex, newText);
+	return NULL;
+}
+
+ASFUNCTIONBODY(TextField,_replaceText)
+{
+	TextField* th=Class<TextField>::cast(obj);
+	int32_t begin;
+	int32_t end;
+	tiny_string newText;
+	ARG_UNPACK(begin) (end) (newText);
+	th->replaceText(begin, end, newText);
+	return NULL;
+}
+
+void TextField::replaceText(unsigned int begin, unsigned int end, const tiny_string& newText)
+{
+	if (!styleSheet.isNull())
+		throw Class<ASError>::getInstanceS("Can not replace text on text field with a style sheet");
+
+	if (begin >= text.numChars())
+	{
+		text = text + newText;
+	}
+	else if (begin > end)
+	{
+		return;
+	}
+	else if (end >= text.numChars())
+	{
+		text = text.substr(0, begin) + newText;
+	}
+	else
+	{
+		text = text.substr(0, begin) + newText + text.substr(end, text.end());
+	}
+
+	textUpdated();
+}
+
+void TextField::validateThickness(number_t /*oldValue*/)
+{
+	thickness = dmin(dmax(thickness, -200.), 200.);
+}
+
+void TextField::validateSharpness(number_t /*oldValue*/)
+{
+	sharpness = dmin(dmax(sharpness, -400.), 400.);
+}
+
+void TextField::validateScrollH(int32_t oldValue)
+{
+	int32_t maxScrollH = getMaxScrollH();
+	if (scrollH > maxScrollH)
+		scrollH = maxScrollH;
+
+	if (onStage && (scrollH != oldValue))
+		requestInvalidation(getSys());
+}
+
+void TextField::validateScrollV(int32_t oldValue)
+{
+	int32_t maxScrollV = getMaxScrollV();
+	if (scrollV < 1)
+		scrollV = 1;
+	else if (scrollV > maxScrollV)
+		scrollV = maxScrollV;
+
+	if (onStage && (scrollV != oldValue))
+		requestInvalidation(getSys());
+}
+
+int32_t TextField::getMaxScrollH()
+{
+	if (wordWrap || (textWidth <= width))
+		return 0;
+	else
+		return textWidth;
+}
+
+int32_t TextField::getMaxScrollV()
+{
+	std::vector<LineData> lines = CairoPangoRenderer::getLineData(*this);
+	if (lines.size() <= 1)
+		return 1;
+
+	int32_t Ymax = lines[lines.size()-1].extents.Ymax;
+	int32_t measuredTextHeight = Ymax - lines[0].extents.Ymin;
+	if (measuredTextHeight <= (int32_t)height)
+		return 1;
+
+	// one full page from the bottom
+	for (int k=(int)lines.size()-1; k>=0; k--)
+	{
+		if (Ymax - lines[k].extents.Ymin > (int32_t)height)
+		{
+			return imin(k+1+1, lines.size());
+		}
+	}
+
+	return 1;
 }
 
 void TextField::updateSizes()
@@ -461,12 +912,53 @@ tiny_string TextField::toHtmlText()
 void TextField::setHtmlText(const tiny_string& html)
 {
 	HtmlTextParser parser;
-	parser.parseTextAndFormating(html, this);
+	if (condenseWhite)
+	{
+		tiny_string processedHtml = compactHTMLWhiteSpace(html);
+		parser.parseTextAndFormating(processedHtml, this);
+	}
+	else
+	{
+		parser.parseTextAndFormating(html, this);
+	}
+	textUpdated();
+}
+
+tiny_string TextField::compactHTMLWhiteSpace(const tiny_string& html)
+{
+	tiny_string compacted;
+	bool previousWasSpace = false;
+	for (CharIterator ch=html.begin(); ch!=html.end(); ++ch)
+	{
+		if (g_unichar_isspace(*ch))
+		{
+			if (!previousWasSpace)
+				compacted += ' ';
+			previousWasSpace = true;
+		}
+		else
+		{
+			compacted += *ch;
+			previousWasSpace = false;
+		}
+	}
+
+	return compacted;
 }
 
 void TextField::updateText(const tiny_string& new_text)
 {
 	text = new_text;
+	textUpdated();
+}
+
+void TextField::textUpdated()
+{
+	scrollH = 0;
+	scrollV = 1;
+	selectionBeginIndex = 0;
+	selectionEndIndex = 0;
+
 	if(onStage)
 		requestInvalidation(getSys());
 	else
@@ -647,8 +1139,9 @@ uint32_t TextField::HtmlTextParser::parseFontSize(const Glib::ustring& sizestr,
 	return (uint32_t)size;
 }
 
-void TextFieldAutoSize ::sinit(Class_base* c)
+void TextFieldAutoSize::sinit(Class_base* c)
 {
+	CLASS_SETUP_NO_CONSTRUCTOR(c, ASObject, CLASS_FINAL | CLASS_SEALED);
 	c->setVariableByQName("CENTER","",Class<ASString>::getInstanceS("center"),DECLARED_TRAIT);
 	c->setVariableByQName("LEFT","",Class<ASString>::getInstanceS("left"),DECLARED_TRAIT);
 	c->setVariableByQName("NONE","",Class<ASString>::getInstanceS("none"),DECLARED_TRAIT);
@@ -657,12 +1150,14 @@ void TextFieldAutoSize ::sinit(Class_base* c)
 
 void TextFieldType::sinit(Class_base* c)
 {
+	CLASS_SETUP_NO_CONSTRUCTOR(c, ASObject, CLASS_FINAL | CLASS_SEALED);
 	c->setVariableByQName("DYNAMIC","",Class<ASString>::getInstanceS("dynamic"),DECLARED_TRAIT);
 	c->setVariableByQName("INPUT","",Class<ASString>::getInstanceS("input"),DECLARED_TRAIT);
 }
 
-void TextFormatAlign ::sinit(Class_base* c)
+void TextFormatAlign::sinit(Class_base* c)
 {
+	CLASS_SETUP_NO_CONSTRUCTOR(c, ASObject, CLASS_FINAL | CLASS_SEALED);
 	c->setVariableByQName("CENTER","",Class<ASString>::getInstanceS("center"),DECLARED_TRAIT);
 	c->setVariableByQName("END","",Class<ASString>::getInstanceS("end"),DECLARED_TRAIT);
 	c->setVariableByQName("JUSTIFY","",Class<ASString>::getInstanceS("justify"),DECLARED_TRAIT);
@@ -673,8 +1168,7 @@ void TextFormatAlign ::sinit(Class_base* c)
 
 void TextFormat::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<ASObject>::getRef());
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_SEALED);
 	REGISTER_GETTER_SETTER(c,align);
 	REGISTER_GETTER_SETTER(c,blockIndent);
 	REGISTER_GETTER_SETTER(c,bold);
@@ -773,8 +1267,7 @@ void StyleSheet::finalize()
 
 void StyleSheet::sinit(Class_base* c)
 {
-	c->setConstructor(NULL);
-	c->setSuper(Class<EventDispatcher>::getRef());
+	CLASS_SETUP_NO_CONSTRUCTOR(c, EventDispatcher, CLASS_DYNAMIC_NOT_FINAL);
 	c->setDeclaredMethodByQName("styleNames","",Class<IFunction>::getFunction(_getStyleNames),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("setStyle","",Class<IFunction>::getFunction(setStyle),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("getStyle","",Class<IFunction>::getFunction(getStyle),NORMAL_METHOD,true);
@@ -833,9 +1326,10 @@ ASFUNCTIONBODY(StyleSheet,_getStyleNames)
 
 void StaticText::sinit(Class_base* c)
 {
-	//TODO: spec says that constructor should throw ArgumentError
-	c->setConstructor(NULL);
-	c->setSuper(Class<DisplayObject>::getRef());
+	// FIXME: the constructor should be
+	// _constructorNotInstantiatable but that breaks when
+	// DisplayObjectContainer::initFrame calls the constructor
+	CLASS_SETUP_NO_CONSTRUCTOR(c, DisplayObject, CLASS_FINAL | CLASS_SEALED);
 	c->setDeclaredMethodByQName("text","",Class<IFunction>::getFunction(_getText),GETTER_METHOD,true);
 }
 
@@ -847,8 +1341,7 @@ ASFUNCTIONBODY(StaticText,_getText)
 
 void FontStyle::sinit(Class_base* c)
 {
-	c->setConstructor(NULL);
-	c->setSuper(Class<ASObject>::getRef());
+	CLASS_SETUP_NO_CONSTRUCTOR(c, ASObject, CLASS_FINAL | CLASS_SEALED);
 	c->setVariableByQName("BOLD","",Class<ASString>::getInstanceS("bold"),DECLARED_TRAIT);
 	c->setVariableByQName("BOLD_ITALIC","",Class<ASString>::getInstanceS("boldItalic"),DECLARED_TRAIT);
 	c->setVariableByQName("ITALIC","",Class<ASString>::getInstanceS("italic"),DECLARED_TRAIT);
@@ -857,8 +1350,7 @@ void FontStyle::sinit(Class_base* c)
 
 void FontType::sinit(Class_base* c)
 {
-	c->setConstructor(NULL);
-	c->setSuper(Class<ASObject>::getRef());
+	CLASS_SETUP_NO_CONSTRUCTOR(c, ASObject, CLASS_FINAL | CLASS_SEALED);
 	c->setVariableByQName("DEVICE","",Class<ASString>::getInstanceS("device"),DECLARED_TRAIT);
 	c->setVariableByQName("EMBEDDED","",Class<ASString>::getInstanceS("embedded"),DECLARED_TRAIT);
 	c->setVariableByQName("EMBEDDED_CFF","",Class<ASString>::getInstanceS("embeddedCFF"),DECLARED_TRAIT);
@@ -866,8 +1358,7 @@ void FontType::sinit(Class_base* c)
 
 void TextDisplayMode::sinit(Class_base* c)
 {
-	c->setConstructor(NULL);
-	c->setSuper(Class<ASObject>::getRef());
+	CLASS_SETUP_NO_CONSTRUCTOR(c, ASObject, CLASS_FINAL | CLASS_SEALED);
 	c->setVariableByQName("CRT","",Class<ASString>::getInstanceS("crt"),DECLARED_TRAIT);
 	c->setVariableByQName("DEFAULT","",Class<ASString>::getInstanceS("default"),DECLARED_TRAIT);
 	c->setVariableByQName("LCD","",Class<ASString>::getInstanceS("lcd"),DECLARED_TRAIT);
@@ -875,25 +1366,29 @@ void TextDisplayMode::sinit(Class_base* c)
 
 void TextColorType::sinit(Class_base* c)
 {
-	c->setConstructor(NULL);
-	c->setSuper(Class<ASObject>::getRef());
+	CLASS_SETUP_NO_CONSTRUCTOR(c, ASObject, CLASS_FINAL | CLASS_SEALED);
 	c->setVariableByQName("DARK_COLOR","",Class<ASString>::getInstanceS("dark"),DECLARED_TRAIT);
 	c->setVariableByQName("LIGHT_COLOR","",Class<ASString>::getInstanceS("light"),DECLARED_TRAIT);
 }
 
 void GridFitType::sinit(Class_base* c)
 {
-	c->setConstructor(NULL);
-	c->setSuper(Class<ASObject>::getRef());
+	CLASS_SETUP_NO_CONSTRUCTOR(c, ASObject, CLASS_FINAL | CLASS_SEALED);
 	c->setVariableByQName("NONE","",Class<ASString>::getInstanceS("none"),DECLARED_TRAIT);
 	c->setVariableByQName("PIXEL","",Class<ASString>::getInstanceS("pixel"),DECLARED_TRAIT);
 	c->setVariableByQName("SUBPIXEL","",Class<ASString>::getInstanceS("subpixel"),DECLARED_TRAIT);
 }
 
+void TextInteractionMode::sinit(Class_base* c)
+{
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_FINAL | CLASS_SEALED);
+	c->setVariableByQName("NORMAL","",Class<ASString>::getInstanceS("normal"),DECLARED_TRAIT);
+	c->setVariableByQName("SELECTION","",Class<ASString>::getInstanceS("selection"),DECLARED_TRAIT);
+}
+
 void TextLineMetrics::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<ASObject>::getRef());
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_SEALED);
 	REGISTER_GETTER_SETTER(c, ascent);
 	REGISTER_GETTER_SETTER(c, descent);
 	REGISTER_GETTER_SETTER(c, height);
diff --git a/src/scripting/flash/text/flashtext.h b/src/scripting/flash/text/flashtext.h
index 7999be0..601b368 100644
--- a/src/scripting/flash/text/flashtext.h
+++ b/src/scripting/flash/text/flashtext.h
@@ -52,6 +52,20 @@ public:
 	ASPROPERTY_GETTER(tiny_string, fontType);
 };
 
+class StyleSheet: public EventDispatcher
+{
+private:
+	std::map<tiny_string, _R<ASObject> > styles;
+public:
+	StyleSheet(Class_base* c):EventDispatcher(c){}
+	void finalize();
+	ASFUNCTION(getStyle);
+	ASFUNCTION(setStyle);
+	ASFUNCTION(_getStyleNames);
+	static void sinit(Class_base* c);
+	static void buildTraits(ASObject* o);
+};
+
 class TextField: public InteractiveObject, public TextData
 {
 private:
@@ -73,7 +87,10 @@ private:
 	};
 
 public:
-	enum EDIT_TYPE {READ_ONLY, EDITABLE};
+	enum EDIT_TYPE { ET_READ_ONLY, ET_EDITABLE };
+	enum ANTI_ALIAS_TYPE { AA_NORMAL, AA_ADVANCED };
+	enum GRID_FIT_TYPE { GF_NONE, GF_PIXEL, GF_SUBPIXEL };
+	enum TEXT_INTERACTION_MODE { TI_NORMAL, TI_SELECTION };
 private:
 	_NR<DisplayObject> hitTestImpl(_NR<DisplayObject> last, number_t x, number_t y, HIT_TYPE type);
 	void renderImpl(RenderContext& ctxt) const;
@@ -84,13 +101,33 @@ private:
 	//Computes and changes (text)width and (text)height using Pango
 	void updateSizes();
 	tiny_string toHtmlText();
+	tiny_string compactHTMLWhiteSpace(const tiny_string&);
+	void validateThickness(number_t oldValue);
+	void validateSharpness(number_t oldValue);
+	void validateScrollH(int32_t oldValue);
+	void validateScrollV(int32_t oldValue);
+	int32_t getMaxScrollH();
+	int32_t getMaxScrollV();
+	void textUpdated();
+	void setSizeAndPositionFromAutoSize();
+	void replaceText(unsigned int begin, unsigned int end, const tiny_string& newText);
 	EDIT_TYPE type;
+	ANTI_ALIAS_TYPE antiAliasType;
+	GRID_FIT_TYPE gridFitType;
+	TEXT_INTERACTION_MODE textInteractionMode;
+        _NR<ASString> restrictChars;
 public:
 	TextField(Class_base* c, const TextData& textData=TextData(), bool _selectable=true, bool readOnly=true);
+	void finalize();
 	static void sinit(Class_base* c);
 	static void buildTraits(ASObject* o);
 	void setHtmlText(const tiny_string& html);
 	ASFUNCTION(appendText);
+	ASFUNCTION(_getAntiAliasType);
+	ASFUNCTION(_setAntiAliasType);
+	ASFUNCTION(_getGridFitType);
+	ASFUNCTION(_setGridFitType);
+	ASFUNCTION(_getLength);
 	ASFUNCTION(_getWidth);
 	ASFUNCTION(_setWidth);
 	ASFUNCTION(_getHeight);
@@ -109,16 +146,45 @@ public:
 	ASFUNCTION(_setTextFormat);
 	ASFUNCTION(_getDefaultTextFormat);
 	ASFUNCTION(_setDefaultTextFormat);
+	ASFUNCTION(_getLineIndexAtPoint);
+	ASFUNCTION(_getLineIndexOfChar);
+	ASFUNCTION(_getLineLength);
 	ASFUNCTION(_getLineMetrics);
+	ASFUNCTION(_getLineOffset);
+	ASFUNCTION(_getLineText);
+	ASFUNCTION(_getNumLines);
+	ASFUNCTION(_getMaxScrollH);
+	ASFUNCTION(_getMaxScrollV);
+	ASFUNCTION(_getBottomScrollV);
+	ASFUNCTION(_getRestrict);
+	ASFUNCTION(_setRestrict);
+	ASFUNCTION(_getTextInteractionMode);
+	ASFUNCTION(_setSelection);
+	ASFUNCTION(_replaceText);
+	ASFUNCTION(_replaceSelectedText);
+	ASPROPERTY_GETTER_SETTER(bool, alwaysShowSelection);
 	ASFUNCTION_GETTER_SETTER(background);
 	ASFUNCTION_GETTER_SETTER(backgroundColor);
 	ASFUNCTION_GETTER_SETTER(border);
 	ASFUNCTION_GETTER_SETTER(borderColor);
+	ASPROPERTY_GETTER(int32_t, caretIndex);
+	ASPROPERTY_GETTER_SETTER(bool, condenseWhite);
+	ASPROPERTY_GETTER_SETTER(bool, displayAsPassword);
+	ASPROPERTY_GETTER_SETTER(bool, embedFonts);
+	ASPROPERTY_GETTER_SETTER(int32_t, maxChars);
 	ASFUNCTION_GETTER_SETTER(multiline);
 	ASPROPERTY_GETTER_SETTER(bool, mouseWheelEnabled);
+	ASFUNCTION_GETTER_SETTER(scrollH);
+	ASFUNCTION_GETTER_SETTER(scrollV);
 	ASPROPERTY_GETTER_SETTER(bool, selectable);
+	ASPROPERTY_GETTER(int32_t, selectionBeginIndex);
+	ASPROPERTY_GETTER(int32_t, selectionEndIndex);
+	ASPROPERTY_GETTER_SETTER(number_t, sharpness);
+	ASPROPERTY_GETTER_SETTER(_NR<StyleSheet>, styleSheet);
 	ASFUNCTION_GETTER_SETTER(textColor);
+	ASPROPERTY_GETTER_SETTER(number_t, thickness);
 	ASFUNCTION_GETTER_SETTER(type);
+	ASPROPERTY_GETTER_SETTER(bool, useRichTextClipboard);
 };
 
 class TextFormat: public ASObject
@@ -172,20 +238,6 @@ public:
 	static void sinit(Class_base* c);
 };
 
-class StyleSheet: public EventDispatcher
-{
-private:
-	std::map<tiny_string, _R<ASObject> > styles;
-public:
-	StyleSheet(Class_base* c):EventDispatcher(c){}
-	void finalize();
-	ASFUNCTION(getStyle);
-	ASFUNCTION(setStyle);
-	ASFUNCTION(_getStyleNames);
-	static void sinit(Class_base* c);
-	static void buildTraits(ASObject* o);
-};
-
 class StaticText: public DisplayObject, public TokenContainer
 {
 private:
@@ -242,6 +294,13 @@ public:
 	static void sinit(Class_base* c);
 };
 
+class TextInteractionMode: public ASObject
+{
+public:
+	TextInteractionMode(Class_base* c):ASObject(c){}
+	static void sinit(Class_base* c);
+};
+
 class TextLineMetrics : public ASObject
 {
 protected:
diff --git a/src/scripting/flash/text/flashtextengine.cpp b/src/scripting/flash/text/flashtextengine.cpp
index c9c4900..69cd51c 100644
--- a/src/scripting/flash/text/flashtextengine.cpp
+++ b/src/scripting/flash/text/flashtextengine.cpp
@@ -29,33 +29,103 @@ using namespace lightspark;
 
 void ContentElement::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<ASObject>::getRef());
+	CLASS_SETUP(c, ASObject, _constructorNotInstantiatable, CLASS_SEALED);
+	REGISTER_GETTER_SETTER(c,elementFormat);
 }
-
-ASFUNCTIONBODY(ContentElement, _constructor)
+ASFUNCTIONBODY_GETTER_SETTER(ContentElement,elementFormat)
+
+ElementFormat::ElementFormat(Class_base *c): ASObject(c),
+	alignmentBaseline("useDominantBaseline"),
+	alpha(1.0),
+	baselineShift(0.0),
+	breakOpportunity("auto"),
+	color(0x000000),
+	digitCase("default"),
+	digitWidth("default"),
+	dominantBaseline("roman"),
+	fontDescription(NULL),
+	fontSize(12.0),
+	kerning("on"),
+	ligatureLevel("common"),
+	locale("en"),
+	locked(false),
+	textRotation("auto"),
+	trackingLeft(0.0),
+	trackingRight(0.0),
+	typographicCase("default")
 {
-	throwError<ArgumentError>(kCantInstantiateError, "ContentElement");
-	return NULL;
+	
 }
 
 void ElementFormat::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<ASObject>::getRef());
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_FINAL | CLASS_SEALED);
 	c->setVariableByQName("GRAPHIC_ELEMENT","",abstract_ui(0xFDEF),CONSTANT_TRAIT);
+	REGISTER_GETTER_SETTER(c,alignmentBaseline);
+	REGISTER_GETTER_SETTER(c,alpha);
+	REGISTER_GETTER_SETTER(c,baselineShift);
+	REGISTER_GETTER_SETTER(c,breakOpportunity);
+	REGISTER_GETTER_SETTER(c,color);
+	REGISTER_GETTER_SETTER(c,digitCase);
+	REGISTER_GETTER_SETTER(c,digitWidth);
+	REGISTER_GETTER_SETTER(c,dominantBaseline);
+	REGISTER_GETTER_SETTER(c,fontDescription);
+	REGISTER_GETTER_SETTER(c,fontSize);
+	REGISTER_GETTER_SETTER(c,kerning);
+	REGISTER_GETTER_SETTER(c,ligatureLevel);
+	REGISTER_GETTER_SETTER(c,locale);
+	REGISTER_GETTER_SETTER(c,locked);
+	REGISTER_GETTER_SETTER(c,textRotation);
+	REGISTER_GETTER_SETTER(c,trackingLeft);
+	REGISTER_GETTER_SETTER(c,trackingRight);
+	REGISTER_GETTER_SETTER(c,typographicCase);
 }
+ASFUNCTIONBODY_GETTER_SETTER(ElementFormat,alignmentBaseline)
+ASFUNCTIONBODY_GETTER_SETTER(ElementFormat,alpha)
+ASFUNCTIONBODY_GETTER_SETTER(ElementFormat,baselineShift)
+ASFUNCTIONBODY_GETTER_SETTER(ElementFormat,breakOpportunity)
+ASFUNCTIONBODY_GETTER_SETTER(ElementFormat,color)
+ASFUNCTIONBODY_GETTER_SETTER(ElementFormat,digitCase)
+ASFUNCTIONBODY_GETTER_SETTER(ElementFormat,digitWidth)
+ASFUNCTIONBODY_GETTER_SETTER(ElementFormat,dominantBaseline)
+ASFUNCTIONBODY_GETTER_SETTER(ElementFormat,fontDescription)
+ASFUNCTIONBODY_GETTER_SETTER(ElementFormat,fontSize)
+ASFUNCTIONBODY_GETTER_SETTER(ElementFormat,kerning)
+ASFUNCTIONBODY_GETTER_SETTER(ElementFormat,ligatureLevel)
+ASFUNCTIONBODY_GETTER_SETTER(ElementFormat,locale)
+ASFUNCTIONBODY_GETTER_SETTER(ElementFormat,locked)
+ASFUNCTIONBODY_GETTER_SETTER(ElementFormat,textRotation)
+ASFUNCTIONBODY_GETTER_SETTER(ElementFormat,trackingLeft)
+ASFUNCTIONBODY_GETTER_SETTER(ElementFormat,trackingRight)
+ASFUNCTIONBODY_GETTER_SETTER(ElementFormat,typographicCase)
 
 ASFUNCTIONBODY(ElementFormat, _constructor)
 {
-	LOG(LOG_NOT_IMPLEMENTED, "ElementFormat class not implemented");
+	ElementFormat* th=static_cast<ElementFormat*>(obj);
+	ARG_UNPACK(th->fontDescription, NullRef)(th->fontSize, 12.0)(th->color, 0x000000) (th->alpha, 1.0)(th->textRotation, "auto")
+			(th->dominantBaseline, "roman") (th->alignmentBaseline, "useDominantBaseline") (th->baselineShift, 0.0)(th->kerning, "on")
+			(th->trackingRight, 0.0)(th->trackingLeft, 0.0)(th->locale, "en")(th->breakOpportunity, "auto")(th->digitCase, "default")
+			(th->digitWidth, "default")(th->ligatureLevel, "common")(th->typographicCase, "default");
 	return NULL;
 }
 
+void FontLookup::sinit(Class_base* c)
+{
+	CLASS_SETUP_NO_CONSTRUCTOR(c, ASObject, CLASS_FINAL | CLASS_SEALED);
+	c->setVariableByQName("DEVICE","",Class<ASString>::getInstanceS("device"),CONSTANT_TRAIT);
+	c->setVariableByQName("EMBEDDED_CFF","",Class<ASString>::getInstanceS("embeddedCFF"),CONSTANT_TRAIT);
+}
+
 void FontDescription::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<ASObject>::getRef());
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_FINAL | CLASS_SEALED);
+	REGISTER_GETTER_SETTER(c,cffHinting);
+	REGISTER_GETTER_SETTER(c,fontLookup);
+	REGISTER_GETTER_SETTER(c,fontName);
+	REGISTER_GETTER_SETTER(c,fontPosture);
+	REGISTER_GETTER_SETTER(c,fontWeight);
+	REGISTER_GETTER_SETTER(c,locked);
+	REGISTER_GETTER_SETTER(c,renderingMode);
 }
 
 ASFUNCTIONBODY(FontDescription, _constructor)
@@ -63,24 +133,103 @@ ASFUNCTIONBODY(FontDescription, _constructor)
 	LOG(LOG_NOT_IMPLEMENTED, "FontDescription class not implemented");
 	return NULL;
 }
+ASFUNCTIONBODY_GETTER_SETTER(FontDescription,cffHinting)
+ASFUNCTIONBODY_GETTER_SETTER(FontDescription,fontLookup)
+ASFUNCTIONBODY_GETTER_SETTER(FontDescription,fontName)
+ASFUNCTIONBODY_GETTER_SETTER(FontDescription,fontPosture)
+ASFUNCTIONBODY_GETTER_SETTER(FontDescription,fontWeight)
+ASFUNCTIONBODY_GETTER_SETTER(FontDescription,locked)
+ASFUNCTIONBODY_GETTER_SETTER(FontDescription,renderingMode)
 
 void FontWeight::sinit(Class_base* c)
 {
-	c->setConstructor(NULL);
-	c->setSuper(Class<ASObject>::getRef());
+	CLASS_SETUP_NO_CONSTRUCTOR(c, ASObject, CLASS_FINAL | CLASS_SEALED);
 	c->setVariableByQName("BOLD","",Class<ASString>::getInstanceS("bold"),CONSTANT_TRAIT);
 	c->setVariableByQName("NORMAL","",Class<ASString>::getInstanceS("normal"),CONSTANT_TRAIT);
 }
 
+void FontMetrics::sinit(Class_base* c)
+{
+	CLASS_SETUP(c, ASObject,_constructor, CLASS_FINAL);
+}
+ASFUNCTIONBODY(FontMetrics, _constructor)
+{
+	//FontMetrics* th=static_cast<FontMetrics*>(obj);
+	LOG(LOG_NOT_IMPLEMENTED, "FontMetrics is a stub");
+	return NULL;
+}
+
+void Kerning::sinit(Class_base* c)
+{
+	CLASS_SETUP_NO_CONSTRUCTOR(c, ASObject, CLASS_FINAL | CLASS_SEALED);
+	c->setVariableByQName("AUTO","",Class<ASString>::getInstanceS("auto"),CONSTANT_TRAIT);
+	c->setVariableByQName("OFF","",Class<ASString>::getInstanceS("off"),CONSTANT_TRAIT);
+	c->setVariableByQName("ON","",Class<ASString>::getInstanceS("on"),CONSTANT_TRAIT);
+}
+
+void LineJustification::sinit(Class_base* c)
+{
+	CLASS_SETUP_NO_CONSTRUCTOR(c, ASObject, CLASS_FINAL | CLASS_SEALED);
+	c->setVariableByQName("ALL_BUT_LAST","",Class<ASString>::getInstanceS("allButLast"),CONSTANT_TRAIT);
+	c->setVariableByQName("ALL_BUT_MANDATORY_BREAK","",Class<ASString>::getInstanceS("allButMandatoryBreak"),CONSTANT_TRAIT);
+	c->setVariableByQName("ALL_INCLUDING_LAST","",Class<ASString>::getInstanceS("allIncludingLast"),CONSTANT_TRAIT);
+	c->setVariableByQName("UNJUSTIFIED","",Class<ASString>::getInstanceS("unjustified"),CONSTANT_TRAIT);
+}
+void TextBaseline::sinit(Class_base* c)
+{
+	CLASS_SETUP_NO_CONSTRUCTOR(c, ASObject, CLASS_FINAL | CLASS_SEALED);
+	c->setVariableByQName("ASCENT","",Class<ASString>::getInstanceS("ascent"),CONSTANT_TRAIT);
+	c->setVariableByQName("DESCENT","",Class<ASString>::getInstanceS("descent"),CONSTANT_TRAIT);
+	c->setVariableByQName("IDEOGRAPHIC_BOTTOM","",Class<ASString>::getInstanceS("ideographicBottom"),CONSTANT_TRAIT);
+	c->setVariableByQName("IDEOGRAPHIC_CENTER","",Class<ASString>::getInstanceS("ideographicCenter"),CONSTANT_TRAIT);
+	c->setVariableByQName("IDEOGRAPHIC_TOP","",Class<ASString>::getInstanceS("ideographicTop"),CONSTANT_TRAIT);
+	c->setVariableByQName("ROMAN","",Class<ASString>::getInstanceS("roman"),CONSTANT_TRAIT);
+	c->setVariableByQName("USE_DOMINANT_BASELINE","",Class<ASString>::getInstanceS("useDominantBaseline"),CONSTANT_TRAIT);
+}
+
+void TextJustifier::sinit(Class_base* c)
+{
+	CLASS_SETUP(c, ASObject, _constructor, 0);
+}
+ASFUNCTIONBODY(TextJustifier, _constructor)
+{
+	throwError<ArgumentError>(kCantInstantiateError, "TextJustifier cannot be instantiated");
+	return NULL;
+}
+void SpaceJustifier::sinit(Class_base* c)
+{
+	CLASS_SETUP(c, TextJustifier, _constructor, CLASS_FINAL);
+}
+ASFUNCTIONBODY(SpaceJustifier, _constructor)
+{
+	//SpaceJustifier* th=static_cast<SpaceJustifier*>(obj);
+	LOG(LOG_NOT_IMPLEMENTED, "SpaceJustifier is a stub");
+	return NULL;
+}
+void EastAsianJustifier::sinit(Class_base* c)
+{
+	CLASS_SETUP(c, TextJustifier, _constructor, CLASS_FINAL);
+}
+ASFUNCTIONBODY(EastAsianJustifier, _constructor)
+{
+	//EastAsianJustifier* th=static_cast<EastAsianJustifier*>(obj);
+	LOG(LOG_NOT_IMPLEMENTED, "EastAsianJustifier is a stub");
+	return NULL;
+}
+
 void TextBlock::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<ASObject>::getRef());
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_FINAL | CLASS_SEALED);
 	c->setDeclaredMethodByQName("createTextLine","",Class<IFunction>::getFunction(createTextLine),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("recreateTextLine","",Class<IFunction>::getFunction(recreateTextLine),NORMAL_METHOD,true);
 	REGISTER_GETTER_SETTER(c, content);
+	REGISTER_GETTER_SETTER(c, textJustifier);
+	REGISTER_GETTER_SETTER(c, bidiLevel);
 }
 
-ASFUNCTIONBODY_GETTER_SETTER(TextBlock, content);
+ASFUNCTIONBODY_GETTER_SETTER(TextBlock, content)
+ASFUNCTIONBODY_GETTER_SETTER(TextBlock, textJustifier)
+ASFUNCTIONBODY_GETTER_SETTER(TextBlock, bidiLevel)
 
 ASFUNCTIONBODY(TextBlock, _constructor)
 {
@@ -97,31 +246,92 @@ ASFUNCTIONBODY(TextBlock, createTextLine)
 	TextBlock* th=static_cast<TextBlock*>(obj);
 	_NR<TextLine> previousLine;
 	int32_t width;
-	ARG_UNPACK (previousLine, NullRef) (width, MAX_LINE_WIDTH);
+	number_t lineOffset;
+	bool fitSomething;
+	ARG_UNPACK (previousLine, NullRef) (width, MAX_LINE_WIDTH) (lineOffset, 0.0) (fitSomething, false);
 
 	if (argslen > 2)
 		LOG(LOG_NOT_IMPLEMENTED, "TextBlock::createTextLine ignored some parameters");
 
-	if (width <= 0 || width > MAX_LINE_WIDTH)
-		throw Class<ArgumentError>::getInstanceS("Invalid width");
-
-	if (!previousLine.isNull())
+	if (!fitSomething && (width < 0 || width > MAX_LINE_WIDTH))
 	{
-		LOG(LOG_NOT_IMPLEMENTED, "TextBlock::createTextLine supports a single line only");
-		return getSys()->getNullRef();
+		throwError<ArgumentError>(kOutOfRangeError,"Invalid width");
 	}
 
+	// TODO handle non TextElement Content
+	if (th->content.isNull() || !th->content->is<TextElement>() || th->content->as<TextElement>()->text.empty())
+		return NULL;
+	tiny_string linetext = th->content->as<TextElement>()->text;
+	if (fitSomething && linetext == "")
+		linetext = " ";
+		
+	LOG(LOG_NOT_IMPLEMENTED,"splitting textblock in multiple lines not implemented");
+	th->content->as<TextElement>()->text = "";
 	th->incRef();
-	TextLine *textLine = Class<TextLine>::getInstanceS(th->content, _MNR(th));
+	TextLine *textLine = Class<TextLine>::getInstanceS(linetext, _MNR(th));
 	textLine->width = (uint32_t)width;
+	textLine->previousLine = previousLine;
 	textLine->updateSizes();
+	if (textLine->width > textLine->textWidth)
+	{
+		delete textLine;
+		th->decRef();
+		return NULL;
+	}
+	if (!previousLine.isNull())
+		previousLine->nextLine == textLine;
 	return textLine;
 }
+ASFUNCTIONBODY(TextBlock, recreateTextLine)
+{
+	TextBlock* th=static_cast<TextBlock*>(obj);
+	_NR<TextLine> previousLine;
+	_NR<TextLine> textLine;
+	int32_t width;
+	number_t lineOffset;
+	bool fitSomething;
+	ARG_UNPACK (textLine) (previousLine, NullRef) (width, MAX_LINE_WIDTH) (lineOffset, 0.0) (fitSomething, false);
+
+	if (argslen > 2)
+		LOG(LOG_NOT_IMPLEMENTED, "TextBlock::recreateTextLine ignored some parameters");
+	LOG(LOG_NOT_IMPLEMENTED, "TextBlock::recreateTextLine doesn't check all parameters for validity");
+
+	// TODO handle non TextElement Content
+	if (th->content.isNull() || !th->content->is<TextElement>() || th->content->as<TextElement>()->text.empty())
+		return NULL;
+
+	if (!fitSomething && (width < 0 || width > MAX_LINE_WIDTH))
+	{
+		throwError<ArgumentError>(kOutOfRangeError,"Invalid width");
+	}
+
+	if (textLine.isNull())
+	{
+		throwError<ArgumentError>(kInvalidArgumentError,"Invalid argument: textLine");
+	}
+
+	if (th != textLine->textBlock.getPtr())
+	{
+		throwError<ArgumentError>(kInvalidArgumentError,"Invalid argument: textLine is in different textBlock");
+	}
+	if (fitSomething && textLine->text == "")
+		textLine->text = " ";
+	textLine->width = (uint32_t)width;
+	textLine->previousLine = previousLine;
+	textLine->updateSizes();
+	if (textLine->width > textLine->textWidth)
+	{
+		return NULL;
+	}
+	if (!previousLine.isNull())
+		previousLine->nextLine == textLine;
+	textLine->incRef();
+	return textLine.getPtr();
+}
 
 void TextElement::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<ContentElement>::getRef());
+	CLASS_SETUP(c, ContentElement, _constructor, CLASS_FINAL | CLASS_SEALED);
 	REGISTER_GETTER_SETTER(c, text);
 }
 
@@ -137,32 +347,37 @@ ASFUNCTIONBODY(TextElement, _constructor)
 	return NULL;
 }
 
-TextLine::TextLine(Class_base* c, _NR<ContentElement> content, _NR<TextBlock> owner)
-  : DisplayObjectContainer(c), TextData()
+TextLine::TextLine(Class_base* c, tiny_string linetext, _NR<TextBlock> owner)
+  : DisplayObjectContainer(c), TextData(),nextLine(NULL),previousLine(NULL),userData(NULL)
 {
 	textBlock = owner;
 
-	if (content.isNull() || !content->is<TextElement>())
-	{
-		LOG(LOG_NOT_IMPLEMENTED, "TextLine supports only TextElements");
-		return;
-	}
-
-	TextElement *textElement = content->as<TextElement>();
-	text = textElement->text;
+	text = linetext;
 	updateSizes();
 	requestInvalidation(getSys());
 }
 
 void TextLine::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<DisplayObjectContainer>::getRef());
-	REGISTER_GETTER(c, textBlock);
+	CLASS_SETUP(c, DisplayObjectContainer, _constructor, CLASS_FINAL | CLASS_SEALED);
 	c->setVariableByQName("MAX_LINE_WIDTH","",abstract_ui(MAX_LINE_WIDTH),CONSTANT_TRAIT);
+	c->setDeclaredMethodByQName("descent","",Class<IFunction>::getFunction(getDescent),GETTER_METHOD,true);
+	c->setDeclaredMethodByQName("ascent","",Class<IFunction>::getFunction(getAscent),GETTER_METHOD,true);
+	c->setDeclaredMethodByQName("textWidth","",Class<IFunction>::getFunction(getTextWidth),GETTER_METHOD,true);
+	c->setDeclaredMethodByQName("textHeight","",Class<IFunction>::getFunction(getTextHeight),GETTER_METHOD,true);
+	REGISTER_GETTER(c, textBlock);
+	REGISTER_GETTER(c, nextLine);
+	REGISTER_GETTER(c, previousLine);
+	REGISTER_GETTER_SETTER(c, validity);
+	REGISTER_GETTER_SETTER(c, userData);
 }
 
+
 ASFUNCTIONBODY_GETTER(TextLine, textBlock);
+ASFUNCTIONBODY_GETTER(TextLine, nextLine);
+ASFUNCTIONBODY_GETTER(TextLine, previousLine);
+ASFUNCTIONBODY_GETTER_SETTER(TextLine, validity);
+ASFUNCTIONBODY_GETTER_SETTER(TextLine, userData);
 
 ASFUNCTIONBODY(TextLine, _constructor)
 {
@@ -171,6 +386,31 @@ ASFUNCTIONBODY(TextLine, _constructor)
 
 	return NULL;
 }
+ASFUNCTIONBODY(TextLine, getDescent)
+{
+	LOG(LOG_NOT_IMPLEMENTED,"TextLine.descent");
+	return abstract_d(0);
+}
+
+ASFUNCTIONBODY(TextLine, getAscent)
+{
+	TextLine* th=static_cast<TextLine*>(obj);
+	LOG(LOG_NOT_IMPLEMENTED,"TextLine.ascent");
+	return abstract_d(th->textHeight);
+}
+
+ASFUNCTIONBODY(TextLine, getTextWidth)
+{
+	TextLine* th=static_cast<TextLine*>(obj);
+	return abstract_d(th->textWidth);
+}
+
+ASFUNCTIONBODY(TextLine, getTextHeight)
+{
+	TextLine* th=static_cast<TextLine*>(obj);
+	return abstract_d(th->textHeight);
+}
+
 
 void TextLine::updateSizes()
 {
@@ -179,7 +419,12 @@ void TextLine::updateSizes()
 	h = height;
 	//Compute (text)width, (text)height
 	CairoPangoRenderer::getBounds(*this, w, h, tw, th);
+	if (w == 0)
+		w = tw;
+	if (h == 0)
+		h = th;
 	width = w; //TODO: check the case when w,h == 0
+	
 	textWidth = w;
 	height = h;
 	textHeight = h;
@@ -243,3 +488,13 @@ _NR<DisplayObject> TextLine::hitTestImpl(_NR<DisplayObject> last, number_t x, nu
 		return DisplayObjectContainer::hitTestImpl(_MR(this), x, y, type);
 	}
 }
+
+void TextLineValidity::sinit(Class_base* c)
+{
+	CLASS_SETUP_NO_CONSTRUCTOR(c, ASObject, CLASS_FINAL | CLASS_SEALED);
+	c->setVariableByQName("INVALID","",Class<ASString>::getInstanceS("invalid"),CONSTANT_TRAIT);
+	c->setVariableByQName("POSSIBLY_INVALID","",Class<ASString>::getInstanceS("possiblyInvalid"),CONSTANT_TRAIT);
+	c->setVariableByQName("STATIC","",Class<ASString>::getInstanceS("static"),CONSTANT_TRAIT);
+	c->setVariableByQName("VALID","",Class<ASString>::getInstanceS("valid"),CONSTANT_TRAIT);
+}
+
diff --git a/src/scripting/flash/text/flashtextengine.h b/src/scripting/flash/text/flashtextengine.h
index df28501..063af79 100644
--- a/src/scripting/flash/text/flashtextengine.h
+++ b/src/scripting/flash/text/flashtextengine.h
@@ -29,51 +29,141 @@
 namespace lightspark
 {
 
+class ElementFormat;
 class ContentElement: public ASObject
 {
 public:
-	ContentElement(Class_base* c): ASObject(c) {};
+	ContentElement(Class_base* c): ASObject(c),elementFormat(NULL) {}
 	static void sinit(Class_base* c);
-	ASFUNCTION(_constructor);
+	ASPROPERTY_GETTER_SETTER(_NR<ElementFormat>,elementFormat);
 };
 
+class FontDescription;
 class ElementFormat: public ASObject
 {
 public:
-	ElementFormat(Class_base* c): ASObject(c) {};
+	ElementFormat(Class_base* c);
 	static void sinit(Class_base* c);
 	ASFUNCTION(_constructor);
+	ASPROPERTY_GETTER_SETTER(tiny_string,alignmentBaseline);
+	ASPROPERTY_GETTER_SETTER(number_t,alpha);
+	ASPROPERTY_GETTER_SETTER(number_t,baselineShift);
+	ASPROPERTY_GETTER_SETTER(tiny_string,breakOpportunity);
+	ASPROPERTY_GETTER_SETTER(uint,color);
+	ASPROPERTY_GETTER_SETTER(tiny_string,digitCase);
+	ASPROPERTY_GETTER_SETTER(tiny_string,digitWidth);
+	ASPROPERTY_GETTER_SETTER(tiny_string,dominantBaseline);
+	ASPROPERTY_GETTER_SETTER(_NR<FontDescription>,fontDescription);
+	ASPROPERTY_GETTER_SETTER(number_t,fontSize);
+	ASPROPERTY_GETTER_SETTER(tiny_string,kerning);
+	ASPROPERTY_GETTER_SETTER(tiny_string,ligatureLevel);
+	ASPROPERTY_GETTER_SETTER(tiny_string,locale);
+	ASPROPERTY_GETTER_SETTER(bool,locked);
+	ASPROPERTY_GETTER_SETTER(tiny_string,textRotation);
+	ASPROPERTY_GETTER_SETTER(number_t,trackingLeft);
+	ASPROPERTY_GETTER_SETTER(number_t,trackingRight);
+	ASPROPERTY_GETTER_SETTER(tiny_string,typographicCase);
+};
+
+class FontLookup: public ASObject
+{
+public:
+	FontLookup(Class_base* c): ASObject(c) {}
+	static void sinit(Class_base* c);
 };
 
 class FontDescription: public ASObject
 {
 public:
-	FontDescription(Class_base* c): ASObject(c) {};
+	FontDescription(Class_base* c): ASObject(c), 
+		cffHinting("horizontalStem"), fontLookup("device"), fontName("_serif"), fontPosture("normal"), fontWeight("normal"),locked(false), renderingMode("cff") {}
 	static void sinit(Class_base* c);
 	ASFUNCTION(_constructor);
+	ASPROPERTY_GETTER_SETTER(tiny_string,cffHinting);
+	ASPROPERTY_GETTER_SETTER(tiny_string,fontLookup);
+	ASPROPERTY_GETTER_SETTER(tiny_string,fontName);
+	ASPROPERTY_GETTER_SETTER(tiny_string,fontPosture);
+	ASPROPERTY_GETTER_SETTER(tiny_string,fontWeight);
+	ASPROPERTY_GETTER_SETTER(bool,locked);
+	ASPROPERTY_GETTER_SETTER(tiny_string,renderingMode);
 };
 
 class FontWeight: public ASObject
 {
 public:
-	FontWeight(Class_base* c): ASObject(c) {};
+	FontWeight(Class_base* c): ASObject(c) {}
+	static void sinit(Class_base* c);
+};
+
+class FontMetrics: public ASObject
+{
+public:
+	FontMetrics(Class_base* c): ASObject(c) {}
+	static void sinit(Class_base* c);
+	ASFUNCTION(_constructor);
+};
+
+class Kerning: public ASObject
+{
+public:
+	Kerning(Class_base* c): ASObject(c) {}
+	static void sinit(Class_base* c);
+};
+class LineJustification: public ASObject
+{
+public:
+	LineJustification(Class_base* c): ASObject(c) {}
+	static void sinit(Class_base* c);
+};
+
+class TextBaseline: public ASObject
+{
+public:
+	TextBaseline(Class_base* c): ASObject(c) {}
 	static void sinit(Class_base* c);
 };
 
+class TextJustifier: public ASObject
+{
+public:
+	TextJustifier(Class_base* c): ASObject(c) {}
+	static void sinit(Class_base* c);
+	ASFUNCTION(_constructor);
+};
+
+class SpaceJustifier: public TextJustifier
+{
+public:
+	SpaceJustifier(Class_base* c): TextJustifier(c) {}
+	static void sinit(Class_base* c);
+	ASFUNCTION(_constructor);
+};
+
+class EastAsianJustifier: public TextJustifier
+{
+public:
+	EastAsianJustifier(Class_base* c): TextJustifier(c) {}
+	static void sinit(Class_base* c);
+	ASFUNCTION(_constructor);
+};
+
 class TextBlock: public ASObject
 {
 public:
-	TextBlock(Class_base* c): ASObject(c) {};
+	TextBlock(Class_base* c): ASObject(c),bidiLevel(0) {}
 	static void sinit(Class_base* c);
 	ASFUNCTION(_constructor);
 	ASFUNCTION(createTextLine);
+	ASFUNCTION(recreateTextLine);
 	ASPROPERTY_GETTER_SETTER(_NR<ContentElement>, content);
+	ASPROPERTY_GETTER_SETTER(_NR<TextJustifier>, textJustifier);
+	ASPROPERTY_GETTER_SETTER(int,bidiLevel);
 };
 
 class TextElement: public ContentElement
 {
 public:
-	TextElement(Class_base* c): ContentElement(c) {};
+	TextElement(Class_base* c): ContentElement(c) {}
 	static void sinit(Class_base* c);
 	ASFUNCTION(_constructor);
 	ASPROPERTY_GETTER_SETTER(tiny_string,text);
@@ -90,12 +180,29 @@ private:
 	void renderImpl(RenderContext& ctxt) const;
 	_NR<DisplayObject> hitTestImpl(_NR<DisplayObject> last, number_t x, number_t y, DisplayObject::HIT_TYPE type);
 public:
-	TextLine(Class_base* c, _NR<ContentElement> content=NullRef, _NR<TextBlock> owner=NullRef);
+	TextLine(Class_base* c,tiny_string linetext = "", _NR<TextBlock> owner=NullRef);
 	static void sinit(Class_base* c);
 	void updateSizes();
 	ASFUNCTION(_constructor);
 	ASPROPERTY_GETTER(_NR<TextBlock>, textBlock);
+	ASPROPERTY_GETTER(_NR<TextLine>, nextLine);
+	ASPROPERTY_GETTER(_NR<TextLine>, previousLine);
+	ASPROPERTY_GETTER_SETTER(tiny_string,validity);
+	ASPROPERTY_GETTER_SETTER(_NR<ASObject>,userData);
+	ASFUNCTION(getDescent);
+	ASFUNCTION(getAscent);
+	ASFUNCTION(getTextWidth);
+	ASFUNCTION(getTextHeight);
+
 };
+
+class TextLineValidity: public ASObject
+{
+public:
+	TextLineValidity(Class_base* c): ASObject(c) {}
+	static void sinit(Class_base* c);
 };
 
+}
+
 #endif
diff --git a/src/scripting/flash/accessibility/flashaccessibility.cpp b/src/scripting/flash/ui/ContextMenu.cpp
similarity index 51%
copy from src/scripting/flash/accessibility/flashaccessibility.cpp
copy to src/scripting/flash/ui/ContextMenu.cpp
index ebc460d..bac02c1 100644
--- a/src/scripting/flash/accessibility/flashaccessibility.cpp
+++ b/src/scripting/flash/ui/ContextMenu.cpp
@@ -1,8 +1,6 @@
 /**************************************************************************
     Lightspark, a free flash player implementation
 
-    Copyright (C) 2009-2013  Alessandro Pignotti (a.pignotti at sssup.it)
-
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU Lesser General Public License as published by
     the Free Software Foundation, either version 3 of the License, or
@@ -17,35 +15,40 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 **************************************************************************/
 
-#include "scripting/flash/accessibility/flashaccessibility.h"
+#include "ContextMenu.h"
 #include "scripting/class.h"
 #include "scripting/argconv.h"
 
+using namespace std;
 using namespace lightspark;
 
-void AccessibilityProperties::sinit(Class_base* c)
+ContextMenu::ContextMenu(Class_base* c):EventDispatcher(c),customItems(Class<Array>::getInstanceS()),builtInItems(Class<ContextMenuBuiltInItems>::getInstanceS())
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<ASObject>::getRef());
-	REGISTER_GETTER_SETTER(c,name);
 }
 
-ASFUNCTIONBODY(AccessibilityProperties,_constructor)
+void ContextMenu::sinit(Class_base* c)
 {
-	LOG(LOG_NOT_IMPLEMENTED, _("AccessibilityProperties class is unimplemented."));
-	return NULL;
+	CLASS_SETUP(c, EventDispatcher, _constructor, CLASS_FINAL);
+	c->setVariableByQName("isSupported","",abstract_b(false),CONSTANT_TRAIT);
+	c->setDeclaredMethodByQName("hideBuiltInItems","",Class<IFunction>::getFunction(hideBuiltInItems),NORMAL_METHOD,true);
+	REGISTER_GETTER_SETTER(c,customItems);
+	REGISTER_GETTER_SETTER(c,builtInItems);
 }
 
-ASFUNCTIONBODY_GETTER_SETTER(AccessibilityProperties,name);
+ASFUNCTIONBODY_GETTER_SETTER(ContextMenu,customItems);
+ASFUNCTIONBODY_GETTER_SETTER(ContextMenu,builtInItems);
 
-void AccessibilityImplementation::sinit(Class_base* c)
+ASFUNCTIONBODY(ContextMenu,_constructor)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<ASObject>::getRef());
+	EventDispatcher::_constructor(obj, NULL, 0);
+	LOG(LOG_NOT_IMPLEMENTED,"ContextMenu constructor is a stub");
+	return NULL;
 }
 
-ASFUNCTIONBODY(AccessibilityImplementation,_constructor)
+ASFUNCTIONBODY(ContextMenu,hideBuiltInItems)
 {
-	LOG(LOG_NOT_IMPLEMENTED, _("AccessibilityImplementation class is unimplemented."));
+	LOG(LOG_NOT_IMPLEMENTED,"ContextMenu hideBuiltInItems is a stub");
 	return NULL;
 }
+
+
diff --git a/src/scripting/flash/sensors/flashsensors.h b/src/scripting/flash/ui/ContextMenu.h
similarity index 64%
copy from src/scripting/flash/sensors/flashsensors.h
copy to src/scripting/flash/ui/ContextMenu.h
index 9f9ef19..9d189c0 100644
--- a/src/scripting/flash/sensors/flashsensors.h
+++ b/src/scripting/flash/ui/ContextMenu.h
@@ -1,8 +1,6 @@
 /**************************************************************************
     Lightspark, a free flash player implementation
 
-    Copyright (C) 2011-2013  Alessandro Pignotti (a.pignotti at sssup.it)
-
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU Lesser General Public License as published by
     the Free Software Foundation, either version 3 of the License, or
@@ -17,25 +15,28 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 **************************************************************************/
 
-#ifndef SCRIPTING_FLASH_SENSORS_FLASHSENSORS_H
-#define SCRIPTING_FLASH_SENSORS_FLASHSENSORS_H 1
+#ifndef SCRIPTING_FLASH_UI_CONTEXTMENU_H
+#define SCRIPTING_FLASH_UI_CONTEXTMENU_H
 
-#include "compat.h"
 #include "asobject.h"
 #include "scripting/flash/events/flashevents.h"
-#include "thread_pool.h"
-#include "backends/netutils.h"
-#include "timer.h"
-#include "backends/interfaces/audio/IAudioPlugin.h"
+#include "scripting/flash/ui/ContextMenuBuiltInItems.h"
+#include "scripting/toplevel/Array.h"
 
 namespace lightspark
 {
-class Accelerometer: public ASObject {
-	public:
-		Accelerometer(Class_base* c);
-		static void sinit(Class_base* c);
-		static void buildTraits(ASObject* o);
-		ASFUNCTION(_isSupported);
+class Array;
+
+class ContextMenu : public EventDispatcher
+{
+public:
+	ContextMenu(Class_base* c);
+	static void sinit(Class_base* c);
+	ASFUNCTION(_constructor);
+	ASFUNCTION(hideBuiltInItems);
+	ASPROPERTY_GETTER_SETTER(_NR<Array>,customItems);
+	ASPROPERTY_GETTER_SETTER(_NR<ContextMenuBuiltInItems>,builtInItems);
 };
+
 }
-#endif /* SCRIPTING_FLASH_SENSORS_FLASHSENSORS_H */
+#endif // SCRIPTING_FLASH_UI_CONTEXTMENU_H
diff --git a/src/scripting/flash/ui/ContextMenuBuiltInItems.cpp b/src/scripting/flash/ui/ContextMenuBuiltInItems.cpp
new file mode 100644
index 0000000..c98bb93
--- /dev/null
+++ b/src/scripting/flash/ui/ContextMenuBuiltInItems.cpp
@@ -0,0 +1,57 @@
+/**************************************************************************
+    Lightspark, a free flash player implementation
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+**************************************************************************/
+
+#include "ContextMenuItem.h"
+#include "scripting/class.h"
+#include "scripting/argconv.h"
+
+using namespace std;
+using namespace lightspark;
+
+ContextMenuBuiltInItems::ContextMenuBuiltInItems(Class_base* c):ASObject(c),
+	forwardAndBack(false),loop(false),play(false),print(false),quality(false),rewind(false),save(false),zoom(false)
+{
+}
+
+void ContextMenuBuiltInItems::sinit(Class_base* c)
+{
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_FINAL);
+	REGISTER_GETTER_SETTER(c,forwardAndBack);
+	REGISTER_GETTER_SETTER(c,loop);
+	REGISTER_GETTER_SETTER(c,play);
+	REGISTER_GETTER_SETTER(c,print);
+	REGISTER_GETTER_SETTER(c,quality);
+	REGISTER_GETTER_SETTER(c,rewind);
+	REGISTER_GETTER_SETTER(c,save);
+	REGISTER_GETTER_SETTER(c,zoom);
+}
+
+ASFUNCTIONBODY_GETTER_SETTER(ContextMenuBuiltInItems,forwardAndBack);
+ASFUNCTIONBODY_GETTER_SETTER(ContextMenuBuiltInItems,loop);
+ASFUNCTIONBODY_GETTER_SETTER(ContextMenuBuiltInItems,play);
+ASFUNCTIONBODY_GETTER_SETTER(ContextMenuBuiltInItems,print);
+ASFUNCTIONBODY_GETTER_SETTER(ContextMenuBuiltInItems,quality);
+ASFUNCTIONBODY_GETTER_SETTER(ContextMenuBuiltInItems,rewind);
+ASFUNCTIONBODY_GETTER_SETTER(ContextMenuBuiltInItems,save);
+ASFUNCTIONBODY_GETTER_SETTER(ContextMenuBuiltInItems,zoom);
+
+ASFUNCTIONBODY(ContextMenuBuiltInItems,_constructor)
+{
+	return NULL;
+}
+
+
diff --git a/src/scripting/flash/accessibility/flashaccessibility.h b/src/scripting/flash/ui/ContextMenuBuiltInItems.h
similarity index 59%
copy from src/scripting/flash/accessibility/flashaccessibility.h
copy to src/scripting/flash/ui/ContextMenuBuiltInItems.h
index 19d00b8..c0dcc03 100644
--- a/src/scripting/flash/accessibility/flashaccessibility.h
+++ b/src/scripting/flash/ui/ContextMenuBuiltInItems.h
@@ -1,7 +1,7 @@
 /**************************************************************************
     Lightspark, a free flash player implementation
 
-    Copyright (C) 2009-2013  Alessandro Pignotti (a.pignotti at sssup.it)
+    Copyright (C) 2013  Antti Ajanki (antti.ajanki at iki.fi)
 
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU Lesser General Public License as published by
@@ -17,31 +17,30 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 **************************************************************************/
 
-#ifndef SCRIPTING_FLASH_ACCESSIBILITY_FLASHACCESSIBILITY_H
-#define SCRIPTING_FLASH_ACCESSIBILITY_FLASHACCESSIBILITY_H 1
+#ifndef SCRIPTING_FLASH_UI_CONTEXTMENUBUILTINITEMS_H
+#define SCRIPTING_FLASH_UI_CONTEXTMENUBUILTINITEMS_H
 
 #include "asobject.h"
 
 namespace lightspark
 {
 
-class AccessibilityProperties : public ASObject
+class ContextMenuBuiltInItems : public ASObject
 {
 private:
-	ASPROPERTY_GETTER_SETTER(tiny_string,name);
+	ASPROPERTY_GETTER_SETTER(bool,forwardAndBack);
+	ASPROPERTY_GETTER_SETTER(bool,loop);
+	ASPROPERTY_GETTER_SETTER(bool,play);
+	ASPROPERTY_GETTER_SETTER(bool,print);
+	ASPROPERTY_GETTER_SETTER(bool,quality);
+	ASPROPERTY_GETTER_SETTER(bool,rewind);
+	ASPROPERTY_GETTER_SETTER(bool,save);
+	ASPROPERTY_GETTER_SETTER(bool,zoom);
 public:
-	AccessibilityProperties(Class_base* c):ASObject(c){}
-	static void sinit(Class_base*);
-	ASFUNCTION(_constructor);
-};
-
-class AccessibilityImplementation : public ASObject
-{
-public:
-	AccessibilityImplementation(Class_base* c):ASObject(c){}
-	static void sinit(Class_base*);
+	ContextMenuBuiltInItems(Class_base* c);
+	static void sinit(Class_base* c);
 	ASFUNCTION(_constructor);
 };
 
 }
-#endif /* SCRIPTING_FLASH_ACCESSIBILITY_FLASHACCESSIBILITY_H */
+#endif // SCRIPTING_FLASH_UI_CONTEXTMENUBUILTINITEMS_H
diff --git a/src/backends/rtmputils.h b/src/scripting/flash/ui/ContextMenuItem.cpp
similarity index 63%
copy from src/backends/rtmputils.h
copy to src/scripting/flash/ui/ContextMenuItem.cpp
index 7e9de51..b46afe6 100644
--- a/src/backends/rtmputils.h
+++ b/src/scripting/flash/ui/ContextMenuItem.cpp
@@ -1,8 +1,6 @@
 /**************************************************************************
     Lightspark, a free flash player implementation
 
-    Copyright (C) 2011-2013  Alessandro Pignotti (a.pignotti at sssup.it)
-
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU Lesser General Public License as published by
     the Free Software Foundation, either version 3 of the License, or
@@ -17,25 +15,25 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 **************************************************************************/
 
-#ifndef BACKENDS_RTMPUTILS_H
-#define BACKENDS_RTMPUTILS_H 1
+#include "ContextMenuItem.h"
+#include "scripting/class.h"
+#include "scripting/argconv.h"
 
-#include "backends/netutils.h"
+using namespace std;
+using namespace lightspark;
 
-namespace lightspark
+void ContextMenuItem::sinit(Class_base* c)
 {
+	CLASS_SETUP(c, EventDispatcher, _constructor, CLASS_FINAL);
+	REGISTER_GETTER_SETTER(c, caption);
+}
 
-class ILoadable;
-
-class RTMPDownloader: public ThreadedDownloader
+ASFUNCTIONBODY(ContextMenuItem,_constructor)
 {
-private:
-	void execute();
-	void threadAbort();
-	tiny_string stream;
-public:
-	RTMPDownloader(const tiny_string& _url, const tiny_string& _stream, ILoadable* o);
-};
-
-};
-#endif /* BACKENDS_RTMPUTILS_H */
+	EventDispatcher::_constructor(obj, NULL, 0);
+	LOG(LOG_NOT_IMPLEMENTED,"ContextMenuItem constructor is a stub");
+	return NULL;
+}
+
+ASFUNCTIONBODY_GETTER_SETTER(ContextMenuItem,caption);
+
diff --git a/src/backends/rtmputils.h b/src/scripting/flash/ui/ContextMenuItem.h
similarity index 65%
copy from src/backends/rtmputils.h
copy to src/scripting/flash/ui/ContextMenuItem.h
index 7e9de51..f2db4b5 100644
--- a/src/backends/rtmputils.h
+++ b/src/scripting/flash/ui/ContextMenuItem.h
@@ -1,7 +1,7 @@
 /**************************************************************************
     Lightspark, a free flash player implementation
 
-    Copyright (C) 2011-2013  Alessandro Pignotti (a.pignotti at sssup.it)
+    Copyright (C) 2013  Antti Ajanki (antti.ajanki at iki.fi)
 
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU Lesser General Public License as published by
@@ -17,25 +17,23 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 **************************************************************************/
 
-#ifndef BACKENDS_RTMPUTILS_H
-#define BACKENDS_RTMPUTILS_H 1
+#ifndef SCRIPTING_FLASH_UI_CONTEXTMENUITEM_H
+#define SCRIPTING_FLASH_UI_CONTEXTMENUITEM_H
 
-#include "backends/netutils.h"
+#include "asobject.h"
+#include "scripting/flash/events/flashevents.h"
 
 namespace lightspark
 {
 
-class ILoadable;
-
-class RTMPDownloader: public ThreadedDownloader
+class ContextMenuItem : public EventDispatcher
 {
-private:
-	void execute();
-	void threadAbort();
-	tiny_string stream;
 public:
-	RTMPDownloader(const tiny_string& _url, const tiny_string& _stream, ILoadable* o);
+	ContextMenuItem(Class_base* c):EventDispatcher(c){}
+	static void sinit(Class_base* c);
+	ASFUNCTION(_constructor);
+	ASPROPERTY_GETTER_SETTER(tiny_string, caption);
 };
 
-};
-#endif /* BACKENDS_RTMPUTILS_H */
+}
+#endif // SCRIPTING_FLASH_UI_CONTEXTMENUITEM_H
diff --git a/src/scripting/flash/ui/Keyboard.cpp b/src/scripting/flash/ui/Keyboard.cpp
index 0541cdb..5b1243c 100644
--- a/src/scripting/flash/ui/Keyboard.cpp
+++ b/src/scripting/flash/ui/Keyboard.cpp
@@ -27,8 +27,7 @@ using namespace lightspark;
 
 void Keyboard::sinit(Class_base* c)
 {
-	c->setConstructor(NULL);
-	c->setSuper(Class<ASObject>::getRef());
+	CLASS_SETUP(c, ASObject, _constructorNotInstantiatable, CLASS_FINAL | CLASS_SEALED);
 	c->setDeclaredMethodByQName("capsLock","",Class<IFunction>::getFunction(capsLock),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("hasVirtualKeyboard","",Class<IFunction>::getFunction(hasVirtualKeyboard),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("numLock","",Class<IFunction>::getFunction(numLock),GETTER_METHOD,true);
@@ -76,8 +75,7 @@ ASFUNCTIONBODY(Keyboard, isAccessible)
 
 void KeyboardType::sinit(Class_base* c)
 {
-	c->setConstructor(NULL);
-	c->setSuper(Class<ASObject>::getRef());
+	CLASS_SETUP(c, ASObject, _constructorNotInstantiatable, CLASS_FINAL | CLASS_SEALED);
 	c->setVariableByQName("ALPHANUMERIC","",Class<ASString>::getInstanceS("alphanumeric"),DECLARED_TRAIT);
 	c->setVariableByQName("KEYPAD","",Class<ASString>::getInstanceS("keypad"),DECLARED_TRAIT);
 	c->setVariableByQName("NONE","",Class<ASString>::getInstanceS("none"),DECLARED_TRAIT);
@@ -85,8 +83,7 @@ void KeyboardType::sinit(Class_base* c)
 
 void KeyLocation::sinit(Class_base* c)
 {
-	c->setConstructor(NULL);
-	c->setSuper(Class<ASObject>::getRef());
+	CLASS_SETUP_NO_CONSTRUCTOR(c, ASObject, CLASS_FINAL | CLASS_SEALED);
 	c->setVariableByQName("LEFT","",Class<UInteger>::getInstanceS(1),DECLARED_TRAIT);
 	c->setVariableByQName("NUM_PAD","",Class<UInteger>::getInstanceS(3),DECLARED_TRAIT);
 	c->setVariableByQName("RIGHT","",Class<UInteger>::getInstanceS(2),DECLARED_TRAIT);
diff --git a/src/scripting/flash/ui/Mouse.cpp b/src/scripting/flash/ui/Mouse.cpp
new file mode 100644
index 0000000..f53d61b
--- /dev/null
+++ b/src/scripting/flash/ui/Mouse.cpp
@@ -0,0 +1,75 @@
+/**************************************************************************
+    Lightspark, a free flash player implementation
+
+    Copyright (C) 2013  Antti Ajanki (antti.ajanki at iki.fi)
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+**************************************************************************/
+
+#include "scripting/flash/ui/Mouse.h"
+#include "scripting/toplevel/ASString.h"
+#include "scripting/toplevel/Error.h"
+#include "scripting/class.h"
+#include "scripting/argconv.h"
+#include "swf.h"
+
+using namespace std;
+using namespace lightspark;
+
+void Mouse::sinit(Class_base* c)
+{
+	CLASS_SETUP(c, ASObject, _constructorNotInstantiatable, CLASS_FINAL | CLASS_SEALED);
+	c->setDeclaredMethodByQName("hide","",Class<IFunction>::getFunction(hide),NORMAL_METHOD,false);
+	c->setDeclaredMethodByQName("show","",Class<IFunction>::getFunction(show),NORMAL_METHOD,false);
+	c->setDeclaredMethodByQName("cursor","",Class<IFunction>::getFunction(getCursor),GETTER_METHOD,false);
+	c->setDeclaredMethodByQName("cursor","",Class<IFunction>::getFunction(setCursor),SETTER_METHOD,false);
+	c->setDeclaredMethodByQName("supportsCursor","",Class<IFunction>::getFunction(getSupportsCursor),GETTER_METHOD,false);
+	c->setDeclaredMethodByQName("supportsNativeCursor","",Class<IFunction>::getFunction(getSupportsNativeCursor),GETTER_METHOD,false);
+}
+
+ASFUNCTIONBODY(Mouse, hide)
+{
+	getSys()->showMouseCursor(false);
+	return NULL;
+}
+
+ASFUNCTIONBODY(Mouse, show)
+{
+	getSys()->showMouseCursor(true);
+	return NULL;
+}
+
+ASFUNCTIONBODY(Mouse, getCursor)
+{
+	return Class<ASString>::getInstanceS("auto");
+}
+
+ASFUNCTIONBODY(Mouse, setCursor)
+{
+	tiny_string cursorName;
+	ARG_UNPACK(cursorName);
+	if (cursorName != "auto")
+		throwError<ArgumentError>(kInvalidEnumError, "cursor");
+	return NULL;
+}
+
+ASFUNCTIONBODY(Mouse, getSupportsCursor)
+{
+	return abstract_b(true);
+}
+
+ASFUNCTIONBODY(Mouse, getSupportsNativeCursor)
+{
+	return abstract_b(false); // until registerCursor() is implemented
+}
diff --git a/src/backends/rtmputils.h b/src/scripting/flash/ui/Mouse.h
similarity index 67%
copy from src/backends/rtmputils.h
copy to src/scripting/flash/ui/Mouse.h
index 7e9de51..e81d34e 100644
--- a/src/backends/rtmputils.h
+++ b/src/scripting/flash/ui/Mouse.h
@@ -1,7 +1,7 @@
 /**************************************************************************
     Lightspark, a free flash player implementation
 
-    Copyright (C) 2011-2013  Alessandro Pignotti (a.pignotti at sssup.it)
+    Copyright (C) 2013  Antti Ajanki (antti.ajanki at iki.fi)
 
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU Lesser General Public License as published by
@@ -17,25 +17,27 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 **************************************************************************/
 
-#ifndef BACKENDS_RTMPUTILS_H
-#define BACKENDS_RTMPUTILS_H 1
+#ifndef SCRIPTING_FLASH_UI_MOUSE_H
+#define SCRIPTING_FLASH_UI_MOUSE_H 1
 
-#include "backends/netutils.h"
+#include "asobject.h"
 
 namespace lightspark
 {
 
-class ILoadable;
-
-class RTMPDownloader: public ThreadedDownloader
+class Mouse : public ASObject
 {
-private:
-	void execute();
-	void threadAbort();
-	tiny_string stream;
 public:
-	RTMPDownloader(const tiny_string& _url, const tiny_string& _stream, ILoadable* o);
+	Mouse(Class_base* c):ASObject(c){}
+	static void sinit(Class_base* c);
+	ASFUNCTION(hide);
+	ASFUNCTION(show);
+	ASFUNCTION(getCursor);
+	ASFUNCTION(setCursor);
+	ASFUNCTION(getSupportsCursor);
+	ASFUNCTION(getSupportsNativeCursor);
 };
 
 };
-#endif /* BACKENDS_RTMPUTILS_H */
+
+#endif /* SCRIPTING_FLASH_UI_MOUSE_H */
diff --git a/src/scripting/flash/utils/flashutils.cpp b/src/scripting/flash/utils/ByteArray.cpp
similarity index 52%
copy from src/scripting/flash/utils/flashutils.cpp
copy to src/scripting/flash/utils/ByteArray.cpp
index 2fd9976..020ed61 100644
--- a/src/scripting/flash/utils/flashutils.cpp
+++ b/src/scripting/flash/utils/ByteArray.cpp
@@ -34,63 +34,9 @@ using namespace lightspark;
 
 #define BA_CHUNK_SIZE 4096
 
-const char* Endian::littleEndian = "littleEndian";
-const char* Endian::bigEndian = "bigEndian";
 
-void Endian::sinit(Class_base* c)
-{
-	c->setConstructor(NULL);
-	c->setVariableByQName("LITTLE_ENDIAN","",Class<ASString>::getInstanceS(littleEndian),DECLARED_TRAIT);
-	c->setVariableByQName("BIG_ENDIAN","",Class<ASString>::getInstanceS(bigEndian),DECLARED_TRAIT);
-}
-
-void IExternalizable::linkTraits(Class_base* c)
-{
-	lookupAndLink(c,"readExternal","flash.utils:IExternalizable");
-	lookupAndLink(c,"writeExternal","flash.utils:IExternalizable");
-}
-
-void IDataInput::linkTraits(Class_base* c)
-{
-	lookupAndLink(c,"bytesAvailable","flash.utils:IDataInput");
-	lookupAndLink(c,"endian","flash.utils:IDataInput");
-	lookupAndLink(c,"objectEncoding","flash.utils:IDataInput");
-	lookupAndLink(c,"readBoolean","flash.utils:IDataInput");
-	lookupAndLink(c,"readByte","flash.utils:IDataInput");
-	lookupAndLink(c,"readBytes","flash.utils:IDataInput");
-	lookupAndLink(c,"readDouble","flash.utils:IDataInput");
-	lookupAndLink(c,"readFloat","flash.utils:IDataInput");
-	lookupAndLink(c,"readInt","flash.utils:IDataInput");
-	lookupAndLink(c,"readMultiByte","flash.utils:IDataInput");
-	lookupAndLink(c,"readObject","flash.utils:IDataInput");
-	lookupAndLink(c,"readShort","flash.utils:IDataInput");
-	lookupAndLink(c,"readUnsignedByte","flash.utils:IDataInput");
-	lookupAndLink(c,"readUnsignedInt","flash.utils:IDataInput");
-	lookupAndLink(c,"readUnsignedShort","flash.utils:IDataInput");
-	lookupAndLink(c,"readUTF","flash.utils:IDataInput");
-	lookupAndLink(c,"readUTFBytes","flash.utils:IDataInput");
-}
-
-void IDataOutput::linkTraits(Class_base* c)
-{
-	lookupAndLink(c,"endian","flash.utils:IDataOutput");
-	lookupAndLink(c,"objectEncoding","flash.utils:IDataOutput");
-	lookupAndLink(c,"writeBoolean","flash.utils:IDataOutput");
-	lookupAndLink(c,"writeByte","flash.utils:IDataOutput");
-	lookupAndLink(c,"writeBytes","flash.utils:IDataOutput");
-	lookupAndLink(c,"writeDouble","flash.utils:IDataOutput");
-	lookupAndLink(c,"writeFloat","flash.utils:IDataOutput");
-	lookupAndLink(c,"writeInt","flash.utils:IDataOutput");
-	lookupAndLink(c,"writeMultiByte","flash.utils:IDataOutput");
-	lookupAndLink(c,"writeObject","flash.utils:IDataOutput");
-	lookupAndLink(c,"writeShort","flash.utils:IDataOutput");
-	lookupAndLink(c,"writeUnsignedInt","flash.utils:IDataOutput");
-	lookupAndLink(c,"writeUTF","flash.utils:IDataOutput");
-	lookupAndLink(c,"writeUTFBytes","flash.utils:IDataOutput");
-}
-
-ByteArray::ByteArray(Class_base* c, uint8_t* b, uint32_t l):ASObject(c),littleEndian(false),objectEncoding(ObjectEncoding::AMF3),
-	position(0),bytes(b),real_len(l),len(l)
+ByteArray::ByteArray(Class_base* c, uint8_t* b, uint32_t l):ASObject(c),littleEndian(false),objectEncoding(ObjectEncoding::AMF3),currentObjectEncoding(ObjectEncoding::AMF3),
+	position(0),bytes(b),real_len(l),len(l),shareable(false)
 {
 #ifdef MEMORY_USAGE_PROFILING
 	c->memoryAccount->addBytes(l);
@@ -110,9 +56,7 @@ ByteArray::~ByteArray()
 
 void ByteArray::sinit(Class_base* c)
 {
-	c->setConstructor(NULL);
-	c->setSuper(Class<ASObject>::getRef());
-
+	CLASS_SETUP_NO_CONSTRUCTOR(c, ASObject, CLASS_SEALED);
 	c->setDeclaredMethodByQName("length","",Class<IFunction>::getFunction(_getLength),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("length","",Class<IFunction>::getFunction(_setLength),SETTER_METHOD,true);
 	c->setDeclaredMethodByQName("bytesAvailable","",Class<IFunction>::getFunction(_getBytesAvailable),GETTER_METHOD,true);
@@ -124,6 +68,7 @@ void ByteArray::sinit(Class_base* c)
 	c->setDeclaredMethodByQName("objectEncoding","",Class<IFunction>::getFunction(_setObjectEncoding),SETTER_METHOD,true);
 	c->setDeclaredMethodByQName("defaultObjectEncoding","",Class<IFunction>::getFunction(_getDefaultObjectEncoding),GETTER_METHOD,false);
 	c->setDeclaredMethodByQName("defaultObjectEncoding","",Class<IFunction>::getFunction(_setDefaultObjectEncoding),SETTER_METHOD,false);
+
 	getSys()->staticByteArrayDefaultObjectEncoding = ObjectEncoding::DEFAULT;
 	c->setDeclaredMethodByQName("clear","",Class<IFunction>::getFunction(clear),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("compress","",Class<IFunction>::getFunction(_compress),NORMAL_METHOD,true);
@@ -157,6 +102,10 @@ void ByteArray::sinit(Class_base* c)
 	c->setDeclaredMethodByQName("writeObject","",Class<IFunction>::getFunction(writeObject),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("writeShort","",Class<IFunction>::getFunction(writeShort),NORMAL_METHOD,true);
 	c->prototype->setVariableByQName("toString","",Class<IFunction>::getFunction(ByteArray::_toString),DYNAMIC_TRAIT);
+	REGISTER_GETTER_SETTER(c,shareable);
+	c->setDeclaredMethodByQName("atomicCompareAndSwapIntAt","",Class<IFunction>::getFunction(atomicCompareAndSwapIntAt),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("atomicCompareAndSwapLength","",Class<IFunction>::getFunction(atomicCompareAndSwapLength),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("toJSON",AS3,Class<IFunction>::getFunction(_toJSON),NORMAL_METHOD,true);
 
 	c->addImplementedInterface(InterfaceClass<IDataInput>::getClass());
 	IDataInput::linkTraits(c);
@@ -168,6 +117,15 @@ void ByteArray::buildTraits(ASObject* o)
 {
 }
 
+void ByteArray::lock()
+{
+	if (shareable) mutex.lock();
+}
+void ByteArray::unlock()
+{
+	if (shareable) mutex.unlock();
+}
+
 uint8_t* ByteArray::getBuffer(unsigned int size, bool enableResize)
 {
 	// the flash documentation doesn't tell how large ByteArrays are allowed to be
@@ -281,7 +239,9 @@ ASFUNCTIONBODY(ByteArray,_getPosition)
 
 void ByteArray::setPosition(uint32_t p)
 {
+	lock();
 	position=p;
+	unlock();
 }
 
 ASFUNCTIONBODY(ByteArray,_setPosition)
@@ -328,6 +288,7 @@ ASFUNCTIONBODY(ByteArray,_setObjectEncoding)
 		throwError<ArgumentError>(kInvalidEnumError, "objectEncoding");
 
 	th->objectEncoding=value;
+	th->currentObjectEncoding=value;
 	return NULL;
 }
 
@@ -353,31 +314,37 @@ ASFUNCTIONBODY(ByteArray,_setLength)
 {
 	ByteArray* th=static_cast<ByteArray*>(obj);
 	assert_and_throw(argslen==1);
+
 	uint32_t newLen=args[0]->toInt();
+	th->lock();
 	if(newLen==th->len) //Nothing to do
 		return NULL;
+	th->setLength(newLen);
+	th->unlock();
+	return NULL;
+}
+void ByteArray::setLength(uint32_t newLen)
+{
 	if (newLen > 0)
 	{
-		th->getBuffer(newLen,true);
+		getBuffer(newLen,true);
 	}
 	else
 	{
-		if (th->bytes)
+		if (bytes)
 		{
 #ifdef MEMORY_USAGE_PROFILING
-			th->getClass()->memoryAccount->removeBytes(th->real_len);
+			getClass()->memoryAccount->removeBytes(th->real_len);
 #endif
-			free(th->bytes);
+			free(bytes);
 		}
-		th->bytes = NULL;
-		th->len = newLen;
-		th->real_len = newLen;
+		bytes = NULL;
+		real_len = newLen;
 	}
-	if (th->position > th->len)
-		th->position = (th->len > 0 ? th->len-1 : 0);
-	return NULL;
+	len = newLen;
+	if (position > len)
+		position = (len > 0 ? len-1 : 0);
 }
-
 ASFUNCTIONBODY(ByteArray,_getLength)
 {
 	ByteArray* th=static_cast<ByteArray*>(obj);
@@ -394,12 +361,15 @@ ASFUNCTIONBODY(ByteArray,readBoolean)
 {
 	ByteArray* th=static_cast<ByteArray*>(obj);
 
+	th->lock();
 	uint8_t ret;
 	if(!th->readByte(ret))
 	{
-		throwError<ArgumentError>(kEOFError);
+		th->unlock();
+		throwError<EOFError>(kEOFError);
 	}
 
+	th->unlock();
 	return abstract_b(ret!=0);
 }
 
@@ -411,6 +381,7 @@ ASFUNCTIONBODY(ByteArray,readBytes)
 	uint32_t length;
 	ARG_UNPACK(out)(offset, 0)(length, 0);
 	
+	th->lock();
 	if(length == 0)
 	{
 		assert(th->len >= th->position);
@@ -420,16 +391,19 @@ ASFUNCTIONBODY(ByteArray,readBytes)
 	//Error checks
 	if(th->position+length > th->len)
 	{
-		throwError<ArgumentError>(kEOFError);
+		th->unlock();
+		throwError<EOFError>(kEOFError);
 	}
 	if((uint64_t)length+offset > 0xFFFFFFFF)
 	{
+		th->unlock();
 		throw Class<RangeError>::getInstanceS("length+offset");
 	}
 	
 	uint8_t* buf=out->getBuffer(length+offset,true);
 	memcpy(buf+offset,th->bytes+th->position,length);
 	th->position+=length;
+	th->unlock();
 
 	return NULL;
 }
@@ -453,11 +427,13 @@ ASFUNCTIONBODY(ByteArray,readUTF)
 	ByteArray* th=static_cast<ByteArray*>(obj);
 
 	tiny_string res;
+	th->lock();
 	if (!th->readUTF(res))
 	{
-		throwError<ArgumentError>(kEOFError);
+		th->unlock();
+		throwError<EOFError>(kEOFError);
 	}
-
+	th->unlock();
 	return Class<ASString>::getInstanceS(res);
 }
 
@@ -467,13 +443,16 @@ ASFUNCTIONBODY(ByteArray,readUTFBytes)
 	uint32_t length;
 
 	ARG_UNPACK (length);
+	th->lock();
 	if(th->position+length > th->len)
 	{
-		throwError<ArgumentError>(kEOFError);
+		th->unlock();
+		throwError<EOFError>(kEOFError);
 	}
 
 	uint8_t *bufStart=th->bytes+th->position;
 	th->position+=length;
+	th->unlock();
 	return Class<ASString>::getInstanceS((char *)bufStart,length);
 }
 
@@ -497,7 +476,9 @@ ASFUNCTIONBODY(ByteArray,writeUTF)
 	assert_and_throw(argslen==1);
 	assert_and_throw(args[0]->getObjectType()==T_STRING);
 	ASString* str=Class<ASString>::cast(args[0]);
+	th->lock();
 	th->writeUTF(str->data);
+	th->unlock();
 	return NULL;
 }
 
@@ -508,9 +489,11 @@ ASFUNCTIONBODY(ByteArray,writeUTFBytes)
 	assert_and_throw(argslen==1);
 	assert_and_throw(args[0]->getObjectType()==T_STRING);
 	ASString* str=Class<ASString>::cast(args[0]);
+	th->lock();
 	th->getBuffer(th->position+str->data.numBytes(),true);
 	memcpy(th->bytes+th->position,str->data.raw_buf(),str->data.numBytes());
 	th->position+=str->data.numBytes();
+	th->unlock();
 
 	return NULL;
 }
@@ -525,9 +508,11 @@ ASFUNCTIONBODY(ByteArray,writeMultiByte)
 	// TODO: should convert from UTF-8 to charset
 	LOG(LOG_NOT_IMPLEMENTED, "ByteArray.writeMultiByte doesn't convert charset");
 
+	th->lock();
 	th->getBuffer(th->position+value.numBytes(),true);
 	memcpy(th->bytes+th->position,value.raw_buf(),value.numBytes());
 	th->position+=value.numBytes();
+	th->unlock();
 
 	return NULL;
 }
@@ -552,7 +537,9 @@ ASFUNCTIONBODY(ByteArray,writeObject)
 	ByteArray* th=static_cast<ByteArray*>(obj);
 	//Validate parameters
 	assert_and_throw(argslen==1);
+	th->lock();
 	th->writeObject(args[0]);
+	th->unlock();
 
 	return NULL;
 }
@@ -571,7 +558,9 @@ ASFUNCTIONBODY(ByteArray,writeShort)
 	int32_t value;
 	ARG_UNPACK(value);
 
+	th->lock();
 	th->writeShort((static_cast<uint16_t>(value & 0xffff)));
+	th->unlock();
 	return NULL;
 }
 
@@ -600,9 +589,11 @@ ASFUNCTIONBODY(ByteArray,writeBytes)
 	if(length == 0)
 		length=(out->getLength()-offset);
 	uint8_t* buf=out->getBuffer(offset+length,false);
+	th->lock();
 	th->getBuffer(th->position+length,true);
 	memcpy(th->bytes+th->position,buf+offset,length);
 	th->position+=length;
+	th->unlock();
 
 	return NULL;
 }
@@ -620,7 +611,9 @@ ASFUNCTIONBODY(ByteArray,writeByte)
 
 	int32_t value=args[0]->toInt();
 
+	th->lock();
 	th->writeByte(value&0xff);
+	th->unlock();
 
 	return NULL;
 }
@@ -631,10 +624,12 @@ ASFUNCTIONBODY(ByteArray,writeBoolean)
 	bool b;
 	ARG_UNPACK (b);
 
+	th->lock();
 	if (b)
 		th->writeByte(1);
 	else
 		th->writeByte(0);
+	th->unlock();
 
 	return NULL;
 }
@@ -648,9 +643,11 @@ ASFUNCTIONBODY(ByteArray,writeDouble)
 	uint64_t *intptr=reinterpret_cast<uint64_t*>(&value);
 	uint64_t value2=th->endianIn(*intptr);
 
+	th->lock();
 	th->getBuffer(th->position+8,true);
 	memcpy(th->bytes+th->position,&value2,8);
 	th->position+=8;
+	th->unlock();
 
 	return NULL;
 }
@@ -664,9 +661,11 @@ ASFUNCTIONBODY(ByteArray,writeFloat)
 	uint32_t *intptr=reinterpret_cast<uint32_t*>(&value);
 	uint32_t value2=th->endianIn(*intptr);
 
+	th->lock();
 	th->getBuffer(th->position+4,true);
 	memcpy(th->bytes+th->position,&value2,4);
 	th->position+=4;
+	th->unlock();
 
 	return NULL;
 }
@@ -678,9 +677,11 @@ ASFUNCTIONBODY(ByteArray,writeInt)
 
 	uint32_t value=th->endianIn(static_cast<uint32_t>(args[0]->toInt()));
 
+	th->lock();
 	th->getBuffer(th->position+4,true);
 	memcpy(th->bytes+th->position,&value,4);
 	th->position+=4;
+	th->unlock();
 
 	return NULL;
 }
@@ -697,11 +698,21 @@ ASFUNCTIONBODY(ByteArray,writeUnsignedInt)
 	ByteArray* th=static_cast<ByteArray*>(obj);
 	assert_and_throw(argslen==1);
 
+	th->lock();
 	uint32_t value=th->endianIn(args[0]->toUInt());
 	th->writeUnsignedInt(value);
+	th->unlock();
 	return NULL;
 }
 
+bool ByteArray::peekByte(uint8_t& b)
+{
+	if (len <= position+1)
+		return false;
+
+	b=bytes[position+1];
+	return true;
+}
 bool ByteArray::readByte(uint8_t& b)
 {
 	if (len <= position)
@@ -745,11 +756,14 @@ ASFUNCTIONBODY(ByteArray, readByte)
 	ByteArray* th=static_cast<ByteArray*>(obj);
 	assert_and_throw(argslen==0);
 
+	th->lock();
 	uint8_t ret;
 	if(!th->readByte(ret))
 	{
-		throwError<ArgumentError>(kEOFError);
+		th->unlock();
+		throwError<EOFError>(kEOFError);
 	}
+	th->unlock();
 	return abstract_i((int8_t)ret);
 }
 
@@ -758,9 +772,11 @@ ASFUNCTIONBODY(ByteArray,readDouble)
 	ByteArray* th=static_cast<ByteArray*>(obj);
 	assert_and_throw(argslen==0);
 
+	th->lock();
 	if(th->len < th->position+8)
 	{
-		throwError<ArgumentError>(kEOFError);
+		th->unlock();
+		throwError<EOFError>(kEOFError);
 	}
 
 	uint64_t ret;
@@ -769,6 +785,7 @@ ASFUNCTIONBODY(ByteArray,readDouble)
 	ret = th->endianOut(ret);
 
 	double *doubleptr=reinterpret_cast<double*>(&ret);
+	th->unlock();
 	return abstract_d(*doubleptr);
 }
 
@@ -777,9 +794,11 @@ ASFUNCTIONBODY(ByteArray,readFloat)
 	ByteArray* th=static_cast<ByteArray*>(obj);
 	assert_and_throw(argslen==0);
 
+	th->lock();
 	if(th->len < th->position+4)
 	{
-		throwError<ArgumentError>(kEOFError);
+		th->unlock();
+		throwError<EOFError>(kEOFError);
 	}
 
 	uint32_t ret;
@@ -788,6 +807,7 @@ ASFUNCTIONBODY(ByteArray,readFloat)
 	ret = th->endianOut(ret);
 
 	float *floatptr=reinterpret_cast<float*>(&ret);
+	th->unlock();
 	return abstract_d(*floatptr);
 }
 
@@ -796,15 +816,17 @@ ASFUNCTIONBODY(ByteArray,readInt)
 	ByteArray* th=static_cast<ByteArray*>(obj);
 	assert_and_throw(argslen==0);
 
+	th->lock();
 	if(th->len < th->position+4)
 	{
-		throwError<ArgumentError>(kEOFError);
+		th->unlock();
+		throwError<EOFError>(kEOFError);
 	}
 
 	uint32_t ret;
 	memcpy(&ret,th->bytes+th->position,4);
 	th->position+=4;
-
+	th->unlock();
 	return abstract_i((int32_t)th->endianOut(ret));
 }
 
@@ -826,11 +848,14 @@ ASFUNCTIONBODY(ByteArray,readShort)
 	assert_and_throw(argslen==0);
 
 	uint16_t ret;
+	th->lock();
 	if(!th->readShort(ret))
 	{
-		throwError<ArgumentError>(kEOFError);
+		th->unlock();
+		throwError<EOFError>(kEOFError);
 	}
 
+	th->unlock();
 	return abstract_i((int16_t)ret);
 }
 
@@ -840,9 +865,11 @@ ASFUNCTIONBODY(ByteArray,readUnsignedByte)
 	assert_and_throw(argslen==0);
 
 	uint8_t ret;
+	th->lock();
 	if (!th->readByte(ret))
 	{
-		throwError<ArgumentError>(kEOFError);
+		th->unlock();
+		throwError<EOFError>(kEOFError);
 	}
 	return abstract_ui(ret);
 }
@@ -865,9 +892,13 @@ ASFUNCTIONBODY(ByteArray,readUnsignedInt)
 	assert_and_throw(argslen==0);
 
 	uint32_t ret;
+	th->lock();
 	if(!th->readUnsignedInt(ret))
-		throwError<ArgumentError>(kEOFError);
-
+	{
+		th->unlock();
+		throwError<EOFError>(kEOFError);
+	}
+	th->unlock();
 	return abstract_ui(ret);
 }
 
@@ -877,9 +908,11 @@ ASFUNCTIONBODY(ByteArray,readUnsignedShort)
 	assert_and_throw(argslen==0);
 
 	uint16_t ret;
+	th->lock();
 	if(!th->readShort(ret))
 	{
-		throwError<ArgumentError>(kEOFError);
+		th->unlock();
+		throwError<EOFError>(kEOFError);
 	}
 
 	return abstract_ui(ret);
@@ -892,9 +925,11 @@ ASFUNCTIONBODY(ByteArray,readMultiByte)
 	tiny_string charset;
 	ARG_UNPACK(strlen)(charset);
 
+	th->lock();
 	if(th->len < th->position+strlen)
 	{
-		throwError<ArgumentError>(kEOFError);
+		th->unlock();
+		throwError<EOFError>(kEOFError);
 	}
 
 	// TODO: should convert from charset to UTF-8
@@ -906,19 +941,25 @@ ASFUNCTIONBODY(ByteArray,readObject)
 {
 	ByteArray* th=static_cast<ByteArray*>(obj);
 	assert_and_throw(argslen==0);
+	th->lock();
 	if(th->bytes==NULL)
 	{
-		throwError<ArgumentError>(kEOFError);
+		th->unlock();
+		// it seems that contrary to the specs Adobe returns Undefined when reading from an empty ByteArray
+		return getSys()->getUndefinedRef();
+		//throwError<EOFError>(kEOFError);
 	}
-	assert_and_throw(th->objectEncoding==ObjectEncoding::AMF3);
+	//assert_and_throw(th->objectEncoding==ObjectEncoding::AMF3);
 	Amf3Deserializer d(th);
 	_NR<ASObject> ret(NullRef);
 	try
 	{
 		ret=d.readObject();
+		th->unlock();
 	}
 	catch(LightsparkException& e)
 	{
+		th->unlock();
 		LOG(LOG_ERROR,"Exception caught while parsing AMF3: " << e.cause);
 		//TODO: throw AS exception
 	}
@@ -1184,7 +1225,9 @@ ASFUNCTIONBODY(ByteArray,_compress)
 	// flash throws an error if compress is called with a compression algorithm,
 	// and always uses the zlib algorithm
 	// but tamarin tests do not catch it, so we simply ignore any parameters provided
+	th->lock();
 	th->compress_zlib();
+	th->unlock();
 	return NULL;
 }
 
@@ -1194,27 +1237,34 @@ ASFUNCTIONBODY(ByteArray,_uncompress)
 	// flash throws an error if uncompress is called with a compression algorithm,
 	// and always uses the zlib algorithm
 	// but tamarin tests do not catch it, so we simply ignore any parameters provided
+	th->lock();
 	th->uncompress_zlib();
+	th->unlock();
 	return NULL;
 }
 
 ASFUNCTIONBODY(ByteArray,_deflate)
 {
 	ByteArray* th=static_cast<ByteArray*>(obj);
+	th->lock();
 	th->compress_zlib();
+	th->unlock();
 	return NULL;
 }
 
 ASFUNCTIONBODY(ByteArray,_inflate)
 {
 	ByteArray* th=static_cast<ByteArray*>(obj);
+	th->lock();
 	th->uncompress_zlib();
+	th->unlock();
 	return NULL;
 }
 
 ASFUNCTIONBODY(ByteArray,clear)
 {
 	ByteArray* th=static_cast<ByteArray*>(obj);
+	th->lock();
 	if(th->bytes)
 	{
 #ifdef MEMORY_USAGE_PROFILING
@@ -1226,44 +1276,22 @@ ASFUNCTIONBODY(ByteArray,clear)
 	th->len=0;
 	th->real_len=0;
 	th->position=0;
+	th->unlock();
 	return NULL;
 }
 
-void Timer::tick()
-{
-	//This will be executed once if repeatCount was originally 1
-	//Otherwise it's executed until stopMe is set to true
-	this->incRef();
-	getVm()->addEvent(_MR(this),_MR(Class<TimerEvent>::getInstanceS("timer")));
-
-	currentCount++;
-	if(repeatCount!=0)
-	{
-		if(currentCount==repeatCount)
-		{
-			this->incRef();
-			getVm()->addEvent(_MR(this),_MR(Class<TimerEvent>::getInstanceS("timerComplete")));
-			stopMe=true;
-			running=false;
-		}
-	}
-}
-
-void Timer::tickFence()
-{
-	tickJobInstance = NullRef;
-}
-
 // this seems to be how AS3 handles generic pop calls in Array class
 ASFUNCTIONBODY(ByteArray,pop)
 {
 	ByteArray* th=static_cast<ByteArray*>(obj);
 	uint8_t res = 0;
+	th->lock();
 	if (th->readByte(res))
 	{
 		memmove(th->bytes,(th->bytes+1),th->getLength()-1);
 		th->len--;
 	}
+	th->unlock();
 	return abstract_ui(res);
 	
 }
@@ -1272,12 +1300,15 @@ ASFUNCTIONBODY(ByteArray,pop)
 ASFUNCTIONBODY(ByteArray,push)
 {
 	ByteArray* th=static_cast<ByteArray*>(obj);
+	th->lock();
 	th->getBuffer(th->len+argslen,true);
 	for (unsigned int i = 0; i < argslen; i++)
 	{
 		th->bytes[th->len+i] = (uint8_t)args[i]->toInt();
 	}
-	return abstract_ui(th->getLength());
+	uint32_t res = th->getLength();
+	th->unlock();
+	return abstract_ui(res);
 }
 
 // this seems to be how AS3 handles generic shift calls in Array class
@@ -1285,11 +1316,13 @@ ASFUNCTIONBODY(ByteArray,shift)
 {
 	ByteArray* th=static_cast<ByteArray*>(obj);
 	uint8_t res = 0;
+	th->lock();
 	if (th->readByte(res))
 	{
 		memmove(th->bytes,(th->bytes+1),th->getLength()-1);
 		th->len--;
 	}
+	th->unlock();
 	return abstract_ui(res);
 }
 
@@ -1297,823 +1330,63 @@ ASFUNCTIONBODY(ByteArray,shift)
 ASFUNCTIONBODY(ByteArray,unshift)
 {
 	ByteArray* th=static_cast<ByteArray*>(obj);
+	th->lock();
 	th->getBuffer(th->len+argslen,true);
 	for (unsigned int i = 0; i < argslen; i++)
 	{
 		memmove((th->bytes+argslen),(th->bytes),th->len);
 		th->bytes[i] = (uint8_t)args[i]->toInt();
 	}
-	return abstract_ui(th->getLength());
-}
-
-void Timer::sinit(Class_base* c)
-{
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<EventDispatcher>::getRef());
-	c->setDeclaredMethodByQName("currentCount","",Class<IFunction>::getFunction(_getCurrentCount),GETTER_METHOD,true);
-	c->setDeclaredMethodByQName("repeatCount","",Class<IFunction>::getFunction(_getRepeatCount),GETTER_METHOD,true);
-	c->setDeclaredMethodByQName("repeatCount","",Class<IFunction>::getFunction(_setRepeatCount),SETTER_METHOD,true);
-	c->setDeclaredMethodByQName("running","",Class<IFunction>::getFunction(_getRunning),GETTER_METHOD,true);
-	c->setDeclaredMethodByQName("delay","",Class<IFunction>::getFunction(_getDelay),GETTER_METHOD,true);
-	c->setDeclaredMethodByQName("delay","",Class<IFunction>::getFunction(_setDelay),SETTER_METHOD,true);
-	c->setDeclaredMethodByQName("start","",Class<IFunction>::getFunction(start),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("reset","",Class<IFunction>::getFunction(reset),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("stop","",Class<IFunction>::getFunction(stop),NORMAL_METHOD,true);
-}
-
-ASFUNCTIONBODY(Timer,_constructor)
-{
-	EventDispatcher::_constructor(obj,NULL,0);
-	Timer* th=static_cast<Timer*>(obj);
-
-	th->delay=args[0]->toInt();
-	if(argslen>=2)
-		th->repeatCount=args[1]->toInt();
-
-	return NULL;
-}
-
-ASFUNCTIONBODY(Timer,_getCurrentCount)
-{
-	Timer* th=static_cast<Timer*>(obj);
-	return abstract_i(th->currentCount);
-}
-
-ASFUNCTIONBODY(Timer,_getRepeatCount)
-{
-	Timer* th=static_cast<Timer*>(obj);
-	return abstract_i(th->repeatCount);
-}
-
-ASFUNCTIONBODY(Timer,_setRepeatCount)
-{
-	assert_and_throw(argslen==1);
-	int32_t count=args[0]->toInt();
-	Timer* th=static_cast<Timer*>(obj);
-	th->repeatCount=count;
-	if(th->repeatCount>0 && th->repeatCount<=th->currentCount)
-	{
-		getSys()->removeJob(th);
-		th->running=false;
-		th->tickJobInstance = NullRef;
-	}
-	return NULL;
-}
-
-ASFUNCTIONBODY(Timer,_getRunning)
-{
-	Timer* th=static_cast<Timer*>(obj);
-	return abstract_b(th->running);
-}
-
-ASFUNCTIONBODY(Timer,_getDelay)
-{
-	Timer* th=static_cast<Timer*>(obj);
-	return abstract_i(th->delay);
-}
-
-ASFUNCTIONBODY(Timer,_setDelay)
-{
-	assert_and_throw(argslen==1);
-	int32_t newdelay = args[0]->toInt();
-	if (newdelay<=0)
-		throw Class<RangeError>::getInstanceS("delay must be positive", 2066);
-
-	Timer* th=static_cast<Timer*>(obj);
-	th->delay=newdelay;
-
-	return NULL;
-}
-
-ASFUNCTIONBODY(Timer,start)
-{
-	Timer* th=static_cast<Timer*>(obj);
-	if(th->running)
-		return NULL;
-	th->running=true;
-	th->stopMe=false;
-	th->incRef();
-	th->tickJobInstance = _MNR(th);
-	if(th->repeatCount==1)
-		getSys()->addWait(th->delay,th);
-	else
-		getSys()->addTick(th->delay,th);
-	return NULL;
+	uint32_t res = th->getLength();
+	th->unlock();
+	return abstract_ui(res);
 }
+ASFUNCTIONBODY_GETTER_SETTER(ByteArray,shareable);
 
-ASFUNCTIONBODY(Timer,reset)
+ASFUNCTIONBODY(ByteArray,atomicCompareAndSwapIntAt)
 {
-	Timer* th=static_cast<Timer*>(obj);
-	if(th->running)
-	{
-		//This spin waits if the timer is running right now
-		getSys()->removeJob(th);
-		//NOTE: although no new events will be sent now there might be old events in the queue.
-		//Is this behaviour right?
-		//This is not anymore used by the timer, so it can die
-		th->tickJobInstance = NullRef;
-		th->running=false;
-	}
-	th->currentCount=0;
-	return NULL;
-}
+	ByteArray* th=static_cast<ByteArray*>(obj);
 
-ASFUNCTIONBODY(Timer,stop)
-{
-	Timer* th=static_cast<Timer*>(obj);
-	if(th->running)
-	{
-		//This spin waits if the timer is running right now
-		getSys()->removeJob(th);
-		//NOTE: although no new events will be sent now there might be old events in the queue.
-		//Is this behaviour right?
-
-		//This is not anymore used by the timer, so it can die
-		th->tickJobInstance = NullRef;
-		th->running=false;
-	}
-	return NULL;
-}
+	int32_t byteindex,expectedValue,newvalue;
+	ARG_UNPACK(byteindex)(expectedValue)(newvalue);
 
-ASFUNCTIONBODY(lightspark,getQualifiedClassName)
-{
-	//CHECK: what to do if ns is empty
-	ASObject* target=args[0];
-	Class_base* c;
-	SWFOBJECT_TYPE otype=target->getObjectType();
-	if(otype==T_NULL)
-		return Class<ASString>::getInstanceS("null");
-	else if(otype==T_UNDEFINED)
-		// Testing shows that this really returns "void"!
-		return Class<ASString>::getInstanceS("void");
-	else if(otype!=T_CLASS)
+	if (byteindex < 0 || byteindex%4)
 	{
-		assert_and_throw(target->getClass());
-		c=target->getClass();
+		throwError<RangeError>(kInvalidRangeError, obj->getClassName());
 	}
-	else
-		c=static_cast<Class_base*>(target);
-
-	return Class<ASString>::getInstanceS(c->getQualifiedClassName());
-}
-
-ASFUNCTIONBODY(lightspark,getQualifiedSuperclassName)
-{
-	//CHECK: what to do is ns is empty
-	ASObject* target=args[0];
-	Class_base* c;
-	if(target->getObjectType()!=T_CLASS)
+	th->lock();
+	if(byteindex >= (int32_t)th->len-4)
 	{
-		assert_and_throw(target->getClass());
-		c=target->getClass()->super.getPtr();
+		th->unlock();
+		throwError<RangeError>(kInvalidRangeError, obj->getClassName());
 	}
-	else
-		c=static_cast<Class_base*>(target)->super.getPtr();
-
-	assert_and_throw(c);
-
-	return Class<ASString>::getInstanceS(c->getQualifiedClassName());
-}
+	int32_t ret;
+	memcpy(&ret,th->bytes+byteindex,4);
 
-ASFUNCTIONBODY(lightspark,getDefinitionByName)
-{
-	assert_and_throw(args && argslen==1);
-	const tiny_string& tmp=args[0]->toString();
-	multiname name(NULL);
-	name.name_type=multiname::NAME_STRING;
-
-	tiny_string nsName;
-	tiny_string tmpName;
-	stringToQName(tmp,tmpName,nsName);
-	name.name_s_id=getSys()->getUniqueStringId(tmpName);
-	name.ns.push_back(nsNameAndKind(nsName,NAMESPACE));
-
-	LOG(LOG_CALLS,_("Looking for definition of ") << name);
-	ASObject* target;
-	ASObject* o=ABCVm::getCurrentApplicationDomain(getVm()->currentCallContext)->getVariableAndTargetByMultiname(name,target);
-
-	//TODO: should raise an exception, for now just return undefined	
-	if(o==NULL)
+	if (ret == expectedValue)
 	{
-		LOG(LOG_ERROR,_("Definition for '") << name << _("' not found."));
-		return getSys()->getUndefinedRef();
+		memcpy(th->bytes+byteindex,&newvalue,4);
 	}
-
-	assert_and_throw(o->getObjectType()==T_CLASS);
-
-	LOG(LOG_CALLS,_("Getting definition for ") << name);
-	o->incRef();
-	return o;
-}
-
-ASFUNCTIONBODY(lightspark,describeType)
-{
-	assert_and_throw(argslen==1);
-	return args[0]->describeType();
-}
-
-ASFUNCTIONBODY(lightspark,getTimer)
-{
-	uint64_t ret=compat_msectiming() - getSys()->startTime;
+	th->unlock();
 	return abstract_i(ret);
 }
-
-Dictionary::Dictionary(Class_base* c):ASObject(c),
-	data(std::less<dictType::key_type>(), reporter_allocator<dictType::value_type>(c->memoryAccount))
-{
-}
-
-void Dictionary::finalize()
-{
-	ASObject::finalize();
-	data.clear();
-}
-
-void Dictionary::sinit(Class_base* c)
-{
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<ASObject>::getRef());
-}
-
-void Dictionary::buildTraits(ASObject* o)
-{
-}
-
-ASFUNCTIONBODY(Dictionary,_constructor)
-{
-	return NULL;
-}
-
-Dictionary::dictType::iterator Dictionary::findKey(ASObject *o)
-{
-	Dictionary::dictType::iterator it = data.begin();
-	for(; it!=data.end(); ++it)
-	{
-		if (it->first->isEqualStrict(o))
-			return it;
-	}
-
-	return data.end();
-}
-
-void Dictionary::setVariableByMultiname_i(const multiname& name, int32_t value)
-{
-	assert_and_throw(implEnable);
-	Dictionary::setVariableByMultiname(name,abstract_i(value),CONST_NOT_ALLOWED);
-}
-
-void Dictionary::setVariableByMultiname(const multiname& name, ASObject* o, CONST_ALLOWED_FLAG allowConst)
-{
-	assert_and_throw(implEnable);
-	if(name.name_type==multiname::NAME_OBJECT)
-	{
-		name.name_o->incRef();
-		_R<ASObject> name_o(name.name_o);
-
-		Dictionary::dictType::iterator it=findKey(name_o.getPtr());
-		if(it!=data.end())
-			it->second=_MR(o);
-		else
-			data.insert(make_pair(name_o,_MR(o)));
-	}
-	else
-	{
-		//Primitive types _must_ be handled by the normal ASObject path
-		//REFERENCE: Dictionary Object on AS3 reference
-		assert(name.name_type==multiname::NAME_STRING ||
-			name.name_type==multiname::NAME_INT ||
-			name.name_type==multiname::NAME_NUMBER);
-		ASObject::setVariableByMultiname(name, o, allowConst);
-	}
-}
-
-bool Dictionary::deleteVariableByMultiname(const multiname& name)
-{
-	assert_and_throw(implEnable);
-
-	if(name.name_type==multiname::NAME_OBJECT)
-	{
-		name.name_o->incRef();
-		_R<ASObject> name_o(name.name_o);
-
-		Dictionary::dictType::iterator it=findKey(name_o.getPtr());
-		if(it != data.end())
-		{
-			data.erase(it);
-			return true;
-		}
-		return false;
-	}
-	else
-	{
-		//Primitive types _must_ be handled by the normal ASObject path
-		//REFERENCE: Dictionary Object on AS3 reference
-		assert(name.name_type==multiname::NAME_STRING ||
-			name.name_type==multiname::NAME_INT ||
-			name.name_type==multiname::NAME_NUMBER);
-		return ASObject::deleteVariableByMultiname(name);
-	}
-}
-
-_NR<ASObject> Dictionary::getVariableByMultiname(const multiname& name, GET_VARIABLE_OPTION opt)
-{
-	if((opt & ASObject::SKIP_IMPL)==0 && implEnable)
-	{
-		if(name.name_type==multiname::NAME_OBJECT)
-		{
-			name.name_o->incRef();
-			_R<ASObject> name_o(name.name_o);
-
-			Dictionary::dictType::iterator it=findKey(name_o.getPtr());
-			if(it != data.end())
-				return it->second;
-			else
-				return NullRef;
-		}
-		else
-		{
-			//Primitive types _must_ be handled by the normal ASObject path
-			//REFERENCE: Dictionary Object on AS3 reference
-			assert(name.name_type==multiname::NAME_STRING ||
-				name.name_type==multiname::NAME_INT ||
-				name.name_type==multiname::NAME_NUMBER);
-			return ASObject::getVariableByMultiname(name, opt);
-		}
-	}
-	//Try with the base implementation
-	return ASObject::getVariableByMultiname(name, opt);
-}
-
-bool Dictionary::hasPropertyByMultiname(const multiname& name, bool considerDynamic, bool considerPrototype)
-{
-	if(considerDynamic==false)
-		return ASObject::hasPropertyByMultiname(name, considerDynamic, considerPrototype);
-
-	if(name.name_type==multiname::NAME_OBJECT)
-	{
-		name.name_o->incRef();
-		_R<ASObject> name_o(name.name_o);
-
-		Dictionary::dictType::iterator it=findKey(name_o.getPtr());
-		return it != data.end();
-	}
-	else
-	{
-		//Primitive types _must_ be handled by the normal ASObject path
-		//REFERENCE: Dictionary Object on AS3 reference
-		assert(name.name_type==multiname::NAME_STRING ||
-			name.name_type==multiname::NAME_INT ||
-			name.name_type==multiname::NAME_NUMBER);
-		return ASObject::hasPropertyByMultiname(name, considerDynamic, considerPrototype);
-	}
-}
-
-uint32_t Dictionary::nextNameIndex(uint32_t cur_index)
+ASFUNCTIONBODY(ByteArray,atomicCompareAndSwapLength)
 {
-	assert_and_throw(implEnable);
-	if(cur_index<data.size())
-		return cur_index+1;
-	else
-	{
-		//Fall back on object properties
-		uint32_t ret=ASObject::nextNameIndex(cur_index-data.size());
-		if(ret==0)
-			return 0;
-		else
-			return ret+data.size();
-
-	}
-}
-
-_R<ASObject> Dictionary::nextName(uint32_t index)
-{
-	assert_and_throw(implEnable);
-	if(index<=data.size())
-	{
-		map<_R<ASObject>,_R<ASObject> >::iterator it=data.begin();
-		for(unsigned int i=1;i<index;i++)
-			++it;
-
-		return it->first;
-	}
-	else
-	{
-		//Fall back on object properties
-		return ASObject::nextName(index-data.size());
-	}
-}
-
-_R<ASObject> Dictionary::nextValue(uint32_t index)
-{
-	assert_and_throw(implEnable);
-	if(index<=data.size())
-	{
-		map<_R<ASObject>,_R<ASObject> >::iterator it=data.begin();
-		for(unsigned int i=1;i<index;i++)
-			++it;
-
-		return it->second;
-	}
-	else
-	{
-		//Fall back on object properties
-		return ASObject::nextValue(index-data.size());
-	}
-}
-
-tiny_string Dictionary::toString()
-{
-	std::stringstream retstr;
-	retstr << "{";
-	map<_R<ASObject>,_R<ASObject> >::iterator it=data.begin();
-	while(it != data.end())
-	{
-		if(it != data.begin())
-			retstr << ", ";
-		retstr << "{" << it->first->toString() << ", " << it->second->toString() << "}";
-		++it;
-	}
-	retstr << "}";
-
-	return retstr.str();
-}
-
-void Proxy::sinit(Class_base* c)
-{
-	//c->constructor=Class<IFunction>::getFunction(_constructor);
-	c->setConstructor(NULL);
-}
-
-void Proxy::buildTraits(ASObject* o)
-{
-}
-
-void Proxy::setVariableByMultiname(const multiname& name, ASObject* o, CONST_ALLOWED_FLAG allowConst)
-{
-	//If a variable named like this already exist, use that
-	if(ASObject::hasPropertyByMultiname(name, true, false) || !implEnable)
-	{
-		ASObject::setVariableByMultiname(name,o,allowConst);
-		return;
-	}
-
-	//Check if there is a custom setter defined, skipping implementation to avoid recursive calls
-	multiname setPropertyName(NULL);
-	setPropertyName.name_type=multiname::NAME_STRING;
-	setPropertyName.name_s_id=getSys()->getUniqueStringId("setProperty");
-	setPropertyName.ns.push_back(nsNameAndKind(flash_proxy,NAMESPACE));
-	_NR<ASObject> proxySetter=getVariableByMultiname(setPropertyName,ASObject::SKIP_IMPL);
-
-	if(proxySetter.isNull())
-	{
-		ASObject::setVariableByMultiname(name,o,allowConst);
-		return;
-	}
-
-	assert_and_throw(proxySetter->getObjectType()==T_FUNCTION);
-
-	IFunction* f=static_cast<IFunction*>(proxySetter.getPtr());
-
-	//Well, I don't how to pass multiname to an as function. I'll just pass the name as a string
-	ASObject* args[2];
-	args[0]=Class<ASString>::getInstanceS(name.normalizedName());
-	args[1]=o;
-	//We now suppress special handling
-	implEnable=false;
-	LOG(LOG_CALLS,_("Proxy::setProperty"));
-	incRef();
-	_R<ASObject> ret=_MR( f->call(this,args,2) );
-	assert_and_throw(ret->is<Undefined>());
-	implEnable=true;
-}
-
-_NR<ASObject> Proxy::getVariableByMultiname(const multiname& name, GET_VARIABLE_OPTION opt)
-{
-	//It seems that various kind of implementation works only with the empty namespace
-	assert_and_throw(name.ns.size()>0);
-	if(!name.ns[0].hasEmptyName() || ASObject::hasPropertyByMultiname(name, true, true) || !implEnable || (opt & ASObject::SKIP_IMPL)!=0)
-		return ASObject::getVariableByMultiname(name,opt);
-
-	//Check if there is a custom getter defined, skipping implementation to avoid recursive calls
-	multiname getPropertyName(NULL);
-	getPropertyName.name_type=multiname::NAME_STRING;
-	getPropertyName.name_s_id=getSys()->getUniqueStringId("getProperty");
-	getPropertyName.ns.push_back(nsNameAndKind(flash_proxy,NAMESPACE));
-	_NR<ASObject> o=getVariableByMultiname(getPropertyName,ASObject::SKIP_IMPL);
-
-	if(o.isNull())
-		return ASObject::getVariableByMultiname(name,opt);
-
-	assert_and_throw(o->getObjectType()==T_FUNCTION);
-
-	IFunction* f=static_cast<IFunction*>(o.getPtr());
-
-	//Well, I don't how to pass multiname to an as function. I'll just pass the name as a string
-	ASObject* arg=Class<ASString>::getInstanceS(name.normalizedName());
-	//We now suppress special handling
-	implEnable=false;
-	LOG(LOG_CALLS,"Proxy::getProperty");
-	incRef();
-	_NR<ASObject> ret=_MNR(f->call(this,&arg,1));
-	implEnable=true;
-	return ret;
-}
-
-bool Proxy::hasPropertyByMultiname(const multiname& name, bool considerDynamic, bool considerPrototype)
-{
-	//If a variable named like this already exist, use that
-	bool asobject_has_property=ASObject::hasPropertyByMultiname(name, considerDynamic, considerPrototype);
-	if(asobject_has_property || !implEnable)
-		return asobject_has_property;
-
-	//Check if there is a custom hasProperty defined, skipping implementation to avoid recursive calls
-	multiname hasPropertyName(NULL);
-	hasPropertyName.name_type=multiname::NAME_STRING;
-	hasPropertyName.name_s_id=getSys()->getUniqueStringId("hasProperty");
-	hasPropertyName.ns.push_back(nsNameAndKind(flash_proxy,NAMESPACE));
-	_NR<ASObject> proxyHasProperty=getVariableByMultiname(hasPropertyName,ASObject::SKIP_IMPL);
-
-	if(proxyHasProperty.isNull())
-	{
-		return false;
-	}
-
-	assert_and_throw(proxyHasProperty->getObjectType()==T_FUNCTION);
-
-	IFunction* f=static_cast<IFunction*>(proxyHasProperty.getPtr());
-
-	//Well, I don't how to pass multiname to an as function. I'll just pass the name as a string
-	ASObject* arg=Class<ASString>::getInstanceS(name.normalizedName());
-	//We now suppress special handling
-	implEnable=false;
-	LOG(LOG_CALLS,_("Proxy::hasProperty"));
-	incRef();
-	_NR<ASObject> ret=_MNR(f->call(this,&arg,1));
-	implEnable=true;
-	Boolean* b = static_cast<Boolean*>(ret.getPtr());
-	return b->val;
-}
-bool Proxy::deleteVariableByMultiname(const multiname& name)
-{
-	//If a variable named like this already exist, use that
-	if(ASObject::hasPropertyByMultiname(name, true, false) || !implEnable)
-	{
-		return ASObject::deleteVariableByMultiname(name);
-	}
-
-	//Check if there is a custom deleter defined, skipping implementation to avoid recursive calls
-	multiname deletePropertyName(NULL);
-	deletePropertyName.name_type=multiname::NAME_STRING;
-	deletePropertyName.name_s_id=getSys()->getUniqueStringId("deleteProperty");
-	deletePropertyName.ns.push_back(nsNameAndKind(flash_proxy,NAMESPACE));
-	_NR<ASObject> proxyDeleter=getVariableByMultiname(deletePropertyName,ASObject::SKIP_IMPL);
-
-	if(proxyDeleter.isNull())
-	{
-		return ASObject::deleteVariableByMultiname(name);
-	}
-
-	assert_and_throw(proxyDeleter->getObjectType()==T_FUNCTION);
-
-	IFunction* f=static_cast<IFunction*>(proxyDeleter.getPtr());
-
-	//Well, I don't how to pass multiname to an as function. I'll just pass the name as a string
-	ASObject* arg=Class<ASString>::getInstanceS(name.normalizedName());
-	//We now suppress special handling
-	implEnable=false;
-	LOG(LOG_CALLS,_("Proxy::deleteProperty"));
-	incRef();
-	_NR<ASObject> ret=_MNR(f->call(this,&arg,1));
-	implEnable=true;
-	Boolean* b = static_cast<Boolean*>(ret.getPtr());
-	return b->val;
-}
-
-uint32_t Proxy::nextNameIndex(uint32_t cur_index)
-{
-	assert_and_throw(implEnable);
-	LOG(LOG_CALLS,"Proxy::nextNameIndex");
-	//Check if there is a custom enumerator, skipping implementation to avoid recursive calls
-	multiname nextNameIndexName(NULL);
-	nextNameIndexName.name_type=multiname::NAME_STRING;
-	nextNameIndexName.name_s_id=getSys()->getUniqueStringId("nextNameIndex");
-	nextNameIndexName.ns.push_back(nsNameAndKind(flash_proxy,NAMESPACE));
-	_NR<ASObject> o=getVariableByMultiname(nextNameIndexName,ASObject::SKIP_IMPL);
-	assert_and_throw(!o.isNull() && o->getObjectType()==T_FUNCTION);
-	IFunction* f=static_cast<IFunction*>(o.getPtr());
-	ASObject* arg=abstract_i(cur_index);
-	this->incRef();
-	ASObject* ret=f->call(this,&arg,1);
-	uint32_t newIndex=ret->toInt();
-	ret->decRef();
-	return newIndex;
-}
-
-_R<ASObject> Proxy::nextName(uint32_t index)
-{
-	assert_and_throw(implEnable);
-	LOG(LOG_CALLS, _("Proxy::nextName"));
-	//Check if there is a custom enumerator, skipping implementation to avoid recursive calls
-	multiname nextNameName(NULL);
-	nextNameName.name_type=multiname::NAME_STRING;
-	nextNameName.name_s_id=getSys()->getUniqueStringId("nextName");
-	nextNameName.ns.push_back(nsNameAndKind(flash_proxy,NAMESPACE));
-	_NR<ASObject> o=getVariableByMultiname(nextNameName,ASObject::SKIP_IMPL);
-	assert_and_throw(!o.isNull() && o->getObjectType()==T_FUNCTION);
-	IFunction* f=static_cast<IFunction*>(o.getPtr());
-	ASObject* arg=abstract_i(index);
-	incRef();
-	return _MR(f->call(this,&arg,1));
-}
-
-_R<ASObject> Proxy::nextValue(uint32_t index)
-{
-	assert_and_throw(implEnable);
-	LOG(LOG_CALLS, _("Proxy::nextValue"));
-	//Check if there is a custom enumerator, skipping implementation to avoid recursive calls
-	multiname nextValueName(NULL);
-	nextValueName.name_type=multiname::NAME_STRING;
-	nextValueName.name_s_id=getSys()->getUniqueStringId("nextValue");
-	nextValueName.ns.push_back(nsNameAndKind(flash_proxy,NAMESPACE));
-	_NR<ASObject> o=getVariableByMultiname(nextValueName,ASObject::SKIP_IMPL);
-	assert_and_throw(!o.isNull() && o->getObjectType()==T_FUNCTION);
-	IFunction* f=static_cast<IFunction*>(o.getPtr());
-	ASObject* arg=abstract_i(index);
-	incRef();
-	return _MR(f->call(this,&arg,1));
-}
-
-ASFUNCTIONBODY(lightspark,setInterval)
-{
-	assert_and_throw(argslen >= 2 && args[0]->getObjectType()==T_FUNCTION);
-
-	//Build arguments array
-	ASObject** callbackArgs = g_newa(ASObject*,argslen-2);
-	uint32_t i;
-	for(i=0; i<argslen-2; i++)
-	{
-		callbackArgs[i] = args[i+2];
-		//incRef all passed arguments
-		args[i+2]->incRef();
-	}
-
-	//incRef the function
-	args[0]->incRef();
-	IFunction* callback=static_cast<IFunction*>(args[0]);
-	//Add interval through manager
-	uint32_t id = getSys()->intervalManager->setInterval(_MR(callback), callbackArgs, argslen-2,
-			_MR(getSys()->getNullRef()), args[1]->toInt());
-	return abstract_i(id);
-}
-
-ASFUNCTIONBODY(lightspark,setTimeout)
-{
-	assert_and_throw(argslen >= 2);
-
-	//Build arguments array
-	ASObject** callbackArgs = g_newa(ASObject*,argslen-2);
-	uint32_t i;
-	for(i=0; i<argslen-2; i++)
-	{
-		callbackArgs[i] = args[i+2];
-		//incRef all passed arguments
-		args[i+2]->incRef();
-	}
-
-	//incRef the function
-	args[0]->incRef();
-	IFunction* callback=static_cast<IFunction*>(args[0]);
-	//Add timeout through manager
-	uint32_t id = getSys()->intervalManager->setTimeout(_MR(callback), callbackArgs, argslen-2,
-			_MR(getSys()->getNullRef()), args[1]->toInt());
-	return abstract_i(id);
-}
-
-ASFUNCTIONBODY(lightspark,clearInterval)
-{
-	assert_and_throw(argslen == 1);
-	getSys()->intervalManager->clearInterval(args[0]->toInt(), IntervalRunner::INTERVAL, true);
-	return NULL;
-}
-
-ASFUNCTIONBODY(lightspark,clearTimeout)
-{
-	assert_and_throw(argslen == 1);
-	getSys()->intervalManager->clearInterval(args[0]->toInt(), IntervalRunner::TIMEOUT, true);
-	return NULL;
-}
-
-IntervalRunner::IntervalRunner(IntervalRunner::INTERVALTYPE _type, uint32_t _id, _R<IFunction> _callback, ASObject** _args,
-		const unsigned int _argslen, _R<ASObject> _obj, uint32_t _interval):
-	EventDispatcher(NULL),type(_type), id(_id), callback(_callback),obj(_obj),argslen(_argslen),interval(_interval)
-{
-	args = new ASObject*[argslen];
-	for(uint32_t i=0; i<argslen; i++)
-		args[i] = _args[i];
-}
-
-IntervalRunner::~IntervalRunner()
-{
-	for(uint32_t i=0; i<argslen; i++)
-		args[i]->decRef();
-	delete[] args;
-}
-
-void IntervalRunner::tick() 
-{
-	//incRef all arguments
-	uint32_t i;
-	for(i=0; i < argslen; i++)
-	{
-		args[i]->incRef();
-	}
-	_R<FunctionEvent> event(new (getSys()->unaccountedMemory) FunctionEvent(callback, obj, args, argslen));
-	getVm()->addEvent(NullRef,event);
-	if(type == TIMEOUT)
-	{
-		//TODO: IntervalRunner deletes itself. Is this allowed?
-		//Delete ourselves from the active intervals list
-		getSys()->intervalManager->clearInterval(id, TIMEOUT, false);
-		//No actions may be performed after this point
-	}
-}
-
-void IntervalRunner::tickFence()
-{
-	delete this;
-}
-
-IntervalManager::IntervalManager() : currentID(1)
-{
-}
+	ByteArray* th=static_cast<ByteArray*>(obj);
+	int32_t expectedLength,newLength;
+	ARG_UNPACK(expectedLength)(newLength);
 
-IntervalManager::~IntervalManager()
-{
-	//Run through all running intervals and remove their tickjob, delete their intervalRunner and erase their entry
-	std::map<uint32_t,IntervalRunner*>::iterator it = runners.begin();
-	while(it != runners.end())
+	th->lock();
+	int32_t ret = th->len;
+	if (ret == expectedLength)
 	{
-		getSys()->removeJob((*it).second);
-		runners.erase(it++);
+		th->setLength(newLength);
 	}
+	th->unlock();
+	return abstract_i(ret);
 }
 
-uint32_t IntervalManager::setInterval(_R<IFunction> callback, ASObject** args, const unsigned int argslen, _R<ASObject> obj, uint32_t interval)
-{
-	Mutex::Lock l(mutex);
-
-	uint32_t id = getFreeID();
-	IntervalRunner* runner = new (getSys()->unaccountedMemory)
-		IntervalRunner(IntervalRunner::INTERVAL, id, callback, args, argslen, obj, interval);
-
-	//Add runner as tickjob
-	getSys()->addTick(interval, runner);
-	//Add runner to map
-	runners[id] = runner;
-	//Increment currentID
-	currentID++;
-
-	return currentID-1;
-}
-uint32_t IntervalManager::setTimeout(_R<IFunction> callback, ASObject** args, const unsigned int argslen, _R<ASObject> obj, uint32_t interval)
-{
-	Mutex::Lock l(mutex);
-
-	uint32_t id = getFreeID();
-	IntervalRunner* runner = new (getSys()->unaccountedMemory)
-		IntervalRunner(IntervalRunner::TIMEOUT, id, callback, args, argslen, obj, interval);
-
-	//Add runner as waitjob
-	getSys()->addWait(interval, runner);
-	//Add runner to map
-	runners[id] = runner;
-	//increment currentID
-	currentID++;
-
-	return currentID-1;
-}
-
-uint32_t IntervalManager::getFreeID()
-{
-	//At the first run every currentID will be available. But eventually the currentID will wrap around.
-	//Thats why we need to check if the currentID isn't used yet
-	while(currentID == 0 || runners.count(currentID) != 0)
-		currentID++;
-	return currentID;
-}
-
-void IntervalManager::clearInterval(uint32_t id, IntervalRunner::INTERVALTYPE type, bool removeJob)
+ASFUNCTIONBODY(ByteArray,_toJSON)
 {
-	Mutex::Lock l(mutex);
-
-	std::map<uint32_t,IntervalRunner*>::iterator it = runners.find(id);
-	//If the entry exists and the types match, remove its tickjob, delete its intervalRunner and erase their entry
-	if(it != runners.end() && (*it).second->getType() == type)
-	{
-		if(removeJob)
-		{
-			getSys()->removeJob((*it).second);
-		}
-		runners.erase(it);
-	}
+	return Class<ASString>::getInstanceS("ByteArray");
 }
diff --git a/src/scripting/flash/utils/ByteArray.h b/src/scripting/flash/utils/ByteArray.h
new file mode 100644
index 0000000..6628d52
--- /dev/null
+++ b/src/scripting/flash/utils/ByteArray.h
@@ -0,0 +1,156 @@
+/**************************************************************************
+    Lightspark, a free flash player implementation
+
+    Copyright (C) 2009-2013  Alessandro Pignotti (a.pignotti at sssup.it)
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+**************************************************************************/
+
+#ifndef SCRIPTING_FLASH_UTILS_BYTEARRAY_H
+#define SCRIPTING_FLASH_UTILS_BYTEARRAY_H 1
+
+#include "compat.h"
+#include "swftypes.h"
+#include "scripting/flash/utils/flashutils.h"
+
+namespace lightspark
+{
+
+class ByteArray: public ASObject, public IDataInput, public IDataOutput
+{
+friend class LoaderThread;
+friend class URLLoader;
+friend class ApplicationDomain;
+friend class LoaderInfo;
+protected:
+	bool littleEndian;
+	uint8_t objectEncoding;
+	uint8_t currentObjectEncoding;
+	uint32_t position;
+	uint8_t* bytes;
+	uint32_t real_len;
+	uint32_t len;
+	void compress_zlib();
+	void uncompress_zlib();
+	Mutex mutex;
+	void lock();
+	void unlock();
+	void setLength(uint32_t newLen);
+public:
+	ByteArray(Class_base* c, uint8_t* b = NULL, uint32_t l = 0);
+	~ByteArray();
+	//Helper interface for serialization
+	bool peekByte(uint8_t& b);
+	bool readByte(uint8_t& b);
+	bool readShort(uint16_t& ret);
+	bool readUnsignedInt(uint32_t& ret);
+	bool readU29(uint32_t& ret);
+	bool readUTF(tiny_string& ret);
+	void writeByte(uint8_t b);
+	void writeShort(uint16_t val);
+	void writeUnsignedInt(uint32_t val);
+	void writeUTF(const tiny_string& str);
+	uint32_t writeObject(ASObject* obj);
+	void writeStringVR(std::map<tiny_string, uint32_t>& stringMap, const tiny_string& s);
+	void writeXMLString(std::map<const ASObject*, uint32_t>& objMap, ASObject *xml, const tiny_string& s);
+	void writeU29(uint32_t val);
+	uint32_t getPosition() const;
+	void setPosition(uint32_t p);
+	
+	uint8_t getCurrentObjectEncoding() const { return currentObjectEncoding; }
+	void setCurrentObjectEncoding(uint8_t encoding) { currentObjectEncoding = encoding; }
+	
+	ASFUNCTION(_getBytesAvailable);
+	ASFUNCTION(_getLength);
+	ASFUNCTION(_setLength);
+	ASFUNCTION(_getPosition);
+	ASFUNCTION(_setPosition);
+	ASFUNCTION(_getEndian);
+	ASFUNCTION(_setEndian);
+	ASFUNCTION(_getObjectEncoding);
+	ASFUNCTION(_setObjectEncoding);
+	ASFUNCTION(_getDefaultObjectEncoding);
+	ASFUNCTION(_setDefaultObjectEncoding);
+	ASFUNCTION(_compress);
+	ASFUNCTION(_uncompress);
+	ASFUNCTION(_deflate);
+	ASFUNCTION(_inflate);
+	ASFUNCTION(clear);
+	ASFUNCTION(readBoolean);
+	ASFUNCTION(readByte);
+	ASFUNCTION(readBytes);
+	ASFUNCTION(readDouble);
+	ASFUNCTION(readFloat);
+	ASFUNCTION(readInt);
+	ASFUNCTION(readMultiByte);
+	ASFUNCTION(readObject);
+	ASFUNCTION(readShort);
+	ASFUNCTION(readUnsignedByte);
+	ASFUNCTION(readUnsignedInt);
+	ASFUNCTION(readUnsignedShort);
+	ASFUNCTION(readUTF);
+	ASFUNCTION(readUTFBytes);
+	ASFUNCTION(writeBoolean);
+	ASFUNCTION(writeByte);
+	ASFUNCTION(writeBytes);
+	ASFUNCTION(writeDouble);
+	ASFUNCTION(writeFloat);
+	ASFUNCTION(writeInt);
+	ASFUNCTION(writeUnsignedInt);
+	ASFUNCTION(writeMultiByte);
+	ASFUNCTION(writeObject);
+	ASFUNCTION(writeShort);
+	ASFUNCTION(writeUTF);
+	ASFUNCTION(writeUTFBytes);
+	ASFUNCTION(_toString);
+	ASPROPERTY_GETTER_SETTER(bool,shareable);
+	ASFUNCTION(atomicCompareAndSwapIntAt);
+	ASFUNCTION(atomicCompareAndSwapLength);
+	ASFUNCTION(_toJSON);
+
+	// these are internal methods used if the generic Array-Methods are called on a ByteArray
+	ASFUNCTION(pop);
+	ASFUNCTION(push);
+	ASFUNCTION(shift);
+	ASFUNCTION(unshift);
+	/**
+		Get ownership over the passed buffer
+		@param buf Pointer to the buffer to acquire, ownership and delete authority is acquired
+		@param bufLen Lenght of the buffer
+		@pre buf must be allocated using new[]
+	*/
+	void acquireBuffer(uint8_t* buf, int bufLen);
+	uint8_t* getBuffer(unsigned int size, bool enableResize);
+	uint32_t getLength() const { return len; }
+
+	uint16_t endianIn(uint16_t value);
+	uint32_t endianIn(uint32_t value);
+	uint64_t endianIn(uint64_t value);
+
+	uint16_t endianOut(uint16_t value);
+	uint32_t endianOut(uint32_t value);
+	uint64_t endianOut(uint64_t value);
+
+	static void sinit(Class_base* c);
+	static void buildTraits(ASObject* o);
+	_NR<ASObject> getVariableByMultiname(const multiname& name, GET_VARIABLE_OPTION opt=NONE);
+	int32_t getVariableByMultiname_i(const multiname& name);
+	void setVariableByMultiname(const multiname& name, ASObject* o, CONST_ALLOWED_FLAG allowConst);
+	void setVariableByMultiname_i(const multiname& name, int32_t value);
+	bool hasPropertyByMultiname(const multiname& name, bool considerDynamic, bool considerPrototype);
+};
+
+}
+
+#endif /* SCRIPTING_FLASH_UTILS_BYTEARRAY_H */
diff --git a/src/scripting/flash/utils/Dictionary.cpp b/src/scripting/flash/utils/Dictionary.cpp
new file mode 100644
index 0000000..c5e7eb9
--- /dev/null
+++ b/src/scripting/flash/utils/Dictionary.cpp
@@ -0,0 +1,344 @@
+/**************************************************************************
+    Lightspark, a free flash player implementation
+
+    Copyright (C) 2009-2013  Alessandro Pignotti (a.pignotti at sssup.it)
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+**************************************************************************/
+
+#include "scripting/abc.h"
+#include "asobject.h"
+#include "scripting/class.h"
+#include "compat.h"
+#include "parsing/amf3_generator.h"
+#include "scripting/argconv.h"
+#include "scripting/flash/errors/flasherrors.h"
+#include "scripting/flash/utils/Dictionary.h"
+
+using namespace std;
+using namespace lightspark;
+
+Dictionary::Dictionary(Class_base* c):ASObject(c),
+	data(std::less<dictType::key_type>(), reporter_allocator<dictType::value_type>(c->memoryAccount))
+{
+}
+
+void Dictionary::finalize()
+{
+	ASObject::finalize();
+	data.clear();
+}
+
+void Dictionary::sinit(Class_base* c)
+{
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_DYNAMIC_NOT_FINAL);
+	c->setDeclaredMethodByQName("toJSON",AS3,Class<IFunction>::getFunction(_toJSON),NORMAL_METHOD,true);
+}
+
+void Dictionary::buildTraits(ASObject* o)
+{
+}
+
+ASFUNCTIONBODY(Dictionary,_constructor)
+{
+	return NULL;
+}
+
+ASFUNCTIONBODY(Dictionary,_toJSON)
+{
+	return Class<ASString>::getInstanceS("Dictionary");
+}
+
+Dictionary::dictType::iterator Dictionary::findKey(ASObject *o)
+{
+	Dictionary::dictType::iterator it = data.begin();
+	for(; it!=data.end(); ++it)
+	{
+		if (it->first->isEqualStrict(o))
+			return it;
+	}
+
+	return data.end();
+}
+
+void Dictionary::setVariableByMultiname_i(const multiname& name, int32_t value)
+{
+	assert_and_throw(implEnable);
+	Dictionary::setVariableByMultiname(name,abstract_i(value),CONST_NOT_ALLOWED);
+}
+
+void Dictionary::setVariableByMultiname(const multiname& name, ASObject* o, CONST_ALLOWED_FLAG allowConst)
+{
+	assert_and_throw(implEnable);
+	if(name.name_type==multiname::NAME_OBJECT)
+	{
+		multiname tmpname(NULL);
+		tmpname.ns.push_back(nsNameAndKind("",NAMESPACE));
+		switch (name.name_o->getObjectType())
+		{
+			case T_BOOLEAN:
+			case T_UINTEGER:
+			case T_INTEGER:
+				tmpname.name_type=multiname::NAME_INT;
+				tmpname.name_i = name.name_o->toInt();
+				ASObject::setVariableByMultiname(tmpname, o, allowConst);
+				return;
+			case T_NUMBER:
+				tmpname.name_type=multiname::NAME_NUMBER;
+				tmpname.name_d = name.name_o->toNumber();
+				ASObject::setVariableByMultiname(tmpname, o, allowConst);
+				return;
+			case T_STRING:
+				tmpname.name_type=multiname::NAME_STRING;
+				tmpname.name_s_id = getSys()->getUniqueStringId(name.name_o->toString());
+				ASObject::setVariableByMultiname(tmpname, o, allowConst);
+				return;
+			default:
+				break;
+		}
+		name.name_o->incRef();
+		_R<ASObject> name_o(name.name_o);
+
+		Dictionary::dictType::iterator it=findKey(name_o.getPtr());
+		if(it!=data.end())
+			it->second=_MR(o);
+		else
+			data.insert(make_pair(name_o,_MR(o)));
+	}
+	else
+	{
+		//Primitive types _must_ be handled by the normal ASObject path
+		//REFERENCE: Dictionary Object on AS3 reference
+		assert(name.name_type==multiname::NAME_STRING ||
+			name.name_type==multiname::NAME_INT ||
+			name.name_type==multiname::NAME_NUMBER);
+		ASObject::setVariableByMultiname(name, o, allowConst);
+	}
+}
+
+bool Dictionary::deleteVariableByMultiname(const multiname& name)
+{
+	assert_and_throw(implEnable);
+
+	if(name.name_type==multiname::NAME_OBJECT)
+	{
+		multiname tmpname(NULL);
+		tmpname.ns.push_back(nsNameAndKind("",NAMESPACE));
+		switch (name.name_o->getObjectType())
+		{
+			case T_BOOLEAN:
+			case T_UINTEGER:
+			case T_INTEGER:
+				tmpname.name_type=multiname::NAME_INT;
+				tmpname.name_i = name.name_o->toInt();
+				return ASObject::deleteVariableByMultiname(tmpname);
+			case T_NUMBER:
+				tmpname.name_type=multiname::NAME_NUMBER;
+				tmpname.name_d = name.name_o->toNumber();
+				return ASObject::deleteVariableByMultiname(tmpname);
+			case T_STRING:
+				tmpname.name_type=multiname::NAME_STRING;
+				tmpname.name_s_id = getSys()->getUniqueStringId(name.name_o->toString());
+				return ASObject::deleteVariableByMultiname(tmpname);
+			default:
+				break;
+		}
+		name.name_o->incRef();
+		_R<ASObject> name_o(name.name_o);
+
+		Dictionary::dictType::iterator it=findKey(name_o.getPtr());
+		if(it != data.end())
+		{
+			data.erase(it);
+			return true;
+		}
+		return false;
+	}
+	else
+	{
+		//Primitive types _must_ be handled by the normal ASObject path
+		//REFERENCE: Dictionary Object on AS3 reference
+		assert(name.name_type==multiname::NAME_STRING ||
+			name.name_type==multiname::NAME_INT ||
+			name.name_type==multiname::NAME_NUMBER);
+		return ASObject::deleteVariableByMultiname(name);
+	}
+}
+
+_NR<ASObject> Dictionary::getVariableByMultiname(const multiname& name, GET_VARIABLE_OPTION opt)
+{
+	if((opt & ASObject::SKIP_IMPL)==0 && implEnable)
+	{
+		if(name.name_type==multiname::NAME_OBJECT)
+		{
+			multiname tmpname(NULL);
+			tmpname.ns.push_back(nsNameAndKind("",NAMESPACE));
+			switch (name.name_o->getObjectType())
+			{
+				case T_BOOLEAN:
+				case T_UINTEGER:
+				case T_INTEGER:
+					tmpname.name_type=multiname::NAME_INT;
+					tmpname.name_i = name.name_o->toInt();
+					return ASObject::getVariableByMultiname(tmpname, opt);
+				case T_NUMBER:
+					tmpname.name_type=multiname::NAME_NUMBER;
+					tmpname.name_d = name.name_o->toNumber();
+					return ASObject::getVariableByMultiname(tmpname, opt);
+				case T_STRING:
+					tmpname.name_type=multiname::NAME_STRING;
+					tmpname.name_s_id = getSys()->getUniqueStringId(name.name_o->toString());
+					return ASObject::getVariableByMultiname(tmpname, opt);
+				default:
+					break;
+			}
+			name.name_o->incRef();
+			_R<ASObject> name_o(name.name_o);
+
+			Dictionary::dictType::iterator it=findKey(name_o.getPtr());
+			if(it != data.end())
+				return it->second;
+			else
+				return NullRef;
+		}
+		else
+		{
+			//Primitive types _must_ be handled by the normal ASObject path
+			//REFERENCE: Dictionary Object on AS3 reference
+			assert(name.name_type==multiname::NAME_STRING ||
+				name.name_type==multiname::NAME_INT ||
+				name.name_type==multiname::NAME_NUMBER);
+			return ASObject::getVariableByMultiname(name, opt);
+		}
+	}
+	//Try with the base implementation
+	return ASObject::getVariableByMultiname(name, opt);
+}
+
+bool Dictionary::hasPropertyByMultiname(const multiname& name, bool considerDynamic, bool considerPrototype)
+{
+	if(considerDynamic==false)
+		return ASObject::hasPropertyByMultiname(name, considerDynamic, considerPrototype);
+
+	if(name.name_type==multiname::NAME_OBJECT)
+	{
+		multiname tmpname(NULL);
+		tmpname.ns.push_back(nsNameAndKind("",NAMESPACE));
+		switch (name.name_o->getObjectType())
+		{
+			case T_BOOLEAN:
+			case T_UINTEGER:
+			case T_INTEGER:
+				tmpname.name_type=multiname::NAME_INT;
+				tmpname.name_i = name.name_o->toInt();
+				return ASObject::hasPropertyByMultiname(tmpname, considerDynamic, considerPrototype);
+			case T_NUMBER:
+				tmpname.name_type=multiname::NAME_NUMBER;
+				tmpname.name_d = name.name_o->toNumber();
+				return ASObject::hasPropertyByMultiname(tmpname, considerDynamic, considerPrototype);
+			case T_STRING:
+				tmpname.name_type=multiname::NAME_STRING;
+				tmpname.name_s_id = getSys()->getUniqueStringId(name.name_o->toString());
+				return ASObject::hasPropertyByMultiname(tmpname, considerDynamic, considerPrototype);
+			default:
+				break;
+		}
+
+		name.name_o->incRef();
+		_R<ASObject> name_o(name.name_o);
+
+		Dictionary::dictType::iterator it=findKey(name_o.getPtr());
+		return it != data.end();
+	}
+	else
+	{
+		//Primitive types _must_ be handled by the normal ASObject path
+		//REFERENCE: Dictionary Object on AS3 reference
+		assert(name.name_type==multiname::NAME_STRING ||
+			name.name_type==multiname::NAME_INT ||
+			name.name_type==multiname::NAME_NUMBER);
+		return ASObject::hasPropertyByMultiname(name, considerDynamic, considerPrototype);
+	}
+}
+
+uint32_t Dictionary::nextNameIndex(uint32_t cur_index)
+{
+	assert_and_throw(implEnable);
+	if(cur_index<data.size())
+		return cur_index+1;
+	else
+	{
+		//Fall back on object properties
+		uint32_t ret=ASObject::nextNameIndex(cur_index-data.size());
+		if(ret==0)
+			return 0;
+		else
+			return ret+data.size();
+
+	}
+}
+
+_R<ASObject> Dictionary::nextName(uint32_t index)
+{
+	assert_and_throw(implEnable);
+	if(index<=data.size())
+	{
+		map<_R<ASObject>,_R<ASObject> >::iterator it=data.begin();
+		for(unsigned int i=1;i<index;i++)
+			++it;
+
+		return it->first;
+	}
+	else
+	{
+		//Fall back on object properties
+		return ASObject::nextName(index-data.size());
+	}
+}
+
+_R<ASObject> Dictionary::nextValue(uint32_t index)
+{
+	assert_and_throw(implEnable);
+	if(index<=data.size())
+	{
+		map<_R<ASObject>,_R<ASObject> >::iterator it=data.begin();
+		for(unsigned int i=1;i<index;i++)
+			++it;
+
+		return it->second;
+	}
+	else
+	{
+		//Fall back on object properties
+		return ASObject::nextValue(index-data.size());
+	}
+}
+
+tiny_string Dictionary::toString()
+{
+	std::stringstream retstr;
+	retstr << "{";
+	map<_R<ASObject>,_R<ASObject> >::iterator it=data.begin();
+	while(it != data.end())
+	{
+		if(it != data.begin())
+			retstr << ", ";
+		retstr << "{" << it->first->toString() << ", " << it->second->toString() << "}";
+		++it;
+	}
+	retstr << "}";
+
+	return retstr.str();
+}
+
diff --git a/src/scripting/flash/utils/Dictionary.h b/src/scripting/flash/utils/Dictionary.h
new file mode 100644
index 0000000..a3732d4
--- /dev/null
+++ b/src/scripting/flash/utils/Dictionary.h
@@ -0,0 +1,64 @@
+/**************************************************************************
+    Lightspark, a free flash player implementation
+
+    Copyright (C) 2009-2013  Alessandro Pignotti (a.pignotti at sssup.it)
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+**************************************************************************/
+
+#ifndef SCRIPTING_FLASH_UTILS_DICTIONARY_H
+#define SCRIPTING_FLASH_UTILS_DICTIONARY_H 1
+
+#include "compat.h"
+#include "swftypes.h"
+
+
+namespace lightspark
+{
+
+class Dictionary: public ASObject
+{
+friend class ABCVm;
+private:
+	typedef std::map<_R<ASObject>,_R<ASObject>,std::less<_R<ASObject>>,
+	       reporter_allocator<std::pair<const _R<ASObject>, _R<ASObject>>>> dictType;
+	dictType data;
+	dictType::iterator findKey(ASObject *);
+public:
+	Dictionary(Class_base* c);
+	void finalize();
+	static void sinit(Class_base*);
+	static void buildTraits(ASObject* o);
+	ASFUNCTION(_constructor);
+	ASFUNCTION(_toJSON);
+
+	_NR<ASObject> getVariableByMultiname(const multiname& name, GET_VARIABLE_OPTION opt=NONE);
+	int32_t getVariableByMultiname_i(const multiname& name)
+	{
+		assert_and_throw(implEnable);
+		throw UnsupportedException("getVariableByMultiName_i not supported for Dictionary");
+	}
+	void setVariableByMultiname(const multiname& name, ASObject* o, CONST_ALLOWED_FLAG allowConst);
+	void setVariableByMultiname_i(const multiname& name, int32_t value);
+	bool deleteVariableByMultiname(const multiname& name);
+	bool hasPropertyByMultiname(const multiname& name, bool considerDynamic, bool considerPrototype);
+	tiny_string toString();
+	uint32_t nextNameIndex(uint32_t cur_index);
+	_R<ASObject> nextName(uint32_t index);
+	_R<ASObject> nextValue(uint32_t index);
+};
+
+}
+
+#endif /* SCRIPTING_FLASH_UTILS_DICTIONARY_H */
diff --git a/src/scripting/flash/utils/IntervalManager.cpp b/src/scripting/flash/utils/IntervalManager.cpp
new file mode 100644
index 0000000..5b07a54
--- /dev/null
+++ b/src/scripting/flash/utils/IntervalManager.cpp
@@ -0,0 +1,106 @@
+/**************************************************************************
+    Lightspark, a free flash player implementation
+
+    Copyright (C) 2009-2013  Alessandro Pignotti (a.pignotti at sssup.it)
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+**************************************************************************/
+
+#include "scripting/abc.h"
+#include "scripting/flash/utils/flashutils.h"
+#include "scripting/flash/utils/IntervalManager.h"
+#include "asobject.h"
+#include "scripting/class.h"
+#include "compat.h"
+#include "parsing/amf3_generator.h"
+#include "scripting/argconv.h"
+#include "scripting/flash/errors/flasherrors.h"
+
+using namespace std;
+using namespace lightspark;
+
+IntervalManager::IntervalManager() : currentID(1)
+{
+}
+
+IntervalManager::~IntervalManager()
+{
+	//Run through all running intervals and remove their tickjob, delete their intervalRunner and erase their entry
+	std::map<uint32_t,IntervalRunner*>::iterator it = runners.begin();
+	while(it != runners.end())
+	{
+		getSys()->removeJob((*it).second);
+		runners.erase(it++);
+	}
+}
+
+uint32_t IntervalManager::setInterval(_R<IFunction> callback, ASObject** args, const unsigned int argslen, _R<ASObject> obj, uint32_t interval)
+{
+	Mutex::Lock l(mutex);
+
+	uint32_t id = getFreeID();
+	IntervalRunner* runner = new (getSys()->unaccountedMemory)
+		IntervalRunner(IntervalRunner::INTERVAL, id, callback, args, argslen, obj, interval);
+
+	//Add runner as tickjob
+	getSys()->addTick(interval, runner);
+	//Add runner to map
+	runners[id] = runner;
+	//Increment currentID
+	currentID++;
+
+	return currentID-1;
+}
+uint32_t IntervalManager::setTimeout(_R<IFunction> callback, ASObject** args, const unsigned int argslen, _R<ASObject> obj, uint32_t interval)
+{
+	Mutex::Lock l(mutex);
+
+	uint32_t id = getFreeID();
+	IntervalRunner* runner = new (getSys()->unaccountedMemory)
+		IntervalRunner(IntervalRunner::TIMEOUT, id, callback, args, argslen, obj, interval);
+
+	//Add runner as waitjob
+	getSys()->addWait(interval, runner);
+	//Add runner to map
+	runners[id] = runner;
+	//increment currentID
+	currentID++;
+
+	return currentID-1;
+}
+
+uint32_t IntervalManager::getFreeID()
+{
+	//At the first run every currentID will be available. But eventually the currentID will wrap around.
+	//Thats why we need to check if the currentID isn't used yet
+	while(currentID == 0 || runners.count(currentID) != 0)
+		currentID++;
+	return currentID;
+}
+
+void IntervalManager::clearInterval(uint32_t id, IntervalRunner::INTERVALTYPE type, bool removeJob)
+{
+	Mutex::Lock l(mutex);
+
+	std::map<uint32_t,IntervalRunner*>::iterator it = runners.find(id);
+	//If the entry exists and the types match, remove its tickjob, delete its intervalRunner and erase their entry
+	if(it != runners.end() && (*it).second->getType() == type)
+	{
+		if(removeJob)
+		{
+			getSys()->removeJob((*it).second);
+		}
+		runners.erase(it);
+	}
+}
diff --git a/src/scripting/flash/accessibility/flashaccessibility.h b/src/scripting/flash/utils/IntervalManager.h
similarity index 57%
copy from src/scripting/flash/accessibility/flashaccessibility.h
copy to src/scripting/flash/utils/IntervalManager.h
index 19d00b8..fc4e798 100644
--- a/src/scripting/flash/accessibility/flashaccessibility.h
+++ b/src/scripting/flash/utils/IntervalManager.h
@@ -17,31 +17,32 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 **************************************************************************/
 
-#ifndef SCRIPTING_FLASH_ACCESSIBILITY_FLASHACCESSIBILITY_H
-#define SCRIPTING_FLASH_ACCESSIBILITY_FLASHACCESSIBILITY_H 1
+#ifndef SCRIPTING_FLASH_UTILS_INTERVALMANAGER_H
+#define SCRIPTING_FLASH_UTILS_INTERVALMANAGER_H 1
+
+#include "compat.h"
+#include "swftypes.h"
+#include "scripting/flash/utils/IntervalRunner.h"
 
-#include "asobject.h"
 
 namespace lightspark
 {
 
-class AccessibilityProperties : public ASObject
+class IntervalManager
 {
 private:
-	ASPROPERTY_GETTER_SETTER(tiny_string,name);
-public:
-	AccessibilityProperties(Class_base* c):ASObject(c){}
-	static void sinit(Class_base*);
-	ASFUNCTION(_constructor);
-};
-
-class AccessibilityImplementation : public ASObject
-{
+	Mutex mutex;
+	std::map<uint32_t,IntervalRunner*> runners;
+	uint32_t currentID;
 public:
-	AccessibilityImplementation(Class_base* c):ASObject(c){}
-	static void sinit(Class_base*);
-	ASFUNCTION(_constructor);
+	IntervalManager();
+	~IntervalManager();
+	uint32_t setInterval(_R<IFunction> callback, ASObject** args, const unsigned int argslen, _R<ASObject> obj, const uint32_t interval);
+	uint32_t setTimeout(_R<IFunction> callback, ASObject** args, const unsigned int argslen, _R<ASObject> obj, const uint32_t interval);
+	uint32_t getFreeID();
+	void clearInterval(uint32_t id, IntervalRunner::INTERVALTYPE type, bool removeJob);
 };
 
 }
-#endif /* SCRIPTING_FLASH_ACCESSIBILITY_FLASHACCESSIBILITY_H */
+
+#endif /* SCRIPTING_FLASH_UTILS_INTERVALMANAGER_H */
diff --git a/src/scripting/flash/utils/IntervalRunner.cpp b/src/scripting/flash/utils/IntervalRunner.cpp
new file mode 100644
index 0000000..99165f2
--- /dev/null
+++ b/src/scripting/flash/utils/IntervalRunner.cpp
@@ -0,0 +1,72 @@
+/**************************************************************************
+    Lightspark, a free flash player implementation
+
+    Copyright (C) 2009-2013  Alessandro Pignotti (a.pignotti at sssup.it)
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+**************************************************************************/
+
+#include "scripting/abc.h"
+#include "scripting/flash/utils/flashutils.h"
+#include "asobject.h"
+#include "scripting/class.h"
+#include "compat.h"
+#include "parsing/amf3_generator.h"
+#include "scripting/argconv.h"
+#include "scripting/flash/errors/flasherrors.h"
+
+using namespace std;
+using namespace lightspark;
+
+
+IntervalRunner::IntervalRunner(IntervalRunner::INTERVALTYPE _type, uint32_t _id, _R<IFunction> _callback, ASObject** _args,
+		const unsigned int _argslen, _R<ASObject> _obj, uint32_t _interval):
+	EventDispatcher(NULL),type(_type), id(_id), callback(_callback),obj(_obj),argslen(_argslen),interval(_interval)
+{
+	args = new ASObject*[argslen];
+	for(uint32_t i=0; i<argslen; i++)
+		args[i] = _args[i];
+}
+
+IntervalRunner::~IntervalRunner()
+{
+	for(uint32_t i=0; i<argslen; i++)
+		args[i]->decRef();
+	delete[] args;
+}
+
+void IntervalRunner::tick() 
+{
+	//incRef all arguments
+	uint32_t i;
+	for(i=0; i < argslen; i++)
+	{
+		args[i]->incRef();
+	}
+	_R<FunctionEvent> event(new (getSys()->unaccountedMemory) FunctionEvent(callback, obj, args, argslen));
+	getVm()->addEvent(NullRef,event);
+	if(type == TIMEOUT)
+	{
+		//TODO: IntervalRunner deletes itself. Is this allowed?
+		//Delete ourselves from the active intervals list
+		getSys()->intervalManager->clearInterval(id, TIMEOUT, false);
+		//No actions may be performed after this point
+	}
+}
+
+void IntervalRunner::tickFence()
+{
+	delete this;
+}
+
diff --git a/src/scripting/toplevel/UInteger.h b/src/scripting/flash/utils/IntervalRunner.h
similarity index 55%
copy from src/scripting/toplevel/UInteger.h
copy to src/scripting/flash/utils/IntervalRunner.h
index fe0fbcc..93191a5 100644
--- a/src/scripting/toplevel/UInteger.h
+++ b/src/scripting/flash/utils/IntervalRunner.h
@@ -17,41 +17,40 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 **************************************************************************/
 
-#ifndef SCRIPTING_TOPLEVEL_UINTEGER_H
-#define SCRIPTING_TOPLEVEL_UINTEGER_H 1
+#ifndef SCRIPTING_FLASH_UTILS_INTERVALRUNNER_H
+#define SCRIPTING_FLASH_UTILS_INTERVALRUNNER_H 1
+
 #include "compat.h"
-#include "asobject.h"
+#include "swftypes.h"
+
 
 namespace lightspark
 {
 
-class UInteger: public ASObject
+class IntervalRunner : public ITickJob, public EventDispatcher
 {
-friend ASObject* abstract_ui(uint32_t i);
 public:
-	uint32_t val;
-	UInteger(Class_base* c,uint32_t v=0):ASObject(c),val(v){type=T_UINTEGER;}
-
-	static void sinit(Class_base* c);
-	tiny_string toString();
-	static tiny_string toString(uint32_t val);
-	int32_t toInt()
-	{
-		return val;
-	}
-	uint32_t toUInt()
-	{
-		return val;
-	}
-	TRISTATE isLess(ASObject* r);
-	bool isEqual(ASObject* o);
-	ASFUNCTION(_constructor);
-	ASFUNCTION(generator);
-	ASFUNCTION(_toString);
-	ASFUNCTION(_valueOf);
-	std::string toDebugString() { return toString()+"ui"; }
-	//CHECK: should this have a special serialization?
+	enum INTERVALTYPE { INTERVAL, TIMEOUT };
+private:
+	// IntervalRunner will delete itself in tickFence, others
+	// should not call the destructor.
+	~IntervalRunner();
+	INTERVALTYPE type;
+	uint32_t id;
+	_R<IFunction> callback;
+	ASObject** args;
+	_R<ASObject> obj;
+	const unsigned int argslen;
+	uint32_t interval;
+public:
+	IntervalRunner(INTERVALTYPE _type, uint32_t _id, _R<IFunction> _callback, ASObject** _args,
+			const unsigned int _argslen, _R<ASObject> _obj, const uint32_t _interval);
+	void tick();
+	void tickFence();
+	INTERVALTYPE getType() { return type; }
 };
 
+
 }
-#endif /* SCRIPTING_TOPLEVEL_UINTEGER_H */
+
+#endif /* SCRIPTING_FLASH_UTILS_FLASHUTILS_H */
diff --git a/src/scripting/flash/utils/Proxy.cpp b/src/scripting/flash/utils/Proxy.cpp
new file mode 100644
index 0000000..77fa04f
--- /dev/null
+++ b/src/scripting/flash/utils/Proxy.cpp
@@ -0,0 +1,251 @@
+/**************************************************************************
+    Lightspark, a free flash player implementation
+
+    Copyright (C) 2009-2013  Alessandro Pignotti (a.pignotti at sssup.it)
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+**************************************************************************/
+
+#include "scripting/abc.h"
+#include "scripting/flash/utils/flashutils.h"
+#include "scripting/flash/utils/Proxy.h"
+#include "asobject.h"
+#include "scripting/class.h"
+#include "compat.h"
+#include "parsing/amf3_generator.h"
+#include "scripting/argconv.h"
+#include "scripting/flash/errors/flasherrors.h"
+#include <sstream>
+#include <zlib.h>
+#include <glib.h>
+
+using namespace std;
+using namespace lightspark;
+
+
+
+void Proxy::sinit(Class_base* c)
+{
+	CLASS_SETUP_NO_CONSTRUCTOR(c, ASObject,CLASS_DYNAMIC_NOT_FINAL);
+}
+
+void Proxy::buildTraits(ASObject* o)
+{
+}
+
+void Proxy::setVariableByMultiname(const multiname& name, ASObject* o, CONST_ALLOWED_FLAG allowConst)
+{
+	//If a variable named like this already exist, use that
+	if(ASObject::hasPropertyByMultiname(name, true, false) || !implEnable)
+	{
+		ASObject::setVariableByMultiname(name,o,allowConst);
+		return;
+	}
+
+	//Check if there is a custom setter defined, skipping implementation to avoid recursive calls
+	multiname setPropertyName(NULL);
+	setPropertyName.name_type=multiname::NAME_STRING;
+	setPropertyName.name_s_id=getSys()->getUniqueStringId("setProperty");
+	setPropertyName.ns.push_back(nsNameAndKind(flash_proxy,NAMESPACE));
+	_NR<ASObject> proxySetter=getVariableByMultiname(setPropertyName,ASObject::SKIP_IMPL);
+
+	if(proxySetter.isNull())
+	{
+		ASObject::setVariableByMultiname(name,o,allowConst);
+		return;
+	}
+
+	assert_and_throw(proxySetter->getObjectType()==T_FUNCTION);
+
+	IFunction* f=static_cast<IFunction*>(proxySetter.getPtr());
+
+	ASObject* namearg = Class<ASString>::getInstanceS(name.normalizedName());
+	namearg->setProxyProperty(name);
+	ASObject* args[2];
+	args[0]=namearg;
+	args[1]=o;
+	//We now suppress special handling
+	implEnable=false;
+	LOG(LOG_CALLS,_("Proxy::setProperty"));
+	incRef();
+	_R<ASObject> ret=_MR( f->call(this,args,2) );
+	assert_and_throw(ret->is<Undefined>());
+	implEnable=true;
+}
+
+_NR<ASObject> Proxy::getVariableByMultiname(const multiname& name, GET_VARIABLE_OPTION opt)
+{
+	//It seems that various kind of implementation works only with the empty namespace
+	assert_and_throw(name.ns.size()>0);
+	_NR<ASObject> o;
+	LOG(LOG_CALLS,"Proxy::getVar "<< name << " " << this->toDebugString());
+	if(ASObject::hasPropertyByMultiname(name, true, true) || !implEnable || (opt & ASObject::SKIP_IMPL)!=0)
+		o = ASObject::getVariableByMultiname(name,opt);
+	if (!o.isNull() || !implEnable || (opt & ASObject::SKIP_IMPL)!=0)
+		return o;
+
+	//Check if there is a custom getter defined, skipping implementation to avoid recursive calls
+	multiname getPropertyName(NULL);
+	getPropertyName.name_type=multiname::NAME_STRING;
+	getPropertyName.name_s_id=getSys()->getUniqueStringId("getProperty");
+	getPropertyName.ns.push_back(nsNameAndKind(flash_proxy,NAMESPACE));
+	o=getVariableByMultiname(getPropertyName,ASObject::SKIP_IMPL);
+
+	if(o.isNull())
+		return ASObject::getVariableByMultiname(name,opt);
+
+	assert_and_throw(o->getObjectType()==T_FUNCTION);
+
+	IFunction* f=static_cast<IFunction*>(o.getPtr());
+
+	ASObject* namearg = Class<ASString>::getInstanceS(name.normalizedName());
+	namearg->setProxyProperty(name);
+	ASObject* arg = namearg;
+	//We now suppress special handling
+	implEnable=false;
+	LOG(LOG_CALLS,"Proxy::getProperty "<< name.normalizedName() << " " << this->toDebugString());
+	incRef();
+	_NR<ASObject> ret=_MNR(f->call(this,&arg,1));
+	implEnable=true;
+	return ret;
+}
+
+bool Proxy::hasPropertyByMultiname(const multiname& name, bool considerDynamic, bool considerPrototype)
+{
+	if (name.normalizedName() == "isAttribute")
+		return true;
+	//If a variable named like this already exist, use that
+	bool asobject_has_property=ASObject::hasPropertyByMultiname(name, considerDynamic, considerPrototype);
+	if(asobject_has_property || !implEnable)
+		return asobject_has_property;
+
+	//Check if there is a custom hasProperty defined, skipping implementation to avoid recursive calls
+	multiname hasPropertyName(NULL);
+	hasPropertyName.name_type=multiname::NAME_STRING;
+	hasPropertyName.name_s_id=getSys()->getUniqueStringId("hasProperty");
+	hasPropertyName.ns.push_back(nsNameAndKind(flash_proxy,NAMESPACE));
+	_NR<ASObject> proxyHasProperty=getVariableByMultiname(hasPropertyName,ASObject::SKIP_IMPL);
+
+	if(proxyHasProperty.isNull())
+	{
+		return false;
+	}
+
+	assert_and_throw(proxyHasProperty->getObjectType()==T_FUNCTION);
+
+	IFunction* f=static_cast<IFunction*>(proxyHasProperty.getPtr());
+
+	ASObject* namearg = Class<ASString>::getInstanceS(name.normalizedName());
+	namearg->setProxyProperty(name);
+	ASObject* arg = namearg;
+	//We now suppress special handling
+	implEnable=false;
+	LOG(LOG_CALLS,_("Proxy::hasProperty"));
+	incRef();
+	_NR<ASObject> ret=_MNR(f->call(this,&arg,1));
+	implEnable=true;
+	Boolean* b = static_cast<Boolean*>(ret.getPtr());
+	return b->val;
+}
+bool Proxy::deleteVariableByMultiname(const multiname& name)
+{
+	//If a variable named like this already exist, use that
+	if(ASObject::hasPropertyByMultiname(name, true, false) || !implEnable)
+	{
+		return ASObject::deleteVariableByMultiname(name);
+	}
+
+	//Check if there is a custom deleter defined, skipping implementation to avoid recursive calls
+	multiname deletePropertyName(NULL);
+	deletePropertyName.name_type=multiname::NAME_STRING;
+	deletePropertyName.name_s_id=getSys()->getUniqueStringId("deleteProperty");
+	deletePropertyName.ns.push_back(nsNameAndKind(flash_proxy,NAMESPACE));
+	_NR<ASObject> proxyDeleter=getVariableByMultiname(deletePropertyName,ASObject::SKIP_IMPL);
+
+	if(proxyDeleter.isNull())
+	{
+		return ASObject::deleteVariableByMultiname(name);
+	}
+
+	assert_and_throw(proxyDeleter->getObjectType()==T_FUNCTION);
+
+	IFunction* f=static_cast<IFunction*>(proxyDeleter.getPtr());
+
+	ASObject* namearg = Class<ASString>::getInstanceS(name.normalizedName());
+	namearg->setProxyProperty(name);
+	ASObject* arg = namearg;
+	//We now suppress special handling
+	implEnable=false;
+	LOG(LOG_CALLS,_("Proxy::deleteProperty"));
+	incRef();
+	_NR<ASObject> ret=_MNR(f->call(this,&arg,1));
+	implEnable=true;
+	Boolean* b = static_cast<Boolean*>(ret.getPtr());
+	return b->val;
+}
+
+uint32_t Proxy::nextNameIndex(uint32_t cur_index)
+{
+	assert_and_throw(implEnable);
+	LOG(LOG_CALLS,"Proxy::nextNameIndex");
+	//Check if there is a custom enumerator, skipping implementation to avoid recursive calls
+	multiname nextNameIndexName(NULL);
+	nextNameIndexName.name_type=multiname::NAME_STRING;
+	nextNameIndexName.name_s_id=getSys()->getUniqueStringId("nextNameIndex");
+	nextNameIndexName.ns.push_back(nsNameAndKind(flash_proxy,NAMESPACE));
+	_NR<ASObject> o=getVariableByMultiname(nextNameIndexName,ASObject::SKIP_IMPL);
+	assert_and_throw(!o.isNull() && o->getObjectType()==T_FUNCTION);
+	IFunction* f=static_cast<IFunction*>(o.getPtr());
+	ASObject* arg=abstract_i(cur_index);
+	this->incRef();
+	ASObject* ret=f->call(this,&arg,1);
+	uint32_t newIndex=ret->toInt();
+	ret->decRef();
+	return newIndex;
+}
+
+_R<ASObject> Proxy::nextName(uint32_t index)
+{
+	assert_and_throw(implEnable);
+	LOG(LOG_CALLS, _("Proxy::nextName"));
+	//Check if there is a custom enumerator, skipping implementation to avoid recursive calls
+	multiname nextNameName(NULL);
+	nextNameName.name_type=multiname::NAME_STRING;
+	nextNameName.name_s_id=getSys()->getUniqueStringId("nextName");
+	nextNameName.ns.push_back(nsNameAndKind(flash_proxy,NAMESPACE));
+	_NR<ASObject> o=getVariableByMultiname(nextNameName,ASObject::SKIP_IMPL);
+	assert_and_throw(!o.isNull() && o->getObjectType()==T_FUNCTION);
+	IFunction* f=static_cast<IFunction*>(o.getPtr());
+	ASObject* arg=abstract_i(index);
+	incRef();
+	return _MR(f->call(this,&arg,1));
+}
+
+_R<ASObject> Proxy::nextValue(uint32_t index)
+{
+	assert_and_throw(implEnable);
+	LOG(LOG_CALLS, _("Proxy::nextValue"));
+	//Check if there is a custom enumerator, skipping implementation to avoid recursive calls
+	multiname nextValueName(NULL);
+	nextValueName.name_type=multiname::NAME_STRING;
+	nextValueName.name_s_id=getSys()->getUniqueStringId("nextValue");
+	nextValueName.ns.push_back(nsNameAndKind(flash_proxy,NAMESPACE));
+	_NR<ASObject> o=getVariableByMultiname(nextValueName,ASObject::SKIP_IMPL);
+	assert_and_throw(!o.isNull() && o->getObjectType()==T_FUNCTION);
+	IFunction* f=static_cast<IFunction*>(o.getPtr());
+	ASObject* arg=abstract_i(index);
+	incRef();
+	return _MR(f->call(this,&arg,1));
+}
+
diff --git a/src/scripting/flash/utils/Proxy.h b/src/scripting/flash/utils/Proxy.h
new file mode 100644
index 0000000..ccb3613
--- /dev/null
+++ b/src/scripting/flash/utils/Proxy.h
@@ -0,0 +1,61 @@
+/**************************************************************************
+    Lightspark, a free flash player implementation
+
+    Copyright (C) 2009-2013  Alessandro Pignotti (a.pignotti at sssup.it)
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+**************************************************************************/
+
+#ifndef SCRIPTING_FLASH_UTILS_PROXY_H
+#define SCRIPTING_FLASH_UTILS_PROXY_H 1
+
+#include "compat.h"
+#include "swftypes.h"
+
+namespace lightspark
+{
+
+class Proxy: public ASObject
+{
+friend class ABCVm;
+public:
+	Proxy(Class_base* c):ASObject(c){}
+	static void sinit(Class_base*);
+	static void buildTraits(ASObject* o);
+//	ASFUNCTION(_constructor);
+	_NR<ASObject> getVariableByMultiname(const multiname& name, GET_VARIABLE_OPTION opt=NONE);
+	int32_t getVariableByMultiname_i(const multiname& name)
+	{
+		assert_and_throw(implEnable);
+		throw UnsupportedException("getVariableByMultiName_i not supported for Proxy");
+	}
+	void setVariableByMultiname(const multiname& name, ASObject* o, CONST_ALLOWED_FLAG allowConst);
+	void setVariableByMultiname_i(const multiname& name, int32_t value)
+	{
+		setVariableByMultiname(name,abstract_i(value),CONST_NOT_ALLOWED);
+	}
+	
+	bool deleteVariableByMultiname(const multiname& name);
+	bool hasPropertyByMultiname(const multiname& name, bool considerDynamic, bool considerPrototype);
+	tiny_string toString()
+	{
+		throw UnsupportedException("Proxy is missing some stuff");
+	}
+	uint32_t nextNameIndex(uint32_t cur_index);
+	_R<ASObject> nextName(uint32_t index);
+	_R<ASObject> nextValue(uint32_t index);
+};
+}
+
+#endif /* SCRIPTING_FLASH_UTILS_PROXY_H */
diff --git a/src/scripting/flash/utils/Timer.cpp b/src/scripting/flash/utils/Timer.cpp
new file mode 100644
index 0000000..775dd52
--- /dev/null
+++ b/src/scripting/flash/utils/Timer.cpp
@@ -0,0 +1,185 @@
+/**************************************************************************
+    Lightspark, a free flash player implementation
+
+    Copyright (C) 2009-2013  Alessandro Pignotti (a.pignotti at sssup.it)
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+**************************************************************************/
+
+#include "scripting/abc.h"
+#include "asobject.h"
+#include "scripting/class.h"
+#include "compat.h"
+#include "parsing/amf3_generator.h"
+#include "scripting/argconv.h"
+#include "scripting/flash/errors/flasherrors.h"
+#include "scripting/flash/utils/Timer.h"
+
+using namespace std;
+using namespace lightspark;
+
+void Timer::tick()
+{
+	//This will be executed once if repeatCount was originally 1
+	//Otherwise it's executed until stopMe is set to true
+	this->incRef();
+	getVm()->addEvent(_MR(this),_MR(Class<TimerEvent>::getInstanceS("timer")));
+
+	currentCount++;
+	if(repeatCount!=0)
+	{
+		if(currentCount==repeatCount)
+		{
+			this->incRef();
+			getVm()->addEvent(_MR(this),_MR(Class<TimerEvent>::getInstanceS("timerComplete")));
+			stopMe=true;
+			running=false;
+		}
+	}
+}
+
+void Timer::tickFence()
+{
+	tickJobInstance = NullRef;
+}
+
+
+void Timer::sinit(Class_base* c)
+{
+	CLASS_SETUP(c, EventDispatcher, _constructor, CLASS_SEALED);
+	c->setDeclaredMethodByQName("currentCount","",Class<IFunction>::getFunction(_getCurrentCount),GETTER_METHOD,true);
+	c->setDeclaredMethodByQName("repeatCount","",Class<IFunction>::getFunction(_getRepeatCount),GETTER_METHOD,true);
+	c->setDeclaredMethodByQName("repeatCount","",Class<IFunction>::getFunction(_setRepeatCount),SETTER_METHOD,true);
+	c->setDeclaredMethodByQName("running","",Class<IFunction>::getFunction(_getRunning),GETTER_METHOD,true);
+	c->setDeclaredMethodByQName("delay","",Class<IFunction>::getFunction(_getDelay),GETTER_METHOD,true);
+	c->setDeclaredMethodByQName("delay","",Class<IFunction>::getFunction(_setDelay),SETTER_METHOD,true);
+	c->setDeclaredMethodByQName("start","",Class<IFunction>::getFunction(start),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("reset","",Class<IFunction>::getFunction(reset),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("stop","",Class<IFunction>::getFunction(stop),NORMAL_METHOD,true);
+}
+
+ASFUNCTIONBODY(Timer,_constructor)
+{
+	EventDispatcher::_constructor(obj,NULL,0);
+	Timer* th=static_cast<Timer*>(obj);
+
+	th->delay=args[0]->toInt();
+	if(argslen>=2)
+		th->repeatCount=args[1]->toInt();
+
+	return NULL;
+}
+
+ASFUNCTIONBODY(Timer,_getCurrentCount)
+{
+	Timer* th=static_cast<Timer*>(obj);
+	return abstract_i(th->currentCount);
+}
+
+ASFUNCTIONBODY(Timer,_getRepeatCount)
+{
+	Timer* th=static_cast<Timer*>(obj);
+	return abstract_i(th->repeatCount);
+}
+
+ASFUNCTIONBODY(Timer,_setRepeatCount)
+{
+	assert_and_throw(argslen==1);
+	int32_t count=args[0]->toInt();
+	Timer* th=static_cast<Timer*>(obj);
+	th->repeatCount=count;
+	if(th->repeatCount>0 && th->repeatCount<=th->currentCount)
+	{
+		getSys()->removeJob(th);
+		th->running=false;
+		th->tickJobInstance = NullRef;
+	}
+	return NULL;
+}
+
+ASFUNCTIONBODY(Timer,_getRunning)
+{
+	Timer* th=static_cast<Timer*>(obj);
+	return abstract_b(th->running);
+}
+
+ASFUNCTIONBODY(Timer,_getDelay)
+{
+	Timer* th=static_cast<Timer*>(obj);
+	return abstract_i(th->delay);
+}
+
+ASFUNCTIONBODY(Timer,_setDelay)
+{
+	assert_and_throw(argslen==1);
+	int32_t newdelay = args[0]->toInt();
+	if (newdelay<=0)
+		throw Class<RangeError>::getInstanceS("delay must be positive", 2066);
+
+	Timer* th=static_cast<Timer*>(obj);
+	th->delay=newdelay;
+
+	return NULL;
+}
+
+ASFUNCTIONBODY(Timer,start)
+{
+	Timer* th=static_cast<Timer*>(obj);
+	if(th->running)
+		return NULL;
+	th->running=true;
+	th->stopMe=false;
+	th->incRef();
+	th->tickJobInstance = _MNR(th);
+	if(th->repeatCount==1)
+		getSys()->addWait(th->delay,th);
+	else
+		getSys()->addTick(th->delay,th);
+	return NULL;
+}
+
+ASFUNCTIONBODY(Timer,reset)
+{
+	Timer* th=static_cast<Timer*>(obj);
+	if(th->running)
+	{
+		//This spin waits if the timer is running right now
+		getSys()->removeJob(th);
+		//NOTE: although no new events will be sent now there might be old events in the queue.
+		//Is this behaviour right?
+		//This is not anymore used by the timer, so it can die
+		th->tickJobInstance = NullRef;
+		th->running=false;
+	}
+	th->currentCount=0;
+	return NULL;
+}
+
+ASFUNCTIONBODY(Timer,stop)
+{
+	Timer* th=static_cast<Timer*>(obj);
+	if(th->running)
+	{
+		//This spin waits if the timer is running right now
+		getSys()->removeJob(th);
+		//NOTE: although no new events will be sent now there might be old events in the queue.
+		//Is this behaviour right?
+
+		//This is not anymore used by the timer, so it can die
+		th->tickJobInstance = NullRef;
+		th->running=false;
+	}
+	return NULL;
+}
+
diff --git a/src/scripting/toplevel/UInteger.h b/src/scripting/flash/utils/Timer.h
similarity index 54%
copy from src/scripting/toplevel/UInteger.h
copy to src/scripting/flash/utils/Timer.h
index fe0fbcc..da7b750 100644
--- a/src/scripting/toplevel/UInteger.h
+++ b/src/scripting/flash/utils/Timer.h
@@ -17,41 +17,49 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 **************************************************************************/
 
-#ifndef SCRIPTING_TOPLEVEL_UINTEGER_H
-#define SCRIPTING_TOPLEVEL_UINTEGER_H 1
+#ifndef SCRIPTING_FLASH_UTILS_TIMER_H
+#define SCRIPTING_FLASH_UTILS_TIMER_H 1
+
 #include "compat.h"
-#include "asobject.h"
+#include "swftypes.h"
+#include "scripting/flash/events/flashevents.h"
+#include "thread_pool.h"
+#include "timer.h"
+
 
 namespace lightspark
 {
 
-class UInteger: public ASObject
+
+class Timer: public EventDispatcher, public ITickJob
 {
-friend ASObject* abstract_ui(uint32_t i);
+private:
+	void tick();
+	void tickFence();
+	//tickJobInstance keeps a reference to self while this
+	//instance is being used by the timer thread.
+	_NR<Timer> tickJobInstance;
+protected:
+	bool running;
+	uint32_t delay;
+	uint32_t repeatCount;
+	uint32_t currentCount;
 public:
-	uint32_t val;
-	UInteger(Class_base* c,uint32_t v=0):ASObject(c),val(v){type=T_UINTEGER;}
-
+	Timer(Class_base* c):EventDispatcher(c),running(false),delay(0),repeatCount(0),currentCount(0){};
 	static void sinit(Class_base* c);
-	tiny_string toString();
-	static tiny_string toString(uint32_t val);
-	int32_t toInt()
-	{
-		return val;
-	}
-	uint32_t toUInt()
-	{
-		return val;
-	}
-	TRISTATE isLess(ASObject* r);
-	bool isEqual(ASObject* o);
 	ASFUNCTION(_constructor);
-	ASFUNCTION(generator);
-	ASFUNCTION(_toString);
-	ASFUNCTION(_valueOf);
-	std::string toDebugString() { return toString()+"ui"; }
-	//CHECK: should this have a special serialization?
+	ASFUNCTION(_getCurrentCount);
+	ASFUNCTION(_getRepeatCount);
+	ASFUNCTION(_setRepeatCount);
+	ASFUNCTION(_getRunning);
+	ASFUNCTION(_getDelay);
+	ASFUNCTION(_setDelay);
+	ASFUNCTION(start);
+	ASFUNCTION(reset);
+	ASFUNCTION(stop);
 };
 
+
 }
-#endif /* SCRIPTING_TOPLEVEL_UINTEGER_H */
+
+#endif /* SCRIPTING_FLASH_UTILS_TIMER_H */
diff --git a/src/scripting/flash/utils/flashutils.cpp b/src/scripting/flash/utils/flashutils.cpp
index 2fd9976..f3b9c4d 100644
--- a/src/scripting/flash/utils/flashutils.cpp
+++ b/src/scripting/flash/utils/flashutils.cpp
@@ -39,7 +39,7 @@ const char* Endian::bigEndian = "bigEndian";
 
 void Endian::sinit(Class_base* c)
 {
-	c->setConstructor(NULL);
+	CLASS_SETUP_NO_CONSTRUCTOR(c, ASObject, CLASS_SEALED | CLASS_FINAL);
 	c->setVariableByQName("LITTLE_ENDIAN","",Class<ASString>::getInstanceS(littleEndian),DECLARED_TRAIT);
 	c->setVariableByQName("BIG_ENDIAN","",Class<ASString>::getInstanceS(bigEndian),DECLARED_TRAIT);
 }
@@ -89,1351 +89,7 @@ void IDataOutput::linkTraits(Class_base* c)
 	lookupAndLink(c,"writeUTFBytes","flash.utils:IDataOutput");
 }
 
-ByteArray::ByteArray(Class_base* c, uint8_t* b, uint32_t l):ASObject(c),littleEndian(false),objectEncoding(ObjectEncoding::AMF3),
-	position(0),bytes(b),real_len(l),len(l)
-{
-#ifdef MEMORY_USAGE_PROFILING
-	c->memoryAccount->addBytes(l);
-#endif
-}
-
-ByteArray::~ByteArray()
-{
-	if(bytes)
-	{
-#ifdef MEMORY_USAGE_PROFILING
-		getClass()->memoryAccount->removeBytes(real_len);
-#endif
-		free(bytes);
-	}
-}
-
-void ByteArray::sinit(Class_base* c)
-{
-	c->setConstructor(NULL);
-	c->setSuper(Class<ASObject>::getRef());
-
-	c->setDeclaredMethodByQName("length","",Class<IFunction>::getFunction(_getLength),GETTER_METHOD,true);
-	c->setDeclaredMethodByQName("length","",Class<IFunction>::getFunction(_setLength),SETTER_METHOD,true);
-	c->setDeclaredMethodByQName("bytesAvailable","",Class<IFunction>::getFunction(_getBytesAvailable),GETTER_METHOD,true);
-	c->setDeclaredMethodByQName("position","",Class<IFunction>::getFunction(_getPosition),GETTER_METHOD,true);
-	c->setDeclaredMethodByQName("position","",Class<IFunction>::getFunction(_setPosition),SETTER_METHOD,true);
-	c->setDeclaredMethodByQName("endian","",Class<IFunction>::getFunction(_getEndian),GETTER_METHOD,true);
-	c->setDeclaredMethodByQName("endian","",Class<IFunction>::getFunction(_setEndian),SETTER_METHOD,true);
-	c->setDeclaredMethodByQName("objectEncoding","",Class<IFunction>::getFunction(_getObjectEncoding),GETTER_METHOD,true);
-	c->setDeclaredMethodByQName("objectEncoding","",Class<IFunction>::getFunction(_setObjectEncoding),SETTER_METHOD,true);
-	c->setDeclaredMethodByQName("defaultObjectEncoding","",Class<IFunction>::getFunction(_getDefaultObjectEncoding),GETTER_METHOD,false);
-	c->setDeclaredMethodByQName("defaultObjectEncoding","",Class<IFunction>::getFunction(_setDefaultObjectEncoding),SETTER_METHOD,false);
-	getSys()->staticByteArrayDefaultObjectEncoding = ObjectEncoding::DEFAULT;
-	c->setDeclaredMethodByQName("clear","",Class<IFunction>::getFunction(clear),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("compress","",Class<IFunction>::getFunction(_compress),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("uncompress","",Class<IFunction>::getFunction(_uncompress),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("deflate","",Class<IFunction>::getFunction(_deflate),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("inflate","",Class<IFunction>::getFunction(_inflate),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("readBoolean","",Class<IFunction>::getFunction(readBoolean),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("readBytes","",Class<IFunction>::getFunction(readBytes),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("readByte","",Class<IFunction>::getFunction(readByte),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("readDouble","",Class<IFunction>::getFunction(readDouble),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("readFloat","",Class<IFunction>::getFunction(readFloat),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("readInt","",Class<IFunction>::getFunction(readInt),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("readMultiByte","",Class<IFunction>::getFunction(readMultiByte),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("readShort","",Class<IFunction>::getFunction(readShort),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("readUnsignedByte","",Class<IFunction>::getFunction(readUnsignedByte),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("readUnsignedInt","",Class<IFunction>::getFunction(readUnsignedInt),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("readUnsignedShort","",Class<IFunction>::getFunction(readUnsignedShort),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("readObject","",Class<IFunction>::getFunction(readObject),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("readUTF","",Class<IFunction>::getFunction(readUTF),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("readUTFBytes","",Class<IFunction>::getFunction(readUTFBytes),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("writeBoolean","",Class<IFunction>::getFunction(writeBoolean),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("writeUTF","",Class<IFunction>::getFunction(writeUTF),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("writeUTFBytes","",Class<IFunction>::getFunction(writeUTFBytes),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("writeBytes","",Class<IFunction>::getFunction(writeBytes),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("writeByte","",Class<IFunction>::getFunction(writeByte),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("writeDouble","",Class<IFunction>::getFunction(writeDouble),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("writeFloat","",Class<IFunction>::getFunction(writeFloat),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("writeInt","",Class<IFunction>::getFunction(writeInt),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("writeMultiByte","",Class<IFunction>::getFunction(writeMultiByte),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("writeUnsignedInt","",Class<IFunction>::getFunction(writeUnsignedInt),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("writeObject","",Class<IFunction>::getFunction(writeObject),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("writeShort","",Class<IFunction>::getFunction(writeShort),NORMAL_METHOD,true);
-	c->prototype->setVariableByQName("toString","",Class<IFunction>::getFunction(ByteArray::_toString),DYNAMIC_TRAIT);
-
-	c->addImplementedInterface(InterfaceClass<IDataInput>::getClass());
-	IDataInput::linkTraits(c);
-	c->addImplementedInterface(InterfaceClass<IDataOutput>::getClass());
-	IDataOutput::linkTraits(c);
-}
-
-void ByteArray::buildTraits(ASObject* o)
-{
-}
-
-uint8_t* ByteArray::getBuffer(unsigned int size, bool enableResize)
-{
-	// the flash documentation doesn't tell how large ByteArrays are allowed to be
-	// so we simply don't allow bytearrays larger than 1GiB
-	// maybe we should set this smaller
-	if (size > 0x4000000) 
-		throwError<ASError>(kOutOfMemoryError);
-	// The first allocation is exactly the size we need,
-	// the subsequent reallocations happen in increments of BA_CHUNK_SIZE bytes
-	uint32_t prevLen = len;
-	if(bytes==NULL)
-	{
-		len=size;
-		real_len=len;
-		bytes = (uint8_t*) malloc(len);
-#ifdef MEMORY_USAGE_PROFILING
-		getClass()->memoryAccount->addBytes(len);
-#endif
-	}
-	else if(enableResize==false)
-	{
-		assert_and_throw(size<=len);
-	}
-	else if(real_len<size) // && enableResize==true
-	{
-#ifdef MEMORY_USAGE_PROFILING
-		uint32_t prev_real_len = real_len;
-#endif
-		while(real_len < size)
-			real_len += BA_CHUNK_SIZE;
-		// Reallocate the buffer, in chunks of BA_CHUNK_SIZE bytes
-		uint8_t* bytes2 = (uint8_t*) realloc(bytes, real_len);
-#ifdef MEMORY_USAGE_PROFILING
-		getClass()->memoryAccount->addBytes(real_len-prev_real_len);
-#endif
-		assert_and_throw(bytes2);
-		bytes = bytes2;
-		len=size;
-		bytes=bytes2;
-	}
-	else if(len<size)
-	{
-		len=size;
-	}
-	if(prevLen<size)
-	{
-		//Extend
-		memset(bytes+prevLen,0,size-prevLen);
-	}
-	return bytes;
-}
-
-uint16_t ByteArray::endianIn(uint16_t value)
-{
-	if(littleEndian)
-		return GUINT16_TO_LE(value);
-	else
-		return GUINT16_TO_BE(value);
-}
-
-uint32_t ByteArray::endianIn(uint32_t value)
-{
-	if(littleEndian)
-		return GUINT32_TO_LE(value);
-	else
-		return GUINT32_TO_BE(value);
-}
-
-uint64_t ByteArray::endianIn(uint64_t value)
-{
-	if(littleEndian)
-		return GUINT64_TO_LE(value);
-	else
-		return GUINT64_TO_BE(value);
-}
-
-uint16_t ByteArray::endianOut(uint16_t value)
-{
-	if(littleEndian)
-		return GUINT16_FROM_LE(value);
-	else
-		return GUINT16_FROM_BE(value);
-}
-
-uint32_t ByteArray::endianOut(uint32_t value)
-{
-	if(littleEndian)
-		return GUINT32_FROM_LE(value);
-	else
-		return GUINT32_FROM_BE(value);
-}
-
-uint64_t ByteArray::endianOut(uint64_t value)
-{
-	if(littleEndian)
-		return GUINT64_FROM_LE(value);
-	else
-		return GUINT64_FROM_BE(value);
-}
-
-uint32_t ByteArray::getPosition() const
-{
-	return position;
-}
-
-ASFUNCTIONBODY(ByteArray,_getPosition)
-{
-	ByteArray* th=static_cast<ByteArray*>(obj);
-	return abstract_i(th->getPosition());
-}
-
-void ByteArray::setPosition(uint32_t p)
-{
-	position=p;
-}
-
-ASFUNCTIONBODY(ByteArray,_setPosition)
-{
-	ByteArray* th=static_cast<ByteArray*>(obj);
-	uint32_t pos=args[0]->toUInt();
-	th->setPosition(pos);
-	return NULL;
-}
-
-ASFUNCTIONBODY(ByteArray,_getEndian)
-{
-	ByteArray* th=static_cast<ByteArray*>(obj);
-	if(th->littleEndian)
-		return Class<ASString>::getInstanceS(Endian::littleEndian);
-	else
-		return Class<ASString>::getInstanceS(Endian::bigEndian);
-}
-
-ASFUNCTIONBODY(ByteArray,_setEndian)
-{
-	ByteArray* th=static_cast<ByteArray*>(obj);
-	if(args[0]->toString() == Endian::littleEndian)
-		th->littleEndian = true;
-	else if(args[0]->toString() == Endian::bigEndian)
-		th->littleEndian = false;
-	else
-		throwError<ArgumentError>(kInvalidEnumError, "endian");
-	return NULL;
-}
-
-ASFUNCTIONBODY(ByteArray,_getObjectEncoding)
-{
-	ByteArray* th=static_cast<ByteArray*>(obj);
-	return abstract_ui(th->objectEncoding);
-}
-
-ASFUNCTIONBODY(ByteArray,_setObjectEncoding)
-{
-	ByteArray* th=static_cast<ByteArray*>(obj);
-	uint32_t value;
-	ARG_UNPACK(value);
-	if(value!=ObjectEncoding::AMF0 && value!=ObjectEncoding::AMF3)
-		throwError<ArgumentError>(kInvalidEnumError, "objectEncoding");
-
-	th->objectEncoding=value;
-	return NULL;
-}
-
-ASFUNCTIONBODY(ByteArray,_getDefaultObjectEncoding)
-{
-	return abstract_i(getSys()->staticNetConnectionDefaultObjectEncoding);
-}
-
-ASFUNCTIONBODY(ByteArray,_setDefaultObjectEncoding)
-{
-	assert_and_throw(argslen == 1);
-	int32_t value = args[0]->toInt();
-	if(value == 0)
-		getSys()->staticByteArrayDefaultObjectEncoding = ObjectEncoding::AMF0;
-	else if(value == 3)
-		getSys()->staticByteArrayDefaultObjectEncoding = ObjectEncoding::AMF3;
-	else
-		throw RunTimeException("Invalid object encoding");
-	return NULL;
-}
-
-ASFUNCTIONBODY(ByteArray,_setLength)
-{
-	ByteArray* th=static_cast<ByteArray*>(obj);
-	assert_and_throw(argslen==1);
-	uint32_t newLen=args[0]->toInt();
-	if(newLen==th->len) //Nothing to do
-		return NULL;
-	if (newLen > 0)
-	{
-		th->getBuffer(newLen,true);
-	}
-	else
-	{
-		if (th->bytes)
-		{
-#ifdef MEMORY_USAGE_PROFILING
-			th->getClass()->memoryAccount->removeBytes(th->real_len);
-#endif
-			free(th->bytes);
-		}
-		th->bytes = NULL;
-		th->len = newLen;
-		th->real_len = newLen;
-	}
-	if (th->position > th->len)
-		th->position = (th->len > 0 ? th->len-1 : 0);
-	return NULL;
-}
-
-ASFUNCTIONBODY(ByteArray,_getLength)
-{
-	ByteArray* th=static_cast<ByteArray*>(obj);
-	return abstract_i(th->len);
-}
-
-ASFUNCTIONBODY(ByteArray,_getBytesAvailable)
-{
-	ByteArray* th=static_cast<ByteArray*>(obj);
-	return abstract_i(th->len-th->position);
-}
-
-ASFUNCTIONBODY(ByteArray,readBoolean)
-{
-	ByteArray* th=static_cast<ByteArray*>(obj);
-
-	uint8_t ret;
-	if(!th->readByte(ret))
-	{
-		throwError<ArgumentError>(kEOFError);
-	}
-
-	return abstract_b(ret!=0);
-}
-
-ASFUNCTIONBODY(ByteArray,readBytes)
-{
-	ByteArray* th=static_cast<ByteArray*>(obj);
-	_NR<ByteArray> out;
-	uint32_t offset;
-	uint32_t length;
-	ARG_UNPACK(out)(offset, 0)(length, 0);
-	
-	if(length == 0)
-	{
-		assert(th->len >= th->position);
-		length = th->len - th->position;
-	}
-
-	//Error checks
-	if(th->position+length > th->len)
-	{
-		throwError<ArgumentError>(kEOFError);
-	}
-	if((uint64_t)length+offset > 0xFFFFFFFF)
-	{
-		throw Class<RangeError>::getInstanceS("length+offset");
-	}
-	
-	uint8_t* buf=out->getBuffer(length+offset,true);
-	memcpy(buf+offset,th->bytes+th->position,length);
-	th->position+=length;
-
-	return NULL;
-}
-
-bool ByteArray::readUTF(tiny_string& ret)
-{
-	uint16_t stringLen;
-	if(!readShort(stringLen))
-		return false;
-	if(len < (position+stringLen))
-		return false;
-	//Very inefficient copy
-	//TODO: optmize
-	ret=string((char*)bytes+position, (size_t)stringLen);
-	position+=stringLen;
-	return true;
-}
-
-ASFUNCTIONBODY(ByteArray,readUTF)
-{
-	ByteArray* th=static_cast<ByteArray*>(obj);
-
-	tiny_string res;
-	if (!th->readUTF(res))
-	{
-		throwError<ArgumentError>(kEOFError);
-	}
-
-	return Class<ASString>::getInstanceS(res);
-}
-
-ASFUNCTIONBODY(ByteArray,readUTFBytes)
-{
-	ByteArray* th=static_cast<ByteArray*>(obj);
-	uint32_t length;
-
-	ARG_UNPACK (length);
-	if(th->position+length > th->len)
-	{
-		throwError<ArgumentError>(kEOFError);
-	}
-
-	uint8_t *bufStart=th->bytes+th->position;
-	th->position+=length;
-	return Class<ASString>::getInstanceS((char *)bufStart,length);
-}
-
-void ByteArray::writeUTF(const tiny_string& str)
-{
-	getBuffer(position+str.numBytes()+2,true);
-	if(str.numBytes() > 65535)
-	{
-		throwError<RangeError>(kParamRangeError);
-	}
-	uint16_t numBytes=endianIn((uint16_t)str.numBytes());
-	memcpy(bytes+position,&numBytes,2);
-	memcpy(bytes+position+2,str.raw_buf(),str.numBytes());
-	position+=str.numBytes()+2;
-}
-
-ASFUNCTIONBODY(ByteArray,writeUTF)
-{
-	ByteArray* th=static_cast<ByteArray*>(obj);
-	//Validate parameters
-	assert_and_throw(argslen==1);
-	assert_and_throw(args[0]->getObjectType()==T_STRING);
-	ASString* str=Class<ASString>::cast(args[0]);
-	th->writeUTF(str->data);
-	return NULL;
-}
-
-ASFUNCTIONBODY(ByteArray,writeUTFBytes)
-{
-	ByteArray* th=static_cast<ByteArray*>(obj);
-	//Validate parameters
-	assert_and_throw(argslen==1);
-	assert_and_throw(args[0]->getObjectType()==T_STRING);
-	ASString* str=Class<ASString>::cast(args[0]);
-	th->getBuffer(th->position+str->data.numBytes(),true);
-	memcpy(th->bytes+th->position,str->data.raw_buf(),str->data.numBytes());
-	th->position+=str->data.numBytes();
-
-	return NULL;
-}
-
-ASFUNCTIONBODY(ByteArray,writeMultiByte)
-{
-	ByteArray* th=static_cast<ByteArray*>(obj);
-	tiny_string value;
-	tiny_string charset;
-	ARG_UNPACK(value)(charset);
-
-	// TODO: should convert from UTF-8 to charset
-	LOG(LOG_NOT_IMPLEMENTED, "ByteArray.writeMultiByte doesn't convert charset");
-
-	th->getBuffer(th->position+value.numBytes(),true);
-	memcpy(th->bytes+th->position,value.raw_buf(),value.numBytes());
-	th->position+=value.numBytes();
-
-	return NULL;
-}
-
-uint32_t ByteArray::writeObject(ASObject* obj)
-{
-	//Return the length of the serialized object
-
-	//TODO: support AMF0
-	assert_and_throw(objectEncoding==ObjectEncoding::AMF3);
-	//TODO: support custom serialization
-	map<tiny_string, uint32_t> stringMap;
-	map<const ASObject*, uint32_t> objMap;
-	map<const Class_base*, uint32_t> traitsMap;
-	uint32_t oldPosition=position;
-	obj->serialize(this, stringMap, objMap,traitsMap);
-	return position-oldPosition;
-}
-
-ASFUNCTIONBODY(ByteArray,writeObject)
-{
-	ByteArray* th=static_cast<ByteArray*>(obj);
-	//Validate parameters
-	assert_and_throw(argslen==1);
-	th->writeObject(args[0]);
-
-	return NULL;
-}
-
-void ByteArray::writeShort(uint16_t val)
-{
-	int16_t value2 = endianIn(val);
-	getBuffer(position+2,true);
-	memcpy(bytes+position,&value2,2);
-	position+=2;
-}
-
-ASFUNCTIONBODY(ByteArray,writeShort)
-{
-	ByteArray* th=static_cast<ByteArray*>(obj);
-	int32_t value;
-	ARG_UNPACK(value);
-
-	th->writeShort((static_cast<uint16_t>(value & 0xffff)));
-	return NULL;
-}
-
-ASFUNCTIONBODY(ByteArray,writeBytes)
-{
-	ByteArray* th=static_cast<ByteArray*>(obj);
-	//Validate parameters
-	assert_and_throw(argslen>=1 && argslen<=3);
-	assert_and_throw(args[0]->getClass()->isSubClass(Class<ByteArray>::getClass()));
-	ByteArray* out=Class<ByteArray>::cast(args[0]);
-	uint32_t offset=0;
-	uint32_t length=0;
-	if(argslen>=2)
-		offset=args[1]->toUInt();
-	if(argslen==3)
-		length=args[2]->toUInt();
-
-	// We need to clamp offset to the beginning of the bytes array
-	if(offset > out->getLength()-1)
-		offset = 0;
-	// We need to clamp length to the end of the bytes array
-	if(length > out->getLength()-offset)
-		length = 0;
-
-	//If the length is 0 the whole buffer must be copied
-	if(length == 0)
-		length=(out->getLength()-offset);
-	uint8_t* buf=out->getBuffer(offset+length,false);
-	th->getBuffer(th->position+length,true);
-	memcpy(th->bytes+th->position,buf+offset,length);
-	th->position+=length;
-
-	return NULL;
-}
-
-void ByteArray::writeByte(uint8_t b)
-{
-	getBuffer(position+1,true);
-	bytes[position++] = b;
-}
-
-ASFUNCTIONBODY(ByteArray,writeByte)
-{
-	ByteArray* th=static_cast<ByteArray*>(obj);
-	assert_and_throw(argslen==1);
-
-	int32_t value=args[0]->toInt();
-
-	th->writeByte(value&0xff);
-
-	return NULL;
-}
-
-ASFUNCTIONBODY(ByteArray,writeBoolean)
-{
-	ByteArray* th=static_cast<ByteArray*>(obj);
-	bool b;
-	ARG_UNPACK (b);
-
-	if (b)
-		th->writeByte(1);
-	else
-		th->writeByte(0);
-
-	return NULL;
-}
-
-ASFUNCTIONBODY(ByteArray,writeDouble)
-{
-	ByteArray* th=static_cast<ByteArray*>(obj);
-	assert_and_throw(argslen==1);
-
-	double value = args[0]->toNumber();
-	uint64_t *intptr=reinterpret_cast<uint64_t*>(&value);
-	uint64_t value2=th->endianIn(*intptr);
-
-	th->getBuffer(th->position+8,true);
-	memcpy(th->bytes+th->position,&value2,8);
-	th->position+=8;
-
-	return NULL;
-}
-
-ASFUNCTIONBODY(ByteArray,writeFloat)
-{
-	ByteArray* th=static_cast<ByteArray*>(obj);
-	assert_and_throw(argslen==1);
-
-	float value = args[0]->toNumber();
-	uint32_t *intptr=reinterpret_cast<uint32_t*>(&value);
-	uint32_t value2=th->endianIn(*intptr);
-
-	th->getBuffer(th->position+4,true);
-	memcpy(th->bytes+th->position,&value2,4);
-	th->position+=4;
-
-	return NULL;
-}
-
-ASFUNCTIONBODY(ByteArray,writeInt)
-{
-	ByteArray* th=static_cast<ByteArray*>(obj);
-	assert_and_throw(argslen==1);
-
-	uint32_t value=th->endianIn(static_cast<uint32_t>(args[0]->toInt()));
-
-	th->getBuffer(th->position+4,true);
-	memcpy(th->bytes+th->position,&value,4);
-	th->position+=4;
-
-	return NULL;
-}
-
-void ByteArray::writeUnsignedInt(uint32_t val)
-{
-	getBuffer(position+4,true);
-	memcpy(bytes+position,&val,4);
-	position+=4;
-}
-
-ASFUNCTIONBODY(ByteArray,writeUnsignedInt)
-{
-	ByteArray* th=static_cast<ByteArray*>(obj);
-	assert_and_throw(argslen==1);
-
-	uint32_t value=th->endianIn(args[0]->toUInt());
-	th->writeUnsignedInt(value);
-	return NULL;
-}
-
-bool ByteArray::readByte(uint8_t& b)
-{
-	if (len <= position)
-		return false;
-
-	b=bytes[position++];
-	return true;
-}
-
-bool ByteArray::readU29(uint32_t& ret)
-{
-	//Be careful! This is different from u32 parsing.
-	//Here the most significant bits appears before in the stream!
-	ret=0;
-	for(uint32_t i=0;i<4;i++)
-	{
-		if (len <= position)
-			return false;
-
-		uint8_t tmp=bytes[position++];
-		ret <<= 7;
-		if(i<3)
-		{
-			ret |= tmp&0x7f;
-			if((tmp&0x80)==0)
-				break;
-		}
-		else
-		{
-			ret |= tmp;
-			//Sign extend
-			if(tmp&0x80)
-				ret|=0xe0000000;
-		}
-	}
-	return true;
-}
-
-ASFUNCTIONBODY(ByteArray, readByte)
-{
-	ByteArray* th=static_cast<ByteArray*>(obj);
-	assert_and_throw(argslen==0);
-
-	uint8_t ret;
-	if(!th->readByte(ret))
-	{
-		throwError<ArgumentError>(kEOFError);
-	}
-	return abstract_i((int8_t)ret);
-}
-
-ASFUNCTIONBODY(ByteArray,readDouble)
-{
-	ByteArray* th=static_cast<ByteArray*>(obj);
-	assert_and_throw(argslen==0);
-
-	if(th->len < th->position+8)
-	{
-		throwError<ArgumentError>(kEOFError);
-	}
-
-	uint64_t ret;
-	memcpy(&ret,th->bytes+th->position,8);
-	th->position+=8;
-	ret = th->endianOut(ret);
-
-	double *doubleptr=reinterpret_cast<double*>(&ret);
-	return abstract_d(*doubleptr);
-}
-
-ASFUNCTIONBODY(ByteArray,readFloat)
-{
-	ByteArray* th=static_cast<ByteArray*>(obj);
-	assert_and_throw(argslen==0);
-
-	if(th->len < th->position+4)
-	{
-		throwError<ArgumentError>(kEOFError);
-	}
-
-	uint32_t ret;
-	memcpy(&ret,th->bytes+th->position,4);
-	th->position+=4;
-	ret = th->endianOut(ret);
-
-	float *floatptr=reinterpret_cast<float*>(&ret);
-	return abstract_d(*floatptr);
-}
-
-ASFUNCTIONBODY(ByteArray,readInt)
-{
-	ByteArray* th=static_cast<ByteArray*>(obj);
-	assert_and_throw(argslen==0);
-
-	if(th->len < th->position+4)
-	{
-		throwError<ArgumentError>(kEOFError);
-	}
-
-	uint32_t ret;
-	memcpy(&ret,th->bytes+th->position,4);
-	th->position+=4;
-
-	return abstract_i((int32_t)th->endianOut(ret));
-}
-
-bool ByteArray::readShort(uint16_t& ret)
-{
-	if (len < position+2)
-		return false;
-
-	uint16_t tmp;
-	memcpy(&tmp,bytes+position,2);
-	ret=endianOut(tmp);
-	position+=2;
-	return true;
-}
-
-ASFUNCTIONBODY(ByteArray,readShort)
-{
-	ByteArray* th=static_cast<ByteArray*>(obj);
-	assert_and_throw(argslen==0);
-
-	uint16_t ret;
-	if(!th->readShort(ret))
-	{
-		throwError<ArgumentError>(kEOFError);
-	}
-
-	return abstract_i((int16_t)ret);
-}
-
-ASFUNCTIONBODY(ByteArray,readUnsignedByte)
-{
-	ByteArray* th=static_cast<ByteArray*>(obj);
-	assert_and_throw(argslen==0);
-
-	uint8_t ret;
-	if (!th->readByte(ret))
-	{
-		throwError<ArgumentError>(kEOFError);
-	}
-	return abstract_ui(ret);
-}
-
-bool ByteArray::readUnsignedInt(uint32_t& ret)
-{
-	if(len < position+4)
-		return false;
-
-	uint32_t tmp;
-	memcpy(&tmp,bytes+position,4);
-	ret=endianOut(tmp);
-	position+=4;
-	return true;
-}
-
-ASFUNCTIONBODY(ByteArray,readUnsignedInt)
-{
-	ByteArray* th=static_cast<ByteArray*>(obj);
-	assert_and_throw(argslen==0);
-
-	uint32_t ret;
-	if(!th->readUnsignedInt(ret))
-		throwError<ArgumentError>(kEOFError);
-
-	return abstract_ui(ret);
-}
-
-ASFUNCTIONBODY(ByteArray,readUnsignedShort)
-{
-	ByteArray* th=static_cast<ByteArray*>(obj);
-	assert_and_throw(argslen==0);
-
-	uint16_t ret;
-	if(!th->readShort(ret))
-	{
-		throwError<ArgumentError>(kEOFError);
-	}
-
-	return abstract_ui(ret);
-}
-
-ASFUNCTIONBODY(ByteArray,readMultiByte)
-{
-	ByteArray* th=static_cast<ByteArray*>(obj);
-	uint32_t strlen;
-	tiny_string charset;
-	ARG_UNPACK(strlen)(charset);
-
-	if(th->len < th->position+strlen)
-	{
-		throwError<ArgumentError>(kEOFError);
-	}
-
-	// TODO: should convert from charset to UTF-8
-	LOG(LOG_NOT_IMPLEMENTED, "ByteArray.readMultiByte doesn't convert charset");
-	return Class<ASString>::getInstanceS((char*)th->bytes+th->position,strlen);
-}
-
-ASFUNCTIONBODY(ByteArray,readObject)
-{
-	ByteArray* th=static_cast<ByteArray*>(obj);
-	assert_and_throw(argslen==0);
-	if(th->bytes==NULL)
-	{
-		throwError<ArgumentError>(kEOFError);
-	}
-	assert_and_throw(th->objectEncoding==ObjectEncoding::AMF3);
-	Amf3Deserializer d(th);
-	_NR<ASObject> ret(NullRef);
-	try
-	{
-		ret=d.readObject();
-	}
-	catch(LightsparkException& e)
-	{
-		LOG(LOG_ERROR,"Exception caught while parsing AMF3: " << e.cause);
-		//TODO: throw AS exception
-	}
-
-	if(ret.isNull())
-	{
-		LOG(LOG_ERROR,"No objects in the AMF3 data. Returning Undefined");
-		return getSys()->getUndefinedRef();
-	}
-	ret->incRef();
-	return ret.getPtr();
-}
-
-ASFUNCTIONBODY(ByteArray,_toString)
-{
-	ByteArray* th=static_cast<ByteArray*>(obj);
-	//TODO: check for Byte Order Mark
-	return Class<ASString>::getInstanceS((char*)th->bytes,th->len);
-}
-
-bool ByteArray::hasPropertyByMultiname(const multiname& name, bool considerDynamic, bool considerPrototype)
-{
-	if(considerDynamic==false)
-		return ASObject::hasPropertyByMultiname(name, considerDynamic, considerPrototype);
-
-	unsigned int index=0;
-	if(!Array::isValidMultiname(name,index))
-		return ASObject::hasPropertyByMultiname(name, considerDynamic, considerPrototype);
-
-	return index<len;
-}
-
-_NR<ASObject> ByteArray::getVariableByMultiname(const multiname& name, GET_VARIABLE_OPTION opt)
-{
-	assert_and_throw(implEnable);
-	unsigned int index=0;
-	if((opt & ASObject::SKIP_IMPL)!=0 || !Array::isValidMultiname(name,index))
-		return ASObject::getVariableByMultiname(name,opt);
-
-	if(index<len)
-	{
-		uint8_t value = bytes[index];
-		return _MNR(abstract_ui(static_cast<uint32_t>(value)));
-	}
-	else
-		return _MNR(getSys()->getUndefinedRef());
-}
-
-int32_t ByteArray::getVariableByMultiname_i(const multiname& name)
-{
-	assert_and_throw(implEnable);
-	unsigned int index=0;
-	if(!Array::isValidMultiname(name,index))
-		return ASObject::getVariableByMultiname_i(name);
-
-	if(index<len)
-	{
-		uint8_t value = bytes[index];
-		return static_cast<uint32_t>(value);
-	}
-	else
-		return _MNR(getSys()->getUndefinedRef());
-}
-
-void ByteArray::setVariableByMultiname(const multiname& name, ASObject* o, CONST_ALLOWED_FLAG allowConst)
-{
-	assert_and_throw(implEnable);
-	unsigned int index=0;
-	if(!Array::isValidMultiname(name,index))
-		return ASObject::setVariableByMultiname(name,o,allowConst);
-
-	if(index>=len)
-	{
-		uint32_t prevLen = len;
-		getBuffer(index+1, true);
-		// Fill the gap between the end of the current data and the index with zeros
-		memset(bytes+prevLen, 0, index-prevLen);
-	}
-
-	// Fill the byte pointed to by index with the truncated uint value of the object.
-	uint8_t value = static_cast<uint8_t>(o->toUInt() & 0xff);
-	bytes[index] = value;
-
-	o->decRef();
-}
-
-void ByteArray::setVariableByMultiname_i(const multiname& name, int32_t value)
-{
-	setVariableByMultiname(name, abstract_i(value),ASObject::CONST_NOT_ALLOWED);
-}
-
-void ByteArray::acquireBuffer(uint8_t* buf, int bufLen)
-{
-	if(bytes)
-	{
-#ifdef MEMORY_USAGE_PROFILING
-		getClass()->memoryAccount->removeBytes(real_len);
-#endif
-		free(bytes);
-	}
-	bytes=buf;
-	real_len=bufLen;
-	len=bufLen;
-#ifdef MEMORY_USAGE_PROFILING
-	getClass()->memoryAccount->addBytes(real_len);
-#endif
-	position=0;
-}
-
-void ByteArray::writeU29(uint32_t val)
-{
-	for(uint32_t i=0;i<4;i++)
-	{
-		uint8_t b;
-		if(i<3)
-		{
-			uint32_t tmp=(val >> ((3-i)*7));
-			if(tmp==0)
-				continue;
-
-			b=(tmp&0x7f)|0x80;
-		}
-		else
-			b=val&0x7f;
-
-		writeByte(b);
-	}
-}
-
-void ByteArray::writeStringVR(map<tiny_string, uint32_t>& stringMap, const tiny_string& s)
-{
-	const uint32_t len=s.numBytes();
-	if(len >= 1<<28)
-		throwError<RangeError>(kParamRangeError);
-
-	//Check if the string is already in the map
-	auto it=stringMap.find(s);
-	if(it!=stringMap.end())
-	{
-		//The first bit must be 0, the next 29 bits
-		//store the index of the string in the map
-		writeU29(it->second << 1);
-	}
-	else
-	{
-		//The AMF3 spec says that the empty string is never sent by reference
-		//So add the string to the map only if it's not the empty string
-		if(len)
-			stringMap.insert(make_pair(s, stringMap.size()));
-
-		//The first bit must be 1, the next 29 bits
-		//store the number of bytes of the string
-		writeU29((len<<1) | 1);
-
-		getBuffer(position+len,true);
-		memcpy(bytes+position,s.raw_buf(),len);
-		position+=len;
-	}
-}
-
-void ByteArray::writeXMLString(std::map<const ASObject*, uint32_t>& objMap,
-			       ASObject *xml,
-			       const tiny_string& xmlstr)
-{
-	if(xmlstr.numBytes() >= 1<<28)
-		throwError<RangeError>(kParamRangeError);
-
-	//Check if the XML object has been already serialized
-	auto it=objMap.find(xml);
-	if(it!=objMap.end())
-	{
-		//The least significant bit is 0 to signal a reference
-		writeU29(it->second << 1);
-	}
-	else
-	{
-		//Add the XML object to the map
-		objMap.insert(make_pair(xml, objMap.size()));
-
-		//The first bit must be 1, the next 29 bits
-		//store the number of bytes of the string
-		writeU29((xmlstr.numBytes()<<1) | 1);
-
-		getBuffer(position+xmlstr.numBytes(),true);
-		memcpy(bytes+position,xmlstr.raw_buf(),xmlstr.numBytes());
-		position+=xmlstr.numBytes();
-	}
-}
-
-void ByteArray::compress_zlib()
-{
-	if(len==0)
-		return;
-
-	unsigned long buflen=compressBound(len);
-	uint8_t *compressed=(uint8_t*) malloc(buflen);
-	assert_and_throw(compressed);
-
-	if(compress(compressed, &buflen, bytes, len)!=Z_OK)
-	{
-		free(compressed);
-		throw RunTimeException("zlib compress failed");
-	}
-
-	acquireBuffer(compressed, buflen);
-	position=buflen;
-}
-
-void ByteArray::uncompress_zlib()
-{
-	z_stream strm;
-	int status;
-
-	if(len==0)
-		return;
-
-	strm.zalloc=Z_NULL;
-	strm.zfree=Z_NULL;
-	strm.opaque=Z_NULL;
-	strm.avail_in=len;
-	strm.next_in=bytes;
-	strm.total_out=0;
-	status=inflateInit(&strm);
-	if(status==Z_VERSION_ERROR)
-		throw Class<IOError>::getInstanceS("not valid compressed data");
-	else if(status!=Z_OK)
-		throw RunTimeException("zlib uncompress failed");
-
-	vector<uint8_t> buf(3*len);
-	do
-	{
-		strm.next_out=&buf[strm.total_out];
-		strm.avail_out=buf.size()-strm.total_out;
-		status=inflate(&strm, Z_NO_FLUSH);
-
-		if(status!=Z_OK && status!=Z_STREAM_END)
-		{
-			inflateEnd(&strm);
-			throw Class<IOError>::getInstanceS("not valid compressed data");
-		}
-
-		if(strm.avail_out==0)
-			buf.resize(buf.size()+len);
-	} while(status!=Z_STREAM_END);
-
-	inflateEnd(&strm);
-
-	len=strm.total_out;
-#ifdef MEMORY_USAGE_PROFILING
-	getClass()->memoryAccount->addBytes(len-real_len);
-#endif
-	real_len = len;
-	uint8_t* bytes2=(uint8_t*) realloc(bytes, len);
-	assert_and_throw(bytes2);
-	bytes = bytes2;
-	memcpy(bytes, &buf[0], len);
-	position=0;
-}
-
-ASFUNCTIONBODY(ByteArray,_compress)
-{
-	ByteArray* th=static_cast<ByteArray*>(obj);
-	// flash throws an error if compress is called with a compression algorithm,
-	// and always uses the zlib algorithm
-	// but tamarin tests do not catch it, so we simply ignore any parameters provided
-	th->compress_zlib();
-	return NULL;
-}
-
-ASFUNCTIONBODY(ByteArray,_uncompress)
-{
-	ByteArray* th=static_cast<ByteArray*>(obj);
-	// flash throws an error if uncompress is called with a compression algorithm,
-	// and always uses the zlib algorithm
-	// but tamarin tests do not catch it, so we simply ignore any parameters provided
-	th->uncompress_zlib();
-	return NULL;
-}
-
-ASFUNCTIONBODY(ByteArray,_deflate)
-{
-	ByteArray* th=static_cast<ByteArray*>(obj);
-	th->compress_zlib();
-	return NULL;
-}
-
-ASFUNCTIONBODY(ByteArray,_inflate)
-{
-	ByteArray* th=static_cast<ByteArray*>(obj);
-	th->uncompress_zlib();
-	return NULL;
-}
-
-ASFUNCTIONBODY(ByteArray,clear)
-{
-	ByteArray* th=static_cast<ByteArray*>(obj);
-	if(th->bytes)
-	{
-#ifdef MEMORY_USAGE_PROFILING
-		th->getClass()->memoryAccount->removeBytes(th->real_len);
-#endif
-		free(th->bytes);
-	}
-	th->bytes = NULL;
-	th->len=0;
-	th->real_len=0;
-	th->position=0;
-	return NULL;
-}
-
-void Timer::tick()
-{
-	//This will be executed once if repeatCount was originally 1
-	//Otherwise it's executed until stopMe is set to true
-	this->incRef();
-	getVm()->addEvent(_MR(this),_MR(Class<TimerEvent>::getInstanceS("timer")));
-
-	currentCount++;
-	if(repeatCount!=0)
-	{
-		if(currentCount==repeatCount)
-		{
-			this->incRef();
-			getVm()->addEvent(_MR(this),_MR(Class<TimerEvent>::getInstanceS("timerComplete")));
-			stopMe=true;
-			running=false;
-		}
-	}
-}
-
-void Timer::tickFence()
-{
-	tickJobInstance = NullRef;
-}
-
-// this seems to be how AS3 handles generic pop calls in Array class
-ASFUNCTIONBODY(ByteArray,pop)
-{
-	ByteArray* th=static_cast<ByteArray*>(obj);
-	uint8_t res = 0;
-	if (th->readByte(res))
-	{
-		memmove(th->bytes,(th->bytes+1),th->getLength()-1);
-		th->len--;
-	}
-	return abstract_ui(res);
-	
-}
-
-// this seems to be how AS3 handles generic push calls in Array class
-ASFUNCTIONBODY(ByteArray,push)
-{
-	ByteArray* th=static_cast<ByteArray*>(obj);
-	th->getBuffer(th->len+argslen,true);
-	for (unsigned int i = 0; i < argslen; i++)
-	{
-		th->bytes[th->len+i] = (uint8_t)args[i]->toInt();
-	}
-	return abstract_ui(th->getLength());
-}
-
-// this seems to be how AS3 handles generic shift calls in Array class
-ASFUNCTIONBODY(ByteArray,shift)
-{
-	ByteArray* th=static_cast<ByteArray*>(obj);
-	uint8_t res = 0;
-	if (th->readByte(res))
-	{
-		memmove(th->bytes,(th->bytes+1),th->getLength()-1);
-		th->len--;
-	}
-	return abstract_ui(res);
-}
-
-// this seems to be how AS3 handles generic unshift calls in Array class
-ASFUNCTIONBODY(ByteArray,unshift)
-{
-	ByteArray* th=static_cast<ByteArray*>(obj);
-	th->getBuffer(th->len+argslen,true);
-	for (unsigned int i = 0; i < argslen; i++)
-	{
-		memmove((th->bytes+argslen),(th->bytes),th->len);
-		th->bytes[i] = (uint8_t)args[i]->toInt();
-	}
-	return abstract_ui(th->getLength());
-}
-
-void Timer::sinit(Class_base* c)
-{
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<EventDispatcher>::getRef());
-	c->setDeclaredMethodByQName("currentCount","",Class<IFunction>::getFunction(_getCurrentCount),GETTER_METHOD,true);
-	c->setDeclaredMethodByQName("repeatCount","",Class<IFunction>::getFunction(_getRepeatCount),GETTER_METHOD,true);
-	c->setDeclaredMethodByQName("repeatCount","",Class<IFunction>::getFunction(_setRepeatCount),SETTER_METHOD,true);
-	c->setDeclaredMethodByQName("running","",Class<IFunction>::getFunction(_getRunning),GETTER_METHOD,true);
-	c->setDeclaredMethodByQName("delay","",Class<IFunction>::getFunction(_getDelay),GETTER_METHOD,true);
-	c->setDeclaredMethodByQName("delay","",Class<IFunction>::getFunction(_setDelay),SETTER_METHOD,true);
-	c->setDeclaredMethodByQName("start","",Class<IFunction>::getFunction(start),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("reset","",Class<IFunction>::getFunction(reset),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("stop","",Class<IFunction>::getFunction(stop),NORMAL_METHOD,true);
-}
-
-ASFUNCTIONBODY(Timer,_constructor)
-{
-	EventDispatcher::_constructor(obj,NULL,0);
-	Timer* th=static_cast<Timer*>(obj);
-
-	th->delay=args[0]->toInt();
-	if(argslen>=2)
-		th->repeatCount=args[1]->toInt();
-
-	return NULL;
-}
-
-ASFUNCTIONBODY(Timer,_getCurrentCount)
-{
-	Timer* th=static_cast<Timer*>(obj);
-	return abstract_i(th->currentCount);
-}
-
-ASFUNCTIONBODY(Timer,_getRepeatCount)
-{
-	Timer* th=static_cast<Timer*>(obj);
-	return abstract_i(th->repeatCount);
-}
-
-ASFUNCTIONBODY(Timer,_setRepeatCount)
-{
-	assert_and_throw(argslen==1);
-	int32_t count=args[0]->toInt();
-	Timer* th=static_cast<Timer*>(obj);
-	th->repeatCount=count;
-	if(th->repeatCount>0 && th->repeatCount<=th->currentCount)
-	{
-		getSys()->removeJob(th);
-		th->running=false;
-		th->tickJobInstance = NullRef;
-	}
-	return NULL;
-}
-
-ASFUNCTIONBODY(Timer,_getRunning)
-{
-	Timer* th=static_cast<Timer*>(obj);
-	return abstract_b(th->running);
-}
-
-ASFUNCTIONBODY(Timer,_getDelay)
-{
-	Timer* th=static_cast<Timer*>(obj);
-	return abstract_i(th->delay);
-}
-
-ASFUNCTIONBODY(Timer,_setDelay)
-{
-	assert_and_throw(argslen==1);
-	int32_t newdelay = args[0]->toInt();
-	if (newdelay<=0)
-		throw Class<RangeError>::getInstanceS("delay must be positive", 2066);
-
-	Timer* th=static_cast<Timer*>(obj);
-	th->delay=newdelay;
-
-	return NULL;
-}
-
-ASFUNCTIONBODY(Timer,start)
-{
-	Timer* th=static_cast<Timer*>(obj);
-	if(th->running)
-		return NULL;
-	th->running=true;
-	th->stopMe=false;
-	th->incRef();
-	th->tickJobInstance = _MNR(th);
-	if(th->repeatCount==1)
-		getSys()->addWait(th->delay,th);
-	else
-		getSys()->addTick(th->delay,th);
-	return NULL;
-}
-
-ASFUNCTIONBODY(Timer,reset)
-{
-	Timer* th=static_cast<Timer*>(obj);
-	if(th->running)
-	{
-		//This spin waits if the timer is running right now
-		getSys()->removeJob(th);
-		//NOTE: although no new events will be sent now there might be old events in the queue.
-		//Is this behaviour right?
-		//This is not anymore used by the timer, so it can die
-		th->tickJobInstance = NullRef;
-		th->running=false;
-	}
-	th->currentCount=0;
-	return NULL;
-}
 
-ASFUNCTIONBODY(Timer,stop)
-{
-	Timer* th=static_cast<Timer*>(obj);
-	if(th->running)
-	{
-		//This spin waits if the timer is running right now
-		getSys()->removeJob(th);
-		//NOTE: although no new events will be sent now there might be old events in the queue.
-		//Is this behaviour right?
-
-		//This is not anymore used by the timer, so it can die
-		th->tickJobInstance = NullRef;
-		th->running=false;
-	}
-	return NULL;
-}
 
 ASFUNCTIONBODY(lightspark,getQualifiedClassName)
 {
@@ -1492,11 +148,9 @@ ASFUNCTIONBODY(lightspark,getDefinitionByName)
 	ASObject* target;
 	ASObject* o=ABCVm::getCurrentApplicationDomain(getVm()->currentCallContext)->getVariableAndTargetByMultiname(name,target);
 
-	//TODO: should raise an exception, for now just return undefined	
 	if(o==NULL)
 	{
-		LOG(LOG_ERROR,_("Definition for '") << name << _("' not found."));
-		return getSys()->getUndefinedRef();
+		throwError<ReferenceError>(kClassNotFoundError, tmp);
 	}
 
 	assert_and_throw(o->getObjectType()==T_CLASS);
@@ -1518,430 +172,6 @@ ASFUNCTIONBODY(lightspark,getTimer)
 	return abstract_i(ret);
 }
 
-Dictionary::Dictionary(Class_base* c):ASObject(c),
-	data(std::less<dictType::key_type>(), reporter_allocator<dictType::value_type>(c->memoryAccount))
-{
-}
-
-void Dictionary::finalize()
-{
-	ASObject::finalize();
-	data.clear();
-}
-
-void Dictionary::sinit(Class_base* c)
-{
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<ASObject>::getRef());
-}
-
-void Dictionary::buildTraits(ASObject* o)
-{
-}
-
-ASFUNCTIONBODY(Dictionary,_constructor)
-{
-	return NULL;
-}
-
-Dictionary::dictType::iterator Dictionary::findKey(ASObject *o)
-{
-	Dictionary::dictType::iterator it = data.begin();
-	for(; it!=data.end(); ++it)
-	{
-		if (it->first->isEqualStrict(o))
-			return it;
-	}
-
-	return data.end();
-}
-
-void Dictionary::setVariableByMultiname_i(const multiname& name, int32_t value)
-{
-	assert_and_throw(implEnable);
-	Dictionary::setVariableByMultiname(name,abstract_i(value),CONST_NOT_ALLOWED);
-}
-
-void Dictionary::setVariableByMultiname(const multiname& name, ASObject* o, CONST_ALLOWED_FLAG allowConst)
-{
-	assert_and_throw(implEnable);
-	if(name.name_type==multiname::NAME_OBJECT)
-	{
-		name.name_o->incRef();
-		_R<ASObject> name_o(name.name_o);
-
-		Dictionary::dictType::iterator it=findKey(name_o.getPtr());
-		if(it!=data.end())
-			it->second=_MR(o);
-		else
-			data.insert(make_pair(name_o,_MR(o)));
-	}
-	else
-	{
-		//Primitive types _must_ be handled by the normal ASObject path
-		//REFERENCE: Dictionary Object on AS3 reference
-		assert(name.name_type==multiname::NAME_STRING ||
-			name.name_type==multiname::NAME_INT ||
-			name.name_type==multiname::NAME_NUMBER);
-		ASObject::setVariableByMultiname(name, o, allowConst);
-	}
-}
-
-bool Dictionary::deleteVariableByMultiname(const multiname& name)
-{
-	assert_and_throw(implEnable);
-
-	if(name.name_type==multiname::NAME_OBJECT)
-	{
-		name.name_o->incRef();
-		_R<ASObject> name_o(name.name_o);
-
-		Dictionary::dictType::iterator it=findKey(name_o.getPtr());
-		if(it != data.end())
-		{
-			data.erase(it);
-			return true;
-		}
-		return false;
-	}
-	else
-	{
-		//Primitive types _must_ be handled by the normal ASObject path
-		//REFERENCE: Dictionary Object on AS3 reference
-		assert(name.name_type==multiname::NAME_STRING ||
-			name.name_type==multiname::NAME_INT ||
-			name.name_type==multiname::NAME_NUMBER);
-		return ASObject::deleteVariableByMultiname(name);
-	}
-}
-
-_NR<ASObject> Dictionary::getVariableByMultiname(const multiname& name, GET_VARIABLE_OPTION opt)
-{
-	if((opt & ASObject::SKIP_IMPL)==0 && implEnable)
-	{
-		if(name.name_type==multiname::NAME_OBJECT)
-		{
-			name.name_o->incRef();
-			_R<ASObject> name_o(name.name_o);
-
-			Dictionary::dictType::iterator it=findKey(name_o.getPtr());
-			if(it != data.end())
-				return it->second;
-			else
-				return NullRef;
-		}
-		else
-		{
-			//Primitive types _must_ be handled by the normal ASObject path
-			//REFERENCE: Dictionary Object on AS3 reference
-			assert(name.name_type==multiname::NAME_STRING ||
-				name.name_type==multiname::NAME_INT ||
-				name.name_type==multiname::NAME_NUMBER);
-			return ASObject::getVariableByMultiname(name, opt);
-		}
-	}
-	//Try with the base implementation
-	return ASObject::getVariableByMultiname(name, opt);
-}
-
-bool Dictionary::hasPropertyByMultiname(const multiname& name, bool considerDynamic, bool considerPrototype)
-{
-	if(considerDynamic==false)
-		return ASObject::hasPropertyByMultiname(name, considerDynamic, considerPrototype);
-
-	if(name.name_type==multiname::NAME_OBJECT)
-	{
-		name.name_o->incRef();
-		_R<ASObject> name_o(name.name_o);
-
-		Dictionary::dictType::iterator it=findKey(name_o.getPtr());
-		return it != data.end();
-	}
-	else
-	{
-		//Primitive types _must_ be handled by the normal ASObject path
-		//REFERENCE: Dictionary Object on AS3 reference
-		assert(name.name_type==multiname::NAME_STRING ||
-			name.name_type==multiname::NAME_INT ||
-			name.name_type==multiname::NAME_NUMBER);
-		return ASObject::hasPropertyByMultiname(name, considerDynamic, considerPrototype);
-	}
-}
-
-uint32_t Dictionary::nextNameIndex(uint32_t cur_index)
-{
-	assert_and_throw(implEnable);
-	if(cur_index<data.size())
-		return cur_index+1;
-	else
-	{
-		//Fall back on object properties
-		uint32_t ret=ASObject::nextNameIndex(cur_index-data.size());
-		if(ret==0)
-			return 0;
-		else
-			return ret+data.size();
-
-	}
-}
-
-_R<ASObject> Dictionary::nextName(uint32_t index)
-{
-	assert_and_throw(implEnable);
-	if(index<=data.size())
-	{
-		map<_R<ASObject>,_R<ASObject> >::iterator it=data.begin();
-		for(unsigned int i=1;i<index;i++)
-			++it;
-
-		return it->first;
-	}
-	else
-	{
-		//Fall back on object properties
-		return ASObject::nextName(index-data.size());
-	}
-}
-
-_R<ASObject> Dictionary::nextValue(uint32_t index)
-{
-	assert_and_throw(implEnable);
-	if(index<=data.size())
-	{
-		map<_R<ASObject>,_R<ASObject> >::iterator it=data.begin();
-		for(unsigned int i=1;i<index;i++)
-			++it;
-
-		return it->second;
-	}
-	else
-	{
-		//Fall back on object properties
-		return ASObject::nextValue(index-data.size());
-	}
-}
-
-tiny_string Dictionary::toString()
-{
-	std::stringstream retstr;
-	retstr << "{";
-	map<_R<ASObject>,_R<ASObject> >::iterator it=data.begin();
-	while(it != data.end())
-	{
-		if(it != data.begin())
-			retstr << ", ";
-		retstr << "{" << it->first->toString() << ", " << it->second->toString() << "}";
-		++it;
-	}
-	retstr << "}";
-
-	return retstr.str();
-}
-
-void Proxy::sinit(Class_base* c)
-{
-	//c->constructor=Class<IFunction>::getFunction(_constructor);
-	c->setConstructor(NULL);
-}
-
-void Proxy::buildTraits(ASObject* o)
-{
-}
-
-void Proxy::setVariableByMultiname(const multiname& name, ASObject* o, CONST_ALLOWED_FLAG allowConst)
-{
-	//If a variable named like this already exist, use that
-	if(ASObject::hasPropertyByMultiname(name, true, false) || !implEnable)
-	{
-		ASObject::setVariableByMultiname(name,o,allowConst);
-		return;
-	}
-
-	//Check if there is a custom setter defined, skipping implementation to avoid recursive calls
-	multiname setPropertyName(NULL);
-	setPropertyName.name_type=multiname::NAME_STRING;
-	setPropertyName.name_s_id=getSys()->getUniqueStringId("setProperty");
-	setPropertyName.ns.push_back(nsNameAndKind(flash_proxy,NAMESPACE));
-	_NR<ASObject> proxySetter=getVariableByMultiname(setPropertyName,ASObject::SKIP_IMPL);
-
-	if(proxySetter.isNull())
-	{
-		ASObject::setVariableByMultiname(name,o,allowConst);
-		return;
-	}
-
-	assert_and_throw(proxySetter->getObjectType()==T_FUNCTION);
-
-	IFunction* f=static_cast<IFunction*>(proxySetter.getPtr());
-
-	//Well, I don't how to pass multiname to an as function. I'll just pass the name as a string
-	ASObject* args[2];
-	args[0]=Class<ASString>::getInstanceS(name.normalizedName());
-	args[1]=o;
-	//We now suppress special handling
-	implEnable=false;
-	LOG(LOG_CALLS,_("Proxy::setProperty"));
-	incRef();
-	_R<ASObject> ret=_MR( f->call(this,args,2) );
-	assert_and_throw(ret->is<Undefined>());
-	implEnable=true;
-}
-
-_NR<ASObject> Proxy::getVariableByMultiname(const multiname& name, GET_VARIABLE_OPTION opt)
-{
-	//It seems that various kind of implementation works only with the empty namespace
-	assert_and_throw(name.ns.size()>0);
-	if(!name.ns[0].hasEmptyName() || ASObject::hasPropertyByMultiname(name, true, true) || !implEnable || (opt & ASObject::SKIP_IMPL)!=0)
-		return ASObject::getVariableByMultiname(name,opt);
-
-	//Check if there is a custom getter defined, skipping implementation to avoid recursive calls
-	multiname getPropertyName(NULL);
-	getPropertyName.name_type=multiname::NAME_STRING;
-	getPropertyName.name_s_id=getSys()->getUniqueStringId("getProperty");
-	getPropertyName.ns.push_back(nsNameAndKind(flash_proxy,NAMESPACE));
-	_NR<ASObject> o=getVariableByMultiname(getPropertyName,ASObject::SKIP_IMPL);
-
-	if(o.isNull())
-		return ASObject::getVariableByMultiname(name,opt);
-
-	assert_and_throw(o->getObjectType()==T_FUNCTION);
-
-	IFunction* f=static_cast<IFunction*>(o.getPtr());
-
-	//Well, I don't how to pass multiname to an as function. I'll just pass the name as a string
-	ASObject* arg=Class<ASString>::getInstanceS(name.normalizedName());
-	//We now suppress special handling
-	implEnable=false;
-	LOG(LOG_CALLS,"Proxy::getProperty");
-	incRef();
-	_NR<ASObject> ret=_MNR(f->call(this,&arg,1));
-	implEnable=true;
-	return ret;
-}
-
-bool Proxy::hasPropertyByMultiname(const multiname& name, bool considerDynamic, bool considerPrototype)
-{
-	//If a variable named like this already exist, use that
-	bool asobject_has_property=ASObject::hasPropertyByMultiname(name, considerDynamic, considerPrototype);
-	if(asobject_has_property || !implEnable)
-		return asobject_has_property;
-
-	//Check if there is a custom hasProperty defined, skipping implementation to avoid recursive calls
-	multiname hasPropertyName(NULL);
-	hasPropertyName.name_type=multiname::NAME_STRING;
-	hasPropertyName.name_s_id=getSys()->getUniqueStringId("hasProperty");
-	hasPropertyName.ns.push_back(nsNameAndKind(flash_proxy,NAMESPACE));
-	_NR<ASObject> proxyHasProperty=getVariableByMultiname(hasPropertyName,ASObject::SKIP_IMPL);
-
-	if(proxyHasProperty.isNull())
-	{
-		return false;
-	}
-
-	assert_and_throw(proxyHasProperty->getObjectType()==T_FUNCTION);
-
-	IFunction* f=static_cast<IFunction*>(proxyHasProperty.getPtr());
-
-	//Well, I don't how to pass multiname to an as function. I'll just pass the name as a string
-	ASObject* arg=Class<ASString>::getInstanceS(name.normalizedName());
-	//We now suppress special handling
-	implEnable=false;
-	LOG(LOG_CALLS,_("Proxy::hasProperty"));
-	incRef();
-	_NR<ASObject> ret=_MNR(f->call(this,&arg,1));
-	implEnable=true;
-	Boolean* b = static_cast<Boolean*>(ret.getPtr());
-	return b->val;
-}
-bool Proxy::deleteVariableByMultiname(const multiname& name)
-{
-	//If a variable named like this already exist, use that
-	if(ASObject::hasPropertyByMultiname(name, true, false) || !implEnable)
-	{
-		return ASObject::deleteVariableByMultiname(name);
-	}
-
-	//Check if there is a custom deleter defined, skipping implementation to avoid recursive calls
-	multiname deletePropertyName(NULL);
-	deletePropertyName.name_type=multiname::NAME_STRING;
-	deletePropertyName.name_s_id=getSys()->getUniqueStringId("deleteProperty");
-	deletePropertyName.ns.push_back(nsNameAndKind(flash_proxy,NAMESPACE));
-	_NR<ASObject> proxyDeleter=getVariableByMultiname(deletePropertyName,ASObject::SKIP_IMPL);
-
-	if(proxyDeleter.isNull())
-	{
-		return ASObject::deleteVariableByMultiname(name);
-	}
-
-	assert_and_throw(proxyDeleter->getObjectType()==T_FUNCTION);
-
-	IFunction* f=static_cast<IFunction*>(proxyDeleter.getPtr());
-
-	//Well, I don't how to pass multiname to an as function. I'll just pass the name as a string
-	ASObject* arg=Class<ASString>::getInstanceS(name.normalizedName());
-	//We now suppress special handling
-	implEnable=false;
-	LOG(LOG_CALLS,_("Proxy::deleteProperty"));
-	incRef();
-	_NR<ASObject> ret=_MNR(f->call(this,&arg,1));
-	implEnable=true;
-	Boolean* b = static_cast<Boolean*>(ret.getPtr());
-	return b->val;
-}
-
-uint32_t Proxy::nextNameIndex(uint32_t cur_index)
-{
-	assert_and_throw(implEnable);
-	LOG(LOG_CALLS,"Proxy::nextNameIndex");
-	//Check if there is a custom enumerator, skipping implementation to avoid recursive calls
-	multiname nextNameIndexName(NULL);
-	nextNameIndexName.name_type=multiname::NAME_STRING;
-	nextNameIndexName.name_s_id=getSys()->getUniqueStringId("nextNameIndex");
-	nextNameIndexName.ns.push_back(nsNameAndKind(flash_proxy,NAMESPACE));
-	_NR<ASObject> o=getVariableByMultiname(nextNameIndexName,ASObject::SKIP_IMPL);
-	assert_and_throw(!o.isNull() && o->getObjectType()==T_FUNCTION);
-	IFunction* f=static_cast<IFunction*>(o.getPtr());
-	ASObject* arg=abstract_i(cur_index);
-	this->incRef();
-	ASObject* ret=f->call(this,&arg,1);
-	uint32_t newIndex=ret->toInt();
-	ret->decRef();
-	return newIndex;
-}
-
-_R<ASObject> Proxy::nextName(uint32_t index)
-{
-	assert_and_throw(implEnable);
-	LOG(LOG_CALLS, _("Proxy::nextName"));
-	//Check if there is a custom enumerator, skipping implementation to avoid recursive calls
-	multiname nextNameName(NULL);
-	nextNameName.name_type=multiname::NAME_STRING;
-	nextNameName.name_s_id=getSys()->getUniqueStringId("nextName");
-	nextNameName.ns.push_back(nsNameAndKind(flash_proxy,NAMESPACE));
-	_NR<ASObject> o=getVariableByMultiname(nextNameName,ASObject::SKIP_IMPL);
-	assert_and_throw(!o.isNull() && o->getObjectType()==T_FUNCTION);
-	IFunction* f=static_cast<IFunction*>(o.getPtr());
-	ASObject* arg=abstract_i(index);
-	incRef();
-	return _MR(f->call(this,&arg,1));
-}
-
-_R<ASObject> Proxy::nextValue(uint32_t index)
-{
-	assert_and_throw(implEnable);
-	LOG(LOG_CALLS, _("Proxy::nextValue"));
-	//Check if there is a custom enumerator, skipping implementation to avoid recursive calls
-	multiname nextValueName(NULL);
-	nextValueName.name_type=multiname::NAME_STRING;
-	nextValueName.name_s_id=getSys()->getUniqueStringId("nextValue");
-	nextValueName.ns.push_back(nsNameAndKind(flash_proxy,NAMESPACE));
-	_NR<ASObject> o=getVariableByMultiname(nextValueName,ASObject::SKIP_IMPL);
-	assert_and_throw(!o.isNull() && o->getObjectType()==T_FUNCTION);
-	IFunction* f=static_cast<IFunction*>(o.getPtr());
-	ASObject* arg=abstract_i(index);
-	incRef();
-	return _MR(f->call(this,&arg,1));
-}
 
 ASFUNCTIONBODY(lightspark,setInterval)
 {
@@ -2003,117 +233,15 @@ ASFUNCTIONBODY(lightspark,clearTimeout)
 	return NULL;
 }
 
-IntervalRunner::IntervalRunner(IntervalRunner::INTERVALTYPE _type, uint32_t _id, _R<IFunction> _callback, ASObject** _args,
-		const unsigned int _argslen, _R<ASObject> _obj, uint32_t _interval):
-	EventDispatcher(NULL),type(_type), id(_id), callback(_callback),obj(_obj),argslen(_argslen),interval(_interval)
-{
-	args = new ASObject*[argslen];
-	for(uint32_t i=0; i<argslen; i++)
-		args[i] = _args[i];
-}
-
-IntervalRunner::~IntervalRunner()
-{
-	for(uint32_t i=0; i<argslen; i++)
-		args[i]->decRef();
-	delete[] args;
-}
-
-void IntervalRunner::tick() 
-{
-	//incRef all arguments
-	uint32_t i;
-	for(i=0; i < argslen; i++)
-	{
-		args[i]->incRef();
-	}
-	_R<FunctionEvent> event(new (getSys()->unaccountedMemory) FunctionEvent(callback, obj, args, argslen));
-	getVm()->addEvent(NullRef,event);
-	if(type == TIMEOUT)
-	{
-		//TODO: IntervalRunner deletes itself. Is this allowed?
-		//Delete ourselves from the active intervals list
-		getSys()->intervalManager->clearInterval(id, TIMEOUT, false);
-		//No actions may be performed after this point
-	}
-}
-
-void IntervalRunner::tickFence()
-{
-	delete this;
-}
-
-IntervalManager::IntervalManager() : currentID(1)
-{
-}
-
-IntervalManager::~IntervalManager()
-{
-	//Run through all running intervals and remove their tickjob, delete their intervalRunner and erase their entry
-	std::map<uint32_t,IntervalRunner*>::iterator it = runners.begin();
-	while(it != runners.end())
-	{
-		getSys()->removeJob((*it).second);
-		runners.erase(it++);
-	}
-}
-
-uint32_t IntervalManager::setInterval(_R<IFunction> callback, ASObject** args, const unsigned int argslen, _R<ASObject> obj, uint32_t interval)
-{
-	Mutex::Lock l(mutex);
-
-	uint32_t id = getFreeID();
-	IntervalRunner* runner = new (getSys()->unaccountedMemory)
-		IntervalRunner(IntervalRunner::INTERVAL, id, callback, args, argslen, obj, interval);
-
-	//Add runner as tickjob
-	getSys()->addTick(interval, runner);
-	//Add runner to map
-	runners[id] = runner;
-	//Increment currentID
-	currentID++;
-
-	return currentID-1;
-}
-uint32_t IntervalManager::setTimeout(_R<IFunction> callback, ASObject** args, const unsigned int argslen, _R<ASObject> obj, uint32_t interval)
-{
-	Mutex::Lock l(mutex);
-
-	uint32_t id = getFreeID();
-	IntervalRunner* runner = new (getSys()->unaccountedMemory)
-		IntervalRunner(IntervalRunner::TIMEOUT, id, callback, args, argslen, obj, interval);
-
-	//Add runner as waitjob
-	getSys()->addWait(interval, runner);
-	//Add runner to map
-	runners[id] = runner;
-	//increment currentID
-	currentID++;
-
-	return currentID-1;
-}
-
-uint32_t IntervalManager::getFreeID()
+ASFUNCTIONBODY(lightspark,escapeMultiByte)
 {
-	//At the first run every currentID will be available. But eventually the currentID will wrap around.
-	//Thats why we need to check if the currentID isn't used yet
-	while(currentID == 0 || runners.count(currentID) != 0)
-		currentID++;
-	return currentID;
+	tiny_string str;
+	ARG_UNPACK (str, "undefined");
+	return Class<ASString>::getInstanceS(URLInfo::encode(str, URLInfo::ENCODE_ESCAPE));
 }
-
-void IntervalManager::clearInterval(uint32_t id, IntervalRunner::INTERVALTYPE type, bool removeJob)
+ASFUNCTIONBODY(lightspark,unescapeMultiByte)
 {
-	Mutex::Lock l(mutex);
-
-	std::map<uint32_t,IntervalRunner*>::iterator it = runners.find(id);
-	//If the entry exists and the types match, remove its tickjob, delete its intervalRunner and erase their entry
-	if(it != runners.end() && (*it).second->getType() == type)
-	{
-		if(removeJob)
-		{
-			getSys()->removeJob((*it).second);
-		}
-		runners.erase(it);
-	}
+	tiny_string str;
+	ARG_UNPACK (str, "undefined");
+	return Class<ASString>::getInstanceS(URLInfo::decode(str, URLInfo::ENCODE_ESCAPE));
 }
diff --git a/src/scripting/flash/utils/flashutils.h b/src/scripting/flash/utils/flashutils.h
index 7b62359..29b4a47 100644
--- a/src/scripting/flash/utils/flashutils.h
+++ b/src/scripting/flash/utils/flashutils.h
@@ -22,11 +22,8 @@
 
 #include "compat.h"
 #include "swftypes.h"
-#include "scripting/flash/events/flashevents.h"
-#include "thread_pool.h"
-#include "timer.h"
+#include "asobject.h"
 
-#include <map>
 
 namespace lightspark
 {
@@ -59,203 +56,7 @@ public:
 	static void linkTraits(Class_base* c);
 };
 
-class ByteArray: public ASObject, public IDataInput, public IDataOutput
-{
-friend class LoaderThread;
-friend class URLLoader;
-protected:
-	bool littleEndian;
-	uint8_t objectEncoding;
-	uint32_t position;
-	uint8_t* bytes;
-	uint32_t real_len;
-	uint32_t len;
-	void compress_zlib();
-	void uncompress_zlib();
-public:
-	ByteArray(Class_base* c, uint8_t* b = NULL, uint32_t l = 0);
-	~ByteArray();
-	//Helper interface for serialization
-	bool readByte(uint8_t& b);
-	bool readShort(uint16_t& ret);
-	bool readUnsignedInt(uint32_t& ret);
-	bool readU29(uint32_t& ret);
-	bool readUTF(tiny_string& ret);
-	void writeByte(uint8_t b);
-	void writeShort(uint16_t val);
-	void writeUnsignedInt(uint32_t val);
-	void writeUTF(const tiny_string& str);
-	uint32_t writeObject(ASObject* obj);
-	void writeStringVR(std::map<tiny_string, uint32_t>& stringMap, const tiny_string& s);
-	void writeXMLString(std::map<const ASObject*, uint32_t>& objMap, ASObject *xml, const tiny_string& s);
-	void writeU29(uint32_t val);
-	uint32_t getPosition() const;
-	void setPosition(uint32_t p);
-
-	ASFUNCTION(_getBytesAvailable);
-	ASFUNCTION(_getLength);
-	ASFUNCTION(_setLength);
-	ASFUNCTION(_getPosition);
-	ASFUNCTION(_setPosition);
-	ASFUNCTION(_getEndian);
-	ASFUNCTION(_setEndian);
-	ASFUNCTION(_getObjectEncoding);
-	ASFUNCTION(_setObjectEncoding);
-	ASFUNCTION(_getDefaultObjectEncoding);
-	ASFUNCTION(_setDefaultObjectEncoding);
-	ASFUNCTION(_compress);
-	ASFUNCTION(_uncompress);
-	ASFUNCTION(_deflate);
-	ASFUNCTION(_inflate);
-	ASFUNCTION(clear);
-	ASFUNCTION(readBoolean);
-	ASFUNCTION(readByte);
-	ASFUNCTION(readBytes);
-	ASFUNCTION(readDouble);
-	ASFUNCTION(readFloat);
-	ASFUNCTION(readInt);
-	ASFUNCTION(readMultiByte);
-	ASFUNCTION(readObject);
-	ASFUNCTION(readShort);
-	ASFUNCTION(readUnsignedByte);
-	ASFUNCTION(readUnsignedInt);
-	ASFUNCTION(readUnsignedShort);
-	ASFUNCTION(readUTF);
-	ASFUNCTION(readUTFBytes);
-	ASFUNCTION(writeBoolean);
-	ASFUNCTION(writeByte);
-	ASFUNCTION(writeBytes);
-	ASFUNCTION(writeDouble);
-	ASFUNCTION(writeFloat);
-	ASFUNCTION(writeInt);
-	ASFUNCTION(writeUnsignedInt);
-	ASFUNCTION(writeMultiByte);
-	ASFUNCTION(writeObject);
-	ASFUNCTION(writeShort);
-	ASFUNCTION(writeUTF);
-	ASFUNCTION(writeUTFBytes);
-	ASFUNCTION(_toString);
-
-	// these are internal methods used if the generic Array-Methods are called on a ByteArray
-	ASFUNCTION(pop);
-	ASFUNCTION(push);
-	ASFUNCTION(shift);
-	ASFUNCTION(unshift);
-	/**
-		Get ownership over the passed buffer
-		@param buf Pointer to the buffer to acquire, ownership and delete authority is acquired
-		@param bufLen Lenght of the buffer
-		@pre buf must be allocated using new[]
-	*/
-	void acquireBuffer(uint8_t* buf, int bufLen);
-	uint8_t* getBuffer(unsigned int size, bool enableResize);
-	uint32_t getLength() const { return len; }
-
-	uint16_t endianIn(uint16_t value);
-	uint32_t endianIn(uint32_t value);
-	uint64_t endianIn(uint64_t value);
-
-	uint16_t endianOut(uint16_t value);
-	uint32_t endianOut(uint32_t value);
-	uint64_t endianOut(uint64_t value);
-
-	static void sinit(Class_base* c);
-	static void buildTraits(ASObject* o);
-	_NR<ASObject> getVariableByMultiname(const multiname& name, GET_VARIABLE_OPTION opt=NONE);
-	int32_t getVariableByMultiname_i(const multiname& name);
-	void setVariableByMultiname(const multiname& name, ASObject* o, CONST_ALLOWED_FLAG allowConst);
-	void setVariableByMultiname_i(const multiname& name, int32_t value);
-	bool hasPropertyByMultiname(const multiname& name, bool considerDynamic, bool considerPrototype);
-};
 
-class Timer: public EventDispatcher, public ITickJob
-{
-private:
-	void tick();
-	void tickFence();
-	//tickJobInstance keeps a reference to self while this
-	//instance is being used by the timer thread.
-	_NR<Timer> tickJobInstance;
-protected:
-	bool running;
-	uint32_t delay;
-	uint32_t repeatCount;
-	uint32_t currentCount;
-public:
-	Timer(Class_base* c):EventDispatcher(c),running(false),delay(0),repeatCount(0),currentCount(0){};
-	static void sinit(Class_base* c);
-	ASFUNCTION(_constructor);
-	ASFUNCTION(_getCurrentCount);
-	ASFUNCTION(_getRepeatCount);
-	ASFUNCTION(_setRepeatCount);
-	ASFUNCTION(_getRunning);
-	ASFUNCTION(_getDelay);
-	ASFUNCTION(_setDelay);
-	ASFUNCTION(start);
-	ASFUNCTION(reset);
-	ASFUNCTION(stop);
-};
-
-class Dictionary: public ASObject
-{
-friend class ABCVm;
-private:
-	typedef std::map<_R<ASObject>,_R<ASObject>,std::less<_R<ASObject>>,
-	       reporter_allocator<std::pair<const _R<ASObject>, _R<ASObject>>>> dictType;
-	dictType data;
-	dictType::iterator findKey(ASObject *);
-public:
-	Dictionary(Class_base* c);
-	void finalize();
-	static void sinit(Class_base*);
-	static void buildTraits(ASObject* o);
-	ASFUNCTION(_constructor);
-	_NR<ASObject> getVariableByMultiname(const multiname& name, GET_VARIABLE_OPTION opt=NONE);
-	int32_t getVariableByMultiname_i(const multiname& name)
-	{
-		assert_and_throw(implEnable);
-		throw UnsupportedException("getVariableByMultiName_i not supported for Dictionary");
-	}
-	void setVariableByMultiname(const multiname& name, ASObject* o, CONST_ALLOWED_FLAG allowConst);
-	void setVariableByMultiname_i(const multiname& name, int32_t value);
-	bool deleteVariableByMultiname(const multiname& name);
-	bool hasPropertyByMultiname(const multiname& name, bool considerDynamic, bool considerPrototype);
-	tiny_string toString();
-	uint32_t nextNameIndex(uint32_t cur_index);
-	_R<ASObject> nextName(uint32_t index);
-	_R<ASObject> nextValue(uint32_t index);
-};
-
-class Proxy: public ASObject
-{
-friend class ABCVm;
-public:
-	Proxy(Class_base* c):ASObject(c){}
-	static void sinit(Class_base*);
-	static void buildTraits(ASObject* o);
-//	ASFUNCTION(_constructor);
-	_NR<ASObject> getVariableByMultiname(const multiname& name, GET_VARIABLE_OPTION opt=NONE);
-	int32_t getVariableByMultiname_i(const multiname& name)
-	{
-		assert_and_throw(implEnable);
-		throw UnsupportedException("getVariableByMultiName_i not supported for Proxy");
-	}
-	void setVariableByMultiname(const multiname& name, ASObject* o, CONST_ALLOWED_FLAG allowConst);
-	void setVariableByMultiname_i(const multiname& name, int32_t value)
-	{
-		setVariableByMultiname(name,abstract_i(value),CONST_NOT_ALLOWED);
-	}
-	
-	bool deleteVariableByMultiname(const multiname& name);
-	bool hasPropertyByMultiname(const multiname& name, bool considerDynamic, bool considerPrototype);
-	tiny_string toString()
-	{
-		throw UnsupportedException("Proxy is missing some stuff");
-	}
-	uint32_t nextNameIndex(uint32_t cur_index);
-	_R<ASObject> nextName(uint32_t index);
-	_R<ASObject> nextValue(uint32_t index);
-};
 
 ASObject* getQualifiedClassName(ASObject*, ASObject* const* args, const unsigned int len);
 ASObject* getQualifiedSuperclassName(ASObject*, ASObject* const* args, const unsigned int len);
@@ -266,45 +67,9 @@ ASObject* setTimeout(ASObject* obj,ASObject* const* args, const unsigned int arg
 ASObject* clearInterval(ASObject* obj,ASObject* const* args, const unsigned int argslen);
 ASObject* clearTimeout(ASObject* obj,ASObject* const* args, const unsigned int argslen);
 ASObject* describeType(ASObject* obj,ASObject* const* args, const unsigned int argslen);
+ASObject* escapeMultiByte(ASObject* obj,ASObject* const* args, const unsigned int argslen);
+ASObject* unescapeMultiByte(ASObject* obj,ASObject* const* args, const unsigned int argslen);
 
-class IntervalRunner : public ITickJob, public EventDispatcher
-{
-public:
-	enum INTERVALTYPE { INTERVAL, TIMEOUT };
-private:
-	// IntervalRunner will delete itself in tickFence, others
-	// should not call the destructor.
-	~IntervalRunner();
-	INTERVALTYPE type;
-	uint32_t id;
-	_R<IFunction> callback;
-	ASObject** args;
-	_R<ASObject> obj;
-	const unsigned int argslen;
-	uint32_t interval;
-public:
-	IntervalRunner(INTERVALTYPE _type, uint32_t _id, _R<IFunction> _callback, ASObject** _args,
-			const unsigned int _argslen, _R<ASObject> _obj, const uint32_t _interval);
-	void tick();
-	void tickFence();
-	INTERVALTYPE getType() { return type; }
-};
-
-class IntervalManager
-{
-private:
-	Mutex mutex;
-	std::map<uint32_t,IntervalRunner*> runners;
-	uint32_t currentID;
-public:
-	IntervalManager();
-	~IntervalManager();
-	uint32_t setInterval(_R<IFunction> callback, ASObject** args, const unsigned int argslen, _R<ASObject> obj, const uint32_t interval);
-	uint32_t setTimeout(_R<IFunction> callback, ASObject** args, const unsigned int argslen, _R<ASObject> obj, const uint32_t interval);
-	uint32_t getFreeID();
-	void clearInterval(uint32_t id, IntervalRunner::INTERVALTYPE type, bool removeJob);
-};
-
-};
+}
 
 #endif /* SCRIPTING_FLASH_UTILS_FLASHUTILS_H */
diff --git a/src/scripting/flash/xml/flashxml.cpp b/src/scripting/flash/xml/flashxml.cpp
index 3d0f0e7..6fcd102 100644
--- a/src/scripting/flash/xml/flashxml.cpp
+++ b/src/scripting/flash/xml/flashxml.cpp
@@ -20,6 +20,7 @@
 #include <libxml++/nodes/textnode.h>
 
 #include "scripting/flash/xml/flashxml.h"
+#include "scripting/flash/utils/ByteArray.h"
 #include "swf.h"
 #include "compat.h"
 #include "scripting/argconv.h"
@@ -40,8 +41,7 @@ void XMLNode::finalize()
 
 void XMLNode::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<ASObject>::getRef());
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_SEALED);
 	c->setDeclaredMethodByQName("toString","",Class<IFunction>::getFunction(_toString),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("attributes","",Class<IFunction>::getFunction(attributes),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("childNodes","",Class<IFunction>::getFunction(XMLNode::childNodes),GETTER_METHOD,true);
@@ -262,8 +262,7 @@ XMLDocument::XMLDocument(Class_base* c, tiny_string s)
 
 void XMLDocument::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<XMLNode>::getRef());
+	CLASS_SETUP(c, XMLNode, _constructor, CLASS_SEALED);
 	c->setDeclaredMethodByQName("parseXML","",Class<IFunction>::getFunction(parseXML),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("toString","",Class<IFunction>::getFunction(_toString),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("firstChild","",Class<IFunction>::getFunction(XMLDocument::firstChild),GETTER_METHOD,true);
@@ -298,7 +297,8 @@ void XMLDocument::serialize(ByteArray* out, std::map<tiny_string, uint32_t>& str
 
 void XMLDocument::parseXMLImpl(const string& str)
 {
-	rootNode=buildFromString(str, ignoreWhite);
+	bool hasParent;
+	rootNode=buildFromString(str, ignoreWhite,&hasParent);
 }
 
 ASFUNCTIONBODY(XMLDocument,_toString)
diff --git a/src/scripting/toplevel/ASString.cpp b/src/scripting/toplevel/ASString.cpp
index 10afb69..d4fb11c 100644
--- a/src/scripting/toplevel/ASString.cpp
+++ b/src/scripting/toplevel/ASString.cpp
@@ -20,6 +20,7 @@
 #include <pcre.h>
 
 #include "scripting/toplevel/ASString.h"
+#include "scripting/flash/utils/ByteArray.h"
 #include "compat.h"
 #include "scripting/argconv.h"
 #include "parsing/amf3_generator.h"
@@ -63,7 +64,7 @@ ASFUNCTIONBODY(ASString,_constructor)
 {
 	ASString* th=static_cast<ASString*>(obj);
 	if(args && argslen==1)
-		th->data=args[0]->toString().raw_buf();
+		th->data=args[0]->toString();
 	return NULL;
 }
 
@@ -74,9 +75,7 @@ ASFUNCTIONBODY(ASString,_getLength)
 
 void ASString::sinit(Class_base* c)
 {
-	c->isFinal = true;
-	c->setSuper(Class<ASObject>::getRef());
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_FINAL | CLASS_SEALED);
 	c->setDeclaredMethodByQName("split",AS3,Class<IFunction>::getFunction(split,2),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("substr",AS3,Class<IFunction>::getFunction(substr,2),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("substring",AS3,Class<IFunction>::getFunction(substring,2),NORMAL_METHOD,true);
@@ -93,6 +92,7 @@ void ASString::sinit(Class_base* c)
 	c->setDeclaredMethodByQName("toLocaleUpperCase",AS3,Class<IFunction>::getFunction(toUpperCase),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("toLowerCase",AS3,Class<IFunction>::getFunction(toLowerCase),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("toUpperCase",AS3,Class<IFunction>::getFunction(toUpperCase),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("localeCompare",AS3,Class<IFunction>::getFunction(localeCompare),NORMAL_METHOD,true);
 	// According to specs fromCharCode belongs to AS3 namespace,
 	// but also empty namespace is seen in the wild and should be
 	// supported.
@@ -120,6 +120,7 @@ void ASString::sinit(Class_base* c)
 	c->prototype->setVariableByQName("toUpperCase","",Class<IFunction>::getFunction(toUpperCase),DYNAMIC_TRAIT);
 	c->prototype->setVariableByQName("toString","",Class<IFunction>::getFunction(_toString),DYNAMIC_TRAIT);
 	c->prototype->setVariableByQName("valueOf","",Class<IFunction>::getFunction(_toString),DYNAMIC_TRAIT);
+	c->prototype->setVariableByQName("localeCompare","",Class<IFunction>::getFunction(localeCompare_prototype),DYNAMIC_TRAIT);
 }
 
 void ASString::buildTraits(ASObject* o)
@@ -456,35 +457,70 @@ double ASString::toNumber() const
 {
 	assert_and_throw(implEnable);
 
-	/* TODO: data holds a utf8-character sequence, not ascii! */
-	const char *s=data.raw_buf();
-	char *end=NULL;
-	while(g_ascii_isspace(*s))
-		s++;
-	double val=g_ascii_strtod(s, &end);
-
-	// strtod converts case-insensitive "inf" and "infinity" to
-	// inf, flash only accepts case-sensitive "Infinity".
-	if(std::isinf(val)) {
-		const char *tmp=s;
-		while(g_ascii_isspace(*tmp))
-			tmp++;
-		if(*tmp=='+' || *tmp=='-')
-			tmp++;
-		if(strncasecmp(tmp, "inf", 3)==0 && strcmp(tmp, "Infinity")!=0)
+	const char *s = data.raw_buf();
+	while (*s && isEcmaSpace(g_utf8_get_char(s)))
+		s = g_utf8_next_char(s);
+
+	double val;
+	char *end = NULL;
+	val = parseStringInfinite(s, &end);
+
+	// If did not parse as infinite, try decimal
+	if (!std::isinf(val))
+	{
+		errno = 0;
+		val = g_ascii_strtod(s, &end);
+
+		if (errno == ERANGE)
+		{
+			if (val == HUGE_VAL)
+				val = numeric_limits<double>::infinity();
+			else if (val == -HUGE_VAL)
+				val = -numeric_limits<double>::infinity();
+		}
+		else if (std::isinf(val))
+		{
+			// strtod accepts values such as "inf" and lowercase
+			// "infinity" which are not valid values in Flash
 			return numeric_limits<double>::quiet_NaN();
+		}
 	}
 
 	// Fail if there is any rubbish after the converted number
 	while(*end) {
-		if(!g_ascii_isspace(*end))
+		if(!isEcmaSpace(g_utf8_get_char(end)))
 			return numeric_limits<double>::quiet_NaN();
-		end++;
+		end = g_utf8_next_char(end);
 	}
 
 	return val;
 }
 
+number_t ASString::parseStringInfinite(const char *s, char **end) const
+{
+	if (end)
+		*end = const_cast<char *>(s);
+	double sign = 1.;
+	if (*s == '+')
+	{
+		sign = +1.;
+		s++;
+	}
+	else if (*s == '-')
+	{
+		sign = -1.;
+		s++;
+	}
+	if (strncmp(s, "Infinity", 8) == 0)
+	{
+		if (end)
+			*end = const_cast<char *>(s+8);
+		return sign*numeric_limits<double>::infinity();
+	}
+
+	return 0.; // not an infinite value
+}
+
 int32_t ASString::toInt()
 {
 	assert_and_throw(implEnable);
@@ -504,6 +540,8 @@ bool ASString::isEqual(ASObject* r)
 	{
 		case T_STRING:
 		{
+			if (!this->isConstructed())
+				return !r->isConstructed();
 			const ASString* s=static_cast<const ASString*>(r);
 			return s->data==data;
 		}
@@ -514,6 +552,8 @@ bool ASString::isEqual(ASObject* r)
 			return toNumber()==r->toNumber();
 		case T_NULL:
 		case T_UNDEFINED:
+			if (!this->isConstructed())
+				return true;
 			return false;
 		default:
 			return r->isEqual(this);
@@ -654,6 +694,27 @@ ASFUNCTIONBODY(ASString,toUpperCase)
 	tiny_string data = obj->toString();
 	return Class<ASString>::getInstanceS(data.uppercase());
 }
+ASFUNCTIONBODY(ASString,localeCompare)
+{
+	tiny_string data = obj->toString();
+	tiny_string other;
+	ARG_UNPACK_MORE_ALLOWED(other);
+	if (argslen > 1)
+		LOG(LOG_NOT_IMPLEMENTED,"localeCompare with more than one parameter not implemented");
+	int ret = data.compare(other);
+	return abstract_i(ret);
+}
+ASFUNCTIONBODY(ASString,localeCompare_prototype)
+{
+	tiny_string data = obj->toString();
+	tiny_string other;
+	ARG_UNPACK_MORE_ALLOWED(other);
+	if (argslen > 1)
+		throwError<ArgumentError>(kWrongArgumentCountError, "localeCompare", "1",Integer::toString(argslen));
+
+	int ret = data.compare(other);
+	return abstract_i(ret);
+}
 
 ASFUNCTIONBODY(ASString,fromCharCode)
 {
@@ -819,3 +880,17 @@ ASFUNCTIONBODY(ASString,generator)
 	else
 		return Class<ASString>::getInstanceS(args[0]->toString());
 }
+
+bool ASString::isEcmaSpace(uint32_t c)
+{
+	return (c == 0x09) || (c == 0x0B) || (c == 0x0C) || (c == 0x20) ||
+		(c == 0xA0) || (c == 0x1680) || (c == 0x180E) ||
+		((c >= 0x2000) && (c <= 0x200B)) || (c == 0x202F) ||
+		(c == 0x205F) || (c == 0x3000) || (c == 0xFEFF) || 
+		isEcmaLineTerminator(c);
+}
+
+bool ASString::isEcmaLineTerminator(uint32_t c)
+{
+	return (c == 0x0A) || (c == 0x0D) || (c == 0x2028) || (c == 0x2029);
+}
diff --git a/src/scripting/toplevel/ASString.h b/src/scripting/toplevel/ASString.h
index 4733829..ab25958 100644
--- a/src/scripting/toplevel/ASString.h
+++ b/src/scripting/toplevel/ASString.h
@@ -34,6 +34,7 @@ class ASString: public ASObject
 {
 private:
 	tiny_string toString_priv() const;
+	number_t parseStringInfinite(const char *s, char **end) const;
 public:
 	ASString(Class_base* c);
 	ASString(Class_base* c, const std::string& s);
@@ -62,6 +63,8 @@ public:
 	ASFUNCTION(toUpperCase);
 	ASFUNCTION(_toString);
 	ASFUNCTION(_getLength);
+	ASFUNCTION(localeCompare);
+	ASFUNCTION(localeCompare_prototype);
 	bool isEqual(ASObject* r);
 	TRISTATE isLess(ASObject* r);
 	number_t toNumber() const;
@@ -73,6 +76,8 @@ public:
 				std::map<const ASObject*, uint32_t>& objMap,
 				std::map<const Class_base*, uint32_t>& traitsMap);
 	std::string toDebugString() { return std::string("\"") + std::string(data) + "\""; }
+	static bool isEcmaSpace(uint32_t c);
+	static bool isEcmaLineTerminator(uint32_t c);
 };
 
 template<>
@@ -85,6 +90,8 @@ inline ASObject* Class<ASString>::coerce(ASObject* o) const
 		o->decRef();
 		return getSys()->getNullRef();
 	}
+	if(!o->isConstructed())
+		return o;
 	tiny_string n = o->toString();
 	o->decRef();
 	return Class<ASString>::getInstanceS(n);
diff --git a/src/scripting/toplevel/Array.cpp b/src/scripting/toplevel/Array.cpp
index 2dd5f36..8a7f1c8 100644
--- a/src/scripting/toplevel/Array.cpp
+++ b/src/scripting/toplevel/Array.cpp
@@ -37,10 +37,7 @@ Array::Array(Class_base* c):ASObject(c),
 
 void Array::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	// public constants
-	c->setSuper(Class<ASObject>::getRef());
-
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_DYNAMIC_NOT_FINAL);
 	c->setVariableByQName("CASEINSENSITIVE","",abstract_d(CASEINSENSITIVE),CONSTANT_TRAIT);
 	c->setVariableByQName("DESCENDING","",abstract_d(DESCENDING),CONSTANT_TRAIT);
 	c->setVariableByQName("NUMERIC","",abstract_d(NUMERIC),CONSTANT_TRAIT);
@@ -53,39 +50,47 @@ void Array::sinit(Class_base* c)
 
 	// public functions
 	c->setDeclaredMethodByQName("concat",AS3,Class<IFunction>::getFunction(_concat,1),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("every",AS3,Class<IFunction>::getFunction(every),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("filter",AS3,Class<IFunction>::getFunction(filter),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("forEach",AS3,Class<IFunction>::getFunction(forEach),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("indexOf",AS3,Class<IFunction>::getFunction(indexOf),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("lastIndexOf",AS3,Class<IFunction>::getFunction(lastIndexOf),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("every",AS3,Class<IFunction>::getFunction(every,1),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("filter",AS3,Class<IFunction>::getFunction(filter,1),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("forEach",AS3,Class<IFunction>::getFunction(forEach,1),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("indexOf",AS3,Class<IFunction>::getFunction(indexOf,1),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("lastIndexOf",AS3,Class<IFunction>::getFunction(lastIndexOf,1),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("join",AS3,Class<IFunction>::getFunction(join,1),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("map",AS3,Class<IFunction>::getFunction(_map,1),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("pop",AS3,Class<IFunction>::getFunction(_pop),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("push",AS3,Class<IFunction>::getFunction(_push_as3),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("push",AS3,Class<IFunction>::getFunction(_push_as3,1),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("reverse",AS3,Class<IFunction>::getFunction(_reverse),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("shift",AS3,Class<IFunction>::getFunction(shift),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("slice",AS3,Class<IFunction>::getFunction(slice,2),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("some",AS3,Class<IFunction>::getFunction(some),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("some",AS3,Class<IFunction>::getFunction(some,1),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("sort",AS3,Class<IFunction>::getFunction(_sort),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("sortOn",AS3,Class<IFunction>::getFunction(sortOn),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("splice",AS3,Class<IFunction>::getFunction(splice,2),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("toLocaleString",AS3,Class<IFunction>::getFunction(_toString),NORMAL_METHOD,true);
-	c->prototype->setVariableByQName("toString","",Class<IFunction>::getFunction(_toString),DYNAMIC_TRAIT);
+	c->setDeclaredMethodByQName("toLocaleString",AS3,Class<IFunction>::getFunction(_toLocaleString),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("unshift",AS3,Class<IFunction>::getFunction(unshift),NORMAL_METHOD,true);
 
+	c->prototype->setVariableByQName("concat","",Class<IFunction>::getFunction(_concat,1),DYNAMIC_TRAIT);
+	c->prototype->setVariableByQName("every","",Class<IFunction>::getFunction(every,1),DYNAMIC_TRAIT);
+	c->prototype->setVariableByQName("filter","",Class<IFunction>::getFunction(filter,1),DYNAMIC_TRAIT);
+	c->prototype->setVariableByQName("forEach","",Class<IFunction>::getFunction(forEach,1),DYNAMIC_TRAIT);
+	c->prototype->setVariableByQName("indexOf","",Class<IFunction>::getFunction(indexOf,1),DYNAMIC_TRAIT);
+	c->prototype->setVariableByQName("lastIndexOf","",Class<IFunction>::getFunction(lastIndexOf,1),DYNAMIC_TRAIT);
+	c->prototype->setVariableByQName("join","",Class<IFunction>::getFunction(join,1),DYNAMIC_TRAIT);
+	c->prototype->setVariableByQName("map","",Class<IFunction>::getFunction(_map,1),DYNAMIC_TRAIT);
 	// workaround, pop was encountered not in the AS3 namespace before, need to investigate it further
 	c->setDeclaredMethodByQName("pop","",Class<IFunction>::getFunction(_pop),NORMAL_METHOD,true);
 	c->prototype->setVariableByQName("pop","",Class<IFunction>::getFunction(_pop),DYNAMIC_TRAIT);
-	c->prototype->setVariableByQName("push","",Class<IFunction>::getFunction(_push),DYNAMIC_TRAIT);
+	c->prototype->setVariableByQName("push","",Class<IFunction>::getFunction(_push,1),DYNAMIC_TRAIT);
+	c->prototype->setVariableByQName("reverse","",Class<IFunction>::getFunction(_reverse),DYNAMIC_TRAIT);
 	c->prototype->setVariableByQName("shift","",Class<IFunction>::getFunction(shift),DYNAMIC_TRAIT);
-	c->prototype->setVariableByQName("unshift","",Class<IFunction>::getFunction(unshift),DYNAMIC_TRAIT);
-	c->prototype->setVariableByQName("concat","",Class<IFunction>::getFunction(_concat,1),DYNAMIC_TRAIT);
 	c->prototype->setVariableByQName("slice","",Class<IFunction>::getFunction(slice,2),DYNAMIC_TRAIT);
-	c->prototype->setVariableByQName("splice","",Class<IFunction>::getFunction(splice,2),DYNAMIC_TRAIT);
-	c->prototype->setVariableByQName("reverse","",Class<IFunction>::getFunction(_reverse),DYNAMIC_TRAIT);
-	c->prototype->setVariableByQName("join","",Class<IFunction>::getFunction(join,1),DYNAMIC_TRAIT);
-	c->prototype->setVariableByQName("map",AS3,Class<IFunction>::getFunction(_map,1),DYNAMIC_TRAIT);
+	c->prototype->setVariableByQName("some","",Class<IFunction>::getFunction(some,1),DYNAMIC_TRAIT);
 	c->prototype->setVariableByQName("sort","",Class<IFunction>::getFunction(_sort),DYNAMIC_TRAIT);
+	c->prototype->setVariableByQName("sortOn","",Class<IFunction>::getFunction(sortOn),DYNAMIC_TRAIT);
+	c->prototype->setVariableByQName("splice","",Class<IFunction>::getFunction(splice,2),DYNAMIC_TRAIT);
+	c->prototype->setVariableByQName("toLocaleString","",Class<IFunction>::getFunction(_toLocaleString),DYNAMIC_TRAIT);
+	c->prototype->setVariableByQName("toString","",Class<IFunction>::getFunction(_toString),DYNAMIC_TRAIT);
+	c->prototype->setVariableByQName("unshift","",Class<IFunction>::getFunction(unshift),DYNAMIC_TRAIT);
 }
 
 void Array::buildTraits(ASObject* o)
@@ -95,50 +100,37 @@ void Array::buildTraits(ASObject* o)
 ASFUNCTIONBODY(Array,_constructor)
 {
 	Array* th=static_cast<Array*>(obj);
-
-	if(argslen==1 && (args[0]->getObjectType()==T_INTEGER || args[0]->getObjectType()==T_UINTEGER || args[0]->getObjectType()==T_NUMBER))
-	{
-		number_t size=args[0]->toNumber();
-		if (size < 0 || size > UINT32_MAX)
-			throwError<RangeError>(kArrayIndexNotIntegerError, Number::toString(size));
-		LOG(LOG_CALLS,_("Creating array of length ") << size);
-		th->resize((uint32_t)size);
-	}
-	else
-	{
-		LOG(LOG_CALLS,_("Called Array constructor"));
-		th->resize(argslen);
-		for(unsigned int i=0;i<argslen;i++)
-		{
-			args[i]->incRef();
-			th->set(i,_MR(args[i]));
-		}
-	}
+	th->constructorImpl(args, argslen);
 	return NULL;
 }
 
 ASFUNCTIONBODY(Array,generator)
 {
 	Array* th=Class<Array>::getInstanceS();
-	if(argslen==1 && (args[0]->getObjectType()==T_INTEGER || args[0]->getObjectType()==T_UINTEGER || args[0]->getObjectType()==T_NUMBER))
+	th->constructorImpl(args, argslen);
+	return th;
+}
+
+void Array::constructorImpl(ASObject* const* args, const unsigned int argslen)
+{
+	if(argslen==1 && (args[0]->is<Integer>() || args[0]->is<UInteger>() || args[0]->is<Number>()))
 	{
-		number_t size=args[0]->toNumber();
-		if (size < 0 || size > UINT32_MAX)
-			throwError<RangeError>(kArrayIndexNotIntegerError, Number::toString(size));
+		uint32_t size = args[0]->toUInt();
+		if ((number_t)size != args[0]->toNumber())
+			throwError<RangeError>(kArrayIndexNotIntegerError, Number::toString(args[0]->toNumber()));
 		LOG(LOG_CALLS,_("Creating array of length ") << size);
-		th->resize((uint32_t)size);
+		resize(size);
 	}
 	else
 	{
 		LOG(LOG_CALLS,_("Called Array constructor"));
-		th->resize(argslen);
+		resize(argslen);
 		for(unsigned int i=0;i<argslen;i++)
 		{
 			args[i]->incRef();
-			th->set(i,_MR(args[i]));
+			set(i,_MR(args[i]));
 		}
 	}
-	return th;
 }
 
 ASFUNCTIONBODY(Array,_concat)
@@ -187,22 +179,32 @@ ASFUNCTIONBODY(Array,_concat)
 ASFUNCTIONBODY(Array,filter)
 {
 	Array* th=static_cast<Array*>(obj);
-	assert_and_throw(argslen==1 || argslen==2);
-	IFunction* f = static_cast<IFunction*>(args[0]);
-	ASObject* params[3];
 	Array* ret=Class<Array>::getInstanceS();
+	_NR<IFunction> f;
+	ARG_UNPACK(f);
+	if (f.isNull())
+		return ret;
+
+	ASObject* params[3];
 	ASObject *funcRet;
 
 	std::map<uint32_t, data_slot>::iterator it=th->data.begin();
 	for(;it != th->data.end();++it)
 	{
-		assert_and_throw(it->second.type==DATA_OBJECT);
-		params[0] = it->second.data;
-		it->second.data->incRef();
+		if (it->second.type==DATA_OBJECT)
+		{
+			params[0] = it->second.data;
+			it->second.data->incRef();
+		}
+		else
+			params[0] =abstract_d(it->second.data_i);
 		params[1] = abstract_i(it->first);
 		params[2] = th;
 		th->incRef();
 
+		// ensure that return values are the original values
+		ASObject *origval = params[0];
+		origval->incRef();
 		if(argslen==1)
 		{
 			funcRet=f->call(getSys()->getNullRef(), params, 3);
@@ -215,10 +217,9 @@ ASFUNCTIONBODY(Array,filter)
 		if(funcRet)
 		{
 			if(Boolean_concrete(funcRet))
-			{
-				it->second.data->incRef();
-				ret->push(_MR(it->second.data));
-			}
+				ret->push(_MR(origval));
+			else
+				origval->decRef();
 			funcRet->decRef();
 		}
 	}
@@ -228,17 +229,24 @@ ASFUNCTIONBODY(Array,filter)
 ASFUNCTIONBODY(Array, some)
 {
 	Array* th=static_cast<Array*>(obj);
-	assert_and_throw(argslen==1 || argslen==2);
-	IFunction* f = static_cast<IFunction*>(args[0]);
+	_NR<IFunction> f;
+	ARG_UNPACK(f);
+	if (f.isNull())
+		return abstract_b(false);
+
 	ASObject* params[3];
 	ASObject *funcRet;
 
 	std::map<uint32_t, data_slot>::iterator it=th->data.begin();
 	for(;it != th->data.end();++it)
 	{
-		assert_and_throw(it->second.type==DATA_OBJECT);
-		params[0] = it->second.data;
-		it->second.data->incRef();
+		if (it->second.type==DATA_OBJECT)
+		{
+			params[0] = it->second.data;
+			it->second.data->incRef();
+		}
+		else
+			params[0] =abstract_d(it->second.data_i);
 		params[1] = abstract_i(it->first);
 		params[2] = th;
 		th->incRef();
@@ -267,17 +275,24 @@ ASFUNCTIONBODY(Array, some)
 ASFUNCTIONBODY(Array, every)
 {
 	Array* th=static_cast<Array*>(obj);
-	assert_and_throw(argslen==1 || argslen==2);
-	IFunction* f = static_cast<IFunction*>(args[0]);
+	_NR<IFunction> f;
+	ARG_UNPACK(f);
+	if (f.isNull())
+		return abstract_b(true);
+
 	ASObject* params[3];
 	ASObject *funcRet;
 
 	std::map<uint32_t, data_slot>::iterator it=th->data.begin();
 	for(;it != th->data.end();++it)
 	{
-		assert_and_throw(it->second.type==DATA_OBJECT);
-		params[0] = it->second.data;
-		it->second.data->incRef();
+		if (it->second.type==DATA_OBJECT)
+		{
+			params[0] = it->second.data;
+			it->second.data->incRef();
+		}
+		else
+			params[0] =abstract_d(it->second.data_i);
 		params[1] = abstract_i(it->first);
 		params[2] = th;
 		th->incRef();
@@ -311,9 +326,9 @@ ASFUNCTIONBODY(Array,_getLength)
 
 ASFUNCTIONBODY(Array,_setLength)
 {
-	assert_and_throw(argslen == 1);
+	uint32_t newLen;
+	ARG_UNPACK(newLen);
 	Array* th=static_cast<Array*>(obj);
-	uint32_t newLen=args[0]->toUInt();
 	//If newLen is equal to size do nothing
 	if(newLen==th->size())
 		return NULL;
@@ -323,17 +338,23 @@ ASFUNCTIONBODY(Array,_setLength)
 
 ASFUNCTIONBODY(Array,forEach)
 {
-	assert_and_throw(argslen == 1 || argslen == 2);
 	Array* th=static_cast<Array*>(obj);
-	IFunction* f = static_cast<IFunction*>(args[0]);
+	_NR<IFunction> f;
+	ARG_UNPACK(f);
+	if (f.isNull())
+		return NULL;
 	ASObject* params[3];
 
 	std::map<uint32_t, data_slot>::iterator it=th->data.begin();
 	for(;it != th->data.end();++it)
 	{
-		assert_and_throw(it->second.type==DATA_OBJECT);
-		params[0] = it->second.data;
-		it->second.data->incRef();
+		if (it->second.type==DATA_OBJECT)
+		{
+			params[0] = it->second.data;
+			it->second.data->incRef();
+		}
+		else
+			params[0] =abstract_d(it->second.data_i);
 		params[1] = abstract_i(it->first);
 		params[2] = th;
 		th->incRef();
@@ -374,11 +395,11 @@ ASFUNCTIONBODY(Array, _reverse)
 ASFUNCTIONBODY(Array,lastIndexOf)
 {
 	Array* th=static_cast<Array*>(obj);
-	assert_and_throw(argslen==1 || argslen==2);
+	_NR<ASObject> arg0;
+	ARG_UNPACK(arg0);
 	int ret=-1;
-	ASObject* arg0=args[0];
 
-	if(th->data.empty())
+	if(argslen == 1 && th->data.empty())
 		return abstract_d(0);
 
 	size_t i = th->size()-1;
@@ -410,7 +431,7 @@ ASFUNCTIONBODY(Array,lastIndexOf)
 		    continue;
 		DATA_TYPE dtype = th->data[i].type;
 		assert_and_throw(dtype==DATA_OBJECT || dtype==DATA_INT);
-		if((dtype == DATA_OBJECT && th->data[i].data->isEqualStrict(arg0)) ||
+		if((dtype == DATA_OBJECT && th->data[i].data->isEqualStrict(arg0.getPtr())) ||
 			(dtype == DATA_INT && arg0->toInt() == th->data[i].data_i))
 		{
 			ret=i;
@@ -494,14 +515,10 @@ int Array::capIndex(int i) const
 ASFUNCTIONBODY(Array,slice)
 {
 	Array* th=static_cast<Array*>(obj);
+	int startIndex;
+	int endIndex;
 
-	int startIndex=0;
-	int endIndex=16777215;
-	if(argslen>0)
-		startIndex=args[0]->toInt();
-	if(argslen>1)
-		endIndex=args[1]->toInt();
-
+	ARG_UNPACK(startIndex, 0) (endIndex, 16777215);
 	startIndex=th->capIndex(startIndex);
 	endIndex=th->capIndex(endIndex);
 
@@ -524,13 +541,11 @@ ASFUNCTIONBODY(Array,slice)
 ASFUNCTIONBODY(Array,splice)
 {
 	Array* th=static_cast<Array*>(obj);
-	assert_and_throw(argslen >= 1);
-	int startIndex=args[0]->toInt();
+	int startIndex;
+	int deleteCount;
 	//By default, delete all the element up to the end
-	//Use the array len, it will be capped below
-	int deleteCount=th->size();
-	if(argslen > 1)
-		deleteCount=args[1]->toUInt();
+	//DeleteCount defaults to the array len, it will be capped below
+	ARG_UNPACK_MORE_ALLOWED(startIndex) (deleteCount, th->size());
 
 	int totalSize=th->size();
 	Array* ret=Class<Array>::getInstanceS();
@@ -590,11 +605,10 @@ ASFUNCTIONBODY(Array,splice)
 ASFUNCTIONBODY(Array,join)
 {
 	Array* th=static_cast<Array*>(obj);
-	
-	tiny_string del = ",";
-	if (argslen == 1)
-	      del=args[0]->toString();
 	string ret;
+	tiny_string del;
+	ARG_UNPACK(del, ",");
+
 	for(uint32_t i=0;i<th->size();i++)
 	{
 		_R<ASObject> o = th->at(i);
@@ -610,11 +624,10 @@ ASFUNCTIONBODY(Array,indexOf)
 {
 	Array* th=static_cast<Array*>(obj);
 	int ret=-1;
-	int32_t index=0;
-	ASObject* arg0 = args[0];
-	if (argslen > 1) 
-		index = args[1]->toInt();
-
+	int32_t index;
+	_NR<ASObject> arg0;
+	ARG_UNPACK(arg0) (index, 0);
+	if (index < 0) index = abs(index);
 
 	DATA_TYPE dtype;
 	std::map<uint32_t,data_slot>::iterator it;
@@ -625,8 +638,8 @@ ASFUNCTIONBODY(Array,indexOf)
 		data_slot sl = it->second;
 		dtype = sl.type;
 		assert_and_throw(dtype==DATA_OBJECT || dtype==DATA_INT);
-		if((dtype == DATA_OBJECT && sl.data->isEqualStrict(arg0)) ||
-			(dtype == DATA_INT && arg0->toInt() == sl.data_i))
+		if((dtype == DATA_OBJECT && sl.data->isEqualStrict(arg0.getPtr())) ||
+			(dtype == DATA_INT && abstract_d(sl.data_i)->isEqualStrict(arg0.getPtr())))
 		{
 			ret=it->first;
 			break;
@@ -765,7 +778,7 @@ bool Array::sortComparatorWrapper::operator()(const data_slot& d1, const data_sl
 	assert(comparator);
 	_NR<ASObject> ret=_MNR(comparator->call(getSys()->getNullRef(), objs, 2));
 	assert_and_throw(ret);
-	return (ret->toInt()<0); //Less
+	return (ret->toNumber()<0); //Less
 }
 
 ASFUNCTIONBODY(Array,_sort)
@@ -877,8 +890,10 @@ bool Array::sortOnComparator::operator()(const data_slot& d1, const data_slot& d
 
 ASFUNCTIONBODY(Array,sortOn)
 {
+	if (argslen != 1 && argslen != 2)
+		throwError<ArgumentError>(kWrongArgumentCountError, "1",
+					  Integer::toString(argslen));
 	Array* th=static_cast<Array*>(obj);
-	assert_and_throw(argslen==1 || argslen==2);
 	std::vector<sorton_field> sortfields;
 	if(args[0]->is<Array>())
 	{
@@ -1133,6 +1148,20 @@ ASFUNCTIONBODY(Array,_toString)
 	return Class<ASString>::getInstanceS(th->toString_priv());
 }
 
+ASFUNCTIONBODY(Array,_toLocaleString)
+{
+	if(Class<Number>::getClass()->prototype->getObj() == obj)
+		return Class<ASString>::getInstanceS("");
+	if(!obj->is<Array>())
+	{
+		LOG(LOG_NOT_IMPLEMENTED, "generic Array::toLocaleString");
+		return Class<ASString>::getInstanceS("");
+	}
+	
+	Array* th=obj->as<Array>();
+	return Class<ASString>::getInstanceS(th->toString_priv(true));
+}
+
 int32_t Array::getVariableByMultiname_i(const multiname& name)
 {
 	assert_and_throw(implEnable);
@@ -1203,7 +1232,7 @@ _NR<ASObject> Array::getVariableByMultiname(const multiname& name, GET_VARIABLE_
 					ret->incRef();
 					break;
 				case DATA_INT:
-					ret=abstract_i(sl.data_i);
+					ret=abstract_d(sl.data_i);
 					break;
 			}
 		}
@@ -1222,6 +1251,8 @@ void Array::setVariableByMultiname_i(const multiname& name, int32_t value)
 		ASObject::setVariableByMultiname_i(name,value);
 		return;
 	}
+	if (index==0xFFFFFFFF)
+		return;
 	if(index>=size())
 		resize(index+1);
 
@@ -1253,17 +1284,45 @@ bool Array::isValidMultiname(const multiname& name, uint32_t& index)
 	assert_and_throw(name.ns.size()!=0);
 	if(!name.ns[0].hasEmptyName())
 		return false;
+	if (name.name_type == multiname::NAME_STRING && 
+	    !isIntegerWithoutLeadingZeros(name.normalizedName()))
+		return false;
 
 	return name.toUInt(index);
 }
 
+bool Array::isIntegerWithoutLeadingZeros(const tiny_string& value)
+{
+	if (value.empty())
+		return false;
+	else if (value == "0")
+		return true;
+
+	bool first = true;
+	for (CharIterator it=value.begin(); it!=value.end(); ++it)
+	{
+		if (!it.isdigit() || (first && *it == '0'))
+			return false;
+
+		first = false;
+	}
+	
+	return true;
+}
+
 void Array::setVariableByMultiname(const multiname& name, ASObject* o, CONST_ALLOWED_FLAG allowConst)
 {
 	assert_and_throw(implEnable);
 	uint32_t index=0;
 	if(!isValidMultiname(name,index))
 		return ASObject::setVariableByMultiname(name,o,allowConst);
-
+	// Derived classes may be sealed!
+	if (getClass() && getClass()->isSealed)
+		throwError<ReferenceError>(kWriteSealedError,
+					   name.normalizedName(),
+					   getClass()->getQualifiedClassName());
+	if (index==0xFFFFFFFF)
+		return;
 	if(index>=size())
 		resize((uint64_t)index+1);
 
@@ -1329,7 +1388,7 @@ tiny_string Array::toString()
 	return toString_priv();
 }
 
-tiny_string Array::toString_priv() const
+tiny_string Array::toString_priv(bool localized) const
 {
 	string ret;
 	for(uint32_t i=0;i<size();i++)
@@ -1340,7 +1399,12 @@ tiny_string Array::toString_priv() const
 			if(sl.type==DATA_OBJECT)
 			{
 				if(sl.data && !sl.data->is<Undefined>() && !sl.data->is<Null>())
-					ret+=sl.data->toString().raw_buf();
+				{
+					if (localized)
+						ret += sl.data->toLocaleString().raw_buf();
+					else
+						ret += sl.data->toString().raw_buf();
+				}
 			}
 			else if(sl.type==DATA_INT)
 			{
@@ -1377,7 +1441,7 @@ _R<ASObject> Array::nextValue(uint32_t index)
 			}
 		}
 		else if(sl.type==DATA_INT)
-			return _MR(abstract_i(sl.data_i));
+			return _MR(abstract_d(sl.data_i));
 		else
 			throw UnsupportedException("Unexpected data type");
 	}
@@ -1429,7 +1493,7 @@ _R<ASObject> Array::nextName(uint32_t index)
 _R<ASObject> Array::at(unsigned int index) const
 {
 	if(size()<=index)
-		outofbounds();
+		outofbounds(index);
 
 	if (!data.count(index))
 		return _MR(getSys()->getUndefinedRef());
@@ -1445,20 +1509,25 @@ _R<ASObject> Array::at(unsigned int index) const
 			}
 		}
 		case DATA_INT:
-			return _MR(abstract_i(sl.data_i));
+			return _MR(abstract_d(sl.data_i));
 	}
 
 	//We should be here only if data is an object and is NULL
 	return _MR(getSys()->getUndefinedRef());
 }
 
-void Array::outofbounds() const
+void Array::outofbounds(unsigned int index) const
 {
-	throw ParseException("Array access out of bounds");
+	throwError<RangeError>(kInvalidArrayLengthError, Number::toString(index));
 }
 
 void Array::resize(uint64_t n)
 {
+	// Bug-for-bug compatible wrapping. See Tamarin test
+	// as3/Array/length_mods.swf and Tamarin bug #685323.
+	if (n > 0xFFFFFFFF)
+		n = (n % 0x100000000);
+
 	std::map<uint32_t,data_slot>::reverse_iterator it;
 	std::map<uint32_t,data_slot>::iterator itstart = n ? data.end() : data.begin();
 	for ( it=data.rbegin() ; it != data.rend(); ++it )
@@ -1514,6 +1583,59 @@ void Array::serialize(ByteArray* out, std::map<tiny_string, uint32_t>& stringMap
 	}
 }
 
+tiny_string Array::toJSON(std::vector<ASObject *> &path, IFunction *replacer, const tiny_string& spaces,const tiny_string& filter)
+{
+	if (has_toJSON())
+	{
+		return call_toJSON();
+	}
+
+	tiny_string res = "[";
+	std::map<uint32_t,data_slot>::iterator it;
+	// check for cylic reference
+	if (std::find(path.begin(),path.end(), this) != path.end())
+		throwError<TypeError>(kJSONCyclicStructure);
+	path.push_back(this);
+	bool bfirst = true;
+	tiny_string newline = (spaces.empty() ? "" : "\n");
+	for (it=data.begin() ; it != data.end(); ++it)
+	{
+		if(it->second.type==DATA_OBJECT && it->second.data)
+		{
+			tiny_string subres;
+			if (replacer != NULL)
+			{
+				ASObject* params[2];
+				
+				params[0] = Class<Number>::getInstanceS(it->first);
+				params[0]->incRef();
+				params[1] = it->second.data;
+				params[1]->incRef();
+				ASObject *funcret=replacer->call(getSys()->getNullRef(), params, 2);
+				if (funcret)
+					subres = funcret->toJSON(path,NULL,spaces,filter);
+			}
+			else
+				subres = it->second.data->toJSON(path,replacer,spaces,filter);
+			if (!subres.empty())
+			{
+				if (!bfirst)
+					res += ",";
+				res += newline+spaces;
+
+				bfirst = false;
+				res += subres;
+			}
+			path.push_back(it->second.data);
+		}
+	}
+	if (!bfirst)
+		res += newline+spaces.substr_bytes(0,spaces.numBytes()/2);
+	res += "]";
+	return res;
+	
+}
+
 Array::~Array()
 {
 	Array::finalize();
@@ -1531,4 +1653,26 @@ void Array::finalize()
 	data.clear();
 }
 
+void Array::set(unsigned int index, _R<ASObject> o)
+{
+	if(index<currentsize)
+	{
+		if(!data.count(index))
+			data[index]=data_slot();
+		if(o->getObjectType()==T_INTEGER)
+		{
+			Integer* i=o->as<Integer>();
+			data[index].data_i=i->val;
+			data[index].type=DATA_INT;
+		}
+		else
+		{
+			o->incRef();
+			data[index].data=o.getPtr();
+			data[index].type=DATA_OBJECT;
+		}
+	}
+	else
+		outofbounds(index);
+}
 
diff --git a/src/scripting/toplevel/Array.h b/src/scripting/toplevel/Array.h
index 75dec81..e27ce27 100644
--- a/src/scripting/toplevel/Array.h
+++ b/src/scripting/toplevel/Array.h
@@ -48,19 +48,17 @@ struct sorton_field
 	sorton_field(const multiname& sortfieldname):isNumeric(false),isCaseInsensitive(false),isDescending(false),fieldname(sortfieldname){}
 };
 
-
 class Array: public ASObject
 {
 friend class ABCVm;
 protected:
-	uint32_t currentsize;
+	uint64_t currentsize;
 	typedef std::map<uint32_t,data_slot,std::less<uint32_t>,
 		reporter_allocator<std::pair<const uint32_t, data_slot>>> arrayType;
 	arrayType data;
-	void outofbounds() const;
+	void outofbounds(unsigned int index) const;
 	~Array();
 private:
-	enum SORTTYPE { CASEINSENSITIVE=1, DESCENDING=2, UNIQUESORT=4, RETURNINDEXEDARRAY=8, NUMERIC=16 };
 	class sortComparatorDefault
 	{
 	private:
@@ -87,9 +85,12 @@ private:
 		sortOnComparator(const std::vector<sorton_field>& sf):fields(sf){}
 		bool operator()(const data_slot& d1, const data_slot& d2);
 	};
-	tiny_string toString_priv() const;
+	void constructorImpl(ASObject* const* args, const unsigned int argslen);
+	tiny_string toString_priv(bool localized=false) const;
 	int capIndex(int i) const;
+	static bool isIntegerWithoutLeadingZeros(const tiny_string& value);
 public:
+	enum SORTTYPE { CASEINSENSITIVE=1, DESCENDING=2, UNIQUESORT=4, RETURNINDEXEDARRAY=8, NUMERIC=16 };
 	Array(Class_base* c);
 	void finalize();
 	//These utility methods are also used by ByteArray
@@ -120,33 +121,21 @@ public:
 	ASFUNCTION(lastIndexOf);
 	ASFUNCTION(_map);
 	ASFUNCTION(_toString);
+	ASFUNCTION(_toLocaleString);
 	ASFUNCTION(slice);
 	ASFUNCTION(every);
 	ASFUNCTION(some);
 
 	_R<ASObject> at(unsigned int index) const;
-	void set(unsigned int index, _R<ASObject> o)
-	{
-		if(index<currentsize)
-		{
-			if(!data.count(index))
-				data[index]=data_slot();
-			o->incRef();
-			data[index].data=o.getPtr();
-			data[index].type=DATA_OBJECT;
-		}
-		else
-			outofbounds();
-	}
+	void set(unsigned int index, _R<ASObject> o);
 	uint64_t size() const
 	{
 		return currentsize;
 	}
 	void push(_R<ASObject> o)
 	{
-		o->incRef();
-		data[currentsize] = data_slot(o.getPtr());
 		currentsize++;
+		set(currentsize-1,o);
 	}
 	void resize(uint64_t n);
 	_NR<ASObject> getVariableByMultiname(const multiname& name, GET_VARIABLE_OPTION opt);
@@ -163,6 +152,7 @@ public:
 	void serialize(ByteArray* out, std::map<tiny_string, uint32_t>& stringMap,
 				std::map<const ASObject*, uint32_t>& objMap,
 				std::map<const Class_base*, uint32_t>& traitsMap);
+	virtual tiny_string toJSON(std::vector<ASObject *> &path,IFunction* replacer, const tiny_string &spaces,const tiny_string& filter);
 };
 
 
diff --git a/src/scripting/toplevel/Boolean.cpp b/src/scripting/toplevel/Boolean.cpp
index 5f31167..cffc28d 100644
--- a/src/scripting/toplevel/Boolean.cpp
+++ b/src/scripting/toplevel/Boolean.cpp
@@ -19,6 +19,7 @@
 
 #include "scripting/toplevel/Boolean.h"
 #include "scripting/toplevel/toplevel.h"
+#include "scripting/flash/utils/ByteArray.h"
 #include "scripting/class.h"
 #include "scripting/argconv.h"
 #include "parsing/amf3_generator.h"
@@ -51,7 +52,16 @@ bool lightspark::Boolean_concrete(const ASObject* o)
 	case T_UINTEGER:
 		return o->as<UInteger>()->val != 0;
 	case T_STRING:
+		if (!o->isConstructed())
+			return false;
 		return !o->as<ASString>()->data.empty();
+	case T_FUNCTION:
+	case T_ARRAY:
+	case T_OBJECT:
+		// not constructed objects return false
+		if (!o->isConstructed())
+			return false;
+		return true;
 	default:
 		//everything else is an Object regarding to the spec
 		return true;
@@ -69,11 +79,10 @@ ASFUNCTIONBODY(Boolean,generator)
 
 void Boolean::sinit(Class_base* c)
 {
-	c->isFinal=true;
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<ASObject>::getRef());
-	c->prototype->setVariableByQName("toString",AS3,Class<IFunction>::getFunction(_toString),DYNAMIC_TRAIT);
-	c->prototype->setVariableByQName("valueOf",AS3,Class<IFunction>::getFunction(_valueOf),DYNAMIC_TRAIT);
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_SEALED | CLASS_FINAL);
+	c->setDeclaredMethodByQName("toString",AS3,Class<IFunction>::getFunction(_toString),NORMAL_METHOD,true);
+	c->prototype->setVariableByQName("toString","",Class<IFunction>::getFunction(_toString),DYNAMIC_TRAIT);
+	c->prototype->setVariableByQName("valueOf","",Class<IFunction>::getFunction(_valueOf),DYNAMIC_TRAIT);
 }
 
 ASFUNCTIONBODY(Boolean,_constructor)
@@ -133,6 +142,9 @@ bool Boolean::isEqual(ASObject* r)
 			return b->val==val;
 		}
 		case T_STRING:
+			if (!r->isConstructed())
+				return false;
+			return val==r->toNumber();
 		case T_INTEGER:
 		case T_UINTEGER:
 		case T_NUMBER:
diff --git a/src/scripting/toplevel/Date.cpp b/src/scripting/toplevel/Date.cpp
index bceaba8..fd3f773 100644
--- a/src/scripting/toplevel/Date.cpp
+++ b/src/scripting/toplevel/Date.cpp
@@ -39,9 +39,7 @@ Date::~Date()
 
 void Date::sinit(Class_base* c)
 {
-	c->isFinal=true;
-	c->setSuper(Class<ASObject>::getRef());
-	c->setConstructor(Class<IFunction>::getFunction(_constructor,7));
+	CLASS_SETUP_CONSTRUCTOR_LENGTH(c, ASObject, _constructor, 7, CLASS_FINAL);
 	c->setDeclaredMethodByQName("getTimezoneOffset",AS3,Class<IFunction>::getFunction(getTimezoneOffset),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("valueOf",AS3,Class<IFunction>::getFunction(valueOf),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("getTime",AS3,Class<IFunction>::getFunction(getTime),NORMAL_METHOD,true);
@@ -821,9 +819,14 @@ ASFUNCTIONBODY(Date,valueOf)
 
 ASObject* Date::msSinceEpoch()
 {
-	return abstract_d(milliseconds+extrayears/400*MS_IN_400_YEARS);
+	return abstract_d(getMsSinceEpoch());
+}
+number_t Date::getMsSinceEpoch()
+{
+	return milliseconds+extrayears/400*MS_IN_400_YEARS;
 }
 
+
 tiny_string Date::toString()
 {
 	assert_and_throw(implEnable);
@@ -1094,6 +1097,23 @@ number_t Date::parse(tiny_string str)
 	
 	return res;
 }
+bool Date::isEqual(ASObject* r)
+{
+	check();
+	//if we are comparing the same object the answer is true
+	if(this==r)
+		return true;
+	if (r->is<Date>())
+		return getMsSinceEpoch() == r->as<Date>()->getMsSinceEpoch();
+	return ASObject::isEqual(r);
+}
+
+TRISTATE Date::isLess(ASObject* o)
+{
+	if (o->is<Date>())
+		return (getMsSinceEpoch() < o->as<Date>()->getMsSinceEpoch())?TTRUE:TFALSE;
+	return ASObject::isLess(o);
+}
 
 void Date::serialize(ByteArray* out, std::map<tiny_string, uint32_t>& stringMap,
 				std::map<const ASObject*, uint32_t>& objMap,
diff --git a/src/scripting/toplevel/Date.h b/src/scripting/toplevel/Date.h
index d456b53..2f72df7 100644
--- a/src/scripting/toplevel/Date.h
+++ b/src/scripting/toplevel/Date.h
@@ -35,6 +35,7 @@ private:
 	GDateTime *datetime;
 	GDateTime *datetimeUTC;
 	ASObject *msSinceEpoch();
+	number_t getMsSinceEpoch();
 	tiny_string toString_priv(bool utc, const char* formatstr) const;
 	void MakeDate(int64_t year, int64_t month, int64_t day, int64_t hour, int64_t minute, int64_t second, int64_t millisecond, bool bIsLocalTime);
 	void MakeDateFromMilliseconds(int64_t ms);
@@ -103,6 +104,9 @@ public:
 	ASFUNCTION(toLocaleString);
 	ASFUNCTION(toLocaleDateString);
 	ASFUNCTION(toLocaleTimeString);
+
+	bool isEqual(ASObject* r);
+	TRISTATE isLess(ASObject* r);
 	tiny_string toString();
 	//Serialization interface
 	void serialize(ByteArray* out, std::map<tiny_string, uint32_t>& stringMap,
diff --git a/src/scripting/toplevel/Error.cpp b/src/scripting/toplevel/Error.cpp
index 3865195..c74b257 100644
--- a/src/scripting/toplevel/Error.cpp
+++ b/src/scripting/toplevel/Error.cpp
@@ -89,11 +89,11 @@ ASFUNCTIONBODY(ASError,getStackTrace)
 tiny_string ASError::toString(bool debugMsg)
 {
 	tiny_string ret;
-	if( !message.empty() )
-		ret = name + ": ";
+	ret = name;
 	if(errorID != 0)
-		ret += tiny_string("Error #") + Integer::toString(errorID) + ": ";
-	ret += message;
+		ret += tiny_string(": Error #") + Integer::toString(errorID);
+	if (!message.empty())
+		ret += tiny_string(": ") + message;
 	return ret;
 }
 
@@ -140,10 +140,10 @@ void ASError::errorGenerator(ASError* obj, ASObject* const* args, const unsigned
 
 void ASError::sinit(Class_base* c)
 {
-	c->setSuper(Class<ASObject>::getRef());
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setDeclaredMethodByQName("getStackTrace",AS3,Class<IFunction>::getFunction(getStackTrace),NORMAL_METHOD,true);
-	c->prototype->setVariableByQName("toString",AS3,Class<IFunction>::getFunction(_toString),DYNAMIC_TRAIT);
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_DYNAMIC_NOT_FINAL);
+	c->setDeclaredMethodByQName("getStackTrace","",Class<IFunction>::getFunction(getStackTrace),NORMAL_METHOD,true);
+	c->prototype->setVariableByQName("toString","",Class<IFunction>::getFunction(_toString),DYNAMIC_TRAIT);
+	c->setDeclaredMethodByQName("toString","",Class<IFunction>::getFunction(_toString),NORMAL_METHOD,true);
 	REGISTER_GETTER(c, errorID);
 	REGISTER_GETTER_SETTER(c, message);
 	REGISTER_GETTER_SETTER(c, name);
@@ -177,8 +177,7 @@ ASFUNCTIONBODY(SecurityError,generator)
 
 void SecurityError::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<ASError>::getRef());
+	CLASS_SETUP(c, ASError, _constructor, CLASS_DYNAMIC_NOT_FINAL);
 }
 
 void SecurityError::buildTraits(ASObject* o)
@@ -205,8 +204,7 @@ ASFUNCTIONBODY(ArgumentError,generator)
 
 void ArgumentError::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<ASError>::getRef());
+	CLASS_SETUP(c, ASError, _constructor, CLASS_DYNAMIC_NOT_FINAL);
 }
 
 void ArgumentError::buildTraits(ASObject* o)
@@ -233,8 +231,7 @@ ASFUNCTIONBODY(DefinitionError,generator)
 
 void DefinitionError::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<ASError>::getRef());
+	CLASS_SETUP(c, ASError, _constructor, CLASS_DYNAMIC_NOT_FINAL);
 }
 
 void DefinitionError::buildTraits(ASObject* o)
@@ -261,8 +258,7 @@ ASFUNCTIONBODY(EvalError,generator)
 
 void EvalError::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<ASError>::getRef());
+	CLASS_SETUP(c, ASError, _constructor, CLASS_DYNAMIC_NOT_FINAL);
 }
 
 void EvalError::buildTraits(ASObject* o)
@@ -289,8 +285,7 @@ ASFUNCTIONBODY(RangeError,generator)
 
 void RangeError::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<ASError>::getRef());
+	CLASS_SETUP(c, ASError, _constructor, CLASS_DYNAMIC_NOT_FINAL);
 }
 
 void RangeError::buildTraits(ASObject* o)
@@ -317,8 +312,7 @@ ASFUNCTIONBODY(ReferenceError,generator)
 
 void ReferenceError::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<ASError>::getRef());
+	CLASS_SETUP(c, ASError, _constructor, CLASS_DYNAMIC_NOT_FINAL);
 }
 
 void ReferenceError::buildTraits(ASObject* o)
@@ -345,8 +339,7 @@ ASFUNCTIONBODY(SyntaxError,generator)
 
 void SyntaxError::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<ASError>::getRef());
+	CLASS_SETUP(c, ASError, _constructor, CLASS_DYNAMIC_NOT_FINAL);
 }
 
 void SyntaxError::buildTraits(ASObject* o)
@@ -373,8 +366,7 @@ ASFUNCTIONBODY(TypeError,generator)
 
 void TypeError::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<ASError>::getRef());
+	CLASS_SETUP(c, ASError, _constructor, CLASS_DYNAMIC_NOT_FINAL);
 }
 
 void TypeError::buildTraits(ASObject* o)
@@ -401,8 +393,7 @@ ASFUNCTIONBODY(URIError,generator)
 
 void URIError::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<ASError>::getRef());
+	CLASS_SETUP(c, ASError, _constructor, CLASS_DYNAMIC_NOT_FINAL);
 }
 
 void URIError::buildTraits(ASObject* o)
@@ -429,8 +420,7 @@ ASFUNCTIONBODY(VerifyError,generator)
 
 void VerifyError::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<ASError>::getRef());
+	CLASS_SETUP(c, ASError, _constructor, CLASS_DYNAMIC_NOT_FINAL);
 }
 
 void VerifyError::buildTraits(ASObject* o)
@@ -457,8 +447,7 @@ ASFUNCTIONBODY(UninitializedError,generator)
 
 void UninitializedError::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<ASError>::getRef());
+	CLASS_SETUP(c, ASError, _constructor, CLASS_DYNAMIC_NOT_FINAL);
 }
 
 void UninitializedError::buildTraits(ASObject* o)
diff --git a/src/scripting/toplevel/Integer.cpp b/src/scripting/toplevel/Integer.cpp
index b920e45..d7efdb3 100644
--- a/src/scripting/toplevel/Integer.cpp
+++ b/src/scripting/toplevel/Integer.cpp
@@ -17,15 +17,20 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 **************************************************************************/
 
+#include <cmath>
 #include "parsing/amf3_generator.h"
 #include "scripting/argconv.h"
 #include "scripting/toplevel/Integer.h"
+#include "scripting/flash/utils/ByteArray.h"
 
 using namespace std;
 using namespace lightspark;
 
 ASFUNCTIONBODY(Integer,_toString)
 {
+	if(Class<Integer>::getClass()->prototype->getObj() == obj)
+		return Class<ASString>::getInstanceS("0");
+
 	Integer* th=static_cast<Integer*>(obj);
 	int radix=10;
 	if(argslen==1)
@@ -190,13 +195,19 @@ tiny_string Integer::toString(int32_t val)
 
 void Integer::sinit(Class_base* c)
 {
-	c->isFinal = true;
-	c->setSuper(Class<ASObject>::getRef());
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setVariableByQName("MAX_VALUE","",new (c->memoryAccount) Integer(c,numeric_limits<int32_t>::max()),CONSTANT_TRAIT);
-	c->setVariableByQName("MIN_VALUE","",new (c->memoryAccount) Integer(c,numeric_limits<int32_t>::min()),CONSTANT_TRAIT);
-	c->prototype->setVariableByQName("toString",AS3,Class<IFunction>::getFunction(Integer::_toString),DYNAMIC_TRAIT);
-	c->prototype->setVariableByQName("valueOf",AS3,Class<IFunction>::getFunction(_valueOf),DYNAMIC_TRAIT);
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_SEALED | CLASS_FINAL);
+	c->setVariableByQName("MAX_VALUE","",abstract_i(numeric_limits<int32_t>::max()),CONSTANT_TRAIT);
+	c->setVariableByQName("MIN_VALUE","",abstract_i(numeric_limits<int32_t>::min()),CONSTANT_TRAIT);
+	c->setDeclaredMethodByQName("toString",AS3,Class<IFunction>::getFunction(_toString),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("toFixed",AS3,Class<IFunction>::getFunction(_toFixed,1),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("toExponential",AS3,Class<IFunction>::getFunction(_toExponential,1),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("toPrecision",AS3,Class<IFunction>::getFunction(_toPrecision,1),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("valueOf",AS3,Class<IFunction>::getFunction(_valueOf),NORMAL_METHOD,true);
+	c->prototype->setVariableByQName("toExponential","",Class<IFunction>::getFunction(Integer::_toExponential, 1),DYNAMIC_TRAIT);
+	c->prototype->setVariableByQName("toFixed","",Class<IFunction>::getFunction(Integer::_toFixed, 1),DYNAMIC_TRAIT);
+	c->prototype->setVariableByQName("toPrecision","",Class<IFunction>::getFunction(Integer::_toPrecision, 1),DYNAMIC_TRAIT);
+	c->prototype->setVariableByQName("toString","",Class<IFunction>::getFunction(Integer::_toString),DYNAMIC_TRAIT);
+	c->prototype->setVariableByQName("valueOf","",Class<IFunction>::getFunction(_valueOf),DYNAMIC_TRAIT);
 }
 
 void Integer::serialize(ByteArray* out, std::map<tiny_string, uint32_t>& stringMap,
@@ -213,7 +224,7 @@ void Integer::serialize(ByteArray* out, std::map<tiny_string, uint32_t>& stringM
 bool Integer::fromStringFlashCompatible(const char* cur, int64_t& ret, int radix)
 {
 	//Skip whitespace chars
-	while(g_unichar_isspace(g_utf8_get_char(cur)))
+	while(ASString::isEcmaSpace(g_utf8_get_char(cur)))
 		cur = g_utf8_next_char(cur);
 
 	int64_t multiplier=1;
@@ -251,8 +262,42 @@ int32_t Integer::stringToASInteger(const char* cur, int radix)
 	int64_t value;
 	bool valid=Integer::fromStringFlashCompatible(cur, value, 0);
 
-	if(valid==false || value<INT32_MIN || value>INT32_MAX)
+	if (!valid)
 		return 0;
 	else
-		return static_cast<int32_t>(value);
+		return static_cast<int32_t>(value & 0xFFFFFFFF);
+}
+
+ASFUNCTIONBODY(Integer,_toExponential)
+{
+	Integer *th=obj->as<Integer>();
+	double v = (double)th->val;
+	int32_t fractionDigits;
+	ARG_UNPACK(fractionDigits, 0);
+	if (argslen == 0 || args[0]->is<Undefined>())
+	{
+		if (v == 0)
+			fractionDigits = 1;
+		else
+			fractionDigits = imin(imax((int32_t)ceil(::log10(::fabs(v))), 1), 20);
+	}
+	return Class<ASString>::getInstanceS(Number::toExponentialString(v, fractionDigits));
+}
+
+ASFUNCTIONBODY(Integer,_toFixed)
+{
+	Integer *th=obj->as<Integer>();
+	int fractiondigits;
+	ARG_UNPACK (fractiondigits, 0);
+	return Class<ASString>::getInstanceS(Number::toFixedString(th->val, fractiondigits));
+}
+
+ASFUNCTIONBODY(Integer,_toPrecision)
+{
+	Integer *th=obj->as<Integer>();
+	if (argslen == 0 || args[0]->is<Undefined>())
+		return Class<ASString>::getInstanceS(th->toString());
+	int precision;
+	ARG_UNPACK (precision);
+	return Class<ASString>::getInstanceS(Number::toPrecisionString(th->val, precision));
 }
diff --git a/src/scripting/toplevel/Integer.h b/src/scripting/toplevel/Integer.h
index 96e571a..4299057 100644
--- a/src/scripting/toplevel/Integer.h
+++ b/src/scripting/toplevel/Integer.h
@@ -49,6 +49,9 @@ public:
 	ASFUNCTION(_constructor);
 	ASFUNCTION(generator);
 	ASFUNCTION(_valueOf);
+	ASFUNCTION(_toExponential);
+	ASFUNCTION(_toFixed);
+	ASFUNCTION(_toPrecision);
 	std::string toDebugString() { return toString()+"i"; }
 	//Serialization interface
 	void serialize(ByteArray* out, std::map<tiny_string, uint32_t>& stringMap,
diff --git a/src/scripting/toplevel/JSON.cpp b/src/scripting/toplevel/JSON.cpp
new file mode 100644
index 0000000..193bee3
--- /dev/null
+++ b/src/scripting/toplevel/JSON.cpp
@@ -0,0 +1,774 @@
+/**************************************************************************
+    Lightspark, a free flash player implementation
+
+    Copyright (C) 2009-2013  Alessandro Pignotti (a.pignotti at sssup.it)
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+**************************************************************************/
+
+#include "scripting/argconv.h"
+#include "scripting/toplevel/JSON.h"
+
+using namespace std;
+using namespace lightspark;
+
+JSON::JSON(Class_base* c):ASObject(c)
+{
+}
+
+
+void JSON::sinit(Class_base* c)
+{
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_SEALED | CLASS_FINAL);
+	c->setDeclaredMethodByQName("parse","",Class<IFunction>::getFunction(_parse,2),NORMAL_METHOD,false);
+	c->setDeclaredMethodByQName("stringify","",Class<IFunction>::getFunction(_stringify,3),NORMAL_METHOD,false);
+}
+void JSON::buildTraits(ASObject* o)
+{
+}
+ASFUNCTIONBODY(JSON,_constructor)
+{
+	throwError<ArgumentError>(kCantInstantiateError);
+	return NULL;
+}
+ASFUNCTIONBODY(JSON,generator)
+{
+	throwError<ArgumentError>(kCoerceArgumentCountError);
+	return NULL;
+}
+
+ASFUNCTIONBODY(JSON,_parse)
+{
+	tiny_string text;
+	IFunction* reviver = NULL;
+
+	if (argslen > 0 && (args[0]->is<Null>() ||args[0]->is<Undefined>()))
+		throwError<SyntaxError>(kJSONInvalidParseInput);
+	ARG_UNPACK(text);
+	if (argslen > 1)
+	{
+		if (!args[1]->is<IFunction>())
+			throwError<TypeError>(kCheckTypeFailedError);
+		reviver = args[1]->as<IFunction>();
+	}
+	ASObject* res = NULL;
+	multiname dummy(NULL);
+	
+	parseAll(text,&res,dummy,reviver);
+	return res;
+}
+
+ASFUNCTIONBODY(JSON,_stringify)
+{
+	_NR<ASObject> value;
+	ARG_UNPACK(value);
+	if (value->has_toJSON())
+		return Class<ASString>::getInstanceS(value->call_toJSON());
+	std::vector<ASObject *> path;
+	tiny_string filter;
+	IFunction* replacer = NULL;
+	if (argslen > 1 && !args[1]->is<Null>() && !args[1]->is<Undefined>())
+	{
+		if (args[1]->is<IFunction>())
+		{
+			replacer = args[1]->as<IFunction>();
+		}
+		else if (args[1]->is<Array>())
+		{
+			filter = " ";
+			Array* ar = args[1]->as<Array>();
+			for (uint64_t i = 0; i < ar->size(); i++)
+			{
+				filter += ar->at(i)->toString();
+				filter += " ";
+			}
+		}
+		else
+			throwError<TypeError>(kJSONInvalidReplacer);
+	}
+
+	tiny_string spaces = "";
+	if (argslen > 2)
+	{
+		ASObject* space = args[2];
+		spaces = "          ";
+		if (space->is<Number>() || space->is<Integer>() || space->is<UInteger>())
+		{
+			int32_t v = space->toInt();
+			if (v < 0) v = 0;
+			if (v > 10) v = 10;
+			spaces = spaces.substr_bytes(0,v);
+		}
+		else if (space->is<Boolean>() || space->is<Null>())
+		{
+			spaces = "";
+		}
+		else
+		{
+			if(space->has_toString())
+			{
+				_R<ASObject> ret = space->call_toString();
+				spaces = ret->toString();
+			}
+			else
+				spaces = space->toString();
+			if (spaces.numBytes() > 10)
+				spaces = spaces.substr_bytes(0,10);
+		}
+	}
+	tiny_string res = value->toJSON(path,replacer,spaces,filter);
+
+	return Class<ASString>::getInstanceS(res);
+}
+void JSON::parseAll(const tiny_string &jsonstring, ASObject** parent , const multiname& key, IFunction *reviver)
+{
+	int len = jsonstring.numBytes();
+	int pos = 0;
+	while (pos < len)
+	{
+		if (*parent && (*parent)->isPrimitive())
+			throwError<SyntaxError>(kJSONInvalidParseInput);
+		pos = parse(jsonstring, pos, parent , key, reviver);
+		while (jsonstring.charAt(pos) == ' ' ||
+			   jsonstring.charAt(pos) == '\t' ||
+			   jsonstring.charAt(pos) == '\n' ||
+			   jsonstring.charAt(pos) == '\r'
+			   )
+			pos++;
+	}
+}
+int JSON::parse(const tiny_string &jsonstring, int pos, ASObject** parent , const multiname& key, IFunction *reviver)
+{
+	while (jsonstring.charAt(pos) == ' ' ||
+		   jsonstring.charAt(pos) == '\t' ||
+		   jsonstring.charAt(pos) == '\n' ||
+		   jsonstring.charAt(pos) == '\r'
+		   )
+		   pos++;
+	int len = jsonstring.numBytes();
+	if (pos < len)
+	{
+		char c = jsonstring.charAt(pos);
+		switch(c)
+		{
+			case '{':
+				pos = parseObject(jsonstring,pos,parent,key, reviver);
+				break;
+			case '[': 
+				pos = parseArray(jsonstring,pos,parent,key, reviver);
+				break;
+			case '"':
+				pos = parseString(jsonstring,pos,parent,key);
+				break;
+			case '0':
+			case '1':
+			case '2':
+			case '3':
+			case '4':
+			case '5':
+			case '6':
+			case '7':
+			case '8':
+			case '9':
+			case '-':
+				pos = parseNumber(jsonstring,pos,parent,key);
+				break;
+			case 't':
+				pos = parseTrue(jsonstring,pos,parent,key);
+				break;
+			case 'f':
+				pos = parseFalse(jsonstring,pos,parent,key);
+				break;
+			case 'n':
+				pos = parseNull(jsonstring,pos,parent,key);
+				break;
+			default:
+				throwError<SyntaxError>(kJSONInvalidParseInput);
+		}
+	}
+	if (reviver)
+	{
+		bool haskey = key.name_type!= multiname::NAME_OBJECT;
+		ASObject* params[2];
+		
+		if (haskey)
+		{
+			params[0] = Class<ASString>::getInstanceS(key.normalizedName());
+			if ((*parent)->hasPropertyByMultiname(key,true,false))
+			{
+				params[1] = (*parent)->getVariableByMultiname(key).getPtr();
+				params[1]->incRef();
+			}
+			else
+				params[1] = getSys()->getNullRef();
+		}
+		else
+		{
+			params[0] = Class<ASString>::getInstanceS("");
+			params[1] = *parent;
+			params[1]->incRef();
+		}
+
+		ASObject *funcret=reviver->call(getSys()->getNullRef(), params, 2);
+		if(funcret)
+		{
+			if (haskey)
+			{
+				if (funcret->is<Undefined>())
+				{
+					(*parent)->deleteVariableByMultiname(key);
+					funcret->decRef();
+				}
+				else
+				{
+					(*parent)->setVariableByMultiname(key,funcret,ASObject::CONST_NOT_ALLOWED);
+				}
+			}
+			else 
+				*parent= funcret;
+		}
+	}
+	return pos;
+}
+int JSON::parseTrue(const tiny_string &jsonstring, int pos,ASObject** parent,const multiname& key)
+{
+	int len = jsonstring.numBytes();
+	if (len >= pos+4)
+	{
+		if (jsonstring.charAt(pos) == 't' && 
+				jsonstring.charAt(pos + 1) == 'r' &&
+				jsonstring.charAt(pos + 2) == 'u' && 
+				jsonstring.charAt(pos + 3) == 'e')
+		{
+			pos += 4;
+			if (*parent == NULL)
+				*parent = abstract_b(true);
+			else 
+				(*parent)->setVariableByMultiname(key,abstract_b(true),ASObject::CONST_NOT_ALLOWED);
+		}
+		else
+			throwError<SyntaxError>(kJSONInvalidParseInput);
+	}
+	else
+		throwError<SyntaxError>(kJSONInvalidParseInput);
+	return pos;
+}
+int JSON::parseFalse(const tiny_string &jsonstring, int pos,ASObject** parent,const multiname& key)
+{
+	int len = jsonstring.numBytes();
+	if (len >= pos+5)
+	{
+		if (jsonstring.charAt(pos) == 'f' && 
+				jsonstring.charAt(pos + 1) == 'a' &&
+				jsonstring.charAt(pos + 2) == 'l' && 
+				jsonstring.charAt(pos + 3) == 's' && 
+				jsonstring.charAt(pos + 4) == 'e')
+		{
+			pos += 5;
+			if (*parent == NULL)
+				*parent = abstract_b(false);
+			else 
+				(*parent)->setVariableByMultiname(key,abstract_b(false),ASObject::CONST_NOT_ALLOWED);
+		}
+		else
+			throwError<SyntaxError>(kJSONInvalidParseInput);
+	}
+	else
+		throwError<SyntaxError>(kJSONInvalidParseInput);
+	return pos;
+}
+int JSON::parseNull(const tiny_string &jsonstring, int pos,ASObject** parent,const multiname& key)
+{
+	int len = jsonstring.numBytes();
+	if (len >= pos+4)
+	{
+		if (jsonstring.charAt(pos) == 'n' && 
+				jsonstring.charAt(pos + 1) == 'u' &&
+				jsonstring.charAt(pos + 2) == 'l' && 
+				jsonstring.charAt(pos + 3) == 'l')
+		{
+			pos += 4;
+			if (*parent == NULL)
+				*parent = getSys()->getNullRef();
+			else 
+				(*parent)->setVariableByMultiname(key,getSys()->getNullRef(),ASObject::CONST_NOT_ALLOWED);
+		}
+		else
+			throwError<SyntaxError>(kJSONInvalidParseInput);
+	}
+	else
+		throwError<SyntaxError>(kJSONInvalidParseInput);
+	return pos;
+}
+int JSON::parseString(const tiny_string &jsonstring, int pos,ASObject** parent,const multiname& key, tiny_string* result)
+{
+	pos++; // ignore starting quotes
+	int len = jsonstring.numChars();
+	if (pos >= len)
+		throwError<SyntaxError>(kJSONInvalidParseInput);
+
+	tiny_string sub = jsonstring.substr(pos,len-pos);
+	
+	tiny_string res;
+	bool done = false;
+	for (CharIterator it=sub.begin(); it!=sub.end(); it++)
+	{
+		pos++;
+		if (*it == '\"')
+		{
+			done = true;
+			break;
+		}
+		else if(*it == '\\')
+		{
+			it++;
+			pos++;
+			if(it == sub.end())
+				break;
+			if(*it == '\"')
+				res += '\"';
+			else if(*it == '\\')
+				res += '\\';
+			else if(*it == '/')
+				res += '/';
+			else if(*it == 'b')
+				res += '\b';
+			else if(*it == 'f')
+				res += '\f';
+			else if(*it == 'n')
+				res += '\n';
+			else if(*it == 'r')
+				res += '\r';
+			else if(*it == 't')
+				res += '\t';
+			else if(*it == 'u')
+			{
+				tiny_string strhex;
+				for (int i = 0; i < 4; i++)
+				{
+					it++; pos++; 
+					if (it==sub.end()) 
+						throwError<SyntaxError>(kJSONInvalidParseInput);
+					switch(*it)
+					{
+						case '0':
+						case '1':
+						case '2':
+						case '3':
+						case '4':
+						case '5':
+						case '6':
+						case '7':
+						case '8':
+						case '9':
+						case 'a':
+						case 'b':
+						case 'c':
+						case 'd':
+						case 'e':
+						case 'f':
+						case 'A':
+						case 'B':
+						case 'C':
+						case 'D':
+						case 'E':
+						case 'F':
+							strhex += *it;
+							break;
+						default:
+							throwError<SyntaxError>(kJSONInvalidParseInput);
+					}
+					if (it==sub.end()) 
+						throwError<SyntaxError>(kJSONInvalidParseInput);
+				}
+				int64_t hexnum;
+				if (Integer::fromStringFlashCompatible(strhex.raw_buf(),hexnum,16))
+				{
+					if (hexnum < 0x20 && hexnum != 0xf)
+						throwError<SyntaxError>(kJSONInvalidParseInput);
+					res += tiny_string::fromChar(hexnum);
+				}
+				else
+					break;
+			}
+			else
+				throwError<SyntaxError>(kJSONInvalidParseInput);
+		}
+		else if (*it < 0x20)
+		{
+			throwError<SyntaxError>(kJSONInvalidParseInput);
+		}
+		else
+		{
+			res += *it;
+		}
+	}
+	if (!done)
+		throwError<SyntaxError>(kJSONInvalidParseInput);
+	
+	if (parent != NULL)
+	{
+		if (*parent == NULL)
+			*parent = Class<ASString>::getInstanceS(res);
+		else 
+			(*parent)->setVariableByMultiname(key,Class<ASString>::getInstanceS(res),ASObject::CONST_NOT_ALLOWED);
+	}
+	if (result)
+		*result =res;
+	return pos;
+}
+int JSON::parseNumber(const tiny_string &jsonstring, int pos, ASObject** parent, const multiname& key)
+{
+	int len = jsonstring.numBytes();
+	tiny_string res;
+	bool done = false;
+	while (!done && pos < len)
+	{
+		char c = jsonstring.charAt(pos);
+		switch(c)
+		{
+			case '0':
+			case '1':
+			case '2':
+			case '3':
+			case '4':
+			case '5':
+			case '6':
+			case '7':
+			case '8':
+			case '9':
+			case '-':
+			case '+':
+			case '.':
+			case 'E':
+			case 'e':
+				res += c;
+				pos++;
+				break;
+			default:
+				done = true;
+				break;
+		}
+	}
+	ASString* numstr = Class<ASString>::getInstanceS(res);
+	number_t num = numstr->toNumber();
+
+	if (std::isnan(num))
+		throwError<SyntaxError>(kJSONInvalidParseInput);
+
+	if (*parent == NULL)
+		*parent = Class<Number>::getInstanceS(num);
+	else 
+	{
+		(*parent)->setVariableByMultiname(key,Class<Number>::getInstanceS(num),ASObject::CONST_NOT_ALLOWED);
+	}
+	return pos;
+}
+int JSON::parseObject(const tiny_string &jsonstring, int pos,ASObject** parent,const multiname& key, IFunction *reviver)
+{
+	int len = jsonstring.numChars();
+	pos++; // ignore '{' or ','
+	ASObject* subobj = Class<ASObject>::getInstanceS();
+	if (*parent == NULL)
+		*parent = subobj;
+	else 
+		(*parent)->setVariableByMultiname(key,subobj,ASObject::CONST_NOT_ALLOWED);
+	multiname name(NULL);
+	name.name_type=multiname::NAME_STRING;
+	name.ns.push_back(nsNameAndKind("",NAMESPACE));
+	name.isAttribute = false;
+	bool done = false;
+	bool bfirst = true;
+	bool needkey = true;
+	bool needvalue = false;
+
+	while (!done && pos < len)
+	{
+		while (jsonstring.charAt(pos) == ' ' ||
+			   jsonstring.charAt(pos) == '\t' ||
+			   jsonstring.charAt(pos) == '\n' ||
+			   jsonstring.charAt(pos) == '\r'
+			   )
+			pos++;
+		char c = jsonstring.charAt(pos);
+		switch(c)
+		{
+			case '}':
+				if (!bfirst && (needkey || needvalue))
+					throwError<SyntaxError>(kJSONInvalidParseInput);
+				done = true;
+				pos++;
+				break;
+			case '\"':
+				{
+					tiny_string keyname;
+					pos = parseString(jsonstring,pos,NULL,name,&keyname);
+					name.name_s_id=getSys()->getUniqueStringId(keyname);
+					needkey = false;
+					needvalue = true;
+				}
+				break;
+			case ',':
+				if (needkey || needvalue)
+					throwError<SyntaxError>(kJSONInvalidParseInput);
+				pos++;
+				name.name_s_id=0;
+				needkey = true;
+				break;
+			case ':':
+				pos++;
+				pos = parse(jsonstring,pos,&subobj,name,reviver);
+				needvalue = false;
+				break;
+			default:
+				throwError<SyntaxError>(kJSONInvalidParseInput);
+		}
+		bfirst=false;
+	}
+	if (!done)
+		throwError<SyntaxError>(kJSONInvalidParseInput);
+
+	return pos;
+}
+
+int JSON::parseArray(const tiny_string &jsonstring, int pos, ASObject** parent, const multiname& key, IFunction *reviver)
+{
+	int len = jsonstring.numChars();
+	pos++; // ignore '['
+	ASObject* subobj = Class<Array>::getInstanceS();
+	if (*parent == NULL)
+		*parent = subobj;
+	else 
+		(*parent)->setVariableByMultiname(key,subobj,ASObject::CONST_NOT_ALLOWED);
+	multiname name(NULL);
+	name.name_type=multiname::NAME_INT;
+	name.name_i = 0;
+	name.ns.push_back(nsNameAndKind("",NAMESPACE));
+	name.isAttribute = false;
+	bool done = false;
+	while (!done && pos < len)
+	{
+		while (jsonstring.charAt(pos) == ' ' ||
+			   jsonstring.charAt(pos) == '\t' ||
+			   jsonstring.charAt(pos) == '\n' ||
+			   jsonstring.charAt(pos) == '\r'
+			   )
+			pos++;
+		char c = jsonstring.charAt(pos);
+		switch(c)
+		{
+			case ']':
+				done = true;
+				pos++;
+				break;
+			case ',':
+				name.name_i++;
+				pos++;
+				break;
+			default:
+				pos = parse(jsonstring,pos,&subobj,name, reviver);
+				break;
+		}
+	}
+	if (!done)
+		throwError<SyntaxError>(kJSONInvalidParseInput);
+
+	return pos;
+}
+
+
+
+
+/***** 
+
+static QString sanitizeString(QString str)
+{
+        str.replace(QLatin1String("\\"), QLatin1String("\\\\"));
+        str.replace(QLatin1String("\""), QLatin1String("\\\""));
+        str.replace(QLatin1String("\b"), QLatin1String("\\b"));
+        str.replace(QLatin1String("\f"), QLatin1String("\\f"));
+        str.replace(QLatin1String("\n"), QLatin1String("\\n"));
+        str.replace(QLatin1String("\r"), QLatin1String("\\r"));
+        str.replace(QLatin1String("\t"), QLatin1String("\\t"));
+        return QString(QLatin1String("\"%1\"")).arg(str);
+}
+
+static QByteArray join(const QList<QByteArray> &list, const QByteArray &sep)
+{
+        QByteArray res;
+        Q_FOREACH(const QByteArray &i, list)
+        {
+                if(!res.isEmpty())
+                {
+                        res += sep;
+                }
+                res += i;
+        }
+        return res;
+}
+
+
+
+static DSVariantList parseArray(const QString &json, int &index, bool &success)
+{
+        DSVariantList list;
+
+        nextToken(json, index);
+
+        bool done = false;
+        while(!done)
+        {
+                int token = lookAhead(json, index);
+
+                if(token == JsonTokenNone)
+                {
+                        success = false;
+                        return DSVariantList();
+                }
+                else if(token == JsonTokenComma)
+                {
+                        nextToken(json, index);
+                }
+                else if(token == JsonTokenSquaredClose)
+                {
+                        nextToken(json, index);
+                        break;
+                }
+                else
+                {
+                        QVariant value = parseValue(json, index, success);
+
+                        if(!success)
+                        {
+                            return DSVariantList();
+                        }
+
+                        list.push_back(value);
+                }
+        }
+
+        return list;
+}
+
+
+static QVariant parseNumber(const QString &json, int &index)
+{
+        eatWhitespace(json, index);
+
+        int lastIndex = lastIndexOfNumber(json, index);
+        int charLength = (lastIndex - index) + 1;
+        QString numberStr;
+
+        numberStr = json.mid(index, charLength);
+
+        index = lastIndex + 1;
+
+        if (numberStr.contains('.')) {
+                return QVariant(numberStr.toDouble(NULL));
+        } else if (numberStr.startsWith('-')) {
+                return QVariant(numberStr.toLongLong(NULL));
+        } else {
+                return QVariant(numberStr.toULongLong(NULL));
+        }
+}
+
+static int lastIndexOfNumber(const QString &json, int index)
+{
+        int lastIndex;
+
+        for(lastIndex = index; lastIndex < json.size(); lastIndex++)
+        {
+                if(QString("0123456789+-.eE").indexOf(json[lastIndex]) == -1)
+                {
+                        break;
+                }
+        }
+
+        return lastIndex -1;
+}
+
+
+
+static int lookAhead(const QString &json, int index)
+{
+        int saveIndex = index;
+        return nextToken(json, saveIndex);
+}
+
+static int nextToken(const QString &json, int &index)
+{
+        eatWhitespace(json, index);
+
+        if(index == json.size())
+        {
+                return JsonTokenNone;
+        }
+
+        QChar c = json[index];
+        index++;
+        switch(c.toLatin1())
+        {
+                case '{': return JsonTokenCurlyOpen;
+                case '}': return JsonTokenCurlyClose;
+                case '[': return JsonTokenSquaredOpen;
+                case ']': return JsonTokenSquaredClose;
+                case ',': return JsonTokenComma;
+                case '"': return JsonTokenString;
+                case '0': case '1': case '2': case '3': case '4':
+                case '5': case '6': case '7': case '8': case '9':
+                case '-': return JsonTokenNumber;
+                case ':': return JsonTokenColon;
+        }
+
+        index--;
+
+        int remainingLength = json.size() - index;
+
+        //True
+        if(remainingLength >= 4)
+        {
+                if (json[index] == 't' && json[index + 1] == 'r' &&
+                        json[index + 2] == 'u' && json[index + 3] == 'e')
+                {
+                        index += 4;
+                        return JsonTokenTrue;
+                }
+        }
+
+        //False
+        if (remainingLength >= 5)
+        {
+                if (json[index] == 'f' && json[index + 1] == 'a' &&
+                        json[index + 2] == 'l' && json[index + 3] == 's' &&
+                        json[index + 4] == 'e')
+                {
+                        index += 5;
+                        return JsonTokenFalse;
+                }
+        }
+
+        //Null
+        if (remainingLength >= 4)
+        {
+                if (json[index] == 'n' && json[index + 1] == 'u' &&
+                        json[index + 2] == 'l' && json[index + 3] == 'l')
+                {
+                        index += 4;
+                        return JsonTokenNull;
+                }
+        }
+
+        return JsonTokenNone;
+}
+*****/
diff --git a/src/scripting/toplevel/JSON.h b/src/scripting/toplevel/JSON.h
new file mode 100644
index 0000000..1614cc7
--- /dev/null
+++ b/src/scripting/toplevel/JSON.h
@@ -0,0 +1,51 @@
+/**************************************************************************
+    Lightspark, a free flash player implementation
+
+    Copyright (C) 2009-2013  Alessandro Pignotti (a.pignotti at sssup.it)
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+**************************************************************************/
+
+#ifndef SCRIPTING_TOPLEVEL_JSON_H
+#define SCRIPTING_TOPLEVEL_JSON_H 1
+#include "compat.h"
+#include "asobject.h"
+
+namespace lightspark
+{
+
+class JSON : public ASObject
+{
+public:
+	JSON(Class_base* c);
+	static void sinit(Class_base* c);
+	static void buildTraits(ASObject* o);
+	ASFUNCTION(_constructor);
+	ASFUNCTION(generator);
+	ASFUNCTION(_parse);
+	ASFUNCTION(_stringify);
+private:
+	static void parseAll(const tiny_string &jsonstring, ASObject** parent , const multiname& key, IFunction *reviver);
+	static int parse(const tiny_string &jsonstring, int pos, ASObject **parent, const multiname &key,IFunction* reviver);
+	static int parseTrue(const tiny_string &jsonstring, int pos, ASObject **parent, const multiname &key);
+	static int parseFalse(const tiny_string &jsonstring, int pos, ASObject **parent, const multiname &key);
+	static int parseNull(const tiny_string &jsonstring, int pos, ASObject **parent, const multiname &key);
+	static int parseString(const tiny_string &jsonstring, int pos, ASObject **parent, const multiname &key, tiny_string *result = NULL);
+	static int parseNumber(const tiny_string &jsonstring, int pos, ASObject **parent, const multiname &key);
+	static int parseObject(const tiny_string &jsonstring, int pos, ASObject **parent, const multiname &key, IFunction *reviver);
+	static int parseArray(const tiny_string &jsonstring, int pos, ASObject **parent, const multiname &key, IFunction *reviver);
+};
+
+}
+#endif /* SCRIPTING_TOPLEVEL_JSON_H */
diff --git a/src/scripting/toplevel/Math.cpp b/src/scripting/toplevel/Math.cpp
index da4ffed..a4822b4 100644
--- a/src/scripting/toplevel/Math.cpp
+++ b/src/scripting/toplevel/Math.cpp
@@ -26,9 +26,7 @@ using namespace lightspark;
 
 void Math::sinit(Class_base* c)
 {
-	c->isFinal=true;
-	c->setSuper(Class<ASObject>::getRef());
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_SEALED | CLASS_FINAL);
 	// public constants
 	c->setVariableByQName("E","",abstract_d(2.71828182845905),CONSTANT_TRAIT);
 	c->setVariableByQName("LN10","",abstract_d(2.302585092994046),CONSTANT_TRAIT);
diff --git a/src/scripting/toplevel/Number.cpp b/src/scripting/toplevel/Number.cpp
index 7c4dbaa..d91b2ac 100644
--- a/src/scripting/toplevel/Number.cpp
+++ b/src/scripting/toplevel/Number.cpp
@@ -20,6 +20,7 @@
 #include "parsing/amf3_generator.h"
 #include "scripting/argconv.h"
 #include "scripting/toplevel/Number.h"
+#include "scripting/flash/utils/ByteArray.h"
 
 using namespace std;
 using namespace lightspark;
@@ -258,24 +259,23 @@ tiny_string Number::toStringRadix(number_t val, int radix)
 
 void Number::sinit(Class_base* c)
 {
-	c->isFinal = true;
-	c->setSuper(Class<ASObject>::getRef());
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	//Must create and link the number the hard way
-	Number* ninf=new (c->memoryAccount) Number(c, -numeric_limits<double>::infinity());
-	Number* pinf=new (c->memoryAccount) Number(c, numeric_limits<double>::infinity());
-	Number* pmax=new (c->memoryAccount) Number(c, numeric_limits<double>::max());
-	Number* pmin=new (c->memoryAccount) Number(c, numeric_limits<double>::min());
-	Number* pnan=new (c->memoryAccount) Number(c, numeric_limits<double>::quiet_NaN());
-	c->setVariableByQName("NEGATIVE_INFINITY","",ninf,CONSTANT_TRAIT);
-	c->setVariableByQName("POSITIVE_INFINITY","",pinf,CONSTANT_TRAIT);
-	c->setVariableByQName("MAX_VALUE","",pmax,CONSTANT_TRAIT);
-	c->setVariableByQName("MIN_VALUE","",pmin,CONSTANT_TRAIT);
-	c->setVariableByQName("NaN","",pnan,CONSTANT_TRAIT);
-	c->prototype->setVariableByQName("toString",AS3,Class<IFunction>::getFunction(Number::_toString),DYNAMIC_TRAIT);
-	c->prototype->setVariableByQName("toLocaleString",AS3,Class<IFunction>::getFunction(Number::_toString),DYNAMIC_TRAIT);
-	c->prototype->setVariableByQName("toFixed",AS3,Class<IFunction>::getFunction(Number::toFixed),DYNAMIC_TRAIT);
-	c->prototype->setVariableByQName("valueOf",AS3,Class<IFunction>::getFunction(_valueOf),DYNAMIC_TRAIT);
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_SEALED | CLASS_FINAL);
+	c->setVariableByQName("NEGATIVE_INFINITY","",abstract_d(-numeric_limits<double>::infinity()),CONSTANT_TRAIT);
+	c->setVariableByQName("POSITIVE_INFINITY","",abstract_d(numeric_limits<double>::infinity()),CONSTANT_TRAIT);
+	c->setVariableByQName("MAX_VALUE","",abstract_d(numeric_limits<double>::max()),CONSTANT_TRAIT);
+	c->setVariableByQName("MIN_VALUE","",abstract_d(numeric_limits<double>::min()),CONSTANT_TRAIT);
+	c->setVariableByQName("NaN","",abstract_d(numeric_limits<double>::quiet_NaN()),CONSTANT_TRAIT);
+	c->setDeclaredMethodByQName("toString",AS3,Class<IFunction>::getFunction(_toString),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("toFixed",AS3,Class<IFunction>::getFunction(toFixed,1),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("toExponential",AS3,Class<IFunction>::getFunction(toExponential,1),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("toPrecision",AS3,Class<IFunction>::getFunction(toPrecision,1),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("valueOf",AS3,Class<IFunction>::getFunction(_valueOf),NORMAL_METHOD,true);
+	c->prototype->setVariableByQName("toString","",Class<IFunction>::getFunction(Number::_toString),DYNAMIC_TRAIT);
+	c->prototype->setVariableByQName("toLocaleString","",Class<IFunction>::getFunction(Number::_toString),DYNAMIC_TRAIT);
+	c->prototype->setVariableByQName("toFixed","",Class<IFunction>::getFunction(Number::toFixed, 1),DYNAMIC_TRAIT);
+	c->prototype->setVariableByQName("toExponential","",Class<IFunction>::getFunction(Number::toExponential, 1),DYNAMIC_TRAIT);
+	c->prototype->setVariableByQName("toPrecision","",Class<IFunction>::getFunction(Number::toPrecision, 1),DYNAMIC_TRAIT);
+	c->prototype->setVariableByQName("valueOf","",Class<IFunction>::getFunction(_valueOf),DYNAMIC_TRAIT);
 }
 
 ASFUNCTIONBODY(Number,_constructor)
@@ -283,7 +283,9 @@ ASFUNCTIONBODY(Number,_constructor)
 	Number* th=static_cast<Number*>(obj);
 	if(argslen==0)
 	{
-		//The number is already initialized to NaN
+		// not constructed Numbers are set to NaN, so we have to set it to the default value during dynamic construction
+		if (std::isnan(th->val))
+			th->val = 0.;
 		return NULL;
 	}
 	th->val=args[0]->toNumber();
@@ -293,39 +295,190 @@ ASFUNCTIONBODY(Number,_constructor)
 ASFUNCTIONBODY(Number,toFixed)
 {
 	number_t val = obj->toNumber();
-	int fractiondigits=0;
+	int fractiondigits;
 	ARG_UNPACK (fractiondigits,0);
+	return Class<ASString>::getInstanceS(toFixedString(val, fractiondigits));
+}
+
+tiny_string Number::toFixedString(double v, int32_t fractiondigits)
+{
 	if (fractiondigits < 0 || fractiondigits > 20)
-		throwError<RangeError>(kInvalidPrecisionError, Integer::toString(fractiondigits));
-	if(std::isnan(val))
-		return  Class<ASString>::getInstanceS("NaN");
+		throwError<RangeError>(kInvalidPrecisionError);
+	if (std::isnan(v))
+		return  "NaN";
+	if (v >= pow(10., 21))
+		return toString(v);
 	number_t fractpart, intpart;
-	if (fractiondigits == 0)
-		val+=0.5;
-	fractpart = modf (val , &intpart);
+	double rounded = v + 0.5*pow(10., -fractiondigits);
+	fractpart = modf(rounded , &intpart);
 
 	tiny_string res("");
-	number_t v = fabs(intpart);
 	char buf[40];
-	snprintf(buf,40,"%ld",int64_t(v));
+	snprintf(buf,40,"%ld",int64_t(fabs(intpart)));
 	res += buf;
 	
 	if (fractiondigits > 0)
 	{
-		int x = fractiondigits;
+		number_t x = fractpart;
 		res += ".";
-		while (fractiondigits) 
+		for (int i=0; i<fractiondigits; i++)
 		{
-			fractpart*=10.0;
-			fractiondigits--;
+			x*=10.0;
+			int n = (int)x;
+			x -= n;
+			res += tiny_string::fromChar('0' + n);
 		}
-		fractpart+=0.5;
-		snprintf(buf,40,"%0*ld",x,int64_t(fractpart));
-		res += buf;
 	}
-	if ( val < 0)
+	if ( v < 0)
 		res = tiny_string::fromChar('-')+res;
-	return Class<ASString>::getInstanceS(res);
+	return res;
+}
+
+ASFUNCTIONBODY(Number,toExponential)
+{
+	Number* th=obj->as<Number>();
+	double v = th->val;
+	int32_t fractionDigits;
+	ARG_UNPACK(fractionDigits, 0);
+	if (argslen == 0 || args[0]->is<Undefined>())
+		fractionDigits = imin(imax(Number::countSignificantDigits(v)-1, 1), 20);
+	return Class<ASString>::getInstanceS(toExponentialString(v, fractionDigits));
+}
+
+tiny_string Number::toExponentialString(double v, int32_t fractionDigits)
+{
+	if (std::isnan(v) || std::isinf(v))
+		return toString(v);
+
+	tiny_string res;
+	if (v < 0)
+	{
+		res = "-";
+		v = -v;
+	}
+
+	if (fractionDigits < 0 || fractionDigits > 20)
+		throwError<RangeError>(kInvalidPrecisionError);
+	
+	char buf[40];
+	snprintf(buf,40,"%.*e", fractionDigits, v);
+	res += buf;
+	res = purgeExponentLeadingZeros(res);
+	return res;
+}
+
+tiny_string Number::purgeExponentLeadingZeros(const tiny_string& exponentialForm)
+{
+	uint32_t i = exponentialForm.find("e");
+	if (i == tiny_string::npos)
+		return exponentialForm;
+
+	tiny_string res;
+	res = exponentialForm.substr(0, i+1);
+
+	i++;
+	if (i >= exponentialForm.numChars())
+		return res;
+
+	uint32_t c = exponentialForm.charAt(i);
+	if (c == '-' || c == '+')
+	{
+		res += c;
+		i++;
+	}
+
+	bool leadingZero = true;
+	while (i < exponentialForm.numChars())
+	{
+		uint32_t c = exponentialForm.charAt(i);
+		if (!leadingZero || (leadingZero && c != '0'))
+		{
+			res += c;
+			leadingZero = false;
+		}
+
+		i++;
+	}
+
+	if (leadingZero)
+		res += '0';
+
+	return res;
+}
+
+/*
+ * Should return the number of significant decimal digits necessary to
+ * uniquely specify v. The actual implementation is a quick-and-dirty
+ * approximation.
+ */
+int32_t Number::countSignificantDigits(double v) {
+	char buf[40];
+	snprintf(buf,40,"%.20e", v);
+	
+	char *p = &buf[0];
+	while (*p == '0' || *p == '.')
+		p++;
+	
+	int32_t digits = 0;
+	int32_t consecutiveZeros = 0;
+	while ((('0' <= *p && *p <= '9') || *p == '.') && consecutiveZeros < 10)
+	{
+		if (*p != '.')
+			digits++;
+
+		if (*p == '0')
+			consecutiveZeros++;
+		else if (*p != '.')
+			consecutiveZeros = 0;
+		p++;
+	}
+
+	digits -= consecutiveZeros;
+
+	if (digits <= 0)
+		digits = 1;
+
+	return digits;
+}
+
+ASFUNCTIONBODY(Number,toPrecision)
+{
+	Number* th=obj->as<Number>();
+	double v = th->val;
+	if (argslen == 0 || args[0]->is<Undefined>())
+		return Class<ASString>::getInstanceS(toString(v));
+
+	int32_t precision;
+	ARG_UNPACK(precision);
+	return Class<ASString>::getInstanceS(toPrecisionString(v, precision));
+}
+
+tiny_string Number::toPrecisionString(double v, int32_t precision)
+{
+	if (precision < 1 || precision > 21)
+	{
+		throwError<RangeError>(kInvalidPrecisionError);
+		return NULL;
+	}
+	else if (std::isnan(v) || std::isinf(v))
+		return toString(v);
+	else if (::fabs(v) > pow(10., precision))
+		return toExponentialString(v, precision-1);
+	else if (v == 0)
+	{
+		tiny_string zero = "0.";
+		for (int i=0; i<precision; i++)
+			zero += "0";
+		return zero;
+	}
+	else
+	{
+		int n = (int)::ceil(::log10(::fabs(v)));
+		if (n < 0)
+			return toExponentialString(v, precision-1);
+		else
+			return toFixedString(v, precision-n);
+	}
 }
 
 ASFUNCTIONBODY(Number,_valueOf)
diff --git a/src/scripting/toplevel/Number.h b/src/scripting/toplevel/Number.h
index f03ddb0..ead2bb9 100644
--- a/src/scripting/toplevel/Number.h
+++ b/src/scripting/toplevel/Number.h
@@ -34,17 +34,24 @@ friend class ABCContext;
 friend class ABCVm;
 private:
 	static void purgeTrailingZeroes(char* buf);
+	static tiny_string purgeExponentLeadingZeros(const tiny_string& exponentialForm);
+	static int32_t countSignificantDigits(double v);
 public:
-	Number(Class_base* c, double v=0.):ASObject(c),val(v){type=T_NUMBER;}
+	Number(Class_base* c, double v=(std::numeric_limits<double>::quiet_NaN())):ASObject(c),val(v){type=T_NUMBER;}
 	static const number_t NaN;
 	double val;
 	ASFUNCTION(_constructor);
 	ASFUNCTION(_toString);
+	ASFUNCTION(toExponential);
+	ASFUNCTION(toPrecision);
 	ASFUNCTION(toFixed);
 	ASFUNCTION(_valueOf);
 	tiny_string toString();
 	static tiny_string toString(number_t val);
 	static tiny_string toStringRadix(number_t val, int radix);
+	static tiny_string toExponentialString(double v, int32_t fractionDigits);
+	static tiny_string toFixedString(double v, int32_t fractionDigits);
+	static tiny_string toPrecisionString(double v, int32_t precision);
 	static bool isInteger(number_t val)
 	{
 		return floor(val) == val;
diff --git a/src/scripting/toplevel/RegExp.cpp b/src/scripting/toplevel/RegExp.cpp
index 1e1c5d5..0d029a2 100644
--- a/src/scripting/toplevel/RegExp.cpp
+++ b/src/scripting/toplevel/RegExp.cpp
@@ -35,12 +35,16 @@ RegExp::RegExp(Class_base* c, const tiny_string& _re):ASObject(c),dotall(false),
 
 void RegExp::sinit(Class_base* c)
 {
-	c->setSuper(Class<ASObject>::getRef());
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_DYNAMIC_NOT_FINAL);
+	c->setDeclaredMethodByQName("exec","",Class<IFunction>::getFunction(exec),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("exec",AS3,Class<IFunction>::getFunction(exec),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("test","",Class<IFunction>::getFunction(test),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("test",AS3,Class<IFunction>::getFunction(test),NORMAL_METHOD,true);
-	c->prototype->setVariableByQName("toString",AS3,Class<IFunction>::getFunction(_toString),DYNAMIC_TRAIT);
+	c->setDeclaredMethodByQName("toString","",Class<IFunction>::getFunction(_toString),NORMAL_METHOD,true);
+	c->prototype->setVariableByQName("toString","",Class<IFunction>::getFunction(_toString),DYNAMIC_TRAIT);
+	c->prototype->setVariableByQName("exec","",Class<IFunction>::getFunction(exec),DYNAMIC_TRAIT);
 	c->prototype->setVariableByQName("exec",AS3,Class<IFunction>::getFunction(exec),DYNAMIC_TRAIT);
+	c->prototype->setVariableByQName("test","",Class<IFunction>::getFunction(test),DYNAMIC_TRAIT);
 	c->prototype->setVariableByQName("test",AS3,Class<IFunction>::getFunction(test),DYNAMIC_TRAIT);
 	REGISTER_GETTER(c,dotall);
 	REGISTER_GETTER(c,global);
@@ -257,6 +261,8 @@ ASFUNCTIONBODY(RegExp,test)
 
 ASFUNCTIONBODY(RegExp,_toString)
 {
+	if(Class<RegExp>::getClass()->prototype->getObj() == obj)
+		return Class<ASString>::getInstanceS("/(?:)/");
 	if(!obj->is<RegExp>())
 		throw Class<TypeError>::getInstanceS("RegExp.toString is not generic");
 
diff --git a/src/scripting/toplevel/UInteger.cpp b/src/scripting/toplevel/UInteger.cpp
index 3a1fc96..ebac801 100644
--- a/src/scripting/toplevel/UInteger.cpp
+++ b/src/scripting/toplevel/UInteger.cpp
@@ -17,6 +17,7 @@
     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 **************************************************************************/
 
+#include <cmath>
 #include "scripting/argconv.h"
 #include "scripting/toplevel/UInteger.h"
 
@@ -115,17 +116,26 @@ ASFUNCTIONBODY(UInteger,_valueOf)
 
 void UInteger::sinit(Class_base* c)
 {
-	c->isFinal = true;
-	c->setSuper(Class<ASObject>::getRef());
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_SEALED | CLASS_FINAL);
 	c->setVariableByQName("MAX_VALUE","",abstract_ui(0xFFFFFFFF),CONSTANT_TRAIT);
 	c->setVariableByQName("MIN_VALUE","",abstract_ui(0),CONSTANT_TRAIT);
-	c->prototype->setVariableByQName("toString",AS3,Class<IFunction>::getFunction(_toString),DYNAMIC_TRAIT);
-	c->prototype->setVariableByQName("valueOf",AS3,Class<IFunction>::getFunction(_valueOf),DYNAMIC_TRAIT);
+	c->setDeclaredMethodByQName("toString",AS3,Class<IFunction>::getFunction(_toString),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("toFixed",AS3,Class<IFunction>::getFunction(_toFixed,1),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("toExponential",AS3,Class<IFunction>::getFunction(_toExponential,1),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("toPrecision",AS3,Class<IFunction>::getFunction(_toPrecision,1),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("valueOf",AS3,Class<IFunction>::getFunction(_valueOf),NORMAL_METHOD,true);
+	c->prototype->setVariableByQName("toExponential","",Class<IFunction>::getFunction(_toExponential, 1),DYNAMIC_TRAIT);
+	c->prototype->setVariableByQName("toFixed","",Class<IFunction>::getFunction(_toFixed, 1),DYNAMIC_TRAIT);
+	c->prototype->setVariableByQName("toPrecision","",Class<IFunction>::getFunction(_toPrecision, 1),DYNAMIC_TRAIT);
+	c->prototype->setVariableByQName("toString","",Class<IFunction>::getFunction(_toString),DYNAMIC_TRAIT);
+	c->prototype->setVariableByQName("valueOf","",Class<IFunction>::getFunction(_valueOf),DYNAMIC_TRAIT);
 }
 
 ASFUNCTIONBODY(UInteger,_toString)
 {
+	if(Class<UInteger>::getClass()->prototype->getObj() == obj)
+		return Class<ASString>::getInstanceS("0");
+
 	UInteger* th=static_cast<UInteger*>(obj);
 	uint32_t radix;
 	ARG_UNPACK (radix,10);
@@ -160,3 +170,37 @@ bool UInteger::isEqual(ASObject* o)
 			return o->isEqual(this);
 	}
 }
+
+ASFUNCTIONBODY(UInteger,_toExponential)
+{
+	UInteger *th=obj->as<UInteger>();
+	double v = (double)th->val;
+	int32_t fractionDigits;
+	ARG_UNPACK(fractionDigits, 0);
+	if (argslen == 0 || args[0]->is<Undefined>())
+	{
+		if (v == 0)
+			fractionDigits = 1;
+		else
+			fractionDigits = imin(imax((int32_t)ceil(::log10(v)), 1), 20);
+	}
+	return Class<ASString>::getInstanceS(Number::toExponentialString(v, fractionDigits));
+}
+
+ASFUNCTIONBODY(UInteger,_toFixed)
+{
+	UInteger *th=obj->as<UInteger>();
+	int fractiondigits;
+	ARG_UNPACK (fractiondigits, 0);
+	return Class<ASString>::getInstanceS(Number::toFixedString(th->val, fractiondigits));
+}
+
+ASFUNCTIONBODY(UInteger,_toPrecision)
+{
+	UInteger *th=obj->as<UInteger>();
+	if (argslen == 0 || args[0]->is<Undefined>())
+		return Class<ASString>::getInstanceS(th->toString());
+	int precision;
+	ARG_UNPACK (precision);
+	return Class<ASString>::getInstanceS(Number::toPrecisionString(th->val, precision));
+}
diff --git a/src/scripting/toplevel/UInteger.h b/src/scripting/toplevel/UInteger.h
index fe0fbcc..197c590 100644
--- a/src/scripting/toplevel/UInteger.h
+++ b/src/scripting/toplevel/UInteger.h
@@ -49,6 +49,9 @@ public:
 	ASFUNCTION(generator);
 	ASFUNCTION(_toString);
 	ASFUNCTION(_valueOf);
+	ASFUNCTION(_toExponential);
+	ASFUNCTION(_toFixed);
+	ASFUNCTION(_toPrecision);
 	std::string toDebugString() { return toString()+"ui"; }
 	//CHECK: should this have a special serialization?
 };
diff --git a/src/scripting/toplevel/Vector.cpp b/src/scripting/toplevel/Vector.cpp
index 383982d..a97f12a 100644
--- a/src/scripting/toplevel/Vector.cpp
+++ b/src/scripting/toplevel/Vector.cpp
@@ -28,31 +28,48 @@ using namespace lightspark;
 
 void Vector::sinit(Class_base* c)
 {
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setSuper(Class<ASObject>::getRef());
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_FINAL);
 	c->setDeclaredMethodByQName("length","",Class<IFunction>::getFunction(getLength),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("length","",Class<IFunction>::getFunction(setLength),SETTER_METHOD,true);
 	c->setDeclaredMethodByQName("toString","",Class<IFunction>::getFunction(_toString),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("toString",AS3,Class<IFunction>::getFunction(_toString),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("fixed","",Class<IFunction>::getFunction(getFixed),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("fixed","",Class<IFunction>::getFunction(setFixed),SETTER_METHOD,true);
+	c->setDeclaredMethodByQName("concat","",Class<IFunction>::getFunction(_concat),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("concat",AS3,Class<IFunction>::getFunction(_concat),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("every","",Class<IFunction>::getFunction(every),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("every",AS3,Class<IFunction>::getFunction(every),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("filter","",Class<IFunction>::getFunction(filter),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("filter",AS3,Class<IFunction>::getFunction(filter),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("forEach","",Class<IFunction>::getFunction(forEach),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("forEach",AS3,Class<IFunction>::getFunction(forEach),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("indexOf","",Class<IFunction>::getFunction(indexOf),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("indexOf",AS3,Class<IFunction>::getFunction(indexOf),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("lastIndexOf","",Class<IFunction>::getFunction(lastIndexOf),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("lastIndexOf",AS3,Class<IFunction>::getFunction(lastIndexOf),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("join","",Class<IFunction>::getFunction(join),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("join",AS3,Class<IFunction>::getFunction(join),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("map","",Class<IFunction>::getFunction(_map),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("map",AS3,Class<IFunction>::getFunction(_map),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("pop","",Class<IFunction>::getFunction(_pop),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("pop",AS3,Class<IFunction>::getFunction(_pop),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("push","",Class<IFunction>::getFunction(push),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("push",AS3,Class<IFunction>::getFunction(push),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("reverse","",Class<IFunction>::getFunction(_reverse),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("reverse",AS3,Class<IFunction>::getFunction(_reverse),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("shift","",Class<IFunction>::getFunction(shift),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("shift",AS3,Class<IFunction>::getFunction(shift),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("slice","",Class<IFunction>::getFunction(slice),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("slice",AS3,Class<IFunction>::getFunction(slice),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("some","",Class<IFunction>::getFunction(some),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("some",AS3,Class<IFunction>::getFunction(some),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("sort","",Class<IFunction>::getFunction(_sort),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("sort",AS3,Class<IFunction>::getFunction(_sort),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("splice","",Class<IFunction>::getFunction(splice),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("splice",AS3,Class<IFunction>::getFunction(splice),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("toLocaleString","",Class<IFunction>::getFunction(_toString),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("toLocaleString",AS3,Class<IFunction>::getFunction(_toString),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("unshift","",Class<IFunction>::getFunction(unshift),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("unshift",AS3,Class<IFunction>::getFunction(unshift),NORMAL_METHOD,true);
 	
 
@@ -77,7 +94,7 @@ void Vector::sinit(Class_base* c)
 	c->prototype->setVariableByQName("unshift",AS3,Class<IFunction>::getFunction(unshift),DYNAMIC_TRAIT);
 }
 
-Vector::Vector(Class_base* c, Type *vtype):ASObject(c),vec_type(vtype),fixed(false),vec(reporter_allocator<ASObject*>(c->memoryAccount))
+Vector::Vector(Class_base* c, const Type *vtype):ASObject(c),vec_type(vtype),fixed(false),vec(reporter_allocator<ASObject*>(c->memoryAccount))
 {
 }
 
@@ -97,18 +114,16 @@ void Vector::finalize()
 	ASObject::finalize();
 }
 
-void Vector::setTypes(const std::vector<Type*>& types)
+void Vector::setTypes(const std::vector<const Type *> &types)
 {
 	assert(vec_type == NULL);
-	assert_and_throw(types.size() == 1);
-	vec_type = types[0];
+	if(types.size() == 1)
+		vec_type = types[0];
 }
-
-bool Vector::sameType(const std::vector<Type*>& types) const
+bool Vector::sameType(const QName& classname) const
 {
-	return (types.size() == 1) && ((types[0] == vec_type) ||
-				       (vec_type == Type::anyType) ||
-				       (types[0] == Type::anyType));
+	tiny_string clsname = this->getClass()->getQualifiedClassName();
+	return (clsname.startsWith(classname.getQualifiedName().raw_buf()));
 }
 
 ASObject* Vector::generator(TemplatedClass<Vector>* o_class, ASObject* const* args, const unsigned int argslen)
@@ -117,7 +132,7 @@ ASObject* Vector::generator(TemplatedClass<Vector>* o_class, ASObject* const* ar
 	assert_and_throw(args[0]->getClass());
 	assert_and_throw(o_class->getTypes().size() == 1);
 
-	Type* type = o_class->getTypes()[0];
+	const Type* type = o_class->getTypes()[0];
 
 	if(args[0]->getClass() == Class<Array>::getClass())
 	{
@@ -127,10 +142,10 @@ ASObject* Vector::generator(TemplatedClass<Vector>* o_class, ASObject* const* ar
 		Array* a = static_cast<Array*>(args[0]);
 		for(unsigned int i=0;i<a->size();++i)
 		{
-			ASObject* obj = a->at(i).getPtr();
+			_R<ASObject> obj = a->at(i);
 			obj->incRef();
 			//Convert the elements of the array to the type of this vector
-			ret->vec.push_back( type->coerce(obj) );
+			ret->vec.push_back( type->coerce(obj.getPtr()) );
 		}
 		return ret;
 	}
@@ -717,6 +732,45 @@ ASFUNCTIONBODY(Vector,indexOf)
 	}
 	return abstract_i(ret);
 }
+bool Vector::sortComparatorDefault::operator()(ASObject* d1, ASObject* d2)
+{
+	if(isNumeric)
+	{
+		number_t a=d1->toNumber();
+
+		number_t b=d2->toNumber();
+
+		if(std::isnan(a) || std::isnan(b))
+			throw RunTimeException("Cannot sort non number with Array.NUMERIC option");
+		if(isDescending)
+			return b>a;
+		else
+			return a<b;
+	}
+	else
+	{
+		//Comparison is always in lexicographic order
+		tiny_string s1 = d1->toString();
+		tiny_string s2 = d2->toString();
+
+		if(isDescending)
+		{
+			//TODO: unicode support
+			if(isCaseInsensitive)
+				return s1.strcasecmp(s2)>0;
+			else
+				return s1>s2;
+		}
+		else
+		{
+			//TODO: unicode support
+			if(isCaseInsensitive)
+				return s1.strcasecmp(s2)<0;
+			else
+				return s1<s2;
+		}
+	}
+}
 bool Vector::sortComparatorWrapper::operator()(ASObject* d1, ASObject* d2)
 {
 	ASObject* objs[2];
@@ -747,10 +801,44 @@ ASFUNCTIONBODY(Vector,_sort)
 		throwError<ArgumentError>(kWrongArgumentCountError, "Vector.sort", "1", Integer::toString(argslen));
 	Vector* th=static_cast<Vector*>(obj);
 	
-	IFunction* comp=static_cast<IFunction*>(args[0]);
+	IFunction* comp=NULL;
+	bool isNumeric=false;
+	bool isCaseInsensitive=false;
+	bool isDescending=false;
+	if(args[0]->getObjectType()==T_FUNCTION) //Comparison func
+	{
+		assert_and_throw(comp==NULL);
+		comp=static_cast<IFunction*>(args[0]);
+	}
+	else
+	{
+		uint32_t options=args[0]->toInt();
+		if(options&Array::NUMERIC)
+			isNumeric=true;
+		if(options&Array::CASEINSENSITIVE)
+			isCaseInsensitive=true;
+		if(options&Array::DESCENDING)
+			isDescending=true;
+		if(options&(~(Array::NUMERIC|Array::CASEINSENSITIVE|Array::DESCENDING)))
+			throw UnsupportedException("Vector::sort not completely implemented");
+	}
+	std::vector<ASObject*> tmp = vector<ASObject*>(th->vec.size());
+	int i = 0;
+	for(auto it=th->vec.begin();it != th->vec.end();++it)
+	{
+		tmp[i++]= *it;
+	}
 	
+	if(comp)
+		sort(tmp.begin(),tmp.end(),sortComparatorWrapper(comp,th->vec_type));
+	else
+		sort(tmp.begin(),tmp.end(),sortComparatorDefault(isNumeric,isCaseInsensitive,isDescending));
 
-	sort(th->vec.begin(),th->vec.end(),sortComparatorWrapper(comp,th->vec_type));
+	th->vec.clear();
+	for(auto ittmp=tmp.begin();ittmp != tmp.end();++ittmp)
+	{
+		th->vec.push_back(*ittmp);
+	}
 	obj->incRef();
 	return obj;
 }
@@ -782,10 +870,17 @@ ASFUNCTIONBODY(Vector,unshift)
 ASFUNCTIONBODY(Vector,_map)
 {
 	Vector* th=static_cast<Vector*>(obj);
-	assert_and_throw(argslen==1 && args[0]->getObjectType()==T_FUNCTION);
-	IFunction* func=static_cast<IFunction*>(args[0]);
+	_NR<IFunction> func;
+	_NR<ASObject> thisObject;
+	
+	if (argslen >= 1 && !args[0]->is<IFunction>())
+		throwError<TypeError>(kCheckTypeFailedError, args[0]->getClassName(), "Function");
+
+	ARG_UNPACK(func)(thisObject,NullRef);
+	
 	Vector* ret= (Vector*)obj->getClass()->getInstance(true,NULL,0);
 
+	ASObject* thisObj;
 	for(uint32_t i=0;i<th->size();i++)
 	{
 		ASObject* funcArgs[3];
@@ -804,7 +899,14 @@ ASFUNCTIONBODY(Vector,_map)
 		funcArgs[1]=abstract_i(i);
 		funcArgs[2]=th;
 		funcArgs[2]->incRef();
-		ASObject* funcRet=func->call(getSys()->getNullRef(), funcArgs, 3);
+		if (thisObject.isNull())
+			thisObj = getSys()->getNullRef();
+		else
+		{
+			thisObj = thisObject.getPtr();
+			thisObj->incRef();
+		}
+		ASObject* funcRet=func->call(thisObj, funcArgs, 3);
 		assert_and_throw(funcRet);
 		ret->vec.push_back(funcRet);
 	}
@@ -975,3 +1077,11 @@ bool Vector::isValidMultiname(const multiname& name, uint32_t& index)
 
 	return validIndex;
 }
+
+ASObject* Vector::at(unsigned int index, ASObject *defaultValue) const
+{
+	if (index < vec.size())
+		return vec.at(index);
+	else
+		return defaultValue;
+}
diff --git a/src/scripting/toplevel/Vector.h b/src/scripting/toplevel/Vector.h
index 4cfd87a..93e5cef 100644
--- a/src/scripting/toplevel/Vector.h
+++ b/src/scripting/toplevel/Vector.h
@@ -28,29 +28,39 @@ namespace lightspark
 template<class T> class TemplatedClass;
 class Vector: public ASObject
 {
-	Type* vec_type;
+	const Type* vec_type;
 	bool fixed;
 	std::vector<ASObject*, reporter_allocator<ASObject*>> vec;
 	int capIndex(int i) const;
+	class sortComparatorDefault
+	{
+	private:
+		bool isNumeric;
+		bool isCaseInsensitive;
+		bool isDescending;
+	public:
+		sortComparatorDefault(bool n, bool ci, bool d):isNumeric(n),isCaseInsensitive(ci),isDescending(d){}
+		bool operator()(ASObject* d1, ASObject* d2);
+	};
 	class sortComparatorWrapper
 	{
 	private:
 		IFunction* comparator;
-		Type* vec_type;
+		const Type* vec_type;
 	public:
-		sortComparatorWrapper(IFunction* c, Type* v):comparator(c),vec_type(v){}
+		sortComparatorWrapper(IFunction* c, const Type* v):comparator(c),vec_type(v){}
 		bool operator()(ASObject* d1, ASObject* d2);
 	};
 public:
-	Vector(Class_base* c, Type *vtype=NULL);
+	Vector(Class_base* c, const Type *vtype=NULL);
 	~Vector();
 	void finalize();
 	static void sinit(Class_base* c);
 	static void buildTraits(ASObject* o) {};
 	static ASObject* generator(TemplatedClass<Vector>* o_class, ASObject* const* args, const unsigned int argslen);
 
-	void setTypes(const std::vector<Type*>& types);
-	bool sameType(const std::vector<Type*>& types) const;
+	void setTypes(const std::vector<const Type*>& types);
+	bool sameType(const QName& classname) const;
 
 	//Overloads
 	tiny_string toString(bool debugMsg=false);
@@ -71,6 +81,9 @@ public:
         {
                 return vec.at(index);
         }
+	//Get value at index, or return defaultValue (a borrowed
+	//reference) if index is out-of-range
+	ASObject* at(unsigned int index, ASObject *defaultValue) const;
 
 	//Appends an object to the Vector. o is coerced to vec_type.
 	//Takes ownership of o.
@@ -78,7 +91,6 @@ public:
 
 	//TODO: do we need to implement generator?
 	ASFUNCTION(_constructor);
-	ASFUNCTION(_applytype);
 
 	ASFUNCTION(push);
 	ASFUNCTION(_concat);
diff --git a/src/scripting/toplevel/XML.cpp b/src/scripting/toplevel/XML.cpp
index 16f0325..3864f2c 100644
--- a/src/scripting/toplevel/XML.cpp
+++ b/src/scripting/toplevel/XML.cpp
@@ -28,47 +28,70 @@
 #include <libxml/tree.h>
 #include <libxml++/parsers/domparser.h>
 #include <libxml++/nodes/textnode.h>
+#include <libxml++/nodes/entityreference.h>
 
 using namespace std;
 using namespace lightspark;
 
-XML::XML(Class_base* c):ASObject(c),node(NULL),constructed(false),ignoreComments(true)
+static bool ignoreComments;
+static bool ignoreProcessingInstructions;
+static bool ignoreWhitespace;
+static int32_t prettyIndent;
+static bool prettyPrinting;
+
+void setDefaultXMLSettings()
 {
+	ignoreComments = true;
+	ignoreProcessingInstructions = true;
+	ignoreWhitespace = true;
+	prettyIndent = 2;
+	prettyPrinting = true;
 }
 
-XML::XML(Class_base* c,const string& str):ASObject(c),node(NULL),constructed(true)
+XML::XML(Class_base* c):ASObject(c),parentNode(0),nodetype((xmlElementType)0),constructed(false), hasParentNode(false)
 {
-	node=buildFromString(str, false);
 }
 
-XML::XML(Class_base* c,_R<XML> _r, xmlpp::Node* _n):ASObject(c),root(_r),node(_n),constructed(true)
+XML::XML(Class_base* c, const std::string &str):ASObject(c),parentNode(0),nodetype((xmlElementType)0),constructed(false)
 {
-	assert(node);
+	createTree(buildFromString(str, false,&hasParentNode));
 }
 
-XML::XML(Class_base* c,xmlpp::Node* _n):ASObject(c),constructed(true)
+XML::XML(Class_base* c,xmlpp::Node* _n):ASObject(c),parentNode(0),nodetype((xmlElementType)0),constructed(false)
 {
-	assert(_n);
-	node=buildCopy(_n);
-	assert(node);
+	createTree(_n);
 }
 
 void XML::finalize()
 {
 	ASObject::finalize();
-	root.reset();
 }
 
 void XML::sinit(Class_base* c)
 {
-	c->setSuper(Class<ASObject>::getRef());
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_SEALED | CLASS_FINAL);
+	setDefaultXMLSettings();
+
+	c->setDeclaredMethodByQName("ignoreComments","",Class<IFunction>::getFunction(_getIgnoreComments),GETTER_METHOD,false);
+	c->setDeclaredMethodByQName("ignoreComments","",Class<IFunction>::getFunction(_setIgnoreComments),SETTER_METHOD,false);
+	c->setDeclaredMethodByQName("ignoreProcessingInstructions","",Class<IFunction>::getFunction(_getIgnoreProcessingInstructions),GETTER_METHOD,false);
+	c->setDeclaredMethodByQName("ignoreProcessingInstructions","",Class<IFunction>::getFunction(_setIgnoreProcessingInstructions),SETTER_METHOD,false);
+	c->setDeclaredMethodByQName("ignoreWhitespace","",Class<IFunction>::getFunction(_getIgnoreWhitespace),GETTER_METHOD,false);
+	c->setDeclaredMethodByQName("ignoreWhitespace","",Class<IFunction>::getFunction(_setIgnoreWhitespace),SETTER_METHOD,false);
+	c->setDeclaredMethodByQName("prettyIndent","",Class<IFunction>::getFunction(_getPrettyIndent),GETTER_METHOD,false);
+	c->setDeclaredMethodByQName("prettyIndent","",Class<IFunction>::getFunction(_setPrettyIndent),SETTER_METHOD,false);
+	c->setDeclaredMethodByQName("prettyPrinting","",Class<IFunction>::getFunction(_getPrettyPrinting),GETTER_METHOD,false);
+	c->setDeclaredMethodByQName("prettyPrinting","",Class<IFunction>::getFunction(_setPrettyPrinting),SETTER_METHOD,false);
+	c->setDeclaredMethodByQName("settings","",Class<IFunction>::getFunction(_getSettings),NORMAL_METHOD,false);
+	c->setDeclaredMethodByQName("setSettings","",Class<IFunction>::getFunction(_setSettings),NORMAL_METHOD,false);
+	c->setDeclaredMethodByQName("defaultSettings","",Class<IFunction>::getFunction(_getDefaultSettings),NORMAL_METHOD,false);
+
 	c->prototype->setVariableByQName("toString","",Class<IFunction>::getFunction(_toString),DYNAMIC_TRAIT);
 	c->setDeclaredMethodByQName("toString",AS3,Class<IFunction>::getFunction(_toString),NORMAL_METHOD,true);
 	c->prototype->setVariableByQName("valueOf","",Class<IFunction>::getFunction(valueOf),DYNAMIC_TRAIT);
 	c->setDeclaredMethodByQName("valueOf",AS3,Class<IFunction>::getFunction(valueOf),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("toXMLString",AS3,Class<IFunction>::getFunction(toXMLString),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("nodeKind",AS3,Class<IFunction>::getFunction(nodeKind),NORMAL_METHOD,true);
+	c->prototype->setVariableByQName("nodeKind","",Class<IFunction>::getFunction(nodeKind),DYNAMIC_TRAIT);	c->setDeclaredMethodByQName("nodeKind",AS3,Class<IFunction>::getFunction(nodeKind),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("child",AS3,Class<IFunction>::getFunction(child),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("children",AS3,Class<IFunction>::getFunction(children),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("childIndex",AS3,Class<IFunction>::getFunction(childIndex),NORMAL_METHOD,true);
@@ -81,19 +104,29 @@ void XML::sinit(Class_base* c)
 	c->setDeclaredMethodByQName("namespace",AS3,Class<IFunction>::getFunction(_namespace),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("normalize",AS3,Class<IFunction>::getFunction(_normalize),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("descendants",AS3,Class<IFunction>::getFunction(descendants),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("appendChild",AS3,Class<IFunction>::getFunction(appendChild),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("appendChild",AS3,Class<IFunction>::getFunction(_appendChild),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("parent",AS3,Class<IFunction>::getFunction(parent),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("inScopeNamespaces",AS3,Class<IFunction>::getFunction(inScopeNamespaces),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("addNamespace",AS3,Class<IFunction>::getFunction(addNamespace),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("hasSimpleContent",AS3,Class<IFunction>::getFunction(_hasSimpleContent),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("hasComplexContent",AS3,Class<IFunction>::getFunction(_hasComplexContent),NORMAL_METHOD,true);
+	c->prototype->setVariableByQName("hasSimpleContent",AS3,Class<IFunction>::getFunction(_hasSimpleContent),DYNAMIC_TRAIT);
+	c->prototype->setVariableByQName("hasComplexContent",AS3,Class<IFunction>::getFunction(_hasComplexContent),DYNAMIC_TRAIT);
 	c->setDeclaredMethodByQName("text",AS3,Class<IFunction>::getFunction(text),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("elements",AS3,Class<IFunction>::getFunction(elements),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("setLocalName",AS3,Class<IFunction>::getFunction(_setLocalName),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("setName",AS3,Class<IFunction>::getFunction(_setName),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("setNamespace",AS3,Class<IFunction>::getFunction(_setNamespace),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("copy",AS3,Class<IFunction>::getFunction(_copy),NORMAL_METHOD,true);
+	c->prototype->setVariableByQName("copy",AS3,Class<IFunction>::getFunction(_copy),DYNAMIC_TRAIT);
 	c->setDeclaredMethodByQName("setChildren",AS3,Class<IFunction>::getFunction(_setChildren),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("toJSON",AS3,Class<IFunction>::getFunction(_toJSON),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("insertChildAfter",AS3,Class<IFunction>::getFunction(insertChildAfter),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("insertChildBefore",AS3,Class<IFunction>::getFunction(insertChildBefore),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("namespaceDeclarations",AS3,Class<IFunction>::getFunction(namespaceDeclarations),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("removeNamespace",AS3,Class<IFunction>::getFunction(removeNamespace),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("comments",AS3,Class<IFunction>::getFunction(comments),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("processingInstructions",AS3,Class<IFunction>::getFunction(processingInstructions),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("propertyIsEnumerable",AS3,Class<IFunction>::getFunction(_propertyIsEnumerable),NORMAL_METHOD,true);
+	c->prototype->setVariableByQName("hasOwnProperty",AS3,Class<IFunction>::getFunction(_hasOwnProperty),DYNAMIC_TRAIT);
+	c->setDeclaredMethodByQName("prependChild",AS3,Class<IFunction>::getFunction(_prependChild),NORMAL_METHOD,true);
 }
 
 ASFUNCTIONBODY(XML,generator)
@@ -146,7 +179,7 @@ ASFUNCTIONBODY(XML,_constructor)
 	   args[0]->is<Null>() || 
 	   args[0]->is<Undefined>())
 	{
-		th->node=th->buildFromString("", false);
+		th->createTree(th->buildFromString("", false,&th->hasParentNode));
 	}
 	else if(args[0]->getClass()->isSubClass(Class<ByteArray>::getClass()))
 	{
@@ -155,8 +188,8 @@ ASFUNCTIONBODY(XML,_constructor)
 		ByteArray* ba=Class<ByteArray>::cast(args[0]);
 		uint32_t len=ba->getLength();
 		const uint8_t* str=ba->getBuffer(len, false);
-		th->node=th->buildFromString(std::string((const char*)str,len), false,
-					     getVm()->getDefaultXMLNamespace());
+		th->createTree(th->buildFromString(std::string((const char*)str,len), false,&th->hasParentNode,
+					     getVm()->getDefaultXMLNamespace()));
 	}
 	else if(args[0]->is<ASString>() ||
 		args[0]->is<Number>() ||
@@ -166,23 +199,24 @@ ASFUNCTIONBODY(XML,_constructor)
 	{
 		//By specs, XML constructor will only convert to string Numbers or Booleans
 		//ints are not explicitly mentioned, but they seem to work
-		th->node=th->buildFromString(args[0]->toString(), false,
-					     getVm()->getDefaultXMLNamespace());
+		th->createTree(th->buildFromString(args[0]->toString(), false,&th->hasParentNode,
+					     getVm()->getDefaultXMLNamespace()));
 	}
 	else if(args[0]->is<XML>())
 	{
-		th->node=th->buildCopy(args[0]->as<XML>()->node);
+		th->createTree(th->buildFromString(args[0]->as<XML>()->toXMLString_internal(), false,&th->hasParentNode,
+					     getVm()->getDefaultXMLNamespace()));
 	}
 	else if(args[0]->is<XMLList>())
 	{
 		XMLList *list=args[0]->as<XMLList>();
 		_R<XML> reduced=list->reduceToXML();
-		th->node=th->buildCopy(reduced->node);
+		th->createTree(th->buildFromString(reduced->toXMLString_internal(), false,&th->hasParentNode));
 	}
 	else
 	{
-		th->node=th->buildFromString(args[0]->toString(), false,
-					     getVm()->getDefaultXMLNamespace());
+		th->createTree(th->buildFromString(args[0]->toString(), false,&th->hasParentNode,
+					     getVm()->getDefaultXMLNamespace()));
 	}
 	return NULL;
 }
@@ -191,23 +225,26 @@ ASFUNCTIONBODY(XML,nodeKind)
 {
 	XML* th=Class<XML>::cast(obj);
 	assert_and_throw(argslen==0);
-	assert(th->node);
-	xmlNodePtr libXml2Node=th->node->cobj();
-	switch(libXml2Node->type)
+	return Class<ASString>::getInstanceS(th->nodekindString());
+}
+const char *XML::nodekindString()
+{
+	switch(nodetype)
 	{
 		case XML_ATTRIBUTE_NODE:
-			return Class<ASString>::getInstanceS("attribute");
+			return "attribute";
 		case XML_ELEMENT_NODE:
-			return Class<ASString>::getInstanceS("element");
+			return "element";
+		case XML_CDATA_SECTION_NODE:
 		case XML_TEXT_NODE:
-			return Class<ASString>::getInstanceS("text");
+			return "text";
 		case XML_COMMENT_NODE:
-			return Class<ASString>::getInstanceS("comment");
+			return "comment";
 		case XML_PI_NODE:
-			return Class<ASString>::getInstanceS("processing-instruction");
+			return "processing-instruction";
 		default:
 		{
-			LOG(LOG_ERROR,"Unsupported XML type " << libXml2Node->type);
+			LOG(LOG_ERROR,"Unsupported XML type " << nodetype);
 			throw UnsupportedException("Unsupported XML node type");
 		}
 	}
@@ -222,27 +259,23 @@ ASFUNCTIONBODY(XML,localName)
 {
 	XML* th=Class<XML>::cast(obj);
 	assert_and_throw(argslen==0);
-	assert(th->node);
-	xmlElementType nodetype=th->node->cobj()->type;
-	if(nodetype==XML_TEXT_NODE || nodetype==XML_COMMENT_NODE)
+	if(th->nodetype==XML_TEXT_NODE || th->nodetype==XML_COMMENT_NODE)
 		return getSys()->getNullRef();
 	else
-		return Class<ASString>::getInstanceS(th->node->get_name());
+		return Class<ASString>::getInstanceS(th->nodename);
 }
 
 ASFUNCTIONBODY(XML,name)
 {
 	XML* th=Class<XML>::cast(obj);
 	assert_and_throw(argslen==0);
-	assert(th->node);
-	xmlElementType nodetype=th->node->cobj()->type;
 	//TODO: add namespace
-	if(nodetype==XML_TEXT_NODE || nodetype==XML_COMMENT_NODE)
+	if(th->nodetype==XML_TEXT_NODE || th->nodetype==XML_COMMENT_NODE)
 		return getSys()->getNullRef();
 	else
 	{
 		ASQName* ret = Class<ASQName>::getInstanceS();
-		ret->setByNode(th->node);
+		ret->setByXML(th);
 		return ret;
 	}
 }
@@ -250,14 +283,16 @@ ASFUNCTIONBODY(XML,name)
 ASFUNCTIONBODY(XML,descendants)
 {
 	XML* th=Class<XML>::cast(obj);
-	tiny_string name;
-	ARG_UNPACK(name,"*");
- 	XMLVector ret;
-	th->getDescendantsByQName(name,"",ret);
- 	return Class<XMLList>::getInstanceS(ret);
+	_NR<ASObject> name;
+	ARG_UNPACK(name,_NR<ASObject>(Class<ASString>::getInstanceS("*")));
+	XMLVector ret;
+	multiname mname(NULL);
+	name->applyProxyProperty(mname);
+	th->getDescendantsByQName(name->toString(),"",mname.isAttribute,ret);
+	return Class<XMLList>::getInstanceS(ret,th->getChildrenlist(),multiname(NULL));
 }
 
-ASFUNCTIONBODY(XML,appendChild)
+ASFUNCTIONBODY(XML,_appendChild)
 {
 	XML* th=Class<XML>::cast(obj);
 	assert_and_throw(argslen==1);
@@ -282,34 +317,50 @@ ASFUNCTIONBODY(XML,appendChild)
 		arg=_MR(Class<XML>::getInstanceS(args[0]->toString()));
 	}
 
-	th->node->import_node(arg->node, true);
+	th->appendChild(arg);
 	th->incRef();
 	return th;
 }
 
+void XML::appendChild(_R<XML> newChild)
+{
+	if (newChild->constructed)
+	{
+		this->incRef();
+		newChild->parentNode = _NR<XML>(this);
+		childrenlist->append(newChild);
+	}
+	else
+		newChild->decRef();
+}
+
 /* returns the named attribute in an XMLList */
 ASFUNCTIONBODY(XML,attribute)
 {
 	XML* th = obj->as<XML>();
 	tiny_string attrname;
 	//see spec for QName handling
-	if(argslen > 0 && args[0]->is<QName>())
-		LOG(LOG_NOT_IMPLEMENTED,"XML.attribute called with QName");
 	ARG_UNPACK (attrname);
-
-	xmlpp::Element* elem=dynamic_cast<xmlpp::Element*>(th->node);
-        if(elem==NULL)
-		return Class<XMLList>::getInstanceS();
-	xmlpp::Attribute* attribute = elem->get_attribute(attrname);
-	if(!attribute)
+	tiny_string tmpns;
+	if(argslen > 0 && args[0]->is<ASQName>())
 	{
-		LOG(LOG_ERROR,"attribute " << attrname << " not found");
-		return Class<XMLList>::getInstanceS();
+		tmpns= args[0]->as<ASQName>()->getURI();
+		attrname = args[0]->as<ASQName>()->getLocalName();
+			
 	}
 
-	XMLVector ret;
-	ret.push_back(_MR(Class<XML>::getInstanceS(th->getRootNode(), attribute)));
-	return Class<XMLList>::getInstanceS(ret);
+	XMLVector tmp;
+	XMLList* res = Class<XMLList>::getInstanceS(tmp,th->getChildrenlist(),multiname(NULL));
+	for (XMLList::XMLListVector::const_iterator it = th->attributelist->nodes.begin(); it != th->attributelist->nodes.end(); it++)
+	{
+		_R<XML> attr = *it;
+		if (attr->nodenamespace_uri == tmpns && (attrname== "*" || attr->nodename == attrname))
+		{
+			attr->incRef();
+			res->append(attr);
+		}
+	}
+	return res;
 }
 
 ASFUNCTIONBODY(XML,attributes)
@@ -320,144 +371,278 @@ ASFUNCTIONBODY(XML,attributes)
 
 XMLList* XML::getAllAttributes()
 {
-	XML::XMLVector attributes=getAttributes();
-	return Class<XMLList>::getInstanceS(attributes);
+	attributelist->incRef();
+	return attributelist.getPtr();
 }
 
-XML::XMLVector XML::getAttributes(const tiny_string& name,
-				  const tiny_string& namespace_uri)
+const tiny_string XML::toXMLString_internal(bool pretty, tiny_string defaultnsprefix, const char *indent,bool bfirst)
 {
-	assert(node);
-	//Use low level libxml2 access for speed
-	const xmlNode* xmlN = node->cobj();
-	XMLVector ret;
-	//Only elements can have attributes
-	if(xmlN->type!=XML_ELEMENT_NODE)
-		return ret;
+	tiny_string res;
+	set<tiny_string> seen_prefix;
 
-	_NR<XML> rootXML=getRootNode();
-	for(xmlAttr* attr=xmlN->properties; attr!=NULL; attr=attr->next)
+	if (bfirst)
 	{
-		if((name=="*" || name==attr->name) &&
-		   (namespace_uri=="*" || (namespace_uri=="" && attr->ns==NULL) || (attr->ns && namespace_uri==attr->ns->href)))
+		tiny_string defns = getVm()->getDefaultXMLNamespace();
+		XML* tmp = this;
+		bool bfound = false;
+		while(tmp)
 		{
-			//NOTE: libxmlpp headers says that Node::create_wrapper
-			//is supposed to be internal API. Still it's very useful and
-			//we use it.
-			xmlpp::Node::create_wrapper(reinterpret_cast<xmlNode*>(attr));
-			xmlpp::Node* attrX=static_cast<xmlpp::Node*>(attr->_private);
-			ret.push_back(_MR(Class<XML>::getInstanceS(rootXML, attrX)));
+			for (uint32_t j = 0; j < tmp->namespacedefs.size(); j++)
+			{
+				bool b;
+				_R<Namespace> tmpns = tmp->namespacedefs[j];
+				if (tmpns->getURI() == defns)
+				{
+					defaultnsprefix = tmpns->getPrefix(b);
+					bfound = true;
+					break;
+				}
+			}
+			if (!bfound && tmp->parentNode)
+				tmp = tmp->parentNode.getPtr();
+			else
+				break;
 		}
 	}
-	return ret;
-}
-
-void XML::toXMLString_priv(xmlBufferPtr buf)
-{
-	//NOTE: this function is not thread-safe, as it can modify the xmlNode
-	xmlDocPtr xmlDoc=getRootNode()->parser.get_document()->cobj();
-	assert(xmlDoc);
-	xmlNodePtr cNode=node->cobj();
-	int retVal;
-	if(cNode->type == XML_ATTRIBUTE_NODE)
-	{
-		//cobj() return a xmlNodePtr for XML_ATTRIBUTE_NODE
-		//even though its actually a different structure
-		//containing only the first few member. Especially,
-		//there is no nsDef member in that struct.
-		retVal=xmlNodeBufGetContent(buf, cNode);
-	}
-	else
+	switch (nodetype)
 	{
-		//As libxml2 does not automatically add the needed namespaces to the dump
-		//we have to workaround the issue
-
-		//Get the needed namespaces
-		xmlNsPtr* neededNamespaces=xmlGetNsList(xmlDoc,cNode);
-		//Save a copy of the namespaces actually defined in the node
-		xmlNsPtr oldNsDef=cNode->nsDef;
-
-		//Copy the namespaces (we need to modify them to create a customized list)
-		vector<xmlNs> localNamespaces;
-		if(neededNamespaces)
+		case XML_TEXT_NODE:
+			res = indent;
+			res += encodeToXML(nodevalue,false);
+			break;
+		case XML_ATTRIBUTE_NODE:
+			res += nodevalue;
+			break;
+		case XML_COMMENT_NODE:
+			res = indent;
+			res += "<!--";
+			res += nodevalue;
+			res += "-->";
+			break;
+		case XML_PI_NODE:
+			if (ignoreProcessingInstructions)
+				break;
+			res = indent;
+			res += "<?";
+			res +=this->nodename;
+			res += " ";
+			res += nodevalue;
+			res += "?>";
+			break;
+		case XML_ELEMENT_NODE:
 		{
-			xmlNsPtr* cur=neededNamespaces;
-			while(*cur)
+			tiny_string curprefix = this->nodenamespace_prefix;
+			res = indent;
+			res += "<";
+			if (this->nodenamespace_prefix.empty())
+			{
+				if (defaultnsprefix != "")
+				{
+					res += defaultnsprefix;
+					res += ":";
+					curprefix = defaultnsprefix;
+				}
+			}
+			else
+			{
+				res += this->nodenamespace_prefix;
+				res += ":";
+			}
+			res +=this->nodename;
+			for (uint32_t i = 0; i < this->namespacedefs.size(); i++)
+			{
+				bool b;
+				_R<Namespace> tmpns = this->namespacedefs[i];
+				tiny_string tmpprefix = tmpns->getPrefix(b);
+				if(tmpprefix == "" || tmpprefix==this->nodenamespace_prefix || seen_prefix.find(tmpprefix)!=seen_prefix.end())
+					continue;
+				seen_prefix.insert(tmpprefix);
+				res += " xmlns:";
+				res += tmpprefix;
+				res += "=\"";
+				res += tmpns->getURI();
+				res += "\"";
+			}
+			if (this->parentNode)
+			{
+				if (bfirst)
+				{
+					XML* tmp = this->parentNode.getPtr();
+					while(tmp)
+					{
+						for (uint32_t i = 0; i < tmp->namespacedefs.size(); i++)
+						{
+							bool b;
+							_R<Namespace> tmpns = tmp->namespacedefs[i];
+							tiny_string tmpprefix = tmpns->getPrefix(b);
+							if(tmpprefix != "" && seen_prefix.find(tmpprefix)==seen_prefix.end())
+							{
+								seen_prefix.insert(tmpprefix);
+								res += " xmlns:";
+								res += tmpprefix;
+								res += "=\"";
+								res += tmpns->getURI();
+								res += "\"";
+							}
+						}
+						if (tmp->parentNode)
+							tmp = tmp->parentNode.getPtr();
+						else
+							break;
+					}
+				}
+				else if (!curprefix.empty())
+				{
+					XML* tmp = this->parentNode.getPtr();
+					bool bfound = false;
+					while(tmp)
+					{
+						for (uint32_t i = 0; i < tmp->namespacedefs.size(); i++)
+						{
+							bool b;
+							_R<Namespace> tmpns = tmp->namespacedefs[i];
+							tiny_string tmpprefix = tmpns->getPrefix(b);
+							if(tmpprefix == curprefix)
+							{
+								seen_prefix.insert(tmpprefix);
+								bfound = true;
+								break;
+							}
+						}
+						if (!bfound && tmp->parentNode)
+							tmp = tmp->parentNode.getPtr();
+						else
+							break;
+					}
+				}
+			}
+			if (!this->nodenamespace_uri.empty() && 
+					((this->nodenamespace_prefix.empty() && defaultnsprefix == "") ||
+					 (!this->nodenamespace_prefix.empty() && seen_prefix.find(this->nodenamespace_prefix)==seen_prefix.end())))
+			{
+				if (!this->nodenamespace_prefix.empty())
+				{
+					seen_prefix.insert(this->nodenamespace_prefix);
+					res += " xmlns:";
+					res += this->nodenamespace_prefix;
+				}
+				else
+					res += " xmlns";
+				res += "=\"";
+				res += this->nodenamespace_uri;
+				res += "\"";
+			}
+			else if (defaultnsprefix != "" && seen_prefix.find(defaultnsprefix)==seen_prefix.end())
+			{
+				seen_prefix.insert(defaultnsprefix);
+				res += " xmlns:";
+				res += defaultnsprefix;
+				res += "=\"";
+				res += getVm()->getDefaultXMLNamespace();
+				res += "\"";
+			}
+			for (XMLList::XMLListVector::const_iterator it = attributelist->nodes.begin(); it != attributelist->nodes.end(); it++)
+			{
+				_R<XML> attr = *it;
+				res += " ";
+				if (attr->nodenamespace_prefix != "")
+				{
+					res += attr->nodenamespace_prefix;
+					res += ":";
+				}
+				res += attr->nodename;
+				res += "=\"";
+				res += encodeToXML(attr->nodevalue,true);
+				res += "\"";
+			}
+			if (childrenlist->nodes.size() == 0)
+			{
+				res += "/>";
+				break;
+			}
+			res += ">";
+			tiny_string newindent;
+			bool bindent = (pretty && prettyPrinting && prettyIndent >=0 && 
+							(childrenlist->nodes.size() >1 || 
+							(childrenlist->nodes[0]->nodetype != XML_TEXT_NODE && childrenlist->nodes[0]->nodetype != XML_CDATA_SECTION_NODE)));
+			if (bindent)
+			{
+				newindent = indent;
+				for (int32_t j = 0; j < prettyIndent; j++)
+				{
+					newindent += " ";
+				}
+			}
+			for (uint32_t i = 0; i < childrenlist->nodes.size(); i++)
+			{
+				if (bindent)
+					res += "\n";
+				_R<XML> child= childrenlist->nodes[i];
+				res += child->toXMLString_internal(pretty,defaultnsprefix,newindent.raw_buf(),false);
+			}
+			if (bindent)
+			{
+				res += "\n";
+				res += indent;
+			}
+			res += "</";
+			if (this->nodenamespace_prefix.empty())
+			{
+				if (defaultnsprefix != "")
+				{
+					res += defaultnsprefix;
+					res += ":";
+				}
+			}
+			else
 			{
-				localNamespaces.emplace_back(**cur);
-				cur++;
+				res += this->nodenamespace_prefix;
+				res += ":";
 			}
-			for(uint32_t i=0;i<localNamespaces.size()-1;++i)
-				localNamespaces[i].next=&localNamespaces[i+1];
-			localNamespaces.back().next=NULL;
-			//Free the namespaces arrary
-			xmlFree(neededNamespaces);
-			//Override the node defined namespaces
-			cNode->nsDef=&localNamespaces.front();
+			res += this->nodename;
+			res += ">";
+			break;
 		}
-		retVal=xmlNodeDump(buf, xmlDoc, cNode, 0, 0);
-		//Restore the previously defined namespaces
-		cNode->nsDef=oldNsDef;
+		case XML_CDATA_SECTION_NODE:
+			res += "<![CDATA[";
+			res += nodevalue;
+			res += "]]>";
+			break;
+		default:
+			LOG(LOG_NOT_IMPLEMENTED,"XML::toXMLString unhandled nodetype:"<<nodetype);
+			break;
 	}
-	if(retVal==-1)
-		throw RunTimeException("Error om XML::toXMLString_priv");
+	return res;
 }
 
 ASFUNCTIONBODY(XML,toXMLString)
 {
 	XML* th=Class<XML>::cast(obj);
 	assert_and_throw(argslen==0);
-	assert(th->node);
-	//Allocate a page at the beginning
-	xmlBufferPtr xmlBuffer=xmlBufferCreateSize(4096);
-	th->toXMLString_priv(xmlBuffer);
-	ASString* ret=Class<ASString>::getInstanceS((char*)xmlBuffer->content);
-	xmlBufferFree(xmlBuffer);
+	tiny_string res = th->toXMLString_internal();
+	ASString* ret=Class<ASString>::getInstanceS(res);
 	return ret;
 }
 
 void XML::childrenImpl(XMLVector& ret, const tiny_string& name)
 {
-	assert(node);
-	const xmlpp::Node::NodeList& list=node->get_children();
-	xmlpp::Node::NodeList::const_iterator it=list.begin();
-	_NR<XML> rootXML=getRootNode();
-	for(;it!=list.end();++it)
+	for (uint32_t i = 0; i < childrenlist->nodes.size(); i++)
 	{
-		if(name!="*" && (*it)->get_name() != name.raw_buf())
-			continue;
-
-		// Ignore white-space-only text nodes
-		xmlpp::TextNode *textnode=dynamic_cast<xmlpp::TextNode*>(*it);
-		if (textnode && textnode->is_white_space())
+		_R<XML> child= childrenlist->nodes[i];
+		if(name!="*" && child->nodename != name)
 			continue;
-
-		ret.push_back(_MR(Class<XML>::getInstanceS(rootXML, *it)));
+		child->incRef();
+		ret.push_back(child);
 	}
 }
 
 void XML::childrenImpl(XMLVector& ret, uint32_t index)
 {
-	assert(node);
-	_NR<XML> rootXML=getRootNode();
-	uint32_t i=0;
-	const xmlpp::Node::NodeList& list=node->get_children();
-	xmlpp::Node::NodeList::const_iterator it=list.begin();
-	while(it!=list.end())
+	if (constructed && index < childrenlist->nodes.size())
 	{
-		xmlpp::TextNode* nodeText = dynamic_cast<xmlpp::TextNode*>(*it);
-		if(!(nodeText && nodeText->is_white_space()))
-		{
-			if(i==index)
-			{
-				ret.push_back(_MR(Class<XML>::getInstanceS(rootXML, *it)));
-				break;
-			}
-
-			++i;
-		}
-
-		++it;
+		_R<XML> child= childrenlist->nodes[index];
+		child->incRef();
+		ret.push_back(child);
 	}
 }
 
@@ -473,11 +658,11 @@ ASFUNCTIONBODY(XML,child)
 	mname.name_type=multiname::NAME_STRING;
 	mname.ns.push_back(nsNameAndKind("",NAMESPACE));
 	mname.isAttribute=false;
-	if(Array::isValidMultiname(mname, index))
+	if(XML::isValidMultiname(mname, index))
 		th->childrenImpl(ret, index);
 	else
 		th->childrenImpl(ret, arg0);
-	XMLList* retObj=Class<XMLList>::getInstanceS(ret);
+	XMLList* retObj=Class<XMLList>::getInstanceS(ret,th->getChildrenlist(),mname);
 	return retObj;
 }
 
@@ -487,38 +672,27 @@ ASFUNCTIONBODY(XML,children)
 	assert_and_throw(argslen==0);
 	XMLVector ret;
 	th->childrenImpl(ret, "*");
-	XMLList* retObj=Class<XMLList>::getInstanceS(ret);
+	multiname mname(NULL);
+	mname.name_s_id=getSys()->getUniqueStringId("*");
+	mname.name_type=multiname::NAME_STRING;
+	mname.ns.push_back(nsNameAndKind("",NAMESPACE));
+	XMLList* retObj=Class<XMLList>::getInstanceS(ret,th->getChildrenlist(),mname);
 	return retObj;
 }
 
 ASFUNCTIONBODY(XML,childIndex)
 {
 	XML* th=Class<XML>::cast(obj);
-	xmlpp::Node *parent=th->node->get_parent();
-	if (parent && (th->node->cobj()->type!=XML_ATTRIBUTE_NODE))
+	if (th->parentNode)
 	{
-		xmlpp::Node::NodeList children=parent->get_children();
-		xmlpp::Node::NodeList::const_iterator it;
-		unsigned int n;
-		
-		it=children.begin();
-		n=0;
-		while(it!=children.end())
+		XML* parent = th->parentNode.getPtr();
+		for (uint32_t i = 0; i < parent->childrenlist->nodes.size(); i++)
 		{
-			if((*it)==th->node)
-				return abstract_i(n);
-
-			// Ignore white-space text nodes
-			xmlpp::TextNode *textnode=dynamic_cast<xmlpp::TextNode*>(*it);
-			if (!(textnode && textnode->is_white_space()))
-			{
-				++n;
-			}
-
-			++it;
+			ASObject* o= parent->childrenlist->nodes[i].getPtr();
+			if (o == th)
+				return abstract_i(i);
 		}
 	}
-
 	return abstract_i(-1);
 }
 
@@ -542,20 +716,15 @@ ASFUNCTIONBODY(XML,valueOf)
 
 void XML::getText(XMLVector& ret)
 {
-	xmlpp::Node::NodeList nl = node->get_children();
-	xmlpp::Node::NodeList::iterator i;
-	_NR<XML> childroot = root;
-	if(childroot.isNull())
+	for (uint32_t i = 0; i < childrenlist->nodes.size(); i++)
 	{
-		this->incRef();
-		childroot = _MR(this);
-	}
-	for(i=nl.begin(); i!= nl.end(); ++i)
-	{
-		xmlpp::TextNode* nodeText = dynamic_cast<xmlpp::TextNode*>(*i);
-		//The official implementation seems to ignore whitespace-only textnodes
-		if(nodeText && !nodeText->is_white_space())
-			ret.push_back( _MR(Class<XML>::getInstanceS(childroot, nodeText)) );
+		_R<XML> child= childrenlist->nodes[i];
+		if (child->getNodeKind() == XML_TEXT_NODE  ||
+			child->getNodeKind() == XML_CDATA_SECTION_NODE)
+		{
+			child->incRef();
+			ret.push_back( child );
+		}
 	}
 }
 
@@ -565,7 +734,7 @@ ASFUNCTIONBODY(XML,text)
 	ARG_UNPACK;
 	XMLVector ret;
 	th->getText(ret);
-	return Class<XMLList>::getInstanceS(ret);
+	return Class<XMLList>::getInstanceS(ret,th->getChildrenlist(),multiname(NULL));
 }
 
 ASFUNCTIONBODY(XML,elements)
@@ -578,19 +747,19 @@ ASFUNCTIONBODY(XML,elements)
 		name="";
 
 	th->getElementNodes(name, ret);
-	return Class<XMLList>::getInstanceS(ret);
+	return Class<XMLList>::getInstanceS(ret,th->getChildrenlist(),multiname(NULL));
 }
 
 void XML::getElementNodes(const tiny_string& name, XMLVector& foundElements)
 {
-	_NR<XML> rootXML=getRootNode();
-	const xmlpp::Node::NodeList& children=node->get_children();
-	xmlpp::Node::NodeList::const_iterator it=children.begin();
-	for(;it!=children.end();++it)
+	for (uint32_t i = 0; i < childrenlist->nodes.size(); i++)
 	{
-		xmlElementType nodetype=(*it)->cobj()->type;
-		if(nodetype==XML_ELEMENT_NODE && (name.empty() || name == (*it)->get_name()))
-			foundElements.push_back(_MR(Class<XML>::getInstanceS(rootXML, *it)));
+		_R<XML> child= childrenlist->nodes[i];
+		if(child->nodetype==XML_ELEMENT_NODE && (name.empty() || name == child->nodename))
+		{
+			child->incRef();
+			foundElements.push_back( child );
+		}
 	}
 }
 
@@ -600,29 +769,25 @@ ASFUNCTIONBODY(XML,inScopeNamespaces)
 	Array *namespaces = Class<Array>::getInstanceS();
 	set<tiny_string> seen_prefix;
 
-	xmlDocPtr xmlDoc=th->getRootNode()->parser.get_document()->cobj();
-	xmlNsPtr *nsarr=xmlGetNsList(xmlDoc, th->node->cobj());
-	if(nsarr)
+	XML* tmp = th;
+	while(tmp)
 	{
-		for(int i=0; nsarr[i]!=NULL; i++)
+		for (uint32_t i = 0; i < tmp->namespacedefs.size(); i++)
 		{
-			if(!nsarr[i]->prefix)
-				continue;
-
-			tiny_string prefix((const char*)nsarr[i]->prefix, true);
-			if(seen_prefix.find(prefix)==seen_prefix.end())
+			bool b;
+			_R<Namespace> tmpns = tmp->namespacedefs[i];
+			if(seen_prefix.find(tmpns->getPrefix(b))==seen_prefix.end())
 			{
-				tiny_string uri((const char*)nsarr[i]->href, true);
-				Namespace *ns=Class<Namespace>::getInstanceS(uri, prefix);
-				namespaces->push(_MR(ns));
+				tmpns->incRef();
+				namespaces->push(tmpns);
+				seen_prefix.insert(tmp->nodenamespace_prefix);
 			}
-
-			seen_prefix.insert(prefix);
 		}
-
-		xmlFree(nsarr);
+		if (tmp->parentNode)
+			tmp = tmp->parentNode.getPtr();
+		else
+			break;
 	}
-
 	return namespaces;
 }
 
@@ -632,34 +797,45 @@ ASFUNCTIONBODY(XML,addNamespace)
 	_NR<ASObject> newNamespace;
 	ARG_UNPACK(newNamespace);
 
-	xmlpp::Element *element=dynamic_cast<xmlpp::Element*>(th->node);
-	if(!element)
-		return NULL;
-
-	// TODO: check if the prefix already exists
 
-	Namespace *ns=dynamic_cast<Namespace *>(newNamespace.getPtr());
-	if(ns)
+	tiny_string ns_uri;
+	tiny_string ns_prefix;
+	if (newNamespace->is<Namespace>())
 	{
-		tiny_string uri=ns->getURI();
-		bool prefix_is_undefined=false;
-		tiny_string prefix=ns->getPrefix(prefix_is_undefined);
-		element->set_namespace_declaration(uri, prefix);
+		Namespace* tmpns = newNamespace->as<Namespace>();
+		bool b;
+		ns_prefix = tmpns->getPrefix(b);
+		ns_uri = tmpns->getURI();
 	}
-	else
+	else if (newNamespace->is<ASQName>())
 	{
-		tiny_string uri=newNamespace->toString();
-		element->set_namespace_declaration(uri);
+		ns_uri = newNamespace->as<ASQName>()->getURI();
 	}
-
+	else
+		ns_uri = newNamespace->toString();
+	if (th->nodenamespace_prefix == ns_prefix)
+		th->nodenamespace_prefix="";
+	for (uint32_t i = 0; i < th->namespacedefs.size(); i++)
+	{
+		bool b;
+		_R<Namespace> tmpns = th->namespacedefs[i];
+		if (tmpns->getPrefix(b) == ns_prefix)
+		{
+			th->namespacedefs[i] = _R<Namespace>(Class<Namespace>::getInstanceS(ns_uri,ns_prefix));
+			return NULL;
+		}
+	}
+	th->namespacedefs.push_back(_R<Namespace>(Class<Namespace>::getInstanceS(ns_uri,ns_prefix)));
 	return NULL;
 }
 
 ASObject *XML::getParentNode()
 {
-	xmlpp::Node *parent=node->get_parent();
-	if (parent)
-		return Class<XML>::getInstanceS(getRootNode(), parent);
+	if (parentNode && parentNode->is<XML>())
+	{
+		parentNode->incRef();
+		return parentNode.getPtr();
+	}
 	else
 		return getSys()->getUndefinedRef();
 }
@@ -687,54 +863,26 @@ ASFUNCTIONBODY(XML,_namespace)
 	tiny_string prefix;
 	ARG_UNPACK(prefix, "");
 
-	xmlElementType nodetype=th->node->cobj()->type;
+	xmlElementType nodetype=th->nodetype;
 	if(prefix.empty() && 
 	   nodetype!=XML_ELEMENT_NODE && 
 	   nodetype!=XML_ATTRIBUTE_NODE)
 	{
 		return getSys()->getNullRef();
 	}
-
-	tiny_string local_uri=th->node->get_namespace_uri();
-	ASObject *ret=NULL;
-	xmlDocPtr xmlDoc=th->getRootNode()->parser.get_document()->cobj();
-	xmlNsPtr *nsarr=xmlGetNsList(xmlDoc, th->node->cobj());
-	if(nsarr)
-	{
-		for(int i=0; nsarr[i]!=NULL; i++)
-		{
-			tiny_string ns_prefix;
-			if(nsarr[i]->prefix)
-				ns_prefix=tiny_string((const char*)nsarr[i]->prefix, true);
-			tiny_string ns_uri((const char*)nsarr[i]->href, true);
-			if(!prefix.empty() && ns_prefix==prefix)
-			{
-				ret=Class<Namespace>::getInstanceS(ns_uri, prefix);
-				break;
-			}
-			else if(prefix.empty() && ns_uri==local_uri)
-			{
-				ret=Class<Namespace>::getInstanceS(ns_uri);
-				break;
-			}
-		}
-
-		xmlFree(nsarr);
-	}
-
-	if(!ret)
+	if (prefix.empty())
+		return Class<Namespace>::getInstanceS(th->nodenamespace_uri, th->nodenamespace_prefix);
+		
+	for (uint32_t i = 0; i < th->namespacedefs.size(); i++)
 	{
-		if(prefix.empty() && local_uri.empty())
-		{
-			ret=Class<Namespace>::getInstanceS();
-		}
-		else
+		bool b;
+		_R<Namespace> tmpns = th->namespacedefs[i];
+		if (tmpns->getPrefix(b) == prefix)
 		{
-			ret=getSys()->getUndefinedRef();
+			return Class<Namespace>::getInstanceS(tmpns->getURI(), prefix);
 		}
 	}
-
-	return ret;
+	return getSys()->getUndefinedRef();
 }
 
 ASFUNCTIONBODY(XML,_setLocalName)
@@ -743,7 +891,7 @@ ASFUNCTIONBODY(XML,_setLocalName)
 	_NR<ASObject> newName;
 	ARG_UNPACK(newName);
 
-	xmlElementType nodetype=th->node->cobj()->type;
+	xmlElementType nodetype=th->nodetype;
 	if(nodetype==XML_TEXT_NODE || nodetype==XML_COMMENT_NODE)
 		return NULL;
 
@@ -768,8 +916,7 @@ void XML::setLocalName(const tiny_string& new_name)
 	{
 		throwError<TypeError>(kXMLInvalidName, new_name);
 	}
-
-	node->set_name(new_name);
+	this->nodename = new_name;
 }
 
 ASFUNCTIONBODY(XML,_setName)
@@ -778,12 +925,12 @@ ASFUNCTIONBODY(XML,_setName)
 	_NR<ASObject> newName;
 	ARG_UNPACK(newName);
 
-	xmlElementType nodetype=th->node->cobj()->type;
-	if(nodetype==XML_TEXT_NODE || nodetype==XML_COMMENT_NODE)
+	if(th->nodetype==XML_TEXT_NODE || th->nodetype==XML_COMMENT_NODE)
 		return NULL;
 
 	tiny_string localname;
 	tiny_string ns_uri;
+	tiny_string ns_prefix = th->nodenamespace_prefix;
 	if(newName->is<ASQName>())
 	{
 		ASQName *qname=newName->as<ASQName>();
@@ -793,10 +940,11 @@ ASFUNCTIONBODY(XML,_setName)
 	else if (!newName->is<Undefined>())
 	{
 		localname=newName->toString();
+		ns_prefix= "";
 	}
 
 	th->setLocalName(localname);
-	th->setNamespace(ns_uri);
+	th->setNamespace(ns_uri,ns_prefix);
 
 	return NULL;
 }
@@ -807,12 +955,10 @@ ASFUNCTIONBODY(XML,_setNamespace)
 	_NR<ASObject> newNamespace;
 	ARG_UNPACK(newNamespace);
 
-	xmlElementType nodetype=th->node->cobj()->type;
-	if(nodetype==XML_TEXT_NODE ||
-	   nodetype==XML_COMMENT_NODE ||
-	   nodetype==XML_PI_NODE)
+	if(th->nodetype==XML_TEXT_NODE ||
+	   th->nodetype==XML_COMMENT_NODE ||
+	   th->nodetype==XML_PI_NODE)
 		return NULL;
-
 	tiny_string ns_uri;
 	tiny_string ns_prefix;
 	if(newNamespace->is<Namespace>())
@@ -826,45 +972,55 @@ ASFUNCTIONBODY(XML,_setNamespace)
 	{
 		ASQName *qname=newNamespace->as<ASQName>();
 		ns_uri=qname->getURI();
+		for (uint32_t i = 0; i < th->namespacedefs.size(); i++)
+		{
+			bool b;
+			_R<Namespace> tmpns = th->namespacedefs[i];
+			if (tmpns->getURI() == ns_uri)
+			{
+				ns_prefix = tmpns->getPrefix(b);
+				break;
+			}
+		}
 	}
 	else if (!newNamespace->is<Undefined>())
 	{
 		ns_uri=newNamespace->toString();
+		for (uint32_t i = 0; i < th->namespacedefs.size(); i++)
+		{
+			bool b;
+			_R<Namespace> tmpns = th->namespacedefs[i];
+			if (tmpns->getURI() == ns_uri)
+			{
+				ns_prefix = tmpns->getPrefix(b);
+				break;
+			}
+		}
 	}
-
 	th->setNamespace(ns_uri, ns_prefix);
+	if (th->nodetype==XML_ATTRIBUTE_NODE && th->parentNode)
+	{
+		XML* tmp = th->parentNode.getPtr();
+		for (uint32_t i = 0; i < tmp->namespacedefs.size(); i++)
+		{
+			bool b;
+			_R<Namespace> tmpns = tmp->namespacedefs[i];
+			if (tmpns->getPrefix(b) == ns_prefix)
+			{
+				tmp->namespacedefs[i] = _R<Namespace>(Class<Namespace>::getInstanceS(ns_uri,ns_prefix));
+				return NULL;
+			}
+		}
+		tmp->namespacedefs.push_back(_R<Namespace>(Class<Namespace>::getInstanceS(ns_uri,ns_prefix)));
+	}
 	
 	return NULL;
 }
 
 void XML::setNamespace(const tiny_string& ns_uri, const tiny_string& ns_prefix)
 {
-	if(ns_uri.empty())
-	{
-		// libxml++ set_namespace() doesn't seem to be able to
-		// reset the namespace to empty (default) namespace,
-		// so we have to do this through libxml2
-		xmlDocPtr xmlDoc=getRootNode()->parser.get_document()->cobj();
-		xmlNsPtr default_ns=xmlSearchNs(xmlDoc, node->cobj(), NULL);
-		xmlSetNs(node->cobj(), default_ns);
-	}
-	else
-	{
-		if(!ns_prefix.empty())
-		{
-			xmlpp::Element *element;
-			element=dynamic_cast<xmlpp::Element *>(node);
-			xmlpp::Attribute *attribute;
-			attribute=dynamic_cast<xmlpp::Attribute *>(node);
-			if(attribute)
-				element=attribute->get_parent();
-
-			if(element)
-				element->set_namespace_declaration(ns_uri, ns_prefix);
-		}
-
-		node->set_namespace(getNamespacePrefixByURI(ns_uri, true));
-	}
+	this->nodenamespace_prefix = ns_prefix;
+	this->nodenamespace_uri = ns_uri;
 }
 
 ASFUNCTIONBODY(XML,_copy)
@@ -873,9 +1029,9 @@ ASFUNCTIONBODY(XML,_copy)
 	return th->copy();
 }
 
-XML *XML::copy() const
+XML *XML::copy()
 {
-	return Class<XML>::getInstanceS(node);
+	return Class<XML>::getInstanceS(this->toXMLString_internal(false));
 }
 
 ASFUNCTIONBODY(XML,_setChildren)
@@ -884,16 +1040,18 @@ ASFUNCTIONBODY(XML,_setChildren)
 	_NR<ASObject> newChildren;
 	ARG_UNPACK(newChildren);
 
-	th->removeAllChildren();
+	th->childrenlist->clear();
 
 	if (newChildren->is<XML>())
 	{
 		XML *newChildrenXML=newChildren->as<XML>();
-		th->node->import_node(newChildrenXML->node);
+		newChildrenXML->incRef();
+		th->appendChild(_R<XML>(newChildrenXML));
 	}
 	else if (newChildren->is<XMLList>())
 	{
 		XMLList *list=newChildren->as<XMLList>();
+		list->incRef();
 		list->appendNodesTo(th);
 	}
 	else
@@ -916,100 +1074,212 @@ ASFUNCTIONBODY(XML,_normalize)
 
 void XML::normalize()
 {
-	normalizeRecursive(node);
-}
-
-void XML::normalizeRecursive(xmlpp::Node *node)
-{
-	// TODO: merge adjacent text nodes
-
-	xmlpp::Node::NodeList children=node->get_children();
-	xmlpp::Node::NodeList::const_iterator it=children.begin();
-	for(;it!=children.end();++it)
-	{
-		if (dynamic_cast<xmlpp::Element*>(*it))
-		{
-			normalizeRecursive(*it);
-		}
-		else
-		{
-			xmlpp::TextNode *textnode = dynamic_cast<xmlpp::TextNode*>(*it);
-			if (textnode && textnode->is_white_space())
-				node->remove_child(*it);
-		}
-	}
+	childrenlist->normalize();
 }
 
 void XML::addTextContent(const tiny_string& str)
 {
 	assert(getNodeKind() == XML_TEXT_NODE);
 
-	xmlNodeAddContentLen(node->cobj(), BAD_CAST str.raw_buf(), str.numBytes());
+	nodevalue += str;
 }
 
-void XML::removeAllChildren()
+void XML::setTextContent(const tiny_string& content)
 {
-	xmlpp::Node::NodeList children=node->get_children();
-	xmlpp::Node::NodeList::const_iterator it=children.begin();
-	for(;it!=children.end();++it)
+	if (getNodeKind() == XML_TEXT_NODE ||
+	    getNodeKind() == XML_ATTRIBUTE_NODE ||
+	    getNodeKind() == XML_COMMENT_NODE ||
+	    getNodeKind() == XML_PI_NODE ||
+		getNodeKind() == XML_CDATA_SECTION_NODE)
 	{
-		node->remove_child(*it);
+		nodevalue = content;
 	}
 }
 
+
 bool XML::hasSimpleContent() const
 {
-	xmlElementType nodetype=node->cobj()->type;
-	if(nodetype==XML_COMMENT_NODE || nodetype==XML_PI_NODE)
+	if (getNodeKind() == XML_COMMENT_NODE ||
+		getNodeKind() == XML_PI_NODE)
 		return false;
-
-	const xmlpp::Node::NodeList& children=node->get_children();
-	xmlpp::Node::NodeList::const_iterator it=children.begin();
-	for(;it!=children.end();++it)
+	for(size_t i=0; i<childrenlist->nodes.size(); i++)
 	{
-		if((*it)->cobj()->type==XML_ELEMENT_NODE)
+		if (childrenlist->nodes[i]->getNodeKind() == XML_ELEMENT_NODE)
 			return false;
 	}
-
 	return true;
 }
 
 bool XML::hasComplexContent() const
 {
-	const xmlpp::Node::NodeList& children=node->get_children();
-	xmlpp::Node::NodeList::const_iterator it=children.begin();
-	for(;it!=children.end();++it)
-	{
-		if((*it)->cobj()->type==XML_ELEMENT_NODE)
-			return true;
-	}
-
-	return false;
+	return !hasSimpleContent();
 }
 
 xmlElementType XML::getNodeKind() const
 {
-	return node->cobj()->type;
+	return nodetype;
 }
 
-void XML::recursiveGetDescendantsByQName(_R<XML> root, xmlpp::Node* node, const tiny_string& name, const tiny_string& ns,
-		XMLVector& ret)
+
+void XML::getDescendantsByQName(const tiny_string& name, const tiny_string& ns, bool bIsAttribute, XMLVector& ret)
 {
-	//Check if this node is being requested. Both "" and "*" strings mean all
-	if(name=="" || name=="*" || name == node->get_name())
-		ret.push_back(_MR(Class<XML>::getInstanceS(root, node)));
-	//NOTE: Creating a temporary list is quite a large overhead, but there is no way in libxml++ to access the first child
-	const xmlpp::Node::NodeList& list=node->get_children();
-	xmlpp::Node::NodeList::const_iterator it=list.begin();
-	for(;it!=list.end();++it)
-		recursiveGetDescendantsByQName(root, *it, name, ns, ret);
+	if (!constructed)
+		return;
+	if (bIsAttribute)
+	{
+		for (uint32_t i = 0; i < attributelist->nodes.size(); i++)
+		{
+			_R<XML> child= attributelist->nodes[i];
+			if(name=="" || name=="*" || (name == child->nodename && (ns == "*" || ns == child->nodenamespace_uri)))
+			{
+				child->incRef();
+				ret.push_back(child);
+			}
+		}
+	}
+	for (uint32_t i = 0; i < childrenlist->nodes.size(); i++)
+	{
+		_R<XML> child= childrenlist->nodes[i];
+		if(!bIsAttribute && (name=="" || name=="*" || (name == child->nodename && (ns == "*" || ns == child->nodenamespace_uri))))
+		{
+			child->incRef();
+			ret.push_back(child);
+		}
+		child->getDescendantsByQName(name, ns, bIsAttribute, ret);
+	}
 }
 
-void XML::getDescendantsByQName(const tiny_string& name, const tiny_string& ns, XMLVector& ret)
+XML::XMLVector XML::getAttributes()
+{ 
+	multiname mn(NULL);
+	mn.name_type=multiname::NAME_STRING;
+	mn.ns.push_back(nsNameAndKind("",NAMESPACE));
+	mn.ns.push_back(nsNameAndKind(AS3,NAMESPACE));
+	mn.isAttribute = true;
+	return getAttributesByMultiname(mn); 
+}
+XML::XMLVector XML::getAttributesByMultiname(const multiname& name)
+{
+	XMLVector ret;
+	tiny_string defns = "|";
+	defns += getVm()->getDefaultXMLNamespace();
+	defns += "|";
+	tiny_string normalizedName= "";
+	if (!name.isEmpty()) normalizedName= name.normalizedName();
+	if (normalizedName.startsWith("@"))
+		normalizedName = normalizedName.substr(1,normalizedName.end());
+	tiny_string namespace_uri="|";
+	uint32_t i = 0;
+	while (i < name.ns.size())
+	{
+		nsNameAndKindImpl ns=name.ns[i].getImpl();
+		if (ns.kind==NAMESPACE && ns.name != AS3)
+		{
+			if (ns.name.empty())
+				namespace_uri +=getVm()->getDefaultXMLNamespace();
+			else
+				namespace_uri +=ns.name;
+			namespace_uri += "|";
+		}
+		i++;
+	}
+	for (uint32_t i = 0; i < attributelist->nodes.size(); i++)
+	{
+		_R<XML> child= attributelist->nodes[i];
+		tiny_string childnamespace_uri = "|";
+		childnamespace_uri += child->nodenamespace_uri;
+		childnamespace_uri += "|";
+		
+		bool bmatch = (
+					((normalizedName=="") &&
+					 ((namespace_uri.find(defns)!= tiny_string::npos) ||
+					  (namespace_uri=="|*|") ||
+					  (namespace_uri.find(childnamespace_uri) != tiny_string::npos)
+					 )
+					)||
+					((normalizedName=="*") &&
+					 ((namespace_uri.find(defns)!= tiny_string::npos) ||
+					  (namespace_uri=="|*|") ||
+					  (namespace_uri.find(childnamespace_uri) != tiny_string::npos)
+					 )
+					)||
+					((normalizedName==child->nodename) &&
+					 (
+					  (namespace_uri=="|*|") ||
+					  (namespace_uri=="|" && childnamespace_uri=="||") ||
+					  (namespace_uri.find(childnamespace_uri) != tiny_string::npos)
+					 )
+					)
+					);
+		if(bmatch)
+		{
+			child->incRef();
+			ret.push_back(child);
+		}
+	}
+	return ret;
+}
+XML::XMLVector XML::getValuesByMultiname(_NR<XMLList> nodelist, const multiname& name)
 {
-	assert(node);
-	assert_and_throw(ns=="");
-	recursiveGetDescendantsByQName(getRootNode(), node, name, ns, ret);
+	XMLVector ret;
+	tiny_string defns = "|";
+	defns += getVm()->getDefaultXMLNamespace();
+	defns += "|";
+	tiny_string normalizedName= "";
+	if (!name.isEmpty()) normalizedName= name.normalizedName();
+	if (normalizedName.startsWith("@"))
+		normalizedName = normalizedName.substr(1,normalizedName.end());
+	tiny_string namespace_uri="|";
+	uint32_t i = 0;
+	while (i < name.ns.size())
+	{
+		nsNameAndKindImpl ns=name.ns[i].getImpl();
+		if (ns.kind==NAMESPACE && ns.name != AS3)
+		{
+			if (ns.name.empty())
+				namespace_uri +=getVm()->getDefaultXMLNamespace();
+			else
+				namespace_uri +=ns.name;
+			namespace_uri += "|";
+		}
+		i++;
+	}
+
+	for (uint32_t i = 0; i < nodelist->nodes.size(); i++)
+	{
+		_R<XML> child= nodelist->nodes[i];
+		tiny_string childnamespace_uri = "|";
+		childnamespace_uri += child->nodenamespace_uri;
+		childnamespace_uri += "|";
+		
+		bool bmatch = (
+					((normalizedName=="") &&
+					 ((namespace_uri.find(defns)!= tiny_string::npos) ||
+					  (namespace_uri=="|*|") ||
+					  (namespace_uri.find(childnamespace_uri) != tiny_string::npos)
+					 )
+					)||
+					((normalizedName=="*") &&
+					 ((namespace_uri.find(defns)!= tiny_string::npos) ||
+					  (namespace_uri=="|*|") ||
+					  (namespace_uri.find(childnamespace_uri) != tiny_string::npos)
+					 )
+					)||
+					((normalizedName==child->nodename) &&
+					 ((namespace_uri.find(defns)!= tiny_string::npos) ||
+					  (namespace_uri=="|*|") ||
+					  (namespace_uri=="|" && childnamespace_uri=="||") ||
+					  (namespace_uri.find(childnamespace_uri) != tiny_string::npos)
+					 )
+					)
+					);
+		if(bmatch)
+		{
+			child->incRef();
+			ret.push_back(child);
+		}
+	}
+	return ret;
 }
 
 _NR<ASObject> XML::getVariableByMultiname(const multiname& name, GET_VARIABLE_OPTION opt)
@@ -1030,46 +1300,21 @@ _NR<ASObject> XML::getVariableByMultiname(const multiname& name, GET_VARIABLE_OP
 		return res;
 	}
 
-	if(node==NULL)
-	{
-		//This is possible if the XML object was created from an empty string
-		return NullRef;
-	}
-
 	bool isAttr=name.isAttribute;
 	unsigned int index=0;
-	//Normalize the name to the string form
-	tiny_string normalizedName=name.normalizedName();
-	if(normalizedName=="*")
-		normalizedName="";
-
-	//Only the first namespace is used, is this right?
-	tiny_string namespace_uri;
-	if(name.ns.size() > 0 && !name.ns[0].hasEmptyName())
-	{
-		nsNameAndKindImpl ns=name.ns[0].getImpl();
-		assert_and_throw(ns.kind==NAMESPACE);
-		namespace_uri=ns.name;
-	}
-
-	// namespace set by "default xml namespace = ..."
-	if(namespace_uri.empty())
-		namespace_uri=getVm()->getDefaultXMLNamespace();
 
-	const char *buf=normalizedName.raw_buf();
+	tiny_string normalizedName=name.normalizedName();
 	if(!normalizedName.empty() && normalizedName.charAt(0)=='@')
 	{
 		isAttr=true;
-		buf+=1;
 	}
 	if(isAttr)
 	{
 		//Lookup attribute
-		tiny_string ns_uri=namespace_uri.empty() ? "*" : namespace_uri;
-		const XMLVector& attributes=getAttributes(buf, ns_uri);
-		return _MNR(Class<XMLList>::getInstanceS(attributes));
+		const XMLVector& attributes=getAttributesByMultiname(name);
+		return _MNR(Class<XMLList>::getInstanceS(attributes,attributelist.getPtr(),name));
 	}
-	else if(Array::isValidMultiname(name,index))
+	else if(XML::isValidMultiname(name,index))
 	{
 		// If the multiname is a valid array property, the XML
 		// object is treated as a single-item XMLList.
@@ -1079,37 +1324,16 @@ _NR<ASObject> XML::getVariableByMultiname(const multiname& name, GET_VARIABLE_OP
 			return _MNR(this);
 		}
 		else
-			return NullRef;
+			return _MNR(getSys()->getUndefinedRef());
 	}
 	else
 	{
-		//Lookup children
-		_NR<XML> rootnode=getRootNode();
-
-		//Use low level libxml2 access for speed
-		const xmlNode* xmlN = node->cobj();
-		XMLVector ret;
-		for(xmlNode* child=xmlN->children; child!=NULL; child=child->next)
-		{
-			bool nameMatches = (normalizedName=="" || normalizedName==child->name);
-			bool nsMatches = (namespace_uri=="*" || 
-					  (namespace_uri=="" && child->ns==NULL) || 
-					  (child->ns && namespace_uri==child->ns->href));
-
-			if(nameMatches && nsMatches)
-			{
-				//NOTE: libxmlpp headers says that Node::create_wrapper
-				//is supposed to be internal API. Still it's very useful and
-				//we use it.
-				xmlpp::Node::create_wrapper(child);
-				xmlpp::Node* attrX=static_cast<xmlpp::Node*>(child->_private);
-				ret.push_back(_MR(Class<XML>::getInstanceS(rootnode, attrX)));
-			}
-		}
+		const XMLVector& ret=getValuesByMultiname(childrenlist,name);
 		if(ret.empty() && (opt & XML_STRICT)!=0)
 			return NullRef;
 
-		return _MNR(Class<XMLList>::getInstanceS(ret));
+		_R<XMLList> ch =_MNR(Class<XMLList>::getInstanceS(ret,this->getChildrenlist(),name));
+		return ch;
 	}
 }
 
@@ -1126,9 +1350,11 @@ void XML::setVariableByMultiname(const multiname& name, ASObject* o, CONST_ALLOW
 	if(name.ns.size() > 0 && !name.ns[0].hasEmptyName())
 	{
 		nsNameAndKindImpl ns=name.ns[0].getImpl();
-		assert_and_throw(ns.kind==NAMESPACE);
-		ns_uri=ns.name;
-		ns_prefix=getNamespacePrefixByURI(ns_uri);
+		if (ns.kind==NAMESPACE)
+		{
+			ns_uri=ns.name;
+			ns_prefix=getNamespacePrefixByURI(ns_uri);
+		}
 	}
 
 	// namespace set by "default xml namespace = ..."
@@ -1143,54 +1369,162 @@ void XML::setVariableByMultiname(const multiname& name, ASObject* o, CONST_ALLOW
 		isAttr=true;
 		buf+=1;
 	}
+	
 	if(isAttr)
 	{
-		//To have attributes we must be an Element
-		xmlpp::Element* element=dynamic_cast<xmlpp::Element*>(node);
-		assert_and_throw(element);
-		element->set_attribute(buf, o->toString(), ns_prefix);
-
-		if(ns_prefix.empty() && !ns_uri.empty())
+		bool found = false;
+		for (XMLList::XMLListVector::iterator it = attributelist->nodes.begin(); it != attributelist->nodes.end(); it++)
 		{
-			element->set_namespace_declaration(ns_uri);
+			_R<XML> attr = *it;
+			if (attr->nodenamespace_uri == ns_uri && (attr->nodename == buf || (*buf==0)))
+			{
+				if(o->is<XMLList>())
+				{
+					_NR<XMLList> x = _NR<XMLList>(o->as<XMLList>());
+					for (auto it = x->nodes.begin(); it != x->nodes.end(); it++)
+					{
+						if (!found)
+							attr->nodevalue = (*it)->toString();
+						else
+						{
+							attr->nodevalue += " ";
+							attr->nodevalue += (*it)->toString();
+						}
+						found = true;
+					}
+				}
+				else
+				{
+					if (!found)
+						attr->nodevalue = o->toString();
+					else
+					{
+						attr->nodevalue += " ";
+						attr->nodevalue += o->toString();
+					}
+					found = true;
+				}
+				
+			}
+		}
+		if (!found && !normalizedName.empty())
+		{
+			_NR<XML> tmp = _MR<XML>(Class<XML>::getInstanceS());
+			this->incRef();
+			tmp->parentNode = _MR<XML>(this);
+			tmp->nodetype = XML_ATTRIBUTE_NODE;
+			tmp->nodename = buf;
+			tmp->nodenamespace_uri = ns_uri;
+			tmp->nodenamespace_prefix = ns_prefix;
+			tmp->nodevalue = o->toString();
+			tmp->constructed = true;
+			attributelist->nodes.push_back(tmp);
 		}
 	}
-	else if(Array::isValidMultiname(name,index))
+	else if(XML::isValidMultiname(name,index))
 	{
-		LOG(LOG_NOT_IMPLEMENTED, "XML::setVariableByMultiname: array indexes");
+		childrenlist->setVariableByMultiname(name,o,allowConst);
 	}
 	else
 	{
-		LOG(LOG_NOT_IMPLEMENTED, "XML::setVariableByMultiname: should replace if a node with the given name exists");
-		if(o->is<XML>() || o->is<XMLList>())
-		{
-			LOG(LOG_NOT_IMPLEMENTED, "XML::setVariableByMultiname: assigning XML values not implemented");
-			return;
-		}
-
-		xmlpp::Element* child = NULL;
-		try
+		bool found = false;
+		XMLVector tmpnodes;
+		while (!childrenlist->nodes.empty())
 		{
-			child=node->add_child(getSys()->getStringFromUniqueId(name.name_s_id), ns_prefix);
+			_R<XML> tmpnode = childrenlist->nodes.back();
+			if (tmpnode->nodenamespace_uri == ns_uri && tmpnode->nodename == normalizedName)
+			{
+				if(o->is<XMLList>())
+				{
+					if (!found)
+					{
+						_NR<XMLList> x = _NR<XMLList>(Class<XMLList>::getInstanceS(o->as<XMLList>()->toXMLString_internal(false)));
+						tmpnodes.insert(tmpnodes.end(), x->nodes.rbegin(),x->nodes.rend());
+					}
+				}
+				else if(o->is<XML>())
+				{
+					_NR<XML> tmp = _MR<XML>(o->as<XML>());
+					tmp->parentNode = _MR<XML>(this);
+					tmp->incRef();
+					
+					if (!found)
+						tmpnodes.push_back(tmp);
+				}
+				else
+				{
+					if (tmpnode->childrenlist->nodes.size() == 1 && tmpnode->childrenlist->nodes[0]->nodetype == XML_TEXT_NODE)
+						tmpnode->childrenlist->nodes[0]->nodevalue = o->toString();
+					else
+					{
+						XML* newnode = Class<XML>::getInstanceS(o->toString());
+						tmpnode->childrenlist->clear();
+						tmpnode->setVariableByMultiname(name,newnode,allowConst);
+					}
+					if (!found)
+					{
+						tmpnode->incRef();
+						tmpnodes.push_back(tmpnode);
+					}
+				}
+				found = true;
+			}
+			else
+			{
+				tmpnode->incRef();
+				tmpnodes.push_back(tmpnode);
+			}
+			childrenlist->nodes.pop_back();
 		}
-		catch (xmlpp::exception& e)
+		if (!found)
 		{
-			LOG(LOG_NOT_IMPLEMENTED, "Adding child node failed: " << e.what());
-			return;
-		}
-
-		child->add_child_text(o->toString());
-
-		if(ns_prefix.empty() && !ns_uri.empty())
-		{
-			child->set_namespace_declaration(ns_uri);
+			if(o->is<XML>())
+			{
+				_R<XML> tmp = _MR<XML>(o->as<XML>());
+				tmp->parentNode = _MR<XML>(this);
+				tmp->incRef();
+				tmpnodes.insert(tmpnodes.begin(),tmp);
+			}
+			else
+			{
+				tiny_string tmpstr = "<";
+				if (!this->nodenamespace_prefix.empty())
+				{
+					tmpstr += ns_prefix;
+					tmpstr += ":";
+				}
+				tmpstr += normalizedName;
+				if (!ns_prefix.empty() && !ns_uri.empty())
+				{
+					tmpstr += " xmlns:";
+					tmpstr += ns_prefix;
+					tmpstr += "=\"";
+					tmpstr += ns_uri;
+					tmpstr += "\"";
+				}
+				tmpstr +=">";
+				tmpstr += encodeToXML(o->toString(),false);
+				tmpstr +="</";
+				if (!ns_prefix.empty())
+				{
+					tmpstr += ns_prefix;
+					tmpstr += ":";
+				}
+				tmpstr += normalizedName;
+				tmpstr +=">";
+				_NR<XML> tmp = _MR<XML>(Class<XML>::getInstanceS(tmpstr));
+				this->incRef();
+				tmp->parentNode = _MR<XML>(this);
+				tmpnodes.push_back(tmp);
+			}
 		}
+		childrenlist->nodes.insert(childrenlist->nodes.begin(), tmpnodes.rbegin(),tmpnodes.rend());
 	}
 }
 
 bool XML::hasPropertyByMultiname(const multiname& name, bool considerDynamic, bool considerPrototype)
 {
-	if(node==NULL || considerDynamic == false)
+	if(considerDynamic == false)
 		return ASObject::hasPropertyByMultiname(name, considerDynamic, considerPrototype);
 
 	//Only the first namespace is used, is this right?
@@ -1221,28 +1555,22 @@ bool XML::hasPropertyByMultiname(const multiname& name, bool considerDynamic, bo
 	if(isAttr)
 	{
 		//Lookup attribute
-		assert(node);
-		//To have attributes we must be an Element
-		xmlpp::Element* element=dynamic_cast<xmlpp::Element*>(node);
-		if(element)
+		for (XMLList::XMLListVector::const_iterator it = attributelist->nodes.begin(); it != attributelist->nodes.end(); it++)
 		{
-			xmlpp::Attribute* attr=element->get_attribute(buf, ns_prefix);
-			if(attr!=NULL)
+			_R<XML> attr = *it;
+			if (attr->nodenamespace_uri == ns_uri && attr->nodename == buf)
 				return true;
 		}
 	}
 	else
 	{
 		//Lookup children
-		assert(node);
-		//Use low level libxml2 access to optimize the code
-		const xmlNode* cNode=node->cobj();
-		for(const xmlNode* cur=cNode->children;cur!=NULL;cur=cur->next)
+		for (uint32_t i = 0; i < childrenlist->nodes.size(); i++)
 		{
-			//NOTE: xmlStrEqual returns 1 when the strings are equal.
-			bool name_match=xmlStrEqual(cur->name,(const xmlChar*)buf);
+			_R<XML> child= childrenlist->nodes[i];
+			bool name_match=(child->nodename == buf);
 			bool ns_match=ns_uri.empty() || 
-				(cur->ns && xmlStrEqual(cur->ns->href, (const xmlChar*)ns_uri.raw_buf()));
+				(child->nodenamespace_uri == ns_uri);
 			if(name_match && ns_match)
 				return true;
 		}
@@ -1251,75 +1579,646 @@ bool XML::hasPropertyByMultiname(const multiname& name, bool considerDynamic, bo
 	//Try the normal path as the last resource
 	return ASObject::hasPropertyByMultiname(name, considerDynamic, considerPrototype);
 }
+bool XML::deleteVariableByMultiname(const multiname& name)
+{
+	unsigned int index=0;
+	if(name.isAttribute)
+	{
+		//Only the first namespace is used, is this right?
+		tiny_string ns_uri;
+		tiny_string ns_prefix;
+		if(name.ns.size() > 0 && !name.ns[0].hasEmptyName())
+		{
+			nsNameAndKindImpl ns=name.ns[0].getImpl();
+			assert_and_throw(ns.kind==NAMESPACE);
+			ns_uri=ns.name;
+			ns_prefix=getNamespacePrefixByURI(ns_uri);
+		}
+		if (ns_uri.empty() && ns_prefix.empty())
+		{
+			ns_uri = getVm()->getDefaultXMLNamespace();
+		}
+		if (attributelist->nodes.size() > 0)
+		{
+			XMLList::XMLListVector::iterator it = attributelist->nodes.end();
+			while (it != attributelist->nodes.begin())
+			{
+				it--;
+				_R<XML> attr = *it;
+				if ((ns_uri=="" && name.normalizedName() == "") ||
+						(ns_uri=="" && name.normalizedName() == attr->nodename) ||
+						(attr->nodenamespace_uri == ns_uri && name.normalizedName() == "") ||
+						(attr->nodenamespace_uri == ns_uri && attr->nodename == name.normalizedName()))
+				{
+					attributelist->nodes.erase(it);
+				}
+			}
+		}
+	}
+	else if(XML::isValidMultiname(name,index))
+	{
+		childrenlist->nodes.erase(childrenlist->nodes.begin() + index);
+	}
+	else
+	{
+		//Only the first namespace is used, is this right?
+		tiny_string ns_uri;
+		if(name.ns.size() > 0 && !name.ns[0].hasEmptyName())
+		{
+			nsNameAndKindImpl ns=name.ns[0].getImpl();
+			assert_and_throw(ns.kind==NAMESPACE);
+			ns_uri=ns.name;
+		}
+		if (childrenlist->nodes.size() > 0)
+		{
+			XMLList::XMLListVector::iterator it = childrenlist->nodes.end();
+			while (it != childrenlist->nodes.begin())
+			{
+				it--;
+				_R<XML> node = *it;
+				if ((ns_uri=="" && name.normalizedName() == "") ||
+						(ns_uri=="" && name.normalizedName() == node->nodename) ||
+						(node->nodenamespace_uri == ns_uri && name.normalizedName() == "") ||
+						(node->nodenamespace_uri == ns_uri && node->nodename == name.normalizedName()))
+				{
+					childrenlist->nodes.erase(it);
+				}
+			}
+		}
+	}
+	return true;
+}
+bool XML::isValidMultiname(const multiname& name, uint32_t& index)
+{
+	//First of all the multiname has to contain the null namespace
+	//As the namespace vector is sorted, we check only the first one
+	if(name.ns.size()!=0 && !name.ns[0].hasEmptyName())
+		return false;
+
+	if (name.isEmpty())
+		return false;
+	bool validIndex=name.toUInt(index, true);
+	// Don't throw for non-numeric NAME_STRING or NAME_OBJECT
+	// because they can still be valid built-in property names.
+	if(!validIndex && (name.name_type==multiname::NAME_INT || name.name_type==multiname::NAME_NUMBER))
+		throwError<RangeError>(kOutOfRangeError, name.normalizedName(), "?");
+
+	return validIndex;
+}
 
 tiny_string XML::getNamespacePrefixByURI(const tiny_string& uri, bool create)
 {
 	tiny_string prefix;
 	bool found=false;
-	xmlDocPtr xmlDoc=getRootNode()->parser.get_document()->cobj();
-	xmlNsPtr* namespaces=xmlGetNsList(xmlDoc,node->cobj());
 
-	if(namespaces)
+
+	XML* tmp = this;
+	while(tmp && tmp->is<XML>())
+	{
+		if(tmp->nodenamespace_uri==uri)
+		{
+			prefix=tmp->nodenamespace_prefix;
+			found = true;
+			break;
+		}
+		if (!tmp->parentNode)
+			break;
+		tmp = tmp->parentNode.getPtr();
+	}
+
+	if(!found && create)
+	{
+		nodenamespace_uri = uri;
+	}
+
+	return prefix;
+}
+
+ASFUNCTIONBODY(XML,_toString)
+{
+	XML* th=Class<XML>::cast(obj);
+	return Class<ASString>::getInstanceS(th->toString_priv());
+}
+
+ASFUNCTIONBODY(XML,_getIgnoreComments)
+{
+	return abstract_b(ignoreComments);
+}
+ASFUNCTIONBODY(XML,_setIgnoreComments)
+{
+	assert(args && argslen==1);
+	ignoreComments = Boolean_concrete(args[0]);
+	return NULL;
+}
+ASFUNCTIONBODY(XML,_getIgnoreProcessingInstructions)
+{
+	return abstract_b(ignoreProcessingInstructions);
+}
+ASFUNCTIONBODY(XML,_setIgnoreProcessingInstructions)
+{
+	assert(args && argslen==1);
+	ignoreProcessingInstructions = Boolean_concrete(args[0]);
+	return NULL;
+}
+ASFUNCTIONBODY(XML,_getIgnoreWhitespace)
+{
+	return abstract_b(ignoreWhitespace);
+}
+ASFUNCTIONBODY(XML,_setIgnoreWhitespace)
+{
+	assert(args && argslen==1);
+	ignoreWhitespace = Boolean_concrete(args[0]);
+	xmlKeepBlanksDefault(ignoreWhitespace ? 0 : 1);
+	return NULL;
+}
+ASFUNCTIONBODY(XML,_getPrettyIndent)
+{
+	return abstract_i(prettyIndent);
+}
+ASFUNCTIONBODY(XML,_setPrettyIndent)
+{
+	assert(args && argslen==1);
+	prettyIndent = args[0]->toInt();
+	return NULL;
+}
+ASFUNCTIONBODY(XML,_getPrettyPrinting)
+{
+	return abstract_b(prettyPrinting);
+}
+ASFUNCTIONBODY(XML,_setPrettyPrinting)
+{
+	assert(args && argslen==1);
+	prettyPrinting = Boolean_concrete(args[0]);
+	return NULL;
+}
+ASFUNCTIONBODY(XML,_getSettings)
+{
+	ASObject* res = Class<ASObject>::getInstanceS();
+	multiname mn(NULL);
+	mn.name_type=multiname::NAME_STRING;
+	mn.ns.push_back(nsNameAndKind("",NAMESPACE));
+	mn.ns.push_back(nsNameAndKind(AS3,NAMESPACE));
+	mn.isAttribute = true;
+
+	mn.name_s_id=getSys()->getUniqueStringId("ignoreComments");
+	res->setVariableByMultiname(mn,abstract_b(ignoreComments),CONST_NOT_ALLOWED);
+	mn.name_s_id=getSys()->getUniqueStringId("ignoreProcessingInstructions");
+	res->setVariableByMultiname(mn,abstract_b(ignoreProcessingInstructions),CONST_NOT_ALLOWED);
+	mn.name_s_id=getSys()->getUniqueStringId("ignoreWhitespace");
+	res->setVariableByMultiname(mn,abstract_b(ignoreWhitespace),CONST_NOT_ALLOWED);
+	mn.name_s_id=getSys()->getUniqueStringId("prettyIndent");
+	res->setVariableByMultiname(mn,abstract_i(prettyIndent),CONST_NOT_ALLOWED);
+	mn.name_s_id=getSys()->getUniqueStringId("prettyPrinting");
+	res->setVariableByMultiname(mn,abstract_b(prettyPrinting),CONST_NOT_ALLOWED);
+	return res;
+}
+ASFUNCTIONBODY(XML,_setSettings)
+{
+	if (argslen == 0)
+	{
+		setDefaultXMLSettings();
+		return getSys()->getNullRef();
+	}
+	_NR<ASObject> arg0;
+	ARG_UNPACK(arg0);
+	if (arg0->is<Null>() || arg0->is<Undefined>())
+	{
+		setDefaultXMLSettings();
+		return getSys()->getNullRef();
+	}
+	multiname mn(NULL);
+	mn.name_type=multiname::NAME_STRING;
+	mn.ns.push_back(nsNameAndKind("",NAMESPACE));
+	mn.ns.push_back(nsNameAndKind(AS3,NAMESPACE));
+	mn.isAttribute = true;
+	_NR<ASObject> o;
+
+	mn.name_s_id=getSys()->getUniqueStringId("ignoreComments");
+	if (arg0->hasPropertyByMultiname(mn,true,true))
+	{
+		o=arg0->getVariableByMultiname(mn,SKIP_IMPL);
+		ignoreComments = o->toInt();
+	}
+
+	mn.name_s_id=getSys()->getUniqueStringId("ignoreProcessingInstructions");
+	if (arg0->hasPropertyByMultiname(mn,true,true))
+	{
+		o=arg0->getVariableByMultiname(mn,SKIP_IMPL);
+		ignoreProcessingInstructions = o->toInt();
+	}
+
+	mn.name_s_id=getSys()->getUniqueStringId("ignoreWhitespace");
+	if (arg0->hasPropertyByMultiname(mn,true,true))
+	{
+		o=arg0->getVariableByMultiname(mn,SKIP_IMPL);
+		ignoreWhitespace = o->toInt();
+	}
+
+	mn.name_s_id=getSys()->getUniqueStringId("prettyIndent");
+	if (arg0->hasPropertyByMultiname(mn,true,true))
+	{
+		o=arg0->getVariableByMultiname(mn,SKIP_IMPL);
+		prettyIndent = o->toInt();
+	}
+
+	mn.name_s_id=getSys()->getUniqueStringId("prettyPrinting");
+	if (arg0->hasPropertyByMultiname(mn,true,true))
 	{
-		for(int i=0; namespaces[i]!=NULL; i++)
+		o=arg0->getVariableByMultiname(mn,SKIP_IMPL);
+		prettyPrinting = o->toInt();
+	}
+	return getSys()->getNullRef();
+}
+ASFUNCTIONBODY(XML,_getDefaultSettings)
+{
+	ASObject* res = Class<ASObject>::getInstanceS();
+	multiname mn(NULL);
+	mn.name_type=multiname::NAME_STRING;
+	mn.ns.push_back(nsNameAndKind("",NAMESPACE));
+	mn.ns.push_back(nsNameAndKind(AS3,NAMESPACE));
+	mn.isAttribute = true;
+
+	mn.name_s_id=getSys()->getUniqueStringId("ignoreComments");
+	res->setVariableByMultiname(mn,abstract_b(true),CONST_NOT_ALLOWED);
+	mn.name_s_id=getSys()->getUniqueStringId("ignoreProcessingInstructions");
+	res->setVariableByMultiname(mn,abstract_b(true),CONST_NOT_ALLOWED);
+	mn.name_s_id=getSys()->getUniqueStringId("ignoreWhitespace");
+	res->setVariableByMultiname(mn,abstract_b(true),CONST_NOT_ALLOWED);
+	mn.name_s_id=getSys()->getUniqueStringId("prettyIndent");
+	res->setVariableByMultiname(mn,abstract_i(2),CONST_NOT_ALLOWED);
+	mn.name_s_id=getSys()->getUniqueStringId("prettyPrinting");
+	res->setVariableByMultiname(mn,abstract_b(true),CONST_NOT_ALLOWED);
+	return res;
+}
+ASFUNCTIONBODY(XML,_toJSON)
+{
+	return Class<ASString>::getInstanceS("XML");
+}
+
+void XML::CheckCyclicReference(XML* node)
+{
+	XML* tmp = node;
+	if (tmp == this)
+		throwError<TypeError>(kXMLIllegalCyclicalLoop);
+	for (auto it = tmp->childrenlist->nodes.begin(); it != tmp->childrenlist->nodes.end(); it++)
+	{
+		if ((*it).getPtr() == this)
+			throwError<TypeError>(kXMLIllegalCyclicalLoop);
+		CheckCyclicReference((*it).getPtr());
+	}
+}
+
+ASFUNCTIONBODY(XML,insertChildAfter)
+{
+	XML* th=Class<XML>::cast(obj);
+	_NR<ASObject> child1;
+	_NR<ASObject> child2;
+	ARG_UNPACK(child1)(child2);
+	if (th->nodetype != XML_ELEMENT_NODE)
+		return getSys()->getUndefinedRef();
+	
+	if (child2->is<XML>())
+		th->CheckCyclicReference(child2->as<XML>());
+	else if (child2->is<XMLList>())
+	{
+		for (auto it = child2->as<XMLList>()->nodes.begin(); it < child2->as<XMLList>()->nodes.end(); it++)
+		{
+			th->CheckCyclicReference((*it).getPtr());
+		}
+	}
+	else
+		child2 = _NR<XML>(Class<XML>::getInstanceS(child2->toString()));
+	if (child1->is<Null>())
+	{
+		th->incRef();
+		child2->as<XML>()->parentNode = _NR<XML>(th);
+		if (child2->is<XML>())
+		{
+			th->incRef();
+			child2->incRef();
+			child2->as<XML>()->parentNode = _NR<XML>(th);
+			th->childrenlist->nodes.insert(th->childrenlist->nodes.begin(),_NR<XML>(child2->as<XML>()));
+		}
+		else if (child2->is<XMLList>())
 		{
-			tiny_string nsuri((const char*)namespaces[i]->href);
-			if(nsuri==uri)
+			for (auto it2 = child2->as<XMLList>()->nodes.begin(); it2 < child2->as<XMLList>()->nodes.end(); it2++)
 			{
-				if(namespaces[i]->prefix)
+				th->incRef();
+				(*it2)->incRef();
+				(*it2)->parentNode = _NR<XML>(th);
+			}
+			th->childrenlist->nodes.insert(th->childrenlist->nodes.begin(),child2->as<XMLList>()->nodes.begin(), child2->as<XMLList>()->nodes.end());
+		}
+		th->incRef();
+		return th;
+	}
+	if (child1->is<XMLList>())
+	{
+		if (child1->as<XMLList>()->nodes.size()==0)
+			return getSys()->getUndefinedRef();
+		child1 = child1->as<XMLList>()->nodes[0];
+	}
+	for (auto it = th->childrenlist->nodes.begin(); it != th->childrenlist->nodes.end(); it++)
+	{
+		if ((*it).getPtr() == child1.getPtr())
+		{
+			th->incRef();
+			if (child2->is<XML>())
+			{
+				th->incRef();
+				child2->incRef();
+				child2->as<XML>()->parentNode = _NR<XML>(th);
+				th->childrenlist->nodes.insert(it+1,_NR<XML>(child2->as<XML>()));
+			}
+			else if (child2->is<XMLList>())
+			{
+				for (auto it2 = child2->as<XMLList>()->nodes.begin(); it2 < child2->as<XMLList>()->nodes.end(); it2++)
 				{
-					prefix=tiny_string((const char*)namespaces[i]->prefix, true);
+					th->incRef();
+					(*it2)->incRef();
+					(*it2)->parentNode = _NR<XML>(th);
 				}
+				th->childrenlist->nodes.insert(it+1,child2->as<XMLList>()->nodes.begin(), child2->as<XMLList>()->nodes.end());
+			}
+			return th;
+		}
+	}
+	return getSys()->getUndefinedRef();
+}
+ASFUNCTIONBODY(XML,insertChildBefore)
+{
+	XML* th=Class<XML>::cast(obj);
+	_NR<ASObject> child1;
+	_NR<ASObject> child2;
+	ARG_UNPACK(child1)(child2);
+	if (th->nodetype != XML_ELEMENT_NODE)
+		return getSys()->getUndefinedRef();
+	
+	if (child2->is<XML>())
+		th->CheckCyclicReference(child2->as<XML>());
+	else if (child2->is<XMLList>())
+	{
+		for (auto it = child2->as<XMLList>()->nodes.begin(); it < child2->as<XMLList>()->nodes.end(); it++)
+		{
+			th->CheckCyclicReference((*it).getPtr());
+		}
+	}
+	else
+		child2 = _NR<XML>(Class<XML>::getInstanceS(child2->toString()));
 
-				found = true;
-				break;
+	if (child1->is<Null>())
+	{
+		if (child2->is<XML>())
+		{
+			th->appendChild(_NR<XML>(child2->as<XML>()));
+		}
+		else if (child2->is<XMLList>())
+		{
+			for (auto it = child2->as<XMLList>()->nodes.begin(); it < child2->as<XMLList>()->nodes.end(); it++)
+			{
+				th->incRef();
+				(*it)->incRef();
+				(*it)->parentNode = _NR<XML>(th);
+				th->childrenlist->nodes.push_back(_NR<XML>(*it));
+			}
+		}
+		th->incRef();
+		return th;
+	}
+	if (child1->is<XMLList>())
+	{
+		if (child1->as<XMLList>()->nodes.size()==0)
+			return getSys()->getUndefinedRef();
+		child1 = child1->as<XMLList>()->nodes[0];
+	}
+	for (auto it = th->childrenlist->nodes.begin(); it != th->childrenlist->nodes.end(); it++)
+	{
+		if ((*it).getPtr() == child1.getPtr())
+		{
+			th->incRef();
+			if (child2->is<XML>())
+			{
+				th->incRef();
+				child2->incRef();
+				child2->as<XML>()->parentNode = _NR<XML>(th);
+				th->childrenlist->nodes.insert(it,_NR<XML>(child2->as<XML>()));
 			}
+			else if (child2->is<XMLList>())
+			{
+				for (auto it2 = child2->as<XMLList>()->nodes.begin(); it2 < child2->as<XMLList>()->nodes.end(); it2++)
+				{
+					th->incRef();
+					(*it2)->incRef();
+					(*it2)->parentNode = _NR<XML>(th);
+				}
+				th->childrenlist->nodes.insert(it,child2->as<XMLList>()->nodes.begin(), child2->as<XMLList>()->nodes.end());
+			}
+			return th;
 		}
+	}
+	return getSys()->getUndefinedRef();
+}
 
-		xmlFree(namespaces);
+ASFUNCTIONBODY(XML,namespaceDeclarations)
+{
+	XML *th = obj->as<XML>();
+	Array *namespaces = Class<Array>::getInstanceS();
+	for (uint32_t i = 0; i < th->namespacedefs.size(); i++)
+	{
+		_R<Namespace> tmpns = th->namespacedefs[i];
+		bool b;
+		if (tmpns->getPrefix(b) != "")
+		{
+			tmpns->incRef();
+			namespaces->push(tmpns);
+		}
 	}
+	return namespaces;
+}
 
-	if(!found && create)
+ASFUNCTIONBODY(XML,removeNamespace)
+{
+	XML *th = obj->as<XML>();
+	_NR<ASObject> arg1;
+	ARG_UNPACK(arg1);
+	Namespace* ns;
+	if (arg1->is<Namespace>())
+		ns = arg1->as<Namespace>();
+	else
+		ns = Class<Namespace>::getInstanceS(arg1->toString(), "");
+
+	th->RemoveNamespace(ns);
+	th->incRef();
+	return th;
+}
+void XML::RemoveNamespace(Namespace *ns)
+{
+	if (this->nodenamespace_uri == ns->getURI())
+	{
+		this->nodenamespace_uri = "";
+		this->nodenamespace_prefix = "";
+	}
+	for (auto it = namespacedefs.begin(); it !=  namespacedefs.end(); it++)
+	{
+		_R<Namespace> tmpns = *it;
+		if (tmpns->getURI() == ns->getURI())
+		{
+			namespacedefs.erase(it);
+			break;
+		}
+	}
+	if (childrenlist)
 	{
-		xmlpp::Element *element=dynamic_cast<xmlpp::Element *>(node);
-		xmlpp::Attribute *attribute=dynamic_cast<xmlpp::Attribute *>(node);
-		if(attribute)
-			element=attribute->get_parent();
-		if(element)
-			element->set_namespace_declaration(uri);
+		for (auto it = childrenlist->nodes.begin(); it != childrenlist->nodes.end(); it++)
+		{
+			(*it)->RemoveNamespace(ns);
+		}
 	}
+}
 
-	return prefix;
+ASFUNCTIONBODY(XML,comments)
+{
+	XML* th=Class<XML>::cast(obj);
+	tiny_string name;
+	ARG_UNPACK(name,"*");
+	XMLVector ret;
+	th->getComments(ret);
+	return Class<XMLList>::getInstanceS(ret,th->getChildrenlist(),multiname(NULL));
+}
+void XML::getComments(XMLVector& ret)
+{
+	if (childrenlist)
+	{
+		for (auto it = childrenlist->nodes.begin(); it != childrenlist->nodes.end(); it++)
+		{
+			if ((*it)->getNodeKind() == XML_COMMENT_NODE)
+			{
+				(*it)->incRef();
+				ret.push_back(*it);
+			}
+		}
+	}
 }
 
-ASFUNCTIONBODY(XML,_toString)
+ASFUNCTIONBODY(XML,processingInstructions)
 {
 	XML* th=Class<XML>::cast(obj);
-	return Class<ASString>::getInstanceS(th->toString_priv());
+	tiny_string name;
+	ARG_UNPACK(name,"*");
+	XMLVector ret;
+	th->getprocessingInstructions(ret,name);
+	return Class<XMLList>::getInstanceS(ret,th->getChildrenlist(),multiname(NULL));
+}
+void XML::getprocessingInstructions(XMLVector& ret, tiny_string name)
+{
+	if (childrenlist)
+	{
+		for (auto it = childrenlist->nodes.begin(); it != childrenlist->nodes.end(); it++)
+		{
+			if ((*it)->getNodeKind() == XML_PI_NODE && (name == "*" || name == (*it)->nodename))
+			{
+				(*it)->incRef();
+				ret.push_back(*it);
+			}
+		}
+	}
+}
+ASFUNCTIONBODY(XML,_propertyIsEnumerable)
+{
+	return abstract_b(argslen == 1 && args[0]->toString() == "0" );
+}
+ASFUNCTIONBODY(XML,_hasOwnProperty)
+{
+	tiny_string prop;
+	ARG_UNPACK(prop);
+
+	bool ret = false;
+	if (prop == "0")
+		ret = true;
+	else
+	{
+		multiname name(NULL);
+		name.name_type=multiname::NAME_STRING;
+		name.name_s_id=getSys()->getUniqueStringId(args[0]->toString());
+		name.ns.push_back(nsNameAndKind("",NAMESPACE));
+		name.ns.push_back(nsNameAndKind(AS3,NAMESPACE));
+		name.isAttribute=false;
+		ret=obj->hasPropertyByMultiname(name, true, true);
+	}
+	return abstract_b(ret);
 }
 
 tiny_string XML::toString_priv()
 {
-	//We have to use vanilla libxml2, libxml++ is not enough
-	xmlNodePtr libXml2Node=node->cobj();
 	tiny_string ret;
-	if(hasSimpleContent())
+	if (getNodeKind() == XML_TEXT_NODE ||
+		getNodeKind() == XML_ATTRIBUTE_NODE ||
+		getNodeKind() == XML_CDATA_SECTION_NODE)
+	{
+		ret=nodevalue;
+	}
+	else if (hasSimpleContent())
 	{
-		xmlChar* content=xmlNodeGetContent(libXml2Node);
-		ret=tiny_string((char*)content,true);
-		xmlFree(content);
+		auto it = childrenlist->nodes.begin();
+		while(it != childrenlist->nodes.end())
+		{
+			if ((*it)->getNodeKind() != XML_COMMENT_NODE &&
+					(*it)->getNodeKind() != XML_PI_NODE)
+				ret += (*it)->toString_priv();
+			it++;
+		}
 	}
 	else
 	{
-		assert_and_throw(!node->get_children().empty());
-		xmlBufferPtr xmlBuffer=xmlBufferCreateSize(4096);
-		toXMLString_priv(xmlBuffer);
-		ret=tiny_string((char*)xmlBuffer->content,true);
-		xmlBufferFree(xmlBuffer);
+		ret=toXMLString_internal();
 	}
 	return ret;
 }
 
+const tiny_string XML::encodeToXML(const tiny_string value, bool bIsAttribute)
+{
+
+	tiny_string res;
+	auto it = value.begin();
+	while (it != value.end())
+	{
+		switch (*it)
+		{
+			case '<':
+				res += "<";
+				break;
+			case '>':
+				res += bIsAttribute ? ">" : ">";
+				break;
+			case '&':
+				res += "&";
+				break;
+			case '\"':
+				res += bIsAttribute ? """ : "\"";
+				break;
+			case '\r':
+				res += bIsAttribute ? "&#xD;" : "\r";
+				break;
+			case '\n':
+				res += bIsAttribute ? "&#xA;" : "\n";
+				break;
+			case '\t':
+				res += bIsAttribute ? "&#x9;" : "\t";
+				break;
+			default:
+				res += *it;
+				break;
+		}
+		it++;
+	}
+	return res;
+}
+
+bool XML::getPrettyPrinting()
+{
+	return prettyPrinting;
+}
+
 tiny_string XML::toString()
 {
 	return toString_priv();
@@ -1330,86 +2229,44 @@ int32_t XML::toInt()
 	if (!hasSimpleContent())
 		return 0;
 
-	tiny_string str = toString();
+	tiny_string str = toString_priv();
 	return Integer::stringToASInteger(str.raw_buf(), 0);
 }
 
-bool XML::nodesEqual(xmlpp::Node *a, xmlpp::Node *b) const
+bool XML::nodesEqual(XML *a, XML *b) const
 {
 	assert(a && b);
 
 	// type
-	if(a->cobj()->type!=b->cobj()->type)
+	if(a->nodetype!=b->nodetype)
 		return false;
 
 	// name
-	if(a->get_name()!=b->get_name() || 
-	   (!a->get_name().empty() && 
-	    a->get_namespace_uri()!=b->get_namespace_uri()))
+	if(a->nodename!=b->nodename || 
+	   (!a->nodename.empty() && 
+	    a->nodenamespace_uri!=b->nodenamespace_uri))
 		return false;
 
 	// attributes
-	xmlpp::Element *el1=dynamic_cast<xmlpp::Element *>(a);
-	xmlpp::Element *el2=dynamic_cast<xmlpp::Element *>(b);
-	if(el1 && el2)
+	if(a->nodetype==XML_ELEMENT_NODE)
 	{
-		xmlpp::Element::AttributeList attrs1=el1->get_attributes();
-		xmlpp::Element::AttributeList attrs2=el2->get_attributes();
-		if(attrs1.size()!=attrs2.size())
+		if (a->attributelist->nodes.size() != b->attributelist->nodes.size())
 			return false;
-
-		xmlpp::Element::AttributeList::iterator it=attrs1.begin();
-		while(it!=attrs1.end())
+			
+		for (int i = 0; i < (int)a->attributelist->nodes.size(); i++)
 		{
-			xmlpp::Attribute *attr=el2->get_attribute((*it)->get_name(),
-								  (*it)->get_namespace_prefix());
-			if(!attr || (*it)->get_value()!=attr->get_value())
+			_R<XML> oa= a->attributelist->nodes[i];
+			_R<XML> ob= b->attributelist->nodes[i];
+			if (!oa->isEqual(ob.getPtr()))
 				return false;
-
-			++it;
 		}
 	}
-
 	// content
-	xmlpp::ContentNode *c1=dynamic_cast<xmlpp::ContentNode *>(a);
-	xmlpp::ContentNode *c2=dynamic_cast<xmlpp::ContentNode *>(b);
-	if(el1 && el2)
-	{
-		xmlpp::TextNode *text1=el1->get_child_text();
-		xmlpp::TextNode *text2=el2->get_child_text();
-
-		if(text1 && text2)
-		{
-			if(text1->get_content()!=text2->get_content())
-				return false;
-		}
-		else if(text1 || text2)
-			return false;
-
-	}
-	else if(c1 && c2)
-	{
-		if(c1->get_content()!=c2->get_content())
-			return false;
-	}
+	if (a->nodevalue != b->nodevalue)
+		return false;
 	
 	// children
-	xmlpp::Node::NodeList myChildren=a->get_children();
-	xmlpp::Node::NodeList otherChildren=b->get_children();
-	if(myChildren.size()!=otherChildren.size())
-		return false;
-
-	xmlpp::Node::NodeList::iterator it1=myChildren.begin();
-	xmlpp::Node::NodeList::iterator it2=otherChildren.begin();
-	while(it1!=myChildren.end())
-	{
-		if (!nodesEqual(*it1, *it2))
-			return false;
-		++it1;
-		++it2;
-	}
-
-	return true;
+	return a->childrenlist->isEqual(b->childrenlist.getPtr());
 }
 
 uint32_t XML::nextNameIndex(uint32_t cur_index)
@@ -1443,7 +2300,7 @@ bool XML::isEqual(ASObject* r)
 {
 	XML *x=dynamic_cast<XML *>(r);
 	if(x)
-		return nodesEqual(node, x->node);
+		return nodesEqual(this, x);
 
 	XMLList *xl=dynamic_cast<XMLList *>(r);
 	if(xl)
@@ -1463,13 +2320,150 @@ void XML::serialize(ByteArray* out, std::map<tiny_string, uint32_t>& stringMap,
 	out->writeXMLString(objMap, this, toString());
 }
 
-_NR<XML> XML::getRootNode()
+void XML::createTree(xmlpp::Node* node)
 {
-	if(root.isNull())
+	const xmlpp::Node::NodeList& list=node->get_children();
+	xmlpp::Node::NodeList::const_iterator it=list.begin();
+	childrenlist = _MR(Class<XMLList>::getInstanceS());
+	childrenlist->incRef();
+
+	this->nodetype = node->cobj()->type;
+	this->nodename = node->get_name();
+	this->nodenamespace_uri = node->get_namespace_uri();
+	this->nodenamespace_prefix = node ->get_namespace_prefix();
+	
+	switch (this->nodetype)
 	{
-		incRef();
-		return _MR(this);
+		case XML_ATTRIBUTE_NODE:
+		case XML_TEXT_NODE:
+		{
+			xmlpp::ContentNode *textnode=dynamic_cast<xmlpp::ContentNode*>(node);
+			this->nodevalue = textnode->get_content();
+			if (ignoreWhitespace)
+			{
+				nodevalue = removeWhitespace(nodevalue);
+				if (nodevalue.empty())
+					return;
+			}
+			break;
+		}
+		case XML_PI_NODE:
+		{
+			xmlpp::ContentNode *textnode=dynamic_cast<xmlpp::ContentNode*>(node);
+			this->nodevalue = textnode->get_content();
+			break;
+		}
+		case XML_COMMENT_NODE:
+		case XML_CDATA_SECTION_NODE:
+		{
+			xmlpp::ContentNode *textnode=dynamic_cast<xmlpp::ContentNode*>(node);
+			this->nodevalue = textnode->get_content();
+			break;
+		}
+		default:
+			break;
+	}
+	for(;it!=list.end();++it)
+	{
+		if (ignoreProcessingInstructions && (*it)->cobj()->type == XML_PI_NODE)
+			continue;
+		if (ignoreComments && (*it)->cobj()->type == XML_COMMENT_NODE)
+			continue;
+		if (ignoreWhitespace && (*it)->cobj()->type == XML_TEXT_NODE)
+		{
+			xmlpp::ContentNode *textnode=dynamic_cast<xmlpp::ContentNode*>(*it);
+			tiny_string tmpstr = textnode->get_content();
+			if (ignoreWhitespace)
+			{
+				tmpstr = removeWhitespace(tmpstr);
+				if (tmpstr.empty())
+					continue;
+			}
+		}
+		_NR<XML> tmp = _MR<XML>(Class<XML>::getInstanceS(*it));
+		this->incRef();
+		tmp->parentNode = _MR<XML>(this);
+		childrenlist->append(_R<XML>(tmp));
+	}
+	const xmlNode* xmlN = node->cobj();
+
+	xmlNsPtr nsdefs = xmlN->nsDef;
+	while (nsdefs)
+	{
+		tiny_string uri;
+		if (nsdefs->href) uri= (char*)nsdefs->href;
+		tiny_string prefix;
+		if (nsdefs->prefix) prefix= (char*)nsdefs->prefix;
+		Namespace* ns = Class<Namespace>::getInstanceS(uri,prefix);
+		namespacedefs.push_back(_MR(ns));
+		nsdefs = nsdefs->next;
+	}
+	attributelist = _MR(Class<XMLList>::getInstanceS());
+	for(xmlAttr* attr=xmlN->properties; attr!=NULL; attr=attr->next)
+	{
+		_NR<XML> tmp = _MR<XML>(Class<XML>::getInstanceS());
+		this->incRef();
+		tmp->parentNode = _MR<XML>(this);
+		tmp->nodetype = XML_ATTRIBUTE_NODE;
+		tmp->nodename = (char*)attr->name;
+		if (attr->ns)
+		{
+			tmp->nodenamespace_uri = (char*)attr->ns->href;
+			tmp->nodenamespace_prefix = (char*)attr->ns->prefix;
+		}
+		else 
+			tmp->nodenamespace_uri = getVm()->getDefaultXMLNamespace();
+
+		//NOTE: libxmlpp headers says that Node::create_wrapper
+		//is supposed to be internal API. Still it's very useful and
+		//we use it.
+		xmlpp::Node::create_wrapper(reinterpret_cast<xmlNode*>(attr));
+		xmlpp::Node* attrX=static_cast<xmlpp::Node*>(attr->_private);
+		xmlpp::Attribute *textnode=dynamic_cast<xmlpp::Attribute*>(attrX);
+		tmp->nodevalue = textnode->get_value();
+		tmp->constructed = true;
+		attributelist->nodes.push_back(tmp);
+	}
+	constructed=true;
+}
+
+ASFUNCTIONBODY(XML,_prependChild)
+{
+	XML* th=Class<XML>::cast(obj);
+	assert_and_throw(argslen==1);
+	_NR<XML> arg;
+	if(args[0]->getClass()==Class<XML>::getClass())
+	{
+		args[0]->incRef();
+		arg=_MR(Class<XML>::cast(args[0]));
+	}
+	else if(args[0]->getClass()==Class<XMLList>::getClass())
+	{
+		XMLList* list=Class<XMLList>::cast(args[0]);
+		list->appendNodesTo(th);
+		th->incRef();
+		return th;
+	}
+	else
+	{
+		//The appendChild specs says that any other type is converted to string
+		//NOTE: this is explicitly different from XML constructor, that will only convert to
+		//string Numbers and Booleans
+		arg=_MR(Class<XML>::getInstanceS(args[0]->toString()));
+	}
+
+	th->appendChild(arg);
+	th->incRef();
+	return th;
+}
+void XML::prependChild(_R<XML> newChild)
+{
+	if (newChild->constructed)
+	{
+		this->incRef();
+		newChild->parentNode = _NR<XML>(this);
+		childrenlist->append(newChild);
 	}
 	else
-		return root;
+		newChild->decRef();
 }
diff --git a/src/scripting/toplevel/XML.h b/src/scripting/toplevel/XML.h
index 5ff172a..e7f34cf 100644
--- a/src/scripting/toplevel/XML.h
+++ b/src/scripting/toplevel/XML.h
@@ -24,32 +24,36 @@
 
 namespace lightspark
 {
+class Namespace;
 class XMLList;
 class XML: public ASObject, public XMLBase
 {
 friend class XMLList;
 public:
 	typedef std::vector<_R<XML>> XMLVector;
+	typedef std::vector<_R<Namespace>> NSVector;
 private:
-	//Pointer to the root XML element, the one that owns the parser that created this node
-	_NR<XML> root;
-	//The node this object represent
-	xmlpp::Node* node;
-	static void recursiveGetDescendantsByQName(_R<XML> root, xmlpp::Node* node, const tiny_string& name, const tiny_string& ns, 
-			XMLVector& ret);
+	_NR<XMLList> childrenlist;
+	_NR<XML> parentNode;
+	xmlElementType nodetype;
+	tiny_string nodename;
+	tiny_string nodevalue;
+	tiny_string nodenamespace_uri;
+	tiny_string nodenamespace_prefix;
+	_NR<XMLList> attributelist;
+	NSVector namespacedefs;
+
+	void createTree(xmlpp::Node* node);
 	tiny_string toString_priv();
+	const char* nodekindString();
+	
 	bool constructed;
-	bool nodesEqual(xmlpp::Node *a, xmlpp::Node *b) const;
-	XMLVector getAttributes(const tiny_string& name="*",
-				const tiny_string& namespace_uri="*");
+	bool nodesEqual(XML *a, XML *b) const;
+	XMLVector getAttributes();
+	XMLVector getAttributesByMultiname(const multiname& name);
+	XMLVector getValuesByMultiname(_NR<XMLList> nodelist, const multiname& name);
 	XMLList* getAllAttributes();
 	void getText(XMLVector& ret);
-	_NR<XML> getRootNode();
-	bool ignoreComments;
-	bool ignoreProcessingInstructions;
-	bool ignoreWhitespace;
-	uint32_t prettyIndent;
-	bool prettyPrinting;
 	/*
 	 * @param name The name of the wanted children, "*" for all children
 	 *
@@ -57,15 +61,22 @@ private:
 	void childrenImpl(XMLVector& ret, const tiny_string& name);
 	void childrenImpl(XMLVector& ret, uint32_t index);
 	tiny_string getNamespacePrefixByURI(const tiny_string& uri, bool create=false);
-        void setLocalName(const tiny_string& localname);
-        void setNamespace(const tiny_string& ns_uri, const tiny_string& ns_prefix="");
-	void removeAllChildren();
-	static void normalizeRecursive(xmlpp::Node *node);
+	void setLocalName(const tiny_string& localname);
+	void setNamespace(const tiny_string& ns_uri, const tiny_string& ns_prefix="");
+	// Append node or attribute to this. Concatenates adjacent
+	// text nodes.
+	void appendChild(_R<XML> child);
+	void prependChild(_R<XML> child);
+	static void normalizeRecursive(XML *node);
 	void addTextContent(const tiny_string& str);
+	bool hasParentNode;
+	void RemoveNamespace(Namespace *ns);
+	void getComments(XMLVector& ret);
+	void getprocessingInstructions(XMLVector& ret, tiny_string name);
+	void CheckCyclicReference(XML* node);
 public:
 	XML(Class_base* c);
 	XML(Class_base* c,const std::string& str);
-	XML(Class_base* c,_R<XML> _r, xmlpp::Node* _n);
 	XML(Class_base* c,xmlpp::Node* _n);
 	void finalize();
 	ASFUNCTION(_constructor);
@@ -79,7 +90,7 @@ public:
 	ASFUNCTION(_copy);
 	ASFUNCTION(attributes);
 	ASFUNCTION(attribute);
-	ASFUNCTION(appendChild);
+	ASFUNCTION(_appendChild);
 	ASFUNCTION(length);
 	ASFUNCTION(localName);
 	ASFUNCTION(name);
@@ -99,21 +110,59 @@ public:
 	ASFUNCTION(_setName);
 	ASFUNCTION(_setNamespace);
 	ASFUNCTION(_setChildren);
-	static void buildTraits(ASObject* o){};
+
+	ASFUNCTION(_getIgnoreComments);
+	ASFUNCTION(_setIgnoreComments);
+	ASFUNCTION(_getIgnoreProcessingInstructions);
+	ASFUNCTION(_setIgnoreProcessingInstructions);
+	ASFUNCTION(_getIgnoreWhitespace);
+	ASFUNCTION(_setIgnoreWhitespace);
+	ASFUNCTION(_getPrettyIndent);
+	ASFUNCTION(_setPrettyIndent);
+	ASFUNCTION(_getPrettyPrinting);
+	ASFUNCTION(_setPrettyPrinting);
+	ASFUNCTION(_getSettings);
+	ASFUNCTION(_setSettings);
+	ASFUNCTION(_getDefaultSettings);
+	ASFUNCTION(_toJSON);
+	ASFUNCTION(insertChildAfter);
+	ASFUNCTION(insertChildBefore);
+	ASFUNCTION(namespaceDeclarations);
+	ASFUNCTION(removeNamespace);
+	ASFUNCTION(comments);
+	ASFUNCTION(processingInstructions);
+	ASFUNCTION(_propertyIsEnumerable);
+	ASFUNCTION(_hasOwnProperty);
+	ASFUNCTION(_prependChild);
+
+	static void buildTraits(ASObject* o){}
 	static void sinit(Class_base* c);
-	void getDescendantsByQName(const tiny_string& name, const tiny_string& ns, XMLVector& ret);
+	
+	static const tiny_string encodeToXML(const tiny_string value, bool bIsAttribute);
+	static bool getPrettyPrinting();
+
+	const tiny_string getName() const { return nodename;}
+	const tiny_string getNamespaceURI() const { return nodenamespace_uri;}
+	XMLList* getChildrenlist() { return childrenlist ? childrenlist.getPtr() : NULL; }
+	
+	
+	void getDescendantsByQName(const tiny_string& name, const tiny_string& ns,bool bIsAttribute, XMLVector& ret);
 	void getElementNodes(const tiny_string& name, XMLVector& foundElements);
-	_NR<ASObject> getVariableByMultiname(const multiname& name, GET_VARIABLE_OPTION opt);
+	_NR<ASObject> getVariableByMultiname(const multiname& name, GET_VARIABLE_OPTION opt=NONE);
 	bool hasPropertyByMultiname(const multiname& name, bool considerDynamic, bool considerPrototype);
 	void setVariableByMultiname(const multiname& name, ASObject* o, CONST_ALLOWED_FLAG allowConst);
+	bool deleteVariableByMultiname(const multiname& name);
+	static bool isValidMultiname(const multiname& name, uint32_t& index);
+
+	void setTextContent(const tiny_string& content);
 	tiny_string toString();
+	const tiny_string toXMLString_internal(bool pretty=true, tiny_string defaultnsprefix = "", const char* indent = "", bool bfirst = true);
 	int32_t toInt();
-	void toXMLString_priv(xmlBufferPtr buf);
 	bool hasSimpleContent() const;
 	bool hasComplexContent() const;
-        xmlElementType getNodeKind() const;
+	xmlElementType getNodeKind() const;
 	ASObject *getParentNode();
-	XML *copy() const;
+	XML *copy();
 	void normalize();
 	bool isEqual(ASObject* r);
 	uint32_t nextNameIndex(uint32_t cur_index);
diff --git a/src/scripting/toplevel/XMLList.cpp b/src/scripting/toplevel/XMLList.cpp
index 0d594c1..231b89e 100644
--- a/src/scripting/toplevel/XMLList.cpp
+++ b/src/scripting/toplevel/XMLList.cpp
@@ -51,35 +51,49 @@ using namespace lightspark;
 		return NULL; \
 	}
 
-XMLList::XMLList(Class_base* c):ASObject(c),nodes(c->memoryAccount),constructed(false)
+XMLList::XMLList(Class_base* c):ASObject(c),nodes(c->memoryAccount),constructed(false),targetobject(NULL),targetproperty(c->memoryAccount)
 {
 }
 
-XMLList::XMLList(Class_base* cb,bool c):ASObject(cb),nodes(cb->memoryAccount),constructed(c)
+XMLList::XMLList(Class_base* cb,bool c):ASObject(cb),nodes(cb->memoryAccount),constructed(c),targetobject(NULL),targetproperty(cb->memoryAccount)
 {
 	assert(c);
 }
 
-XMLList::XMLList(Class_base* c, const std::string& str):ASObject(c),nodes(c->memoryAccount),constructed(true)
+XMLList::XMLList(Class_base* c, const std::string& str):ASObject(c),nodes(c->memoryAccount),constructed(true),targetobject(NULL),targetproperty(c->memoryAccount)
 {
 	buildFromString(str);
 }
 
-XMLList::XMLList(Class_base* c,const XML::XMLVector& r):
-	ASObject(c),nodes(r.begin(),r.end(),c->memoryAccount),constructed(true)
+XMLList::XMLList(Class_base* c, const XML::XMLVector& r):
+	ASObject(c),nodes(r.begin(),r.end(),c->memoryAccount),constructed(true),targetobject(NULL),targetproperty(c->memoryAccount)
 {
 }
+XMLList::XMLList(Class_base* c, const XML::XMLVector& r, XMLList *targetobject, const multiname &targetproperty):
+	ASObject(c),nodes(r.begin(),r.end(),c->memoryAccount),constructed(true),targetobject(targetobject),targetproperty(c->memoryAccount)
+{
+	if (targetobject)
+		targetobject->incRef();
+	this->targetproperty.name_type = targetproperty.name_type;
+	this->targetproperty.isAttribute = targetproperty.isAttribute;
+	this->targetproperty.name_s_id = targetproperty.name_s_id;
+	for (auto it = targetproperty.ns.begin();it != targetproperty.ns.end(); it++)
+	{
+		this->targetproperty.ns.push_back(*it);
+	}
+}
 
 void XMLList::finalize()
 {
-	nodes.clear();
+	if (targetobject)
+		targetobject->decRef();
+	//nodes.clear();
 	ASObject::finalize();
 }
 
 void XMLList::sinit(Class_base* c)
 {
-	c->setSuper(Class<ASObject>::getRef());
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_SEALED | CLASS_FINAL);
 	c->setDeclaredMethodByQName("length","",Class<IFunction>::getFunction(_getLength),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("attribute",AS3,Class<IFunction>::getFunction(attribute),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("attributes",AS3,Class<IFunction>::getFunction(attributes),NORMAL_METHOD,true);
@@ -89,7 +103,7 @@ void XMLList::sinit(Class_base* c)
 	c->setDeclaredMethodByQName("copy",AS3,Class<IFunction>::getFunction(copy),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("descendants",AS3,Class<IFunction>::getFunction(descendants),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("elements",AS3,Class<IFunction>::getFunction(elements),NORMAL_METHOD,true);
-	c->setDeclaredMethodByQName("normalize",AS3,Class<IFunction>::getFunction(normalize),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("normalize",AS3,Class<IFunction>::getFunction(_normalize),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("parent",AS3,Class<IFunction>::getFunction(parent),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("hasSimpleContent",AS3,Class<IFunction>::getFunction(_hasSimpleContent),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("hasComplexContent",AS3,Class<IFunction>::getFunction(_hasComplexContent),NORMAL_METHOD,true);
@@ -99,39 +113,42 @@ void XMLList::sinit(Class_base* c)
 	c->setDeclaredMethodByQName("valueOf",AS3,Class<IFunction>::getFunction(valueOf),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("toXMLString",AS3,Class<IFunction>::getFunction(toXMLString),NORMAL_METHOD,true);
 	c->setDeclaredMethodByQName("text",AS3,Class<IFunction>::getFunction(text),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("comments",AS3,Class<IFunction>::getFunction(comments),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("processingInstructions",AS3,Class<IFunction>::getFunction(processingInstructions),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("propertyIsEnumerable",AS3,Class<IFunction>::getFunction(_propertyIsEnumerable),NORMAL_METHOD,true);
 	REGISTER_XML_DELEGATE(addNamespace);
-	REGISTER_XML_DELEGATE(appendChild);
+	REGISTER_XML_DELEGATE2(appendChild,_appendChild);
 	REGISTER_XML_DELEGATE(childIndex);
 	REGISTER_XML_DELEGATE(inScopeNamespaces);
-	//REGISTER_XML_DELEGATE(insertChildAfter);
-	//REGISTER_XML_DELEGATE(insertChildBefore);
+	REGISTER_XML_DELEGATE(insertChildAfter);
+	REGISTER_XML_DELEGATE(insertChildBefore);
 	REGISTER_XML_DELEGATE(localName);
 	REGISTER_XML_DELEGATE(name);
 	REGISTER_XML_DELEGATE2(namespace,_namespace);
-	//REGISTER_XML_DELEGATE(namespaceDeclarations);
+	REGISTER_XML_DELEGATE(namespaceDeclarations);
 	REGISTER_XML_DELEGATE(nodeKind);
-	//REGISTER_XML_DELEGATE(prependChild);
-	//REGISTER_XML_DELEGATE(removeNamespace);
+	REGISTER_XML_DELEGATE2(prependChild,_appendChild);
+	REGISTER_XML_DELEGATE(removeNamespace);
 	//REGISTER_XML_DELEGATE(replace);
-	REGISTER_XML_DELEGATE(_setChildren);
+	REGISTER_XML_DELEGATE2(setChildren,_setChildren);
 	REGISTER_XML_DELEGATE2(setLocalName,_setLocalName);
 	REGISTER_XML_DELEGATE2(setName,_setName);
 	REGISTER_XML_DELEGATE2(setNamespace,_setNamespace);
 }
 
 ASFUNCTIONBODY_XML_DELEGATE(addNamespace);
-ASFUNCTIONBODY_XML_DELEGATE(appendChild);
+ASFUNCTIONBODY_XML_DELEGATE(_appendChild);
 ASFUNCTIONBODY_XML_DELEGATE(childIndex);
 ASFUNCTIONBODY_XML_DELEGATE(inScopeNamespaces);
-//ASFUNCTIONBODY_XML_DELEGATE(insertChildAfter);
-//ASFUNCTIONBODY_XML_DELEGATE(insertChildBefore);
+ASFUNCTIONBODY_XML_DELEGATE(insertChildAfter);
+ASFUNCTIONBODY_XML_DELEGATE(insertChildBefore);
 ASFUNCTIONBODY_XML_DELEGATE(localName);
 ASFUNCTIONBODY_XML_DELEGATE(name);
 ASFUNCTIONBODY_XML_DELEGATE(_namespace);
-//ASFUNCTIONBODY_XML_DELEGATE(namespaceDeclarations);
+ASFUNCTIONBODY_XML_DELEGATE(namespaceDeclarations);
 ASFUNCTIONBODY_XML_DELEGATE(nodeKind);
-//ASFUNCTIONBODY_XML_DELEGATE(prependChild);
-//ASFUNCTIONBODY_XML_DELEGATE(removeNamespace);
+ASFUNCTIONBODY_XML_DELEGATE(_prependChild);
+ASFUNCTIONBODY_XML_DELEGATE(removeNamespace);
 //ASFUNCTIONBODY_XML_DELEGATE(replace);
 ASFUNCTIONBODY_XML_DELEGATE(_setChildren);
 ASFUNCTIONBODY_XML_DELEGATE(_setLocalName);
@@ -151,6 +168,7 @@ ASFUNCTIONBODY(XMLList,_constructor)
 	   args[0]->is<Null>() || 
 	   args[0]->is<Undefined>())
 	{
+		th->constructed=true;
 		return NULL;
 	}
 	else if(args[0]->is<XML>())
@@ -183,7 +201,12 @@ void XMLList::buildFromString(const std::string& str)
 {
 	xmlpp::DomParser parser;
 	std::string default_ns=getVm()->getDefaultXMLNamespace();
-	std::string expanded="<parent xmlns=\"" + default_ns + "\">" + str + "</parent>";
+	std::string xmldecl;
+	std::string str_without_xmldecl = extractXMLDeclaration(str, xmldecl);
+	std::string expanded = xmldecl + 
+		"<parent xmlns=\"" + default_ns + "\">" + 
+		XMLBase::parserQuirks(str_without_xmldecl) + 
+		"</parent>";
 	try
 	{
 		parser.parse_memory(expanded);
@@ -203,7 +226,47 @@ void XMLList::buildFromString(const std::string& str)
 	  parser.get_document()->get_root_node()->get_children();
 	xmlpp::Node::NodeList::const_iterator it;
 	for(it=children.begin(); it!=children.end(); ++it)
-		nodes.push_back(_MR(Class<XML>::getInstanceS(*it)));
+	{
+		_R<XML> tmp = _MR(Class<XML>::getInstanceS(*it));
+		if (tmp->constructed)
+			nodes.push_back(tmp);
+	}
+}
+
+std::string XMLList::extractXMLDeclaration(const std::string& xml, std::string& xmldecl_out)
+{
+	if (xml.compare(0, 2, "<?") != 0)
+		return xml;
+	std::string res = xml;
+	xmldecl_out = "";
+	size_t declEnd = 0;
+	size_t len = xml.length();
+	while (declEnd<len && declEnd != xml.npos)
+	{
+		if (g_unichar_isspace(xml[declEnd]))
+				declEnd++;
+		else
+		{
+			if (xml.compare(declEnd, 2, "<?") == 0)
+			{
+				size_t tmp = xml.find("?>",declEnd);
+				if (tmp == xml.npos)
+					break;
+				declEnd = tmp +2;
+			}
+			else
+				break;
+		}
+	}
+	if (declEnd && declEnd != xml.npos)
+	{
+		xmldecl_out = xml.substr(0, declEnd);
+		if (declEnd<len)
+			res = xml.substr(declEnd);
+		else
+			res = "";
+	}
+	return res;
 }
 
 _R<XML> XMLList::reduceToXML() const
@@ -279,12 +342,13 @@ ASFUNCTIONBODY(XMLList,generator)
 ASFUNCTIONBODY(XMLList,descendants)
 {
 	XMLList* th=Class<XMLList>::cast(obj);
-	tiny_string name;
-	assert_and_throw(argslen==0 || args[0]->getObjectType()!=T_QNAME);
-	ARG_UNPACK(name,"*");
+	_NR<ASObject> name;
+	ARG_UNPACK(name,_NR<ASObject>(Class<ASString>::getInstanceS("*")));
 	XML::XMLVector ret;
-	th->getDescendantsByQName(name,"",ret);
-	return Class<XMLList>::getInstanceS(ret);
+	multiname mname(NULL);
+	name->applyProxyProperty(mname);
+	th->getDescendantsByQName(name->toString(),"",mname.isAttribute,ret);
+	return Class<XMLList>::getInstanceS(ret,th->targetobject,multiname(NULL));
 }
 
 ASFUNCTIONBODY(XMLList,elements)
@@ -295,11 +359,11 @@ ASFUNCTIONBODY(XMLList,elements)
 
 	XML::XMLVector elems;
 	auto it=th->nodes.begin();
-        for(; it!=th->nodes.end(); ++it)
-        {
+	for(; it!=th->nodes.end(); ++it)
+	{
 		(*it)->getElementNodes(name, elems);
 	}
-	return Class<XMLList>::getInstanceS(elems);
+	return Class<XMLList>::getInstanceS(elems,th->targetobject,multiname(NULL));
 }
 
 ASFUNCTIONBODY(XMLList,parent)
@@ -313,8 +377,8 @@ ASFUNCTIONBODY(XMLList,parent)
 	ASObject *parent=(*it)->getParentNode();
 	++it;
 
-        for(; it!=th->nodes.end(); ++it)
-        {
+	for(; it!=th->nodes.end(); ++it)
+	{
 		ASObject *otherParent=(*it)->getParentNode();
 		if(!parent->isEqual(otherParent))
 			return getSys()->getUndefinedRef();
@@ -333,14 +397,28 @@ ASFUNCTIONBODY(XMLList,child)
 {
 	XMLList* th = obj->as<XMLList>();
 	assert_and_throw(argslen==1);
-	const tiny_string& arg0=args[0]->toString();
 	XML::XMLVector ret;
-	auto it=th->nodes.begin();
-        for(; it!=th->nodes.end(); ++it)
-        {
-		(*it)->childrenImpl(ret, arg0);
+	if(args[0]->is<Number>() ||
+		args[0]->is<Integer>() ||
+		args[0]->is<UInteger>())
+	{
+		uint32_t index =args[0]->toUInt();
+		auto it=th->nodes.begin();
+		for(; it!=th->nodes.end(); ++it)
+		{
+			(*it)->childrenImpl(ret, index);
+		}
 	}
-	XMLList* retObj=Class<XMLList>::getInstanceS(ret);
+	else
+	{
+		const tiny_string& arg0=args[0]->toString();
+		auto it=th->nodes.begin();
+		for(; it!=th->nodes.end(); ++it)
+		{
+			(*it)->childrenImpl(ret, arg0);
+		}
+	}
+	XMLList* retObj=Class<XMLList>::getInstanceS(ret,th->targetobject,multiname(NULL));
 	return retObj;
 }
 
@@ -350,11 +428,11 @@ ASFUNCTIONBODY(XMLList,children)
 	assert_and_throw(argslen==0);
 	XML::XMLVector ret;
 	auto it=th->nodes.begin();
-        for(; it!=th->nodes.end(); ++it)
-        {
+	for(; it!=th->nodes.end(); ++it)
+	{
 		(*it)->childrenImpl(ret, "*");
 	}
-	XMLList* retObj=Class<XMLList>::getInstanceS(ret);
+	XMLList* retObj=Class<XMLList>::getInstanceS(ret,th->targetobject,multiname(NULL));
 	return retObj;
 }
 
@@ -364,11 +442,11 @@ ASFUNCTIONBODY(XMLList,text)
 	ARG_UNPACK;
 	XML::XMLVector ret;
 	auto it=th->nodes.begin();
-        for(; it!=th->nodes.end(); ++it)
-        {
+	for(; it!=th->nodes.end(); ++it)
+	{
 		(*it)->getText(ret);
 	}
-	return Class<XMLList>::getInstanceS(ret);
+	return Class<XMLList>::getInstanceS(ret,th->targetobject,multiname(NULL));
 }
 
 ASFUNCTIONBODY(XMLList,contains)
@@ -380,8 +458,8 @@ ASFUNCTIONBODY(XMLList,contains)
 		return abstract_b(false);
 
 	auto it=th->nodes.begin();
-        for(; it!=th->nodes.end(); ++it)
-        {
+	for(; it!=th->nodes.end(); ++it)
+	{
 		if((*it)->isEqual(value.getPtr()))
 			return abstract_b(true);
 	}
@@ -393,9 +471,10 @@ ASFUNCTIONBODY(XMLList,copy)
 {
 	XMLList* th = obj->as<XMLList>();
 	XMLList *dest = Class<XMLList>::getInstanceS();
+	dest->targetobject = th->targetobject;
 	auto it=th->nodes.begin();
-        for(; it!=th->nodes.end(); ++it)
-        {
+	for(; it!=th->nodes.end(); ++it)
+	{
 		dest->nodes.push_back(_MR((*it)->copy()));
 	}
 	return dest;
@@ -435,11 +514,59 @@ ASFUNCTIONBODY(XMLList,attributes)
 	return res;
 }
 
-ASFUNCTIONBODY(XMLList,normalize)
+ASFUNCTIONBODY(XMLList,comments)
 {
-	XMLList *th = obj->as<XMLList>();
+	XMLList* th=Class<XMLList>::cast(obj);
+
+	XMLList *res = Class<XMLList>::getInstanceS();
+	XML::XMLVector nodecomments;
 	auto it=th->nodes.begin();
-	while (it!=th->nodes.end())
+	for(; it!=th->nodes.end(); ++it)
+	{
+		(*it)->getComments(nodecomments);
+	}
+	res->nodes.insert(res->nodes.end(), nodecomments.begin(), nodecomments.end());
+	return res;
+}
+ASFUNCTIONBODY(XMLList,processingInstructions)
+{
+	XMLList* th=Class<XMLList>::cast(obj);
+	tiny_string name;
+	ARG_UNPACK(name,"*");
+
+	XMLList *res = Class<XMLList>::getInstanceS();
+	XML::XMLVector nodeprocessingInstructions;
+	auto it=th->nodes.begin();
+	for(; it!=th->nodes.end(); ++it)
+	{
+		(*it)->getprocessingInstructions(nodeprocessingInstructions,name);
+	}
+	res->nodes.insert(res->nodes.end(), nodeprocessingInstructions.begin(), nodeprocessingInstructions.end());
+	return res;
+}
+ASFUNCTIONBODY(XMLList,_propertyIsEnumerable)
+{
+	XMLList* th=Class<XMLList>::cast(obj);
+	if (argslen == 1)
+	{
+		int32_t n = args[0]->toInt();
+		return abstract_b(n < (int32_t)th->nodes.size());
+		
+	}
+	return abstract_b(false);
+}
+
+ASFUNCTIONBODY(XMLList,_normalize)
+{
+	XMLList *th = obj->as<XMLList>();
+	th->normalize();
+	th->incRef();
+	return th;
+}
+void XMLList::normalize()
+{
+	auto it=nodes.begin();
+	while (it!=nodes.end())
 	{
 		if ((*it)->getNodeKind() == XML_ELEMENT_NODE)
 		{
@@ -450,17 +577,17 @@ ASFUNCTIONBODY(XMLList,normalize)
 		{
 			if ((*it)->toString().empty())
 			{
-				it = th->nodes.erase(it);
+				it = nodes.erase(it);
 			}
 			else
 			{
 				_R<XML> textnode = *it;
 
 				++it;
-				while (it!=th->nodes.end() && (*it)->getNodeKind() == XML_TEXT_NODE)
+				while (it!=nodes.end() && (*it)->getNodeKind() == XML_TEXT_NODE)
 				{
 					textnode->addTextContent((*it)->toString());
-					it = th->nodes.erase(it);
+					it = nodes.erase(it);
 				}
 			}
 
@@ -470,9 +597,51 @@ ASFUNCTIONBODY(XMLList,normalize)
 			++it;
 		}
 	}
+}
 
-	th->incRef();
-	return th;
+void XMLList::clear()
+{
+	nodes.clear();
+}
+void XMLList::getTargetVariables(const multiname& name,XML::XMLVector& retnodes)
+{
+	unsigned int index=0;
+	if(XML::isValidMultiname(name,index))
+	{
+		retnodes.push_back(nodes[index]);
+	}
+	else
+	{
+		tiny_string normalizedName=name.normalizedName();
+		
+		//Only the first namespace is used, is this right?
+		tiny_string namespace_uri;
+		if(name.ns.size() > 0 && !name.ns[0].hasEmptyName())
+		{
+			nsNameAndKindImpl ns=name.ns[0].getImpl();
+			if (ns.kind==NAMESPACE)
+				namespace_uri=ns.name;
+		}
+		
+		// namespace set by "default xml namespace = ..."
+		if(namespace_uri.empty())
+			namespace_uri=getVm()->getDefaultXMLNamespace();
+
+		for (uint32_t i = 0; i < nodes.size(); i++)
+		{
+			_R<XML> child= nodes[i];
+			bool nameMatches = (normalizedName=="" || normalizedName==child->nodename);
+			bool nsMatches = (namespace_uri=="" || 
+							  (child->nodenamespace_uri == namespace_uri));
+			
+			if(nameMatches && nsMatches)
+			{
+				retnodes.push_back(child);
+			}
+			if (child->childrenlist)
+				child->childrenlist->getTargetVariables(name,retnodes);
+		}
+	}
 }
 
 _NR<ASObject> XMLList::getVariableByMultiname(const multiname& name, GET_VARIABLE_OPTION opt)
@@ -493,14 +662,33 @@ _NR<ASObject> XMLList::getVariableByMultiname(const multiname& name, GET_VARIABL
 
 		return res;
 	}
+	if (name.isAttribute)
+	{
+		XML::XMLVector retnodes;
+		auto it=nodes.begin();
+		for(; it!=nodes.end(); ++it)
+		{
+			_NR<ASObject> o=(*it)->getVariableByMultiname(name,opt);
+			XMLList *x=dynamic_cast<XMLList *>(o.getPtr());
+			if(!x)
+				continue;
+
+			retnodes.insert(retnodes.end(), x->nodes.begin(), x->nodes.end());
+		}
 
+		if(retnodes.size()==0 && (opt & XML_STRICT)!=0)
+			return NullRef;
+
+		this->incRef();
+		return _MNR(Class<XMLList>::getInstanceS(retnodes,this,name));
+	}
 	unsigned int index=0;
-	if(Array::isValidMultiname(name,index))
+	if(XML::isValidMultiname(name,index))
 	{
 		if(index<nodes.size())
 			return nodes[index];
 		else
-			return NullRef;
+			return _MNR(getSys()->getUndefinedRef());
 	}
 	else
 	{
@@ -519,7 +707,8 @@ _NR<ASObject> XMLList::getVariableByMultiname(const multiname& name, GET_VARIABL
 		if(retnodes.size()==0 && (opt & XML_STRICT)!=0)
 			return NullRef;
 
-		return _MNR(Class<XMLList>::getInstanceS(retnodes));
+		this->incRef();
+		return _MNR(Class<XMLList>::getInstanceS(retnodes,this,name));
 	}
 }
 
@@ -528,16 +717,11 @@ bool XMLList::hasPropertyByMultiname(const multiname& name, bool considerDynamic
 	if(considerDynamic==false)
 		return ASObject::hasPropertyByMultiname(name, considerDynamic, considerPrototype);
 
-	assert_and_throw(name.ns.size()>0);
-	if(!name.ns[0].hasEmptyName())
-		return ASObject::hasPropertyByMultiname(name, considerDynamic, considerPrototype);
-
 	unsigned int index=0;
-	if(Array::isValidMultiname(name,index))
+	if(XML::isValidMultiname(name,index))
 		return index<nodes.size();
 	else
 	{
-		XML::XMLVector retnodes;
 		auto it=nodes.begin();
 		for(; it!=nodes.end(); ++it)
 		{
@@ -554,23 +738,123 @@ void XMLList::setVariableByMultiname(const multiname& name, ASObject* o, CONST_A
 {
 	assert_and_throw(implEnable);
 	unsigned int index=0;
-	if(!Array::isValidMultiname(name,index))
-		return ASObject::setVariableByMultiname(name,o,allowConst);
-
-	XML* newNode=dynamic_cast<XML*>(o);
-	if(newNode==NULL)
-		return ASObject::setVariableByMultiname(name,o,allowConst);
+	XML::XMLVector retnodes;
+	XMLList* tmplist = targetobject;
+	multiname tmpprop = targetproperty;
+	if (targetobject)
+	{
+		while (tmplist->targetobject)
+		{
+			tmpprop = tmplist->targetproperty;
+			tmplist = tmplist->targetobject;
+		}
+		if (tmplist && !tmpprop.isEmpty())
+		{
+			tmplist->getTargetVariables(tmpprop,retnodes);
+		}
+	}
+	if(XML::isValidMultiname(name,index))
+	{
+		if (index >= nodes.size())
+		{
+			if (targetobject)
+				targetobject->appendSingleNode(o);
+			appendSingleNode(o);
+		}
+		else
+		{
+			replace(index, o,retnodes,allowConst);
+		}
+	}
+	else if (nodes.size() == 0)
+	{
+		if (tmplist)
+		{
+			if (!tmpprop.isEmpty())
+			{
+				XML* tmp = Class<XML>::getInstanceS();
+				tmp->nodetype = XML_ELEMENT_NODE;
+				tmp->nodename = targetproperty.normalizedName();
+				tmp->attributelist = _MR(Class<XMLList>::getInstanceS());
+				tmp->constructed = true;
+				tmp->setVariableByMultiname(name,o,allowConst);
+				tmp->incRef();
+				tiny_string tmpname = tmpprop.normalizedName();
+				if (retnodes.empty() && tmpname != "" && tmpname != "*")
+				{
+					XML* tmp2 = Class<XML>::getInstanceS();
+					tmp2->nodetype = XML_ELEMENT_NODE;
+					tmp2->nodename = tmpname;
+					tmp2->attributelist = _MR(Class<XMLList>::getInstanceS());
+					tmp2->constructed = true;
+					tmp2->setVariableByMultiname(targetproperty,tmp,allowConst);
+					tmp2->incRef();
+					tmplist->appendSingleNode(tmp2);
+					appendSingleNode(tmp2);
+				}
+				else
+					tmplist->setVariableByMultiname(tmpprop,tmp,allowConst);
+			}
+			else
+			{
+				tmplist->appendSingleNode(o);
+				appendSingleNode(o);
+			}
+		}
+		else
+			appendSingleNode(o);
+	}
+	else if (nodes.size() == 1)
+	{
+		nodes[0]->setVariableByMultiname(name, o, allowConst);
+	}
+	else
+	{
+		// do nothing, see ECMA-357, Section 9.2.1.2
+	}
+}
 
-	//Nodes are always added at the end. The requested index are ignored. This is a tested behaviour.
-	nodes.push_back(_MR(newNode));
+bool XMLList::deleteVariableByMultiname(const multiname& name)
+{
+	unsigned int index=0;
+	bool bdeleted = false;
+	
+	if(XML::isValidMultiname(name,index))
+	{
+		_R<XML> node = nodes[index];
+		if (node->parentNode)
+		{
+			XMLList::XMLListVector::iterator it = node->parentNode->childrenlist->nodes.end();
+			while (it != node->parentNode->childrenlist->nodes.begin())
+			{
+				it--;
+				_R<XML> n = *it;
+				if (n.getPtr() == node.getPtr())
+				{
+					node->parentNode->childrenlist->nodes.erase(it);
+					break;
+				}
+			}
+		}
+	}
+	else
+	{
+		for (XMLList::XMLListVector::iterator it = nodes.begin(); it != nodes.end(); it++)
+		{
+			_R<XML> node = *it;
+			if (node->deleteVariableByMultiname(name))
+				bdeleted = true;
+		}
+	}
+	return bdeleted;
 }
 
-void XMLList::getDescendantsByQName(const tiny_string& name, const tiny_string& ns, XML::XMLVector& ret)
+void XMLList::getDescendantsByQName(const tiny_string& name, const tiny_string& ns, bool bIsAttribute, XML::XMLVector& ret)
 {
 	auto it=nodes.begin();
 	for(; it!=nodes.end(); ++it)
 	{
-		(*it)->getDescendantsByQName(name, ns, ret);
+		(*it)->getDescendantsByQName(name, ns, bIsAttribute, ret);
 	}
 }
 
@@ -584,40 +868,50 @@ _NR<XML> XMLList::convertToXML() const
 
 bool XMLList::hasSimpleContent() const
 {
-	if(nodes.size()==0)
-		return true;
-	else if(nodes.size()==1)
-		return nodes[0]->hasSimpleContent();
-	else
+	switch(nodes.size())
 	{
-		auto it=nodes.begin();
-		for(; it!=nodes.end(); ++it)
-		{
-			if((*it)->getNodeKind()==XML_ELEMENT_NODE)
-				return false;
-		}
+		case 0:
+			return true;
+		case 1:
+			return nodes[0]->hasSimpleContent();
+	}
+	auto it = nodes.begin();
+	while (it != nodes.end())
+	{
+		if ((*it)->nodetype == XML_ELEMENT_NODE)
+			return false;
+		it++;
 	}
-
 	return true;
 }
 
 bool XMLList::hasComplexContent() const
 {
-	if(nodes.size()==0)
-		return false;
-	else if(nodes.size()==1)
-		return nodes[0]->hasComplexContent();
-	else
+	return !hasSimpleContent();
+}
+
+void XMLList::appendSingleNode(ASObject *x)
+{
+	if (x->is<XML>())
 	{
-		auto it=nodes.begin();
-		for(; it!=nodes.end(); ++it)
+		x->incRef();
+		append(_MR(x->as<XML>()));
+	}
+	else if (x->is<XMLList>())
+	{
+		XMLList *list = x->as<XMLList>();
+		if (list->nodes.size() == 1)
 		{
-			if((*it)->getNodeKind()==XML_ELEMENT_NODE)
-				return true;
+			append(list->nodes[0]);
 		}
+		// do nothing, if length != 1. See ECMA-357, Section
+		// 9.2.1.2
+	}
+	else
+	{
+		tiny_string str = x->toString();
+		append(_MR(Class<XML>::getInstanceS(str)));
 	}
-
-	return false;
 }
 
 void XMLList::append(_R<XML> x)
@@ -630,27 +924,118 @@ void XMLList::append(_R<XMLList> x)
 	nodes.insert(nodes.end(),x->nodes.begin(),x->nodes.end());
 }
 
-tiny_string XMLList::toString_priv() const
+void XMLList::prepend(_R<XML> x)
+{
+	nodes.insert(nodes.begin(),x);
+}
+
+void XMLList::prepend(_R<XMLList> x)
+{
+	nodes.insert(nodes.begin(),x->nodes.begin(),x->nodes.end());
+}
+
+void XMLList::replace(unsigned int idx, ASObject *o, const XML::XMLVector &retnodes,CONST_ALLOWED_FLAG allowConst)
 {
-	if(hasSimpleContent())
+	if (idx >= nodes.size())
+		return;
+
+	if (nodes[idx]->getNodeKind() == XML_ATTRIBUTE_NODE || nodes[idx]->getNodeKind() == XML_TEXT_NODE)
 	{
-		tiny_string ret;
-		for(uint32_t i=0;i<nodes.size();i++)
+		if (targetobject)
+			targetobject->setVariableByMultiname(targetproperty,o,allowConst);
+		nodes[idx]->setTextContent(o->toString());
+	}
+	else if (o->is<XMLList>())
+	{
+		if (targetobject)
 		{
-			xmlElementType kind=nodes[i]->getNodeKind();
-			if(kind!=XML_COMMENT_NODE && kind!=XML_PI_NODE)
-				ret+=nodes[i]->toString();
+			for (uint32_t i = 0; i < targetobject->nodes.size(); i++)
+			{
+				XML* n= targetobject->nodes[i].getPtr();
+				if (n == nodes[idx].getPtr())
+				{
+					multiname m(NULL);
+					m.name_type = multiname::NAME_INT;
+					m.name_i = i;
+					m.ns.push_back(nsNameAndKind("",NAMESPACE));
+					targetobject->setVariableByMultiname(m,o,allowConst);
+					break;
+				}
+			}
 		}
-		return ret;
+		unsigned int k = 0;
+		vector<_R<XML>, reporter_allocator<_R<XML>>>::iterator it = nodes.begin();
+		while (k < idx && it!=nodes.end())
+		{
+			++k;
+			++it;
+		}
+
+		it = nodes.erase(it);
+
+		XMLList *toAdd = o->as<XMLList>();
+		nodes.insert(it, toAdd->nodes.begin(), toAdd->nodes.end());
+	}
+	else if (o->is<XML>())
+	{
+		if (retnodes.size() > idx)
+		{
+			multiname m(NULL);
+			m.name_type = multiname::NAME_INT;
+			m.name_i = idx;
+			m.ns.push_back(nsNameAndKind("",NAMESPACE));
+			targetobject->setVariableByMultiname(m,o,allowConst);
+		}
+		o->incRef();
+		nodes[idx] = _MR(o->as<XML>());
 	}
 	else
 	{
-		xmlBufferPtr xmlBuffer=xmlBufferCreateSize(4096);
-		toXMLString_priv(xmlBuffer);
-		tiny_string ret((char*)xmlBuffer->content, true);
-		xmlBufferFree(xmlBuffer);
+		if (nodes[idx]->nodetype == XML_TEXT_NODE)
+			nodes[idx]->nodevalue = o->toString();
+		else 
+		{
+			nodes[idx]->childrenlist->clear();
+			_R<XML> tmp = _MR<XML>(Class<XML>::getInstanceS());
+			nodes[idx]->incRef();
+			tmp->parentNode = nodes[idx];
+			tmp->nodetype = XML_TEXT_NODE;
+			tmp->nodename = "text";
+			tmp->nodenamespace_uri = "";
+			tmp->nodenamespace_prefix = "";
+			tmp->nodevalue = o->toString();
+			tmp->constructed = true;
+			nodes[idx]->childrenlist->append(tmp);
+		}
+	}
+}
+
+tiny_string XMLList::toString_priv()
+{
+	if (hasSimpleContent())
+	{
+		tiny_string ret;
+		for(size_t i=0; i<nodes.size(); i++)
+		{
+			xmlElementType kind=nodes[i]->getNodeKind();
+			switch (kind)
+			{
+				case XML_COMMENT_NODE:
+				case XML_PI_NODE:
+					break;
+				case XML_ATTRIBUTE_NODE:
+					ret+=nodes[i]->toString_priv();
+					break;
+				default:
+					ret+=nodes[i]->toString_priv();
+					break;
+			}
+
+				
+		}
 		return ret;
 	}
+	return toXMLString_internal();
 }
 
 tiny_string XMLList::toString()
@@ -673,24 +1058,28 @@ ASFUNCTIONBODY(XMLList,_toString)
 	return Class<ASString>::getInstanceS(th->toString_priv());
 }
 
-void XMLList::toXMLString_priv(xmlBufferPtr buf) const
+tiny_string XMLList::toXMLString_internal(bool pretty)
 {
-	for(size_t i=0; i<nodes.size(); i++)
+	tiny_string res;
+	size_t len = nodes.size();
+	for(size_t i=0; i<len; i++)
 	{
-		if(i>0)
-			xmlBufferWriteChar(buf, "\n");
-		nodes[i].getPtr()->toXMLString_priv(buf);
+		tiny_string tmp = nodes[i].getPtr()->toXMLString_internal(pretty);
+		if (tmp != "")
+		{
+			res += tmp;
+			if (pretty && i < len-1)
+				res += "\n";
+		}
 	}
+	return res;
 }
 
 ASFUNCTIONBODY(XMLList,toXMLString)
 {
 	XMLList* th=Class<XMLList>::cast(obj);
 	assert_and_throw(argslen==0);
-	xmlBufferPtr xmlBuffer=xmlBufferCreateSize(4096);
-	th->toXMLString_priv(xmlBuffer);
-	ASString* ret=Class<ASString>::getInstanceS((char*)xmlBuffer->content);
-	xmlBufferFree(xmlBuffer);
+	ASString* ret=Class<ASString>::getInstanceS(th->toXMLString_internal());
 	return ret;
 }
 
@@ -749,7 +1138,7 @@ void XMLList::appendNodesTo(XML *dest) const
 	for (it=nodes.begin(); it!=nodes.end(); ++it)
 	{
 		ASObject *arg0=it->getPtr();
-		ASObject *ret=XML::appendChild(dest, &arg0, 1);
+		ASObject *ret=XML::_appendChild(dest, &arg0, 1);
 		if(ret)
 			ret->decRef();
 	}
diff --git a/src/scripting/toplevel/XMLList.h b/src/scripting/toplevel/XMLList.h
index e336061..e723a1f 100644
--- a/src/scripting/toplevel/XMLList.h
+++ b/src/scripting/toplevel/XMLList.h
@@ -28,12 +28,21 @@ namespace lightspark
 {
 class XMLList: public ASObject
 {
+friend class XML;
+public:
+	typedef std::vector<_R<XML>, reporter_allocator<_R<XML>>> XMLListVector;
 private:
-	std::vector<_R<XML>, reporter_allocator<_R<XML>>> nodes;
+	XMLListVector nodes;
 	bool constructed;
-	tiny_string toString_priv() const;
+	XMLList* targetobject;
+	multiname targetproperty;
+
+	tiny_string toString_priv();
 	void buildFromString(const std::string& str);
-	void toXMLString_priv(xmlBufferPtr buf) const;
+	std::string extractXMLDeclaration(const std::string& xml, std::string& xmldecl_out);
+	void appendSingleNode(ASObject *x);
+	void replace(unsigned int i, ASObject *x, const XML::XMLVector& retnodes, CONST_ALLOWED_FLAG allowConst);
+	void getTargetVariables(const multiname& name, XML::XMLVector& retnodes);
 public:
 	XMLList(Class_base* c);
 	/*
@@ -41,15 +50,16 @@ public:
 	*/
 	XMLList(Class_base* cb,bool c);
 	XMLList(Class_base* c,const XML::XMLVector& r);
+	XMLList(Class_base* c,const XML::XMLVector& r,XMLList* targetobject,const multiname& targetproperty);
 	XMLList(Class_base* c,const std::string& str);
 	void finalize();
-	static void buildTraits(ASObject* o){};
+	static void buildTraits(ASObject* o){}
 	static void sinit(Class_base* c);
 	ASFUNCTION(_constructor);
 	ASFUNCTION(_getLength);
 	ASFUNCTION(attribute);
 	ASFUNCTION(attributes);
-	ASFUNCTION(appendChild);
+	ASFUNCTION(_appendChild);
 	ASFUNCTION(child);
 	ASFUNCTION(children);
 	ASFUNCTION(childIndex);
@@ -68,7 +78,7 @@ public:
 	ASFUNCTION(_namespace);
 	ASFUNCTION(name);
 	ASFUNCTION(nodeKind);
-	ASFUNCTION(normalize);
+	ASFUNCTION(_normalize);
 	ASFUNCTION(localName);
 	ASFUNCTION(inScopeNamespaces);
 	ASFUNCTION(addNamespace);
@@ -76,16 +86,28 @@ public:
 	ASFUNCTION(_setLocalName);
 	ASFUNCTION(_setName);
 	ASFUNCTION(_setNamespace);
+	ASFUNCTION(insertChildAfter);
+	ASFUNCTION(insertChildBefore);
+	ASFUNCTION(namespaceDeclarations);
+	ASFUNCTION(removeNamespace);
+	ASFUNCTION(comments);
+	ASFUNCTION(processingInstructions);
+	ASFUNCTION(_propertyIsEnumerable);
+	ASFUNCTION(_prependChild);
 	_NR<ASObject> getVariableByMultiname(const multiname& name, GET_VARIABLE_OPTION opt);
 	void setVariableByMultiname(const multiname& name, ASObject* o, CONST_ALLOWED_FLAG allowConst);
 	bool hasPropertyByMultiname(const multiname& name, bool considerDynamic, bool considerPrototype);
-	void getDescendantsByQName(const tiny_string& name, const tiny_string& ns, XML::XMLVector& ret);
+	bool deleteVariableByMultiname(const multiname& name);
+	void getDescendantsByQName(const tiny_string& name, const tiny_string& ns, bool bIsAttribute, XML::XMLVector& ret);
 	_NR<XML> convertToXML() const;
 	bool hasSimpleContent() const;
 	bool hasComplexContent() const;
 	void append(_R<XML> x);
 	void append(_R<XMLList> x);
+	void prepend(_R<XML> x);
+	void prepend(_R<XMLList> x);
 	tiny_string toString();
+	tiny_string toXMLString_internal(bool pretty=true);
 	int32_t toInt();
 	bool isEqual(ASObject* r);
 	uint32_t nextNameIndex(uint32_t cur_index);
@@ -93,6 +115,9 @@ public:
 	_R<ASObject> nextValue(uint32_t index);
 	_R<XML> reduceToXML() const;
 	void appendNodesTo(XML *dest) const;
+	void normalize();
+	void clear();
+	XMLList* getTargetObject() { return targetobject; }
 };
 }
 #endif /* SCRIPTING_TOPLEVEL_XMLLIST_H */
diff --git a/src/scripting/toplevel/toplevel.cpp b/src/scripting/toplevel/toplevel.cpp
index 95037b6..673a203 100644
--- a/src/scripting/toplevel/toplevel.cpp
+++ b/src/scripting/toplevel/toplevel.cpp
@@ -45,7 +45,6 @@
 #include "parsing/amf3_generator.h"
 #include "scripting/argconv.h"
 #include "scripting/toplevel/Number.h"
-#include "scripting/toplevel/XML.h"
 
 using namespace std;
 using namespace lightspark;
@@ -86,9 +85,13 @@ bool Undefined::isEqual(ASObject* r)
 		case T_NUMBER:
 		case T_INTEGER:
 		case T_UINTEGER:
-		case T_STRING:
 		case T_BOOLEAN:
 			return false;
+		case T_FUNCTION:
+		case T_STRING:
+			if (!r->isConstructed())
+				return true;
+			return false;
 		default:
 			return r->isEqual(this);
 	}
@@ -113,8 +116,7 @@ void Undefined::serialize(ByteArray* out, std::map<tiny_string, uint32_t>& strin
 
 void Undefined::setVariableByMultiname(const multiname& name, ASObject* o, CONST_ALLOWED_FLAG allowConst)
 {
-	LOG(LOG_NOT_IMPLEMENTED, "Ignoring set on Undefined " << name);
-	o->decRef();
+	throwError<TypeError>(kConvertUndefinedToObjectError);
 }
 
 IFunction::IFunction(Class_base* c):ASObject(c),length(0),inClass(NULL)
@@ -128,6 +130,18 @@ void IFunction::finalize()
 	closure_this.reset();
 }
 
+void IFunction::sinit(Class_base* c)
+{
+	c->prototype->setVariableByQName("toString","",Class<IFunction>::getFunction(IFunction::_toString),DYNAMIC_TRAIT);
+
+	c->setDeclaredMethodByQName("call","",Class<IFunction>::getFunction(IFunction::_call),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("call",AS3,Class<IFunction>::getFunction(IFunction::_call),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("apply","",Class<IFunction>::getFunction(IFunction::apply),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("apply",AS3,Class<IFunction>::getFunction(IFunction::apply),NORMAL_METHOD,true);
+	c->setDeclaredMethodByQName("length","",Class<IFunction>::getFunction(IFunction::_getter_length),GETTER_METHOD,true);
+	c->setDeclaredMethodByQName("toString","",Class<IFunction>::getFunction(IFunction::_toString),NORMAL_METHOD,false);
+}
+
 ASFUNCTIONBODY_GETTER_SETTER(IFunction,prototype);
 ASFUNCTIONBODY_GETTER(IFunction,length);
 
@@ -206,6 +220,15 @@ ASFUNCTIONBODY(IFunction,_toString)
 	return Class<ASString>::getInstanceS("function Function() {}");
 }
 
+ASObject* Class<IFunction>::generator(ASObject* const* args, const unsigned int argslen)
+{
+	for(unsigned int i=0;i<argslen;i++)
+		args[i]->decRef();
+	if (argslen > 0)
+		throwError<EvalError>(kFunctionConstructorError);
+	return getNopFunction();
+}
+
 ASObject *IFunction::describeType() const
 {
 	xmlpp::DomParser p;
@@ -350,6 +373,8 @@ ASObject* SyntheticFunction::call(ASObject* obj, ASObject* const* args, uint32_t
 	cc.scope_stack=func_scope;
 	cc.initialScopeStack=func_scope.size();
 	cc.exec_pos=0;
+	if (getVm()->currentCallContext)
+		cc.defaultNamespaceUri = getVm()->currentCallContext->defaultNamespaceUri;
 
 	/* Set the current global object, each script in each DoABCTag has its own */
 	call_context* saved_cc = getVm()->currentCallContext;
@@ -530,6 +555,13 @@ ASObject* Function::call(ASObject* obj, ASObject* const* args, uint32_t num_args
 		ret=getSys()->getUndefinedRef();
 	return ret;
 }
+bool Function::isEqual(ASObject* r)
+{
+	Function* f=dynamic_cast<Function*>(r);
+	if(f==NULL)
+		return false;
+	return (val==f->val) && (closure_this==f->closure_this);
+}
 
 bool Null::isEqual(ASObject* r)
 {
@@ -541,9 +573,13 @@ bool Null::isEqual(ASObject* r)
 		case T_INTEGER:
 		case T_UINTEGER:
 		case T_NUMBER:
-		case T_STRING:
 		case T_BOOLEAN:
 			return false;
+		case T_FUNCTION:
+		case T_STRING:
+			if (!r->isConstructed())
+				return true;
+			return false;
 		default:
 			return r->isEqual(this);
 	}
@@ -658,7 +694,7 @@ Type* Type::getBuiltinType(const multiname* mn)
  * by running ABCContext::exec() for all ABCContexts.
  * Therefore, all classes are at least declared.
  */
-const Type* Type::getTypeFromMultiname(const multiname* mn, const ABCContext* context)
+const Type* Type::getTypeFromMultiname(const multiname* mn, ABCContext* context)
 {
 	if(mn == 0) //multiname idx zero indicates any type
 		return Type::anyType;
@@ -671,17 +707,17 @@ const Type* Type::getTypeFromMultiname(const multiname* mn, const ABCContext* co
 		&& mn->ns.size() == 1 && mn->ns[0].hasEmptyName())
 		return Type::voidType;
 
-	ASObject* typeObject;
+	ASObject* typeObject = NULL;
 	/*
-	 * During the newClass opcode, the class is added to context->classesBeingDefined.
+	 * During the newClass opcode, the class is added to context->root->applicationDomain->classesBeingDefined.
 	 * The class variable in the global scope is only set a bit later.
 	 * When the class has to be resolved in between (for example, the
 	 * class has traits of the class's type), then we'll find it in
 	 * classesBeingDefined, but context->root->getVariableAndTargetByMultiname()
 	 * would still return "Undefined".
 	 */
-	auto i = context->classesBeingDefined.find(mn);
-	if(i != context->classesBeingDefined.end())
+	auto i = context->root->applicationDomain->classesBeingDefined.find(mn);
+	if(i != context->root->applicationDomain->classesBeingDefined.end())
 		typeObject = i->second;
 	else
 	{
@@ -691,17 +727,11 @@ const Type* Type::getTypeFromMultiname(const multiname* mn, const ABCContext* co
 
 	if(!typeObject)
 	{
-		//HACK: until we have implemented all flash classes, we need this hack
-		LOG(LOG_NOT_IMPLEMENTED,"getTypeFromMultiname: could not find " << *mn << ", using AnyType");
-		return Type::anyType;
-	}
-
-	if(!typeObject->is<Type>())
-	{
-		//It actually happens in the wild that the class for a member might be a private class
-		//that is defined later in the same script. We have no way to solve the dependency, so return any
-		LOG(LOG_NOT_IMPLEMENTED,"Not resolvable type " << *mn << ", using AnyType");
-		return Type::anyType;
+		if (mn->ns.size() >= 1 && mn->ns[0].getImpl().name == "__AS3__.vec")
+		{
+			QName qname(getSys()->getStringFromUniqueId(mn->name_s_id),mn->ns[0].getImpl().name);
+			typeObject = Template<Vector>::getTemplateInstance(qname,context).getPtr();
+		}
 	}
 	return typeObject->as<Type>();
 }
@@ -753,6 +783,23 @@ void Class_base::copyBorrowedTraitsFromSuper()
 	}
 }
 
+void Class_base::initStandardProps()
+{
+	incRef();
+	constructorprop = _NR<ObjectConstructor>(new_objectConstructor(this,0));
+	constructorprop->incRef();
+	addConstructorGetter();
+	
+	setDeclaredMethodByQName("toString","",Class<IFunction>::getFunction(Class_base::_toString),NORMAL_METHOD,false);
+	incRef();
+	prototype->setVariableByQName("constructor","",this,DYNAMIC_TRAIT);
+
+	if(super)
+		prototype->prevPrototype=super->prototype;
+	addPrototypeGetter();
+	addLengthGetter();
+}
+
 
 ASObject* Class_base::coerce(ASObject* o) const
 {
@@ -760,12 +807,15 @@ ASObject* Class_base::coerce(ASObject* o) const
 		return o;
 	if(o->is<Class_base>())
 	{ /* classes can be cast to the type 'Object' or 'Class' */
-	       if(this == Class<ASObject>::getClass()
+		if(this == Class<ASObject>::getClass()
 		|| (class_name.name=="Class" && class_name.ns==""))
-		       return o; /* 'this' is the type of a class */
-	       else
-		       throwError<TypeError>(kCheckTypeFailedError, o->getClassName(), getQualifiedClassName());
+			return o; /* 'this' is the type of a class */
+		else
+			throwError<TypeError>(kCheckTypeFailedError, o->getClassName(), getQualifiedClassName());
 	}
+	if (o->is<ObjectConstructor>())
+		return o;
+
 	//o->getClass() == NULL for primitive types
 	//those are handled in overloads Class<Number>::coerce etc.
 	if(!o->getClass() || !o->getClass()->isSubClass(this))
@@ -783,6 +833,11 @@ ASFUNCTIONBODY(Class_base,_toString)
 	return Class<ASString>::getInstanceS(ret);
 }
 
+void Class_base::addConstructorGetter()
+{
+	setDeclaredMethodByQName("constructor","",Class<IFunction>::getFunction(_getter_constructorprop),GETTER_METHOD,false);
+}
+
 void Class_base::addPrototypeGetter()
 {
 	setDeclaredMethodByQName("prototype","",Class<IFunction>::getFunction(_getter_prototype),GETTER_METHOD,false);
@@ -799,6 +854,20 @@ Class_base::~Class_base()
 		LOG(LOG_ERROR,_("Class destroyed without cleanUp called"));
 }
 
+ASObject* Class_base::_getter_constructorprop(ASObject* obj, ASObject* const* args, const unsigned int argslen)
+{
+	Class_base* th = NULL;
+	if(obj->is<Class_base>())
+		th = obj->as<Class_base>();
+	else
+		th = obj->getClass();
+	if(argslen != 0)
+		throw Class<ArgumentError>::getInstanceS("Arguments provided in getter");
+	ASObject* ret=th->constructorprop.getPtr();
+	ret->incRef();
+	return ret;
+}
+
 ASObject* Class_base::_getter_prototype(ASObject* obj, ASObject* const* args, const unsigned int argslen)
 {
 	if(!obj->is<Class_base>())
@@ -832,7 +901,7 @@ void Class_base::addImplementedInterface(Class_base* i)
 
 tiny_string Class_base::toString()
 {
-	tiny_string ret="[Class ";
+	tiny_string ret="[class ";
 	ret+=class_name.name;
 	ret+="]";
 	return ret;
@@ -888,13 +957,16 @@ void Class_base::handleConstruction(ASObject* target, ASObject* const* args, uns
 	{
 		target->incRef();
 		ASObject* ret=constructor->call(target,args,argslen);
+		target->constructIndicator = true;
 		assert_and_throw(ret->is<Undefined>());
 		ret->decRef();
 	}
 	else
 	{
+		target->constructIndicator = true;
 		for(uint32_t i=0;i<argslen;i++)
 			args[i]->decRef();
+		//throwError<TypeError>(kConstructOfNonFunctionError);
 	}
 }
 
@@ -990,25 +1062,40 @@ void Class_object::finalize()
 	Class_base::finalize();
 }
 
-const std::vector<Class_base*>& Class_base::getInterfaces() const
+const std::vector<Class_base*>& Class_base::getInterfaces(bool *alldefined) const
 {
+	if (alldefined)
+		*alldefined = true;
 	if(!interfaces.empty())
 	{
 		//Recursively get interfaces implemented by this interface
-		for(unsigned int i=0;i<interfaces.size();i++)
+		std::vector<multiname>::iterator it = interfaces.begin();
+		while (it !=interfaces.end())
 		{
 			ASObject* target;
 			ASObject* interface_obj=this->context->root->applicationDomain->
-				getVariableAndTargetByMultiname(interfaces[i], target);
-			assert_and_throw(interface_obj && interface_obj->getObjectType()==T_CLASS);
-			Class_base* inter=static_cast<Class_base*>(interface_obj);
-
-			interfaces_added.push_back(inter);
-			//Probe the interface for its interfaces
-			inter->getInterfaces();
+					getVariableAndTargetByMultiname(*it, target);
+			if (interface_obj)
+			{
+				assert_and_throw(interface_obj->getObjectType()==T_CLASS);
+				Class_base* inter=static_cast<Class_base*>(interface_obj);
+				//Probe the interface for its interfaces
+				bool bAllDefinedSub;
+				inter->getInterfaces(&bAllDefinedSub);
+				
+				if (bAllDefinedSub)
+				{
+					interfaces_added.push_back(inter);
+					interfaces.erase(it);
+					continue;
+				}
+				else if (alldefined)
+					*alldefined = false;
+			}
+			else if (alldefined)
+				*alldefined = false;
+			it++;
 		}
-		//Clean the interface vector to save some space
-		interfaces.clear();
 	}
 	return interfaces_added;
 }
@@ -1043,6 +1130,11 @@ bool Class_base::isSubClass(const Class_base* cls, bool considerInterfaces) cons
 	if(cls==this || cls==Class<ASObject>::getClass())
 		return true;
 
+	// it seems that classes with the same name from different applicationDomains 
+	// are treated as equal, so we test for same names
+	if (this->getQualifiedClassName() == cls->getQualifiedClassName())
+		return true;
+
 	//Now check the interfaces
 	if (considerInterfaces)
 	{
@@ -1146,7 +1238,7 @@ void Class_base::describeTraits(xmlpp::Element* root,
 		int kind=t.kind&0xf;
 		multiname* mname=context->getMultiname(t.name,NULL);
 		if (mname->name_type!=multiname::NAME_STRING ||
-		    (mname->ns.size()==1 && !mname->ns[0].hasEmptyName()) ||
+		    (mname->ns.size()==1 && (!mname->ns[0].hasEmptyName() || mname->ns[0].getImpl().kind == PRIVATE_NAMESPACE)) ||
 		    mname->ns.size() > 1)
 			continue;
 		
@@ -1278,9 +1370,9 @@ void Class_base::initializeProtectedNamespace(const tiny_string& name, const nam
 		protected_ns=nsNameAndKind(name,baseNs->nsId,(NS_KIND)(int)ns.kind);
 }
 
-const variable* Class_base::findBorrowedGettable(const multiname& name) const
+const variable* Class_base::findBorrowedGettable(const multiname& name,NS_KIND& nskind) const
 {
-	return ASObject::findGettableImpl(borrowedVariables,name);
+	return ASObject::findGettableImpl(borrowedVariables,name,nskind);
 }
 
 variable* Class_base::findBorrowedSettable(const multiname& name, bool* has_getter)
@@ -1288,9 +1380,25 @@ variable* Class_base::findBorrowedSettable(const multiname& name, bool* has_gett
 	return ASObject::findSettableImpl(borrowedVariables,name,has_getter);
 }
 
+variable* Class_base::findSettableInPrototype(const multiname& name)
+{
+	Prototype* proto = prototype.getPtr();
+	while(proto)
+	{
+		variable *obj = proto->getObj()->findSettable(name);
+		if (obj)
+			return obj;
+
+		proto = proto->prevPrototype.getPtr();
+	}
+
+	return NULL;
+}
+
 EARLY_BIND_STATUS Class_base::resolveMultinameStatically(const multiname& name) const
 {
-	if(findBorrowedGettable(name)!=NULL)
+	NS_KIND nskind;
+	if(findBorrowedGettable(name,nskind)!=NULL)
 		return BINDED;
 	else
 		return NOT_BINDED;
@@ -1306,14 +1414,19 @@ void ASQName::setByNode(xmlpp::Node* node)
 	local_name = node->get_name();
 	uri=node->get_namespace_uri();
 }
+void ASQName::setByXML(XML* node)
+{
+	uri_is_null=false;
+	local_name = node->getName();
+	uri=node->getNamespaceURI();
+}
 
 void ASQName::sinit(Class_base* c)
 {
-	c->setSuper(Class<ASObject>::getRef());
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_SEALED | CLASS_FINAL);
 	c->setDeclaredMethodByQName("uri","",Class<IFunction>::getFunction(_getURI),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("localName","",Class<IFunction>::getFunction(_getLocalName),GETTER_METHOD,true);
-	c->prototype->setVariableByQName("toString",AS3,Class<IFunction>::getFunction(_toString),DYNAMIC_TRAIT);
+	c->prototype->setVariableByQName("toString","",Class<IFunction>::getFunction(_toString),DYNAMIC_TRAIT);
 }
 
 ASFUNCTIONBODY(ASQName,_constructor)
@@ -1404,9 +1517,7 @@ ASFUNCTIONBODY(ASQName,generator)
 	{
 		th->local_name="";
 		th->uri_is_null=false;
-		th->uri="";
-		// Should set th->uri to the default namespace
-		LOG(LOG_NOT_IMPLEMENTED, "QName constructor not completely implemented");
+		th->uri=getVm()->getDefaultXMLNamespace();
 		return th;
 	}
 	if(argslen==1)
@@ -1448,9 +1559,7 @@ ASFUNCTIONBODY(ASQName,generator)
 		}
 		else
 		{
-			// Should set th->uri to the default namespace
-			LOG(LOG_NOT_IMPLEMENTED, "QName constructor not completely implemented");
-			th->uri="";
+			th->uri=getVm()->getDefaultXMLNamespace();
 		}
 	}
 	else if(namespaceval->getObjectType()==T_NULL)
@@ -1517,14 +1626,14 @@ tiny_string ASQName::toString()
 	return s + local_name;
 }
 
-Namespace::Namespace(Class_base* c):ASObject(c)
+Namespace::Namespace(Class_base* c):ASObject(c),nskind(NAMESPACE)
 {
 	type=T_NAMESPACE;
 	prefix_is_undefined=false;
 }
 
 Namespace::Namespace(Class_base* c, const tiny_string& _uri, const tiny_string& _prefix)
-  : ASObject(c),uri(_uri),prefix(_prefix)
+  : ASObject(c),nskind(NAMESPACE),uri(_uri),prefix(_prefix)
 {
 	type=T_NAMESPACE;
 	prefix_is_undefined=false;
@@ -1532,11 +1641,10 @@ Namespace::Namespace(Class_base* c, const tiny_string& _uri, const tiny_string&
 
 void Namespace::sinit(Class_base* c)
 {
-	c->setSuper(Class<ASObject>::getRef());
-	c->setConstructor(Class<IFunction>::getFunction(_constructor));
-	c->setDeclaredMethodByQName("uri","",Class<IFunction>::getFunction(_setURI),SETTER_METHOD,true);
+	CLASS_SETUP(c, ASObject, _constructor, CLASS_SEALED | CLASS_FINAL);
+	//c->setDeclaredMethodByQName("uri","",Class<IFunction>::getFunction(_setURI),SETTER_METHOD,true);
 	c->setDeclaredMethodByQName("uri","",Class<IFunction>::getFunction(_getURI),GETTER_METHOD,true);
-	c->setDeclaredMethodByQName("prefix","",Class<IFunction>::getFunction(_setPrefix),SETTER_METHOD,true);
+	//c->setDeclaredMethodByQName("prefix","",Class<IFunction>::getFunction(_setPrefix),SETTER_METHOD,true);
 	c->setDeclaredMethodByQName("prefix","",Class<IFunction>::getFunction(_getPrefix),GETTER_METHOD,true);
 	c->setDeclaredMethodByQName("valueOf",AS3,Class<IFunction>::getFunction(_valueOf),NORMAL_METHOD,true);
 	c->prototype->setVariableByQName("toString","",Class<IFunction>::getFunction(_toString),DYNAMIC_TRAIT);
@@ -1720,20 +1828,20 @@ ASFUNCTIONBODY(Namespace,generator)
 	}
 	return th;
 }
-
+/*
 ASFUNCTIONBODY(Namespace,_setURI)
 {
 	Namespace* th=static_cast<Namespace*>(obj);
 	th->uri=args[0]->toString();
 	return NULL;
 }
-
+*/
 ASFUNCTIONBODY(Namespace,_getURI)
 {
 	Namespace* th=static_cast<Namespace*>(obj);
 	return Class<ASString>::getInstanceS(th->uri);
 }
-
+/*
 ASFUNCTIONBODY(Namespace,_setPrefix)
 {
 	Namespace* th=static_cast<Namespace*>(obj);
@@ -1749,7 +1857,7 @@ ASFUNCTIONBODY(Namespace,_setPrefix)
 	}
 	return NULL;
 }
-
+*/
 ASFUNCTIONBODY(Namespace,_getPrefix)
 {
 	Namespace* th=static_cast<Namespace*>(obj);
@@ -1809,7 +1917,10 @@ ASObject* Class<IFunction>::getInstance(bool construct, ASObject* const* args, c
 {
 	if (argslen > 0)
 		throwError<EvalError>(kFunctionConstructorError);
-	return getNopFunction();
+	ASObject* ret = getNopFunction();
+	if (construct)
+		ret->setConstructIndicator();
+	return ret;
 }
 
 Class<IFunction>* Class<IFunction>::getClass()
@@ -1831,6 +1942,7 @@ Class<IFunction>* Class<IFunction>::getClass()
 		ret->prototype = _MNR(new_functionPrototype(ret, ret->super->prototype));
 		ret->incRef();
 		ret->prototype->getObj()->setVariableByQName("constructor","",ret,DYNAMIC_TRAIT);
+		ret->prototype->getObj()->setConstructIndicator();
 		ret->incRef();
 		*retAddr = ret;
 
@@ -1838,15 +1950,14 @@ Class<IFunction>* Class<IFunction>::getClass()
 		//addPrototypeGetter and setDeclaredMethodByQName.
 		//Thus we make sure that everything is in order when getFunction() below is called
 		ret->addPrototypeGetter();
-		//copy borrowed traits from ASObject by ourself
-		ASObject::sinit(ret);
-		ret->setDeclaredMethodByQName("call",AS3,Class<IFunction>::getFunction(IFunction::_call),NORMAL_METHOD,true);
-		ret->setDeclaredMethodByQName("apply",AS3,Class<IFunction>::getFunction(IFunction::apply),NORMAL_METHOD,true);
+		IFunction::sinit(ret);
+		ret->constructorprop = _NR<ObjectConstructor>(new_objectConstructor(ret,ret->length));
+		ret->constructorprop->incRef();
+
+		ret->addConstructorGetter();
+
 		ret->setDeclaredMethodByQName("prototype","",Class<IFunction>::getFunction(IFunction::_getter_prototype),GETTER_METHOD,true);
 		ret->setDeclaredMethodByQName("prototype","",Class<IFunction>::getFunction(IFunction::_setter_prototype),SETTER_METHOD,true);
-		ret->setDeclaredMethodByQName("length","",Class<IFunction>::getFunction(IFunction::_getter_length),GETTER_METHOD,true);
-		ret->prototype->setVariableByQName("toString",AS3,Class<IFunction>::getFunction(IFunction::_toString),DYNAMIC_TRAIT);
-		ret->setDeclaredMethodByQName("toString",AS3,Class<IFunction>::getFunction(Class_base::_toString),NORMAL_METHOD,false);
 	}
 	else
 		ret=static_cast<Class<IFunction>*>(*retAddr);
@@ -2243,8 +2354,15 @@ ASFUNCTIONBODY(lightspark,_isXMLName)
 
 ObjectPrototype::ObjectPrototype(Class_base* c) : ASObject(c)
 {
+	traitsInitialized = true;
+	constructIndicator = true;
+}
+bool ObjectPrototype::isEqual(ASObject* r)
+{
+	if (r->is<ObjectPrototype>())
+		return this->getClass() == r->getClass();
+	return ASObject::isEqual(r);
 }
-
 void ObjectPrototype::finalize()
 {
 	ASObject::finalize();
@@ -2260,6 +2378,31 @@ _NR<ASObject> ObjectPrototype::getVariableByMultiname(const multiname& name, GET
 	return prevPrototype->getObj()->getVariableByMultiname(name, opt);
 }
 
+
+ObjectConstructor::ObjectConstructor(Class_base* c,uint32_t length) : ASObject(c),_length(length)
+{
+	Class<ASObject>::getRef()->prototype->incRef();
+	this->prototype = Class<ASObject>::getRef()->prototype.getPtr();
+}
+
+_NR<ASObject> ObjectConstructor::getVariableByMultiname(const multiname& name, GET_VARIABLE_OPTION opt)
+{
+	if (name.normalizedName() == "prototype")
+	{
+		prototype->getObj()->incRef();
+		return _NR<ASObject>(prototype->getObj());
+	}
+	if (name.normalizedName() == "length")
+	{
+		return _NR<ASObject>(abstract_d(_length));
+	}
+	return getClass()->getVariableByMultiname(name, opt);
+}
+bool ObjectConstructor::isEqual(ASObject* r)
+{
+	return this == r || getClass() == r;
+}
+
 FunctionPrototype::FunctionPrototype(Class_base* c, _NR<Prototype> p) : Function(c, ASNop)
 {
 	prevPrototype=p;
diff --git a/src/scripting/toplevel/toplevel.h b/src/scripting/toplevel/toplevel.h
index 500f85a..3d75de4 100644
--- a/src/scripting/toplevel/toplevel.h
+++ b/src/scripting/toplevel/toplevel.h
@@ -29,7 +29,7 @@
 #include "scripting/abcutils.h"
 #include "scripting/toplevel/Boolean.h"
 #include "scripting/toplevel/Error.h"
-//#include "scripting/toplevel/XML.h"
+#include "scripting/toplevel/XML.h"
 #include "memory_support.h"
 #include <libxml++/parsers/domparser.h>
 #include <boost/intrusive/list.hpp>
@@ -45,7 +45,7 @@ class ASString;
 class method_info;
 struct call_context;
 struct traits_info;
-class namespace_info;
+struct namespace_info;
 class Any;
 class Void;
 class Class_object;
@@ -74,7 +74,7 @@ public:
 	 * then an exception is thrown.
 	 * The caller does not own the object returned.
 	 */
-	static const Type* getTypeFromMultiname(const multiname* mn, const ABCContext* context);
+	static const Type* getTypeFromMultiname(const multiname* mn, ABCContext* context);
 	/*
 	 * Checks if the type is already in sys->classes
 	 */
@@ -136,6 +136,7 @@ public:
 };
 
 class Prototype;
+class ObjectConstructor;
 
 class Class_base: public ASObject, public Type
 {
@@ -158,9 +159,11 @@ private:
 protected:
 	void copyBorrowedTraitsFromSuper();
 	ASFUNCTION(_toString);
+	void initStandardProps();
 public:
 	variables_map borrowedVariables;
 	ASPROPERTY_GETTER(_NR<Prototype>,prototype);
+	ASPROPERTY_GETTER(_NR<ObjectConstructor>,constructorprop);
 	_NR<Class_base> super;
 	//We need to know what is the context we are referring to
 	ABCContext* context;
@@ -175,11 +178,13 @@ private:
 	//TODO: move in Class_inherit
 	bool use_protected:1;
 public:
+	void addConstructorGetter();
 	void addPrototypeGetter();
 	void addLengthGetter();
 	void setupDeclaredTraits(ASObject *target);
 	void handleConstruction(ASObject* target, ASObject* const* args, unsigned int argslen, bool buildAndLink);
 	void setConstructor(IFunction* c);
+	bool hasConstructor() { return constructor != NULL; }
 	Class_base(const QName& name, MemoryAccount* m);
 	//Special constructor for Class_object
 	Class_base(const Class_object*);
@@ -189,7 +194,7 @@ public:
 	void addImplementedInterface(const multiname& i);
 	void addImplementedInterface(Class_base* i);
 	virtual void buildInstanceTraits(ASObject* o) const=0;
-	const std::vector<Class_base*>& getInterfaces() const;
+	const std::vector<Class_base*>& getInterfaces(bool *alldefined = NULL) const;
 	virtual void linkInterface(Class_base* c) const;
 	/*
 	 * Returns true when 'this' is a subclass of 'cls',
@@ -198,7 +203,7 @@ public:
 	 */
 	bool isSubClass(const Class_base* cls, bool considerInterfaces=true) const;
 	tiny_string getQualifiedClassName() const;
-	tiny_string getName() const { return class_name.name; }
+	tiny_string getName() const { return (class_name.ns.empty() ? class_name.name : class_name.ns +"$"+ class_name.name); }
 	tiny_string toString();
 	virtual ASObject* generator(ASObject* const* args, const unsigned int argslen);
 	ASObject *describeType() const;
@@ -220,8 +225,9 @@ public:
 		super = super_;
 		copyBorrowedTraitsFromSuper();
 	}
-	const variable* findBorrowedGettable(const multiname& name) const DLL_LOCAL;
+	const variable* findBorrowedGettable(const multiname& name, NS_KIND &nskind) const DLL_LOCAL;
 	variable* findBorrowedSettable(const multiname& name, bool* has_getter=NULL) DLL_LOCAL;
+	variable* findSettableInPrototype(const multiname& name) DLL_LOCAL;
 	EARLY_BIND_STATUS resolveMultinameStatically(const multiname& name) const;
 	const multiname* resolveSlotTypeName(uint32_t slotId) const { /*TODO: implement*/ return NULL; }
 };
@@ -232,7 +238,7 @@ private:
 	QName template_name;
 public:
 	Template_base(QName name);
-	virtual Class_base* applyType(const std::vector<Type*>& t)=0;
+	virtual Class_base* applyType(const std::vector<const Type*>& t)=0;
 };
 
 class Class_object: public Class_base
@@ -247,7 +253,7 @@ private:
 	}
 	void buildInstanceTraits(ASObject* o) const
 	{
-		throw RunTimeException("Class_object::buildInstanceTraits");
+//		throw RunTimeException("Class_object::buildInstanceTraits");
 	}
 	void finalize();
 public:
@@ -284,8 +290,25 @@ public:
 	void decRef() { ASObject::decRef(); }
 	ASObject* getObj() { return this; }
 	_NR<ASObject> getVariableByMultiname(const multiname& name, GET_VARIABLE_OPTION opt=NONE);
+	bool isEqual(ASObject* r);
 };
 
+/* Special object used as constructor property for classes
+ * It has its own prototype object, but everything else is forwarded to the class object
+ */
+class ObjectConstructor: public ASObject
+{
+	Prototype* prototype;
+	uint32_t _length;
+public:
+	ObjectConstructor(Class_base* c,uint32_t length);
+	void incRef() { getClass()->incRef(); }
+	void decRef() { getClass()->decRef(); }
+	_NR<ASObject> getVariableByMultiname(const multiname& name, GET_VARIABLE_OPTION opt=NONE);
+	bool isEqual(ASObject* r);
+};
+
+
 /* Special object returned when new func() syntax is used.
  * This object looks for properties on the prototype object that is passed in the constructor
  */
@@ -311,6 +334,8 @@ protected:
 	IFunction(Class_base *c);
 	virtual IFunction* clone()=0;
 	_NR<ASObject> closure_this;
+
+	static void sinit(Class_base* c);
 public:
 	/* If this is a method, inClass is the class this is defined in.
 	 * If this is a function, inClass == NULL
@@ -319,6 +344,7 @@ public:
 	/* returns whether this is this a method of a function */
 	bool isMethod() const { return inClass != NULL; }
 	bool isBound() const { return closure_this; }
+	bool isConstructed() const { return constructIndicator; }
 	void finalize();
 	ASFUNCTION(apply);
 	ASFUNCTION(_call);
@@ -348,6 +374,7 @@ public:
 				ret->setClass(getClass());
 			}
 			ret->closure_this=c;
+			ret->constructIndicator = true;
 			//std::cout << "Binding " << ret << std::endl;
 			return ret;
 		}
@@ -365,6 +392,8 @@ public:
  * Implements the IFunction interface for functions implemented
  * in c-code.
  */
+class FunctionPrototype;
+
 class Function : public IFunction
 {
 friend class Class<IFunction>;
@@ -381,13 +410,7 @@ protected:
 	method_info* getMethodInfo() const { return NULL; }
 public:
 	ASObject* call(ASObject* obj, ASObject* const* args, uint32_t num_args);
-	bool isEqual(ASObject* r)
-	{
-		Function* f=dynamic_cast<Function*>(r);
-		if(f==NULL)
-			return false;
-		return (val==f->val) && (closure_this==f->closure_this);
-	}
+	bool isEqual(ASObject* r);
 };
 
 /* Special object used as prototype for the Function class
@@ -469,6 +492,7 @@ public:
 	{
 		Class<IFunction>* c=Class<IFunction>::getClass();
 		Function* ret=new (c->memoryAccount) Function(c, v);
+		ret->constructIndicator = true;
 		return ret;
 	}
 	static Function* getFunction(Function::as_function v, int len)
@@ -476,18 +500,21 @@ public:
 		Class<IFunction>* c=Class<IFunction>::getClass();
 		Function* ret=new (c->memoryAccount) Function(c, v);
 		ret->length = len;
+		ret->constructIndicator = true;
 		return ret;
 	}
 	static SyntheticFunction* getSyntheticFunction(method_info* m)
 	{
 		Class<IFunction>* c=Class<IFunction>::getClass();
 		SyntheticFunction* ret=new (c->memoryAccount) SyntheticFunction(c, m);
+		ret->constructIndicator = true;
 		c->handleConstruction(ret,NULL,0,true);
 		return ret;
 	}
 	void buildInstanceTraits(ASObject* o) const
 	{
 	}
+	virtual ASObject* generator(ASObject* const* args, const unsigned int argslen);
 };
 
 class Undefined : public ASObject
@@ -525,7 +552,7 @@ public:
 
 class ASQName: public ASObject
 {
-friend class multiname;
+friend struct multiname;
 friend class Namespace;
 private:
 	bool uri_is_null;
@@ -534,6 +561,7 @@ private:
 public:
 	ASQName(Class_base* c);
 	void setByNode(xmlpp::Node* node);
+	void setByXML(XML* node);
 	static void sinit(Class_base*);
 	ASFUNCTION(_constructor);
 	ASFUNCTION(generator);
@@ -551,6 +579,7 @@ class Namespace: public ASObject
 friend class ASQName;
 friend class ABCContext;
 private:
+	NS_KIND nskind;
 	bool prefix_is_undefined;
 	tiny_string uri;
 	tiny_string prefix;
@@ -562,9 +591,10 @@ public:
 	ASFUNCTION(_constructor);
 	ASFUNCTION(generator);
 	ASFUNCTION(_getURI);
-	ASFUNCTION(_setURI);
+	// according to ECMA-357 and tamarin tests uri/prefix properties are readonly
+	//ASFUNCTION(_setURI);
 	ASFUNCTION(_getPrefix);
-	ASFUNCTION(_setPrefix);
+	//ASFUNCTION(_setPrefix);
 	ASFUNCTION(_toString);
 	ASFUNCTION(_valueOf);
 	ASFUNCTION(_ECMA_valueOf);
diff --git a/src/swf.cpp b/src/swf.cpp
index 008fdaf..e1504bc 100644
--- a/src/swf.cpp
+++ b/src/swf.cpp
@@ -52,22 +52,22 @@ extern "C" {
 using namespace std;
 using namespace lightspark;
 
-static GStaticPrivate tls_system = G_STATIC_PRIVATE_INIT;
+DEFINE_AND_INITIALIZE_TLS(tls_system);
 SystemState* lightspark::getSys()
 {
-	SystemState* ret = (SystemState*)g_static_private_get(&tls_system);
+	SystemState* ret = (SystemState*)tls_get(&tls_system);
 	return ret;
 }
 
 void lightspark::setTLSSys(SystemState* sys)
 {
-        g_static_private_set(&tls_system,sys,NULL);
+        tls_set(&tls_system,sys);
 }
 
-static GStaticPrivate parse_thread_tls = G_STATIC_PRIVATE_INIT; /* TLS */
+DEFINE_AND_INITIALIZE_TLS(parse_thread_tls);
 ParseThread* lightspark::getParseThread()
 {
-	ParseThread* pt = (ParseThread*)g_static_private_get(&parse_thread_tls);
+	ParseThread* pt = (ParseThread*)tls_get(&parse_thread_tls);
 	assert(pt);
 	return pt;
 }
@@ -145,6 +145,7 @@ RootMovieClip* RootMovieClip::getInstance(_NR<LoaderInfo> li, _R<ApplicationDoma
 {
 	Class_base* movieClipClass = Class<MovieClip>::getClass();
 	RootMovieClip* ret=new (movieClipClass->memoryAccount) RootMovieClip(li, appDomain, secDomain, movieClipClass);
+	ret->constructIndicator = true;
 	return ret;
 }
 
@@ -1271,7 +1272,7 @@ void ParseThread::parseSWFHeader(RootMovieClip *root, UI8 ver)
 
 void ParseThread::execute()
 {
-	g_static_private_set(&parse_thread_tls,this,NULL);
+	tls_set(&parse_thread_tls,this);
 	try
 	{
 		UI8 Signature[4];
@@ -1315,6 +1316,14 @@ void ParseThread::execute()
 
 void ParseThread::parseSWF(UI8 ver)
 {
+	if (loader && !loader->allowLoadingSWF())
+	{
+		_NR<LoaderInfo> li=loader->getContentLoaderInfo();
+		getVm()->addEvent(li,_MR(Class<SecurityErrorEvent>::getInstanceS(
+			"Cannot import a SWF file when LoaderContext.allowCodeImport is false."))); // 3226
+		return;
+	}
+
 	objectSpinlock.lock();
 	RootMovieClip* root=NULL;
 	if(parsedObject.isNull())
@@ -1333,10 +1342,15 @@ void ParseThread::parseSWF(UI8 ver)
 	}
 	objectSpinlock.unlock();
 
-	std::queue<const ControlTag*> symbolClassTags;
+	std::queue<const ControlTag*> queuedTags;
 	try
 	{
 		parseSWFHeader(root, ver);
+		if (loader)
+		{
+			_NR<LoaderInfo> li=loader->getContentLoaderInfo();
+			li->swfVersion = root->version;
+		}
 		if(root->version < 9)
 		{
 			LOG(LOG_INFO,"SWF version " << root->version << " is not handled by lightspark, falling back to gnash (if available)");
@@ -1359,7 +1373,10 @@ void ParseThread::parseSWF(UI8 ver)
 		{
 			getSys()->needsAVM2(fat->ActionScript3);
 			if(!fat->ActionScript3)
+			{
+                                delete fat;
 				return; /* no more parsing necessary, handled by fallback */
+                        }
 			if(fat->UseNetwork
 			&& getSys()->securityManager->getSandboxType() == SecurityManager::LOCAL_WITH_FILE)
 			{
@@ -1378,14 +1395,14 @@ void ParseThread::parseSWF(UI8 ver)
 			{
 				case END_TAG:
 				{
-					// The whole frame has been parsed, now execute all queued SymbolClass tags,
+					// The whole frame has been parsed, now execute all queued tags,
 					// in the order in which they appeared in the file.
-					while(!symbolClassTags.empty())
+					while(!queuedTags.empty())
 					{
-						const ControlTag* t=symbolClassTags.front();
+						const ControlTag* t=queuedTags.front();
 						t->execute(root);
 						delete t;
-						symbolClassTags.pop();
+						queuedTags.pop();
 					}
 
 					if(!empty)
@@ -1411,12 +1428,12 @@ void ParseThread::parseSWF(UI8 ver)
 				case SHOW_TAG:
 					// The whole frame has been parsed, now execute all queued SymbolClass tags,
 					// in the order in which they appeared in the file.
-					while(!symbolClassTags.empty())
+					while(!queuedTags.empty())
 					{
-						const ControlTag* t=symbolClassTags.front();
+						const ControlTag* t=queuedTags.front();
 						t->execute(root);
 						delete t;
-						symbolClassTags.pop();
+						queuedTags.pop();
 					}
 
 					root->commitFrame(true);
@@ -1424,13 +1441,14 @@ void ParseThread::parseSWF(UI8 ver)
 					delete tag;
 					break;
 				case SYMBOL_CLASS_TAG:
+				case ACTION_TAG:
 				{
-					// Add symbol class tags to the queue, to be executed when the rest of the 
+					// Add symbol class tags or action to the queue, to be executed when the rest of the 
 					// frame has been parsed. This is to handle invalid SWF files that define ID's
 					// used in the SymbolClass tag only after the tag, which would otherwise result
 					// in "undefined dictionary ID" errors.
 					const ControlTag* stag = static_cast<const ControlTag*>(tag);
-					symbolClassTags.push(stag);
+					queuedTags.push(stag);
 					break;
 				}
 				case CONTROL_TAG:
@@ -1932,6 +1950,14 @@ void SystemState::openPageInBrowser(const tiny_string& url, const tiny_string& w
 	engineData->openPageInBrowser(url, window);
 }
 
+void SystemState::showMouseCursor(bool visible)
+{
+	if (visible)
+		EngineData::runInGtkThread(sigc::mem_fun(engineData, &EngineData::showMouseCursor));
+	else
+		EngineData::runInGtkThread(sigc::mem_fun(engineData, &EngineData::hideMouseCursor));
+}
+
 /* This is run in vm's thread context */
 void RootMovieClip::initFrame()
 {
diff --git a/src/swf.h b/src/swf.h
index 419204a..a778a1c 100644
--- a/src/swf.h
+++ b/src/swf.h
@@ -30,6 +30,7 @@
 #include "swftypes.h"
 #include "scripting/flash/display/flashdisplay.h"
 #include "scripting/flash/net/flashnet.h"
+#include "scripting/flash/utils/IntervalManager.h"
 #include "timer.h"
 #include "memory_support.h"
 #include "platforms/engineutils.h"
@@ -429,6 +430,8 @@ public:
 
 	//Opening web pages
 	void openPageInBrowser(const tiny_string& url, const tiny_string& window);
+
+	void showMouseCursor(bool visible);
 };
 
 class ParseThread: public IThreadJob
diff --git a/src/swftypes.cpp b/src/swftypes.cpp
index 1ec1807..f0bd3c1 100644
--- a/src/swftypes.cpp
+++ b/src/swftypes.cpp
@@ -43,7 +43,7 @@ multiname::multiname(MemoryAccount* m):name_o(NULL),ns(reporter_allocator<nsName
 
 tiny_string multiname::qualifiedString() const
 {
-	assert_and_throw(ns.size()==1);
+	assert_and_throw(ns.size()>=1);
 	assert_and_throw(name_type==NAME_STRING);
 	const tiny_string nsName=ns[0].getImpl().name;
 	const tiny_string& name=getSys()->getStringFromUniqueId(name_s_id);
@@ -162,6 +162,7 @@ bool multiname::toUInt(uint32_t& index, bool acceptStringFractions) const
 			if(str.empty())
 				return false;
 			index=0;
+			uint64_t parsed = 0;
 			for(auto i=str.begin(); i!=str.end(); ++i)
 			{
 				if (*i == '.' && acceptStringFractions)
@@ -175,14 +176,21 @@ bool multiname::toUInt(uint32_t& index, bool acceptStringFractions) const
 					for (; i!=str.end(); ++i)
 						if (*i != '0')
 							return false;
-					return true;
+					break;
 				}
 				else if(!i.isdigit())
 					return false;
 
-				index*=10;
-				index+=i.digit_value();
+				parsed*=10;
+				parsed+=i.digit_value();
+				if (parsed > UINT32_MAX)
+					break;
 			}
+
+			if (parsed > UINT32_MAX)
+				return false;
+
+			index = (uint32_t)parsed;
 			break;
 		}
 		//This is already an int, so its good enough
@@ -192,7 +200,7 @@ bool multiname::toUInt(uint32_t& index, bool acceptStringFractions) const
 			index=name_i;
 			break;
 		case multiname::NAME_NUMBER:
-			if(!Number::isInteger(name_d) || name_d < 0)
+			if(!Number::isInteger(name_d) || name_d < 0 || name_d > UINT32_MAX)
 				return false;
 			index=name_d;
 			break;
@@ -515,10 +523,14 @@ std::istream& lightspark::operator>>(std::istream& s, FILLSTYLEARRAY& v)
 	assert(v.version!=0xff);
 	UI8 FillStyleCount;
 	s >> FillStyleCount;
+	int fsc = FillStyleCount;
 	if(FillStyleCount==0xff)
-		LOG(LOG_ERROR,_("Fill array extended not supported"));
-
-	for(int i=0;i<FillStyleCount;i++)
+	{
+		UI16_SWF ExtendedFillStyleCount;
+		s >> ExtendedFillStyleCount;
+		fsc = ExtendedFillStyleCount;
+	}
+	for(int i=0;i<fsc;i++)
 	{
 		FILLSTYLE t(v.version);
 		s >> t;
@@ -806,7 +818,7 @@ std::istream& lightspark::operator>>(std::istream& s, FILLSTYLE& v)
 	else
 	{
 		LOG(LOG_ERROR,_("Not supported fill style ") << (int)v.FillStyleType);
-		throw ParseException("Not supported fill style");
+	throw ParseException("Not supported fill style");
 	}
 	return s;
 }
@@ -1315,7 +1327,9 @@ std::istream& lightspark::operator>>(std::istream& s, CLIPACTIONS& v)
 
 ASObject* lightspark::abstract_d(number_t i)
 {
-	Number* ret=Class<Number>::getInstanceS(i);
+	Number* ret=Class<Number>::getInstanceS();
+	// we have to set the value seperately, because for i = NaN, getInstanceS will overwrite the value
+	ret->val = i;
 	return ret;
 }
 
@@ -1342,7 +1356,7 @@ void lightspark::stringToQName(const tiny_string& tmp, tiny_string& name, tiny_s
 		assert_and_throw(collon != tmp.raw_buf() && *(collon-1) == ':');
 		uint32_t collon_offset = collon-tmp.raw_buf();
 		ns = tmp.substr_bytes(0,collon_offset-1);
-		name = tmp.substr_bytes(collon_offset+1,tmp.numChars()-collon_offset-1);
+		name = tmp.substr_bytes(collon_offset+1,tmp.numBytes()-collon_offset-1);
 		return;
 	}
 	// No namespace, look for a package name
@@ -1351,7 +1365,7 @@ void lightspark::stringToQName(const tiny_string& tmp, tiny_string& name, tiny_s
 	{
 		uint32_t dot_offset = dot-tmp.raw_buf();
 		ns = tmp.substr_bytes(0,dot_offset);
-		name = tmp.substr_bytes(dot_offset+1,tmp.numChars()-dot_offset-1);
+		name = tmp.substr_bytes(dot_offset+1,tmp.numBytes()-dot_offset-1);
 		return;
 	}
 	//No namespace or package in the string
@@ -1398,6 +1412,18 @@ FILLSTYLE::~FILLSTYLE()
 {
 }
 
+FILLSTYLE& FILLSTYLE::operator=(FILLSTYLE r)
+{
+	std::swap(Matrix, r.Matrix);
+	std::swap(Gradient, r.Gradient);
+	std::swap(FocalGradient, r.FocalGradient);
+	std::swap(bitmap, r.bitmap);
+	std::swap(Color, r.Color);
+	std::swap(FillStyleType, r.FillStyleType);
+	std::swap(version, r.version);
+	return *this;
+}
+
 nsNameAndKind::nsNameAndKind(const tiny_string& _name, NS_KIND _kind)
 {
 	nsNameAndKindImpl tmp(_name, _kind);
@@ -1504,3 +1530,26 @@ tiny_string RGB::toString() const
 
 	return ss.str();
 }
+
+std::istream& lightspark::operator>>(std::istream& stream, SOUNDINFO& v)
+{
+	BitStream bs(stream);
+	UB(2,bs); // reserved
+	v.SyncStop = UB(1,bs);
+	v.SyncNoMultiple = UB(1,bs);
+	v.HasEnvelope = UB(1,bs);
+	v.HasLoops = UB(1,bs);
+	v.HasOutPoint = UB(1,bs);
+	v.HasInPoint = UB(1,bs);
+	if (v.HasInPoint)
+		stream >> v.InPoint;
+	if (v.HasOutPoint)
+		stream >> v.OutPoint;
+	if (v.HasLoops)
+		stream >> v.LoopCount;
+	if (v.HasEnvelope)
+		stream >> v.EnvPoints;
+	// TODO: EnvelopeRecords
+	return stream;
+}
+
diff --git a/src/swftypes.h b/src/swftypes.h
index 4022ec9..b477e09 100644
--- a/src/swftypes.h
+++ b/src/swftypes.h
@@ -83,7 +83,7 @@ typedef double number_t;
 
 class ASObject;
 class ABCContext;
-class namespace_info;
+struct namespace_info;
 
 struct multiname;
 class QName
@@ -376,6 +376,7 @@ struct multiname: public memory_reporter
 	void resetNameIfObject();
 	bool isQName() const { return ns.size() == 1; }
 	bool toUInt(uint32_t& out, bool acceptStringFractions=false) const;
+	bool isEmpty() const { return name_type == NAME_OBJECT && name_o == NULL;}
 };
 
 class FLOAT 
@@ -885,6 +886,7 @@ class FILLSTYLE
 public:
 	FILLSTYLE(uint8_t v);
 	FILLSTYLE(const FILLSTYLE& r);
+	FILLSTYLE& operator=(FILLSTYLE r);
 	virtual ~FILLSTYLE();
 	MATRIX Matrix;
 	GRADIENT Gradient;
@@ -924,10 +926,10 @@ public:
 class LINESTYLE2
 {
 public:
-	LINESTYLE2(uint8_t v):FillType(v),version(v){}
+	LINESTYLE2(uint8_t v):HasFillFlag(false),FillType(v),version(v){}
 	UB StartCapStyle;
 	UB JointStyle;
-	UB HasFillFlag;
+	bool HasFillFlag;
 	UB NoHScaleFlag;
 	UB NoVScaleFlag;
 	UB PixelHintingFlag;
@@ -1295,6 +1297,21 @@ public:
 	CLIPEVENTFLAGS AllEventFlags;
 };
 
+class SOUNDINFO
+{
+public:
+	UB SyncStop;
+	UB SyncNoMultiple;
+	UB HasEnvelope;
+	UB HasLoops;
+	UB HasOutPoint;
+	UB HasInPoint;
+	UI32_SWF InPoint;
+	UI32_SWF OutPoint;
+	UI16_SWF LoopCount;
+	UI8 EnvPoints;
+};
+
 class RunState
 {
 public:
@@ -1359,7 +1376,7 @@ std::istream& operator>>(std::istream& stream, GRADIENTGLOWFILTER& v);
 std::istream& operator>>(std::istream& stream, CONVOLUTIONFILTER& v);
 std::istream& operator>>(std::istream& stream, COLORMATRIXFILTER& v);
 std::istream& operator>>(std::istream& stream, GRADIENTBEVELFILTER& v);
-
+std::istream& operator>>(std::istream& stream, SOUNDINFO& v);
 
 };
 #endif /* SWFTYPES_H */
diff --git a/src/threading.cpp b/src/threading.cpp
index 26666a8..3e6c31a 100644
--- a/src/threading.cpp
+++ b/src/threading.cpp
@@ -26,6 +26,33 @@
 
 using namespace lightspark;
 
+#if GLIB_CHECK_VERSION(2, 31, 0)
+
+void lightspark::tls_set(GPrivate *key, gpointer value)
+{
+	g_private_set(key, value);
+}
+
+gpointer lightspark::tls_get(GPrivate *key)
+{
+	return g_private_get(key);
+}
+
+#else
+
+void lightspark::tls_set(GStaticPrivate *key, gpointer value)
+{
+	g_static_private_set(key, value, NULL);
+}
+
+gpointer lightspark::tls_get(GStaticPrivate *key)
+{
+	return g_static_private_get(key);
+}
+
+#endif
+
+
 Semaphore::Semaphore(uint32_t init):value(init)
 {
 }
diff --git a/src/threading.h b/src/threading.h
index eef5a2e..e6604cf 100644
--- a/src/threading.h
+++ b/src/threading.h
@@ -55,6 +55,16 @@ typedef Mutex::Lock Locker;
 typedef Mutex Spinlock;
 typedef Mutex::Lock SpinlockLocker;
 
+#if GLIB_CHECK_VERSION(2, 31, 0)
+#define DEFINE_AND_INITIALIZE_TLS(name) static GPrivate (name)
+void tls_set(GPrivate *key, gpointer value);
+gpointer tls_get(GPrivate *key);
+#else
+#define DEFINE_AND_INITIALIZE_TLS(name) static GStaticPrivate (name) = G_STATIC_PRIVATE_INIT
+void tls_set(GStaticPrivate *key, gpointer value);
+gpointer tls_get(GStaticPrivate *key);
+#endif
+
 class DLL_PUBLIC Semaphore
 {
 private:
diff --git a/src/tiny_string.cpp b/src/tiny_string.cpp
index 8257cae..9fec690 100644
--- a/src/tiny_string.cpp
+++ b/src/tiny_string.cpp
@@ -42,6 +42,78 @@ tiny_string::tiny_string(std::istream& in, int len):buf(_buf_static),stringSize(
 	buf[len]='\0';
 }
 
+tiny_string::tiny_string(const char* s,bool copy):_buf_static(),buf(_buf_static),type(READONLY)
+{
+	if(copy)
+		makePrivateCopy(s);
+	else
+	{
+		stringSize=strlen(s)+1;
+		buf=(char*)s; //This is an unsafe conversion, we have to take care of the RO data
+	}
+}
+
+tiny_string::tiny_string(const tiny_string& r):_buf_static(),buf(_buf_static),stringSize(r.stringSize),type(STATIC)
+{
+	//Fast path for static read-only strings
+	if(r.type==READONLY)
+	{
+		type=READONLY;
+		buf=r.buf;
+		return;
+	}
+	if(stringSize > STATIC_SIZE)
+		createBuffer(stringSize);
+	memcpy(buf,r.buf,stringSize);
+}
+
+tiny_string::tiny_string(const std::string& r):_buf_static(),buf(_buf_static),stringSize(r.size()+1),type(STATIC)
+{
+	if(stringSize > STATIC_SIZE)
+		createBuffer(stringSize);
+	memcpy(buf,r.c_str(),stringSize);
+}
+
+tiny_string::~tiny_string()
+{
+	resetToStatic();
+}
+
+tiny_string& tiny_string::operator=(const tiny_string& s)
+{
+	resetToStatic();
+	stringSize=s.stringSize;
+	//Fast path for static read-only strings
+	if(s.type==READONLY)
+	{
+		type=READONLY;
+		buf=s.buf;
+	}
+	else
+	{
+		if(stringSize > STATIC_SIZE)
+			createBuffer(stringSize);
+		memcpy(buf,s.buf,stringSize);
+	}
+	return *this;
+}
+
+tiny_string& tiny_string::operator=(const std::string& s)
+{
+	resetToStatic();
+	stringSize=s.size()+1;
+	if(stringSize > STATIC_SIZE)
+		createBuffer(stringSize);
+	memcpy(buf,s.c_str(),stringSize);
+	return *this;
+}
+
+tiny_string& tiny_string::operator=(const char* s)
+{
+	makePrivateCopy(s);
+	return *this;
+}
+
 tiny_string& tiny_string::operator=(const Glib::ustring& r)
 {
 	resetToStatic();
@@ -123,6 +195,17 @@ tiny_string& tiny_string::operator+=(const tiny_string& r)
 	return *this;
 }
 
+tiny_string& tiny_string::operator+=(const std::string& s)
+{
+	//TODO: optimize
+	return *this += tiny_string(s);
+}
+
+tiny_string& tiny_string::operator+=(uint32_t c)
+{
+	return (*this += tiny_string::fromChar(c));
+}
+
 const tiny_string tiny_string::operator+(const tiny_string& r) const
 {
 	tiny_string ret(*this);
@@ -130,6 +213,218 @@ const tiny_string tiny_string::operator+(const tiny_string& r) const
 	return ret;
 }
 
+const tiny_string tiny_string::operator+(const char* s) const
+{
+	return *this + tiny_string(s);
+}
+
+const tiny_string tiny_string::operator+(const std::string& r) const
+{
+	return *this + tiny_string(r);
+}
+
+bool tiny_string::operator<(const tiny_string& r) const
+{
+	//don't check trailing \0
+	return memcmp(buf,r.buf,std::min(stringSize,r.stringSize))<0;
+}
+
+bool tiny_string::operator>(const tiny_string& r) const
+{
+	//don't check trailing \0
+	return memcmp(buf,r.buf,std::min(stringSize,r.stringSize))>0;
+}
+
+bool tiny_string::operator==(const tiny_string& r) const
+{
+	//The length is checked as an optimization before checking the contents
+	if(stringSize != r.stringSize)
+		return false;
+	//don't check trailing \0
+	return memcmp(buf,r.buf,stringSize-1)==0;
+}
+
+bool tiny_string::operator==(const std::string& r) const
+{
+	//The length is checked as an optimization before checking the contents
+	if(stringSize != r.size()+1)
+		return false;
+	//don't check trailing \0
+	return memcmp(buf,r.c_str(),stringSize-1)==0;
+}
+
+bool tiny_string::operator!=(const std::string& r) const
+{
+	if(stringSize != r.size()+1)
+		return true;
+	//don't check trailing \0
+	return memcmp(buf,r.c_str(),stringSize-1)!=0;
+}
+
+bool tiny_string::operator!=(const tiny_string& r) const
+{
+	return !(*this==r);
+}
+
+bool tiny_string::operator==(const char* r) const
+{
+	return strcmp(buf,r)==0;
+}
+
+bool tiny_string::operator==(const xmlChar* r) const
+{
+	return strcmp(buf,reinterpret_cast<const char*>(r))==0;
+}
+
+bool tiny_string::operator!=(const char* r) const
+{
+	return !(*this==r);
+}
+
+const char* tiny_string::raw_buf() const
+{
+	return buf;
+}
+
+bool tiny_string::empty() const
+{
+	return stringSize == 1;
+}
+
+/* returns the length in bytes, not counting the trailing \0 */
+uint32_t tiny_string::numBytes() const
+{
+	return stringSize-1;
+}
+
+/* returns the length in utf-8 characters, not counting the trailing \0 */
+uint32_t tiny_string::numChars() const
+{
+	//we cannot use g_utf8_strlen, as we may have '\0' inside our string
+	uint32_t len = 0;
+	char* end = buf+numBytes();
+	char* p = buf;
+	while(p < end)
+	{
+		p = g_utf8_next_char(p);
+		++len;
+	}
+	return len;
+}
+
+char* tiny_string::strchr(char c) const
+{
+	//TODO: does this handle '\0' in middle of buf gracefully?
+	return g_utf8_strchr(buf, numBytes(), c);
+}
+
+char* tiny_string::strchrr(char c) const
+{
+	//TODO: does this handle '\0' in middle of buf gracefully?
+	return g_utf8_strrchr(buf, numBytes(), c);
+}
+
+tiny_string::operator std::string() const
+{
+	return std::string(buf,stringSize-1);
+}
+
+bool tiny_string::startsWith(const char* o) const
+{
+	return strncmp(buf,o,strlen(o)) == 0;
+}
+bool tiny_string::endsWith(const char* o) const
+{
+	size_t olen = strlen(o);
+	return (numBytes() >= olen) && 
+		(strncmp(buf+numBytes()-olen,o,olen) == 0);
+}
+
+/* idx is an index of utf-8 characters */
+uint32_t tiny_string::charAt(uint32_t idx) const
+{
+	return g_utf8_get_char(g_utf8_offset_to_pointer(buf,idx));
+}
+
+/* start is an index of characters.
+ * returns index of character */
+uint32_t tiny_string::find(const tiny_string& needle, uint32_t start) const
+{
+	//TODO: omit copy into std::string
+	size_t bytestart = g_utf8_offset_to_pointer(buf,start) - buf;
+	size_t bytepos = std::string(*this).find(needle.raw_buf(),bytestart,needle.numBytes());
+	if(bytepos == std::string::npos)
+		return npos;
+	else
+		return g_utf8_pointer_to_offset(buf,buf+bytepos);
+}
+
+uint32_t tiny_string::rfind(const tiny_string& needle, uint32_t start) const
+{
+	//TODO: omit copy into std::string
+	size_t bytestart;
+	if(start == npos)
+		bytestart = std::string::npos;
+	else
+		bytestart = g_utf8_offset_to_pointer(buf,start) - buf;
+
+	size_t bytepos = std::string(*this).rfind(needle.raw_buf(),bytestart,needle.numBytes());
+	if(bytepos == std::string::npos)
+		return npos;
+	else
+		return g_utf8_pointer_to_offset(buf,buf+bytepos);
+}
+
+void tiny_string::makePrivateCopy(const char* s)
+{
+	resetToStatic();
+	stringSize=strlen(s)+1;
+	if(stringSize > STATIC_SIZE)
+		createBuffer(stringSize);
+	strcpy(buf,s);
+}
+
+void tiny_string::createBuffer(uint32_t s)
+{
+	type=DYNAMIC;
+	reportMemoryChange(s);
+	buf=new char[s];
+}
+
+void tiny_string::resizeBuffer(uint32_t s)
+{
+	assert(type==DYNAMIC);
+	char* oldBuf=buf;
+	reportMemoryChange(s-stringSize);
+	buf=new char[s];
+	assert(s >= stringSize);
+	memcpy(buf,oldBuf,stringSize);
+	delete[] oldBuf;
+}
+
+void tiny_string::resetToStatic()
+{
+	if(type==DYNAMIC)
+	{
+		reportMemoryChange(-stringSize);
+		delete[] buf;
+	}
+	stringSize=1;
+	_buf_static[0] = '\0';
+	buf=_buf_static;
+	type=STATIC;
+}
+
+tiny_string tiny_string::fromChar(uint32_t c)
+{
+	tiny_string ret;
+	ret.buf = ret._buf_static;
+	ret.type = STATIC;
+	ret.stringSize = g_unichar_to_utf8(c,ret.buf) + 1;
+	ret.buf[ret.stringSize-1] = '\0';
+	return ret;
+}
+
 tiny_string& tiny_string::replace(uint32_t pos1, uint32_t n1, const tiny_string& o )
 {
 	assert(pos1 <= numChars());
@@ -202,6 +497,109 @@ std::list<tiny_string> tiny_string::split(uint32_t delimiter) const
 	return res;
 }
 
+tiny_string tiny_string::lowercase() const
+{
+	// have to loop manually, because g_utf8_strdown doesn't
+	// handle nul-chars
+	tiny_string ret;
+	uint32_t allocated = 2*numBytes()+7;
+	ret.createBuffer(allocated);
+	char *p = ret.buf;
+	uint32_t len = 0;
+	for (CharIterator it=begin(); it!=end(); it++)
+	{
+		assert(pend-p >= 6);
+		gunichar c = g_unichar_tolower(*it);
+		gint n = g_unichar_to_utf8(c, p);
+		p += n;
+		len += n;
+	}
+	*p = '\0';
+	ret.stringSize = len+1;
+	return ret;
+}
+
+tiny_string tiny_string::uppercase() const
+{
+	// have to loop manually, because g_utf8_strup doesn't
+	// handle nul-chars
+	tiny_string ret;
+	uint32_t allocated = 2*numBytes()+7;
+	ret.createBuffer(allocated);
+	char *p = ret.buf;
+	uint32_t len = 0;
+	for (CharIterator it=begin(); it!=end(); it++)
+	{
+		assert(pend-p >= 6);
+		gunichar c = g_unichar_toupper(*it);
+		gint n = g_unichar_to_utf8(c, p);
+		p += n;
+		len += n;
+	}
+	*p = '\0';
+	ret.stringSize = len+1;
+	return ret;
+}
+
+/* like strcasecmp(s1.raw_buf(),s2.raw_buf()) but for unicode
+ * TODO: slow! */
+int tiny_string::strcasecmp(tiny_string& s2) const
+{
+	char* str1 = g_utf8_casefold(this->raw_buf(),this->numBytes());
+	char* str2 = g_utf8_casefold(s2.raw_buf(),s2.numBytes());
+	int ret = g_utf8_collate(str1,str2);
+	g_free(str1);
+	g_free(str2);
+	return ret;
+}
+
+uint32_t tiny_string::bytePosToIndex(uint32_t bytepos) const
+{
+	if (bytepos >= numBytes())
+		return numChars();
+
+	return g_utf8_pointer_to_offset(raw_buf(), raw_buf() + bytepos);
+}
+
+CharIterator tiny_string::begin()
+{
+	return CharIterator(buf);
+}
+
+CharIterator tiny_string::begin() const
+{
+	return CharIterator(buf);
+}
+
+CharIterator tiny_string::end()
+{
+	//points to the trailing '\0' byte
+	return CharIterator(buf+numBytes());
+}
+
+CharIterator tiny_string::end() const
+{
+	//points to the trailing '\0' byte
+	return CharIterator(buf+numBytes());
+}
+
+int tiny_string::compare(const tiny_string& r) const
+{
+	int l = std::min(stringSize,r.stringSize);
+	int res = 0;
+	for(int i=0;i < l-1;i++)
+	{
+		res = (int)buf[i] - (int)r.buf[i];
+		if (res != 0)
+			return res;
+	}
+	if (stringSize > r.stringSize)
+		res = 1;
+	else if (stringSize < r.stringSize)
+		res = -1;
+	return res;
+}
+
 #ifdef MEMORY_USAGE_PROFILING
 void tiny_string::reportMemoryChange(int32_t change) const
 {
diff --git a/src/tiny_string.h b/src/tiny_string.h
index 8c05750..a8f18a7 100644
--- a/src/tiny_string.h
+++ b/src/tiny_string.h
@@ -56,8 +56,8 @@ public:
 	CharIterator operator++(int) // postfix
 	{
 		CharIterator result = *this;
-	    ++(*this);
-	    return result;
+		++(*this);
+		return result;
 	}
 	bool operator==(const CharIterator& o) const
 	{
@@ -83,7 +83,7 @@ public:
  * The string can contain '\0's, so don't use raw_buf().
  * Use len() to determine actual size.
  */
-class tiny_string
+class DLL_PUBLIC tiny_string
 {
 friend std::ostream& operator<<(std::ostream& s, const tiny_string& r);
 private:
@@ -105,224 +105,52 @@ private:
 	void reportMemoryChange(int32_t change) const {}
 #endif
 	//TODO: use static buffer again if reassigning to short string
-	void makePrivateCopy(const char* s)
-	{
-		resetToStatic();
-		stringSize=strlen(s)+1;
-		if(stringSize > STATIC_SIZE)
-			createBuffer(stringSize);
-		strcpy(buf,s);
-	}
-	void createBuffer(uint32_t s)
-	{
-		type=DYNAMIC;
-		reportMemoryChange(s);
-		buf=new char[s];
-	}
-	void resizeBuffer(uint32_t s)
-	{
-		assert(type==DYNAMIC);
-		char* oldBuf=buf;
-		reportMemoryChange(s-stringSize);
-		buf=new char[s];
-		assert(s >= stringSize);
-		memcpy(buf,oldBuf,stringSize);
-		delete[] oldBuf;
-	}
-	void resetToStatic()
-	{
-		if(type==DYNAMIC)
-		{
-			reportMemoryChange(-stringSize);
-			delete[] buf;
-		}
-		stringSize=1;
-		_buf_static[0] = '\0';
-		buf=_buf_static;
-		type=STATIC;
-	}
+	void makePrivateCopy(const char* s);
+	void createBuffer(uint32_t s);
+	void resizeBuffer(uint32_t s);
+	void resetToStatic();
 public:
 	static const uint32_t npos = (uint32_t)(-1);
 
 	tiny_string():_buf_static(),buf(_buf_static),stringSize(1),type(STATIC){buf[0]=0;}
 	/* construct from utf character */
-	static tiny_string fromChar(uint32_t c)
-	{
-		tiny_string ret;
-		ret.buf = ret._buf_static;
-		ret.type = STATIC;
-		ret.stringSize = g_unichar_to_utf8(c,ret.buf) + 1;
-		ret.buf[ret.stringSize-1] = '\0';
-		return ret;
-	}
-	tiny_string(const char* s,bool copy=false):_buf_static(),buf(_buf_static),type(READONLY)
-	{
-		if(copy)
-			makePrivateCopy(s);
-		else
-		{
-			stringSize=strlen(s)+1;
-			buf=(char*)s; //This is an unsafe conversion, we have to take care of the RO data
-		}
-	}
-	tiny_string(const tiny_string& r):_buf_static(),buf(_buf_static),stringSize(r.stringSize),type(STATIC)
-	{
-		//Fast path for static read-only strings
-		if(r.type==READONLY)
-		{
-			type=READONLY;
-			buf=r.buf;
-			return;
-		}
-		if(stringSize > STATIC_SIZE)
-			createBuffer(stringSize);
-		memcpy(buf,r.buf,stringSize);
-	}
-	tiny_string(const std::string& r):_buf_static(),buf(_buf_static),stringSize(r.size()+1),type(STATIC)
-	{
-		if(stringSize > STATIC_SIZE)
-			createBuffer(stringSize);
-		memcpy(buf,r.c_str(),stringSize);
-	}
+	static tiny_string fromChar(uint32_t c);
+	tiny_string(const char* s,bool copy=false);
+	tiny_string(const tiny_string& r);
+	tiny_string(const std::string& r);
 	tiny_string(const Glib::ustring& r);
 	tiny_string(std::istream& in, int len);
-	~tiny_string()
-	{
-		resetToStatic();
-	}
-	tiny_string& operator=(const tiny_string& s)
-	{
-		resetToStatic();
-		stringSize=s.stringSize;
-		//Fast path for static read-only strings
-		if(s.type==READONLY)
-		{
-			type=READONLY;
-			buf=s.buf;
-		}
-		else
-		{
-			if(stringSize > STATIC_SIZE)
-				createBuffer(stringSize);
-			memcpy(buf,s.buf,stringSize);
-		}
-		return *this;
-	}
-	tiny_string& operator=(const std::string& s)
-	{
-		resetToStatic();
-		stringSize=s.size()+1;
-		if(stringSize > STATIC_SIZE)
-			createBuffer(stringSize);
-		memcpy(buf,s.c_str(),stringSize);
-		return *this;
-	}
-	tiny_string& operator=(const char* s)
-	{
-		makePrivateCopy(s);
-		return *this;
-	}
+	~tiny_string();
+	tiny_string& operator=(const tiny_string& s);
+	tiny_string& operator=(const std::string& s);
+	tiny_string& operator=(const char* s);
 	tiny_string& operator=(const Glib::ustring& s);
 	tiny_string& operator+=(const char* s);
 	tiny_string& operator+=(const tiny_string& r);
-	tiny_string& operator+=(const std::string& s)
-	{
-		//TODO: optimize
-		return *this += tiny_string(s);
-	}
+	tiny_string& operator+=(const std::string& s);
 	tiny_string& operator+=(const Glib::ustring& s);
-	tiny_string& operator+=(uint32_t c)
-	{
-		return (*this += tiny_string::fromChar(c));
-	}
+	tiny_string& operator+=(uint32_t c);
 	const tiny_string operator+(const tiny_string& r) const;
-	const tiny_string operator+(const char* s) const
-	{
-		return *this + tiny_string(s);
-	}
-	const tiny_string operator+(const std::string& r) const
-	{
-		return *this + tiny_string(r);
-	}
+	const tiny_string operator+(const char* s) const;
+	const tiny_string operator+(const std::string& r) const;
 	const tiny_string operator+(const Glib::ustring& r) const;
-	bool operator<(const tiny_string& r) const
-	{
-		//don't check trailing \0
-		return memcmp(buf,r.buf,std::min(stringSize,r.stringSize))<0;
-	}
-	bool operator>(const tiny_string& r) const
-	{
-		//don't check trailing \0
-		return memcmp(buf,r.buf,std::min(stringSize,r.stringSize))>0;
-	}
-	bool operator==(const tiny_string& r) const
-	{
-		//The length is checked as an optimization before checking the contents
-		if(stringSize != r.stringSize)
-			return false;
-		//don't check trailing \0
-		return memcmp(buf,r.buf,stringSize-1)==0;
-	}
-	bool operator==(const std::string& r) const
-	{
-		//The length is checked as an optimization before checking the contents
-		if(stringSize != r.size()+1)
-			return false;
-		//don't check trailing \0
-		return memcmp(buf,r.c_str(),stringSize-1)==0;
-	}
-	bool operator!=(const std::string& r) const
-	{
-		if(stringSize != r.size()+1)
-			return true;
-		//don't check trailing \0
-		return memcmp(buf,r.c_str(),stringSize-1)!=0;
-	}
-	bool operator!=(const tiny_string& r) const
-	{
-		return !(*this==r);
-	}
-	bool operator==(const char* r) const
-	{
-		return strcmp(buf,r)==0;
-	}
-	bool operator==(const xmlChar* r) const
-	{
-		return strcmp(buf,reinterpret_cast<const char*>(r))==0;
-	}
-	bool operator!=(const char* r) const
-	{
-		return !(*this==r);
-	}
+	bool operator<(const tiny_string& r) const;
+	bool operator>(const tiny_string& r) const;
+	bool operator==(const tiny_string& r) const;
+	bool operator==(const std::string& r) const;
+	bool operator!=(const std::string& r) const;
+	bool operator!=(const tiny_string& r) const;
+	bool operator==(const char* r) const;
+	bool operator==(const xmlChar* r) const;
+	bool operator!=(const char* r) const;
 	bool operator==(const Glib::ustring&) const;
 	bool operator!=(const Glib::ustring&) const;
-	const char* raw_buf() const
-	{
-		return buf;
-	}
-	bool empty() const
-	{
-		return stringSize == 1;
-	}
+	const char* raw_buf() const;
+	bool empty() const;
 	/* returns the length in bytes, not counting the trailing \0 */
-	uint32_t numBytes() const
-	{
-		return stringSize-1;
-	}
+	uint32_t numBytes() const;
 	/* returns the length in utf-8 characters, not counting the trailing \0 */
-	uint32_t numChars() const
-	{
-		//we cannot use g_utf8_strlen, as we may have '\0' inside our string
-		uint32_t len = 0;
-		char* end = buf+numBytes();
-		char* p = buf;
-		while(p < end)
-		{
-			p = g_utf8_next_char(p);
-			++len;
-		}
-		return len;
-	}
+	uint32_t numChars() const;
 	/* start and len are indices of utf8-characters */
 	tiny_string substr(uint32_t start, uint32_t len) const;
 	tiny_string substr(uint32_t start, const CharIterator& end) const;
@@ -330,113 +158,34 @@ public:
 	tiny_string substr_bytes(uint32_t start, uint32_t len) const;
 	/* finds the first occurence of char in the utf-8 string
 	 * Return NULL if not found, else ptr to beginning of first occurence of c */
-	char* strchr(char c) const
-	{
-		//TODO: does this handle '\0' in middle of buf gracefully?
-		return g_utf8_strchr(buf, numBytes(), c);
-	}
-	char* strchrr(char c) const
-	{
-		//TODO: does this handle '\0' in middle of buf gracefully?
-		return g_utf8_strrchr(buf, numBytes(), c);
-	}
-	/*explicit*/ operator std::string() const
-	{
-		return std::string(buf,stringSize-1);
-	}
+	char* strchr(char c) const;
+	char* strchrr(char c) const;
+	/*explicit*/ operator std::string() const;
 	operator Glib::ustring() const;
-	bool startsWith(const char* o) const
-	{
-		return strncmp(buf,o,strlen(o)) == 0;
-	}
-        bool endsWith(const char* o) const
-        {
-                size_t olen = strlen(o);
-                return (numBytes() >= olen) && 
-                        (strncmp(buf+numBytes()-olen,o,olen) == 0);
-        }
+	bool startsWith(const char* o) const;
+        bool endsWith(const char* o) const;
 	/* idx is an index of utf-8 characters */
-	uint32_t charAt(uint32_t idx) const
-	{
-		return g_utf8_get_char(g_utf8_offset_to_pointer(buf,idx));
-	}
+	uint32_t charAt(uint32_t idx) const;
 	/* start is an index of characters.
 	 * returns index of character */
-	uint32_t find(const tiny_string& needle, uint32_t start = 0) const
-	{
-		//TODO: omit copy into std::string
-		size_t bytestart = g_utf8_offset_to_pointer(buf,start) - buf;
-		size_t bytepos = std::string(*this).find(needle.raw_buf(),bytestart,needle.numBytes());
-		if(bytepos == std::string::npos)
-			return npos;
-		else
-			return g_utf8_pointer_to_offset(buf,buf+bytepos);
-	}
-	uint32_t rfind(const tiny_string& needle, uint32_t start = npos) const
-	{
-		//TODO: omit copy into std::string
-		size_t bytestart;
-		if(start == npos)
-			bytestart = std::string::npos;
-		else
-			bytestart = g_utf8_offset_to_pointer(buf,start) - buf;
-
-		size_t bytepos = std::string(*this).rfind(needle.raw_buf(),bytestart,needle.numBytes());
-		if(bytepos == std::string::npos)
-			return npos;
-		else
-			return g_utf8_pointer_to_offset(buf,buf+bytepos);
-	}
+	uint32_t find(const tiny_string& needle, uint32_t start = 0) const;
+	uint32_t rfind(const tiny_string& needle, uint32_t start = npos) const;
 	tiny_string& replace(uint32_t pos1, uint32_t n1, const tiny_string& o);
 	tiny_string& replace_bytes(uint32_t bytestart, uint32_t bytenum, const tiny_string& o);
-	tiny_string lowercase() const
-	{
-		//TODO: omit copy, handle \0 in string
-		char *strdown = g_utf8_strdown(buf,numBytes());
-		tiny_string ret(strdown,/*copy:*/true);
-		g_free(strdown);
-		return ret;
-	}
-	tiny_string uppercase() const
-	{
-		//TODO: omit copy, handle \0 in string
-		char *strup = g_utf8_strup(buf,numBytes());
-		tiny_string ret(strup,/*copy:*/true);
-		g_free(strup);
-		return ret;
-	}
-	/* like strcasecmp(s1.raw_buf(),s2.raw_buf()) but for unicode
-	 * TODO: slow! */
-	int strcasecmp(tiny_string& s2) const
-	{
-		char* str1 = g_utf8_casefold(this->raw_buf(),this->numBytes());
-		char* str2 = g_utf8_casefold(s2.raw_buf(),s2.numBytes());
-		int ret = g_utf8_collate(str1,str2);
-		g_free(str1);
-		g_free(str2);
-		return ret;
-	}
+	tiny_string lowercase() const;
+	tiny_string uppercase() const;
+	/* like strcasecmp(s1.raw_buf(),s2.raw_buf()) but for unicode */
+	int strcasecmp(tiny_string& s2) const;
 	/* split string at each occurrence of delimiter character */
 	std::list<tiny_string> split(uint32_t delimiter) const;
+	/* Convert from byte offset to UTF-8 character index */
+	uint32_t bytePosToIndex(uint32_t bytepos) const;
 	/* iterate over utf8 characters */
-	CharIterator begin()
-	{
-		return CharIterator(buf);
-	}
-	CharIterator begin() const
-	{
-		return CharIterator(buf);
-	}
-	CharIterator end()
-	{
-		//points to the trailing '\0' byte
-		return CharIterator(buf+numBytes());
-	}
-	CharIterator end() const
-	{
-		//points to the trailing '\0' byte
-		return CharIterator(buf+numBytes());
-	}
+	CharIterator begin();
+	CharIterator begin() const;
+	CharIterator end();
+	CharIterator end() const;
+	int compare(const tiny_string& r) const;
 };
 
 };
diff --git a/tests/encodeURI_test.mxml b/tests/encodeURI_test.mxml
index e00f7e3..d84daa7 100644
--- a/tests/encodeURI_test.mxml
+++ b/tests/encodeURI_test.mxml
@@ -14,15 +14,82 @@
 		var encodedStr:String = "0189ABYZabyz;/?:@&=+$,#-_.!~*'()%20%7B%7D&";
 		var lowerEncodedStr:String = "0189ABYZabyz;/?:@&=+$,#-_.!~*'()%20%7b%7d&";
 		Tests.assertEquals(encodedStr, encodeURI(decodedStr), "encodeURI(): standard encodeURI");
+		Tests.assertEquals("a%C3%A4o%C3%B6", encodeURI("aäoö"), "encodeURI(): UTF-8 string");
 		Tests.assertEquals(decodedStr, decodeURI(encodedStr), "deocdeURI(): standard decodeURI");
 		Tests.assertEquals(decodedStr, decodeURI(lowerEncodedStr), "decodeURI(): decode lowercase encoded string");
+		Tests.assertEquals("ABC %3B%2F%3F%3A%40%26%3D%2B%24%2C%23 DEF", decodeURI("ABC%20%3B%2F%3F%3A%40%26%3D%2B%24%2C%23%20DEF"), "decodeURI(): reserved characters are not decoded");
+		Tests.assertEquals("aäoö", decodeURI("a%C3%A4o%C3%B6"), "decodeURI(): UTF-8 string");
+
+		var actual:String = "no exception thrown";
+		try {
+			decodeURI("%3X");
+		} catch (e:URIError) {
+			actual="URIError";
+		} catch (e:Error) {
+			actual = "wrong Error";
+		}
+		Tests.assertEquals("URIError", actual, "decodeURI(): invalid percent encoding");
+
+		actual = "no exception thrown";
+		try {
+			decodeURI("%C0%80");
+		} catch (e:URIError) {
+			actual="URIError";
+		} catch (e:Error) {
+			actual = "wrong Error";
+		}
+		Tests.assertEquals("URIError", actual, "decodeURI(): invalid UTF-8 sequence");
+
+		actual = "no exception thrown";
+		try {
+			decodeURI("%C3xyz");
+		} catch (e:URIError) {
+			actual="URIError";
+		} catch (e:Error) {
+			actual = "wrong Error";
+		}
+		Tests.assertEquals("URIError", actual, "decodeURI(): truncated UTF-8 sequence");
 
 		decodedStr = "0189ABYZabyz;/?:@&=+$,#-_.!~*'() {}&";
 		encodedStr = "0189ABYZabyz%3B%2F%3F%3A%40%26%3D%2B%24%2C%23-_.!~*'()%20%7B%7D%26";
 		lowerEncodedStr = "0189ABYZabyz%3b%2f%3f%3a%40%26%3d%2b%24%2c%23-_.!~*'()%20%7b%7d%26";
 		Tests.assertEquals(encodedStr, encodeURIComponent(decodedStr), "encodeURIComponent(): standard encodeURIComponent");
+		Tests.assertEquals("a%C3%A4o%C3%B6", encodeURIComponent("aäoö"), "encodeURIComponent(): UTF-8 string");
 		Tests.assertEquals(decodedStr, decodeURIComponent(encodedStr), "deocdeURIComponent(): standard decodeURIComponent");
 		Tests.assertEquals(decodedStr, decodeURIComponent(lowerEncodedStr), "decodeURIComponent(): decode lowercase encoded string");
+		Tests.assertEquals("aäoö", decodeURIComponent("a%C3%A4o%C3%B6"), "decodeURIComponent(): UTF-8 string");
+
+		actual = "no exception thrown";
+		try {
+			decodeURIComponent("%3X");
+		} catch (e:URIError) {
+			actual="URIError";
+		} catch (e:Error) {
+			actual = "wrong Error";
+		}
+		Tests.assertEquals("URIError", actual, "decodeURIComponent(): invalid percent encoding");
+
+		actual = "no exception thrown";
+		try {
+			decodeURIComponent("%C0%80");
+		} catch (e:URIError) {
+			actual="URIError";
+		} catch (e:Error) {
+			actual = "wrong Error";
+		}
+		Tests.assertEquals("URIError", actual, "decodeURIComponent(): invalid UTF-8 sequence");
+
+		actual = "no exception thrown";
+		try {
+			decodeURIComponent("%C3xyz");
+		} catch (e:URIError) {
+			actual="URIError";
+		} catch (e:Error) {
+			actual = "wrong Error";
+		}
+		Tests.assertEquals("URIError", actual, "decodeURIComponent(): truncated UTF-8 sequence");
+
+
 		Tests.report(visual, this.name);
 	}
 	]]>
diff --git a/tests/make-tamarin b/tests/make-tamarin
index 3e5ff89..7c73243 100755
--- a/tests/make-tamarin
+++ b/tests/make-tamarin
@@ -5,6 +5,7 @@ echo "or ./make-tamarin ecma3/Boolean"
 
 TAMARIN=${TAMARIN:-tamarin}
 ASC=${ASC:-`pwd`/asc.jar}
+AVM=${AVM:-${TAMARIN}/objdir/shell/avmshell}
 if [[ ! -d $TAMARIN ]]; then
   echo "Directory tamarin not found, please run"
   echo "hg clone http://hg.mozilla.org/tamarin-redux tamarin"
@@ -23,15 +24,111 @@ if [[ `java -jar $ASC | sed -n -e 's/version [^ ]* build \(.*\)/\1/p'` -lt 18513
   exit 1
 fi
 
-CUR=`pwd`
-
-#cd $TAMARIN/test/acceptance && \
-#rm -f ats_temp.abc ats_temp.as shell.as && \
-#echo "override| -optimize -in $CUR/tamarin-lightspark.as -AS3 -swf 200,200 -in ./ats_temp.as" > dir.asc_args && \
-#./runtests.py --asc $ASC --builtinabc ../../core/builtin.abc --shellabc ../../shell/shell_toplevel.abc --ats --atsdir $CUR/tamarin-SWF || exit 1
-(cd $TAMARIN/test/acceptance && \
-rm -f ats_temp.abc ats_temp.as shell.as && \
-grep USES_SWFVERSION . -R --files-with-matches | xargs --no-run-if-empty rm && \
-echo "override| -optimize -in $CUR/tamarin-lightspark.as -AS3 -swf 200,200 -in ./ats_temp.as" > dir.asc_args && \
-./runtests.py --asc $ASC --builtinabc ../../generated/builtin.abc --shellabc ../../generated/shell_toplevel.abc --ats --atsdir $CUR/tamarin-SWF $1) \
-|| echo "Compiling tests failed. Make sure you have the latest tamarin-redux and asc.jar from http://hg.mozilla.org/tamarin-redux and ftp://ftp.mozilla.org/pub/js/tamarin/builds/asc/latest/asc.jar, respectively."
+export CUR=`pwd`
+
+printCompileErrorAndExit()
+{
+    echo "Compiling tests failed. Make sure you have the latest tamarin-redux and asc.jar from http://hg.mozilla.org/tamarin-redux and ftp://ftp.mozilla.org/pub/js/tamarin/builds/asc/latest/asc.jar, respectively."
+    exit 1;
+}
+
+# compile tests from Tamarin before commit 7555
+makeTamarin1()
+{
+    (cd $TAMARIN/test/acceptance && \
+    rm -f ats_temp.abc ats_temp.as shell.as && \
+    grep USES_SWFVERSION . -R --files-with-matches | xargs --no-run-if-empty rm && \
+    echo "override| -optimize -in $CUR/tamarin-lightspark.as -AS3 -swf 200,200 -in ./ats_temp.as" > dir.asc_args && \
+    ./runtests.py --asc $ASC --builtinabc ../../generated/builtin.abc --shellabc ../../generated/shell_toplevel.abc --ats --atsdir $CUR/tamarin-SWF $1) \
+    || printCompileErrorAndExit;
+}
+
+# compile tests from Tamarin commit 7555 and later
+makeTamarin2()
+{
+    if [[ ! -f $AVM ]]; then
+        echo "Set shell variable AVM to point to avmshell executable"
+        exit 1
+    fi
+
+    java -jar $ASC -import $TAMARIN/generated/builtin.abc quit.as
+
+    cd $TAMARIN/test/acceptance
+    compiled=$(./runtests.py --asc $ASC --avm $AVM --builtinabc ../../generated/builtin.abc --shellabc ../../generated/shell_toplevel.abc --rebuildtests $1)
+    if [[ $? -ne 0 ]]; then
+        printCompileErrorAndExit;
+    fi
+
+    # The first sed selects lines starting with "compiling" unless the
+    # following lines starts with "Excluding".
+    #
+    # The second sed filters out some strange cases (TODO: check
+    # these!).
+    echo "$compiled" | \
+        sed -n '/^compiling/{N; /\nExcluding/ b excluded; P; D; b; :excluded d}' | \
+        sed -n '/ascompiling\|mmgc\/outofmemory\.as\|mmgc\/memlimit\.as\|bug_515935.as\|abc_$/!p' | \
+        sed -e 's/compiling \(.*\)/\1/' \
+            -e 's/\(.*\.\)[a-z]\+$/\1abc/' | \
+        xargs -L 1 bash -c 'linkTamarinTest $0'
+    cd -
+}
+
+# Sort classes in $TEST_SUPPORT in dependecy order: put interface
+# classes first and sort other classes alphabetically.
+function sortSupportClasses() {
+    local interfaces=$(echo "$TEST_SUPPORT" | tr " " "\n" | grep Interface)
+    local classes=$(echo "$TEST_SUPPORT" | tr " " "\n" | grep -v Interface | sort)
+    TEST_SUPPORT=$(echo "$interfaces $classes" | tr "\n" " ")
+}
+
+# Create a .swf for a Tamarin test case by figuring out which .abc
+# files belong to the test case and merging them.
+# Input: the name of test case's main .abc or .abs file
+function linkTamarinTest() {
+    shouldExcludeTest "$1"
+    local exclude_test=$?
+
+    if [[ -f "$1" && "$exclude_test" -eq 0 ]]; then
+        echo "Linking $1"
+
+        mkdir -p $CUR/tamarin-SWF/$(dirname $1)
+        OUTPUT_SWF="$CUR/tamarin-SWF/${1/%ab[cs]/swf}"
+
+        COMMON="Assert.abc Utils.abc"
+        ABS_SUPPORT=$(if [[ -f ${1/%abc/abs} ]]; then echo abcasm/abs_helper.abc; fi)
+        TEST_SUPPORT=$(if [[ -d ${1/%.abc/} ]]; then echo $(ls ${1/%.abc/}/*.abc 2> /dev/null); fi)
+        sortSupportClasses
+        ABC_FILES="$COMMON $TEST_SUPPORT $ABS_SUPPORT $1 $CUR/quit.abc"
+
+        $CUR/../tools/mergeABCtoSWF $ABC_FILES -o $OUTPUT_SWF
+    elif [[ "$exclude_test" -ne 0 ]]; then
+	echo "Excluding $1"
+    fi
+}
+
+# Exclude testcases that need imports from shell_toplevel (avmplus,
+# avmshell packages) until versioned identifiers are supported.
+function shouldExcludeTest() {
+    local asfile=${1/ab[cs]/as}
+    grep --quiet --no-messages "import avmplus\|import avmshell" "$asfile"
+    if [[ $? -eq 0 ]]; then
+	return 1
+    else
+	return 0
+    fi
+}
+
+export -f linkTamarinTest sortSupportClasses shouldExcludeTest
+
+if [[ "x$1" = "x" ]]; then
+    rm -rf tamarin-SWF/*
+fi
+
+# Tamarin testing framework changed in commit 7555 in a way that is
+# incompatible with previous version of this script. Use Assert.as, a
+# file introduced in that commit, to detect the new test setup.
+if [[ -f $TAMARIN/test/acceptance/Assert.as ]]; then
+    makeTamarin2;
+else
+    makeTamarin1;
+fi
diff --git a/tests/methodNamespace_test.mxml b/tests/methodNamespace_test.mxml
new file mode 100644
index 0000000..141714d
--- /dev/null
+++ b/tests/methodNamespace_test.mxml
@@ -0,0 +1,141 @@
+<?xml version="1.0"?>
+<mx:Application name="lightspark_methodNamespace_test"
+	xmlns:mx="http://www.adobe.com/2006/mxml"
+	layout="absolute"
+	applicationComplete="appComplete();"
+	backgroundColor="white">
+
+<mx:Script>
+	<![CDATA[
+	import Tests;
+	private function appComplete():void
+	{
+		namespace as3_ns = "http://adobe.com/AS3/2006/builtin";
+		namespace public_ns = "";
+
+		testMethods(Object.prototype, "Object prototype",
+			[["toString", public_ns, "exists"],
+			 ["toString", as3_ns, "ReferenceError"]]);
+
+		testMethods(new Object(), "Object instance",
+			[["toString", public_ns, "exists"],
+			 ["toString", as3_ns, "ReferenceError"]]);
+
+		testMethods(String.prototype, "String prototype",
+			[["toString", public_ns, "exists"],
+			 ["toString", as3_ns, "ReferenceError"],
+			 ["split", public_ns, "exists"],
+			 ["split", as3_ns, "ReferenceError"]]);
+
+		testMethods(new String(""), "String instance",
+			[["toString", public_ns, "exists"],
+			 ["toString", as3_ns, "exists"],
+			 ["split", public_ns, "exists"],
+			 ["split", as3_ns, "exists"]]);
+
+		testMethods(Number.prototype, "Number prototype",
+			[["toString", public_ns, "exists"],
+			 ["toString", as3_ns, "ReferenceError"]]);
+
+		testMethods(new Number(0), "Number instance",
+			[["toString", public_ns, "exists"],
+			 ["toString", as3_ns, "exists"]]);
+
+		testMethods(Boolean.prototype, "Boolean prototype",
+			[["toString", public_ns, "exists"],
+			 ["toString", as3_ns, "ReferenceError"]]);
+
+		testMethods(new Boolean(), "Boolean instance",
+			[["toString", public_ns, "exists"],
+			 ["toString", as3_ns, "exists"]]);
+
+		testMethods(Function.prototype, "Function prototype",
+			[["toString", public_ns, "exists"],
+			 ["toString", as3_ns, "ReferenceError"],
+			 ["call", public_ns, "exists"],
+			 ["call", as3_ns, "exists"]]);
+
+		testMethods(function():void {}, "function instance",
+			[["toString", public_ns, "exists"],
+			 ["toString", as3_ns, "ReferenceError"],
+			 ["call", public_ns, "exists"],
+			 ["call", as3_ns, "exists"]]);
+
+		testMethods(Math, "Math",
+			[["toString", public_ns, "exists"],
+			 ["toString", as3_ns, "ReferenceError"]]);
+
+		testMethods(Error, "Error",
+			[["toString", public_ns, "exists"],
+			 ["toString", as3_ns, "ReferenceError"]]);
+
+		testMethods(new Error(), "Error instance",
+			[["toString", public_ns, "exists"],
+			 ["toString", as3_ns, "ReferenceError"]]);
+
+		testMethods(Date, "Date",
+			[["toString", public_ns, "exists"],
+			 ["toString", as3_ns, "ReferenceError"]]);
+
+		testMethods(new Date(), "Date",
+			[["toString", public_ns, "exists"],
+			 ["toString", as3_ns, "exists"]]);
+
+		testMethods(RegExp.prototype, "RegExp prototype",
+			[["toString", public_ns, "exists"],
+			 ["toString", as3_ns, "ReferenceError"],
+			 ["exec", public_ns, "exists"],
+			 ["exec", as3_ns, "exists"]]);
+
+		testMethods(new RegExp(), "RegExp instance",
+			[["toString", public_ns, "exists"],
+			 ["toString", as3_ns, "ReferenceError"],
+			 ["exec", public_ns, "exists"],
+			 ["exec", as3_ns, "exists"]]);
+
+		testMethods(Vector.prototype, "Vector prototype",
+			[["toString", public_ns, "exists"],
+			 ["toString", as3_ns, "ReferenceError"],
+			 ["every", public_ns, "undefined"],
+			 ["every", as3_ns, "ReferenceError"]]);
+
+		testMethods(new Vector.<int>(), "Vector instance",
+			[["toString", public_ns, "exists"],
+			 ["toString", as3_ns, "exists"],
+			 ["every", public_ns, "exists"],
+			 ["every", as3_ns, "exists"]]);
+
+		Tests.report(visual, this.name);
+	}
+
+	private function testMethods(obj:*, testName:String, methodsAndExpectedResults:Array):void {
+		for (var i:int=0; i<methodsAndExpectedResults.length; i++) {
+			var method:String = methodsAndExpectedResults[i][0];
+			var ns:Namespace = methodsAndExpectedResults[i][1];
+			var expected:String = methodsAndExpectedResults[i][2];
+			var s:String = checkMethodExists(obj, ns, method);
+			var name:String = ns.toString() + "::" + method + " on " + testName;
+			Tests.assertEquals(expected, s, name);
+		}
+	}
+
+	private function checkMethodExists(obj:*, ns:Namespace, method:String):String {
+		var result:String = "exists";
+		try {
+			var f:* = obj.ns::[method];
+			if (f == undefined) {
+			    result = "undefined";
+			}
+		} catch(e:ReferenceError) {
+			result = "ReferenceError";
+		} catch(e:Error) {
+			result = e.toString();
+		}
+		return result;
+	}
+	]]>
+</mx:Script>
+
+<mx:UIComponent id="visual" />
+
+</mx:Application>
diff --git a/tests/quit.as b/tests/quit.as
new file mode 100644
index 0000000..368487a
--- /dev/null
+++ b/tests/quit.as
@@ -0,0 +1,2 @@
+namespace flashsystemns = "flash.system";
+flashsystemns::fscommand("quit");
diff --git a/tests/tests b/tests/tests
index e57dccd..e89bbc5 100755
--- a/tests/tests
+++ b/tests/tests
@@ -33,6 +33,56 @@ BLACKLIST=0;
 JUNITFILE=""
 NOXVFB=0;
 
+# Convert output from local and pre-7555 commit Tamarin testcases to JUnit XML
+function writeJUnit1() {
+	tcnum=0
+	#Find all lines that start with '. [' or 'F [' or 'A ..F.. ['
+	tcnum=$(echo "$1" | sed -n -e "/^\(A \)\?[F\.]\+ \[.*/p" \
+	| { while read L
+	do
+		tcnum=`expr $tcnum + 1`
+		#Escape <>& and remove non-printable characters
+		xml_l=`echo -e "$L" | sed -e 's/[^[:print:]]//g' -e 's/\&/\&/g' -e 's/</\</g' -e 's/>/\>/g'`
+		#Check if L starts with an 'F' or with 'A ...F'
+		if echo -e "$L" | grep -e "^\(A \.*\)\?F" > /dev/null ; then
+			echo "<testcase classname=\"$2\" name=\"${3}_tc${tcnum}\"><failure type=\"testfailure\">$xml_l</failure></testcase>" >> "$JUNITFILE"
+		else
+			echo "<testcase classname=\"$2\" name=\"${3}_tc${tcnum}\"/>" >> "$JUNITFILE"
+		fi
+	done
+	echo $tcnum
+	})
+
+	if [[ "$tcnum" != "$4" ]]; then
+		echo -e "\nError parsing test output of $test: Not enough testcases seen"
+		exit 1
+	fi
+}
+
+# Convert output from post-7555 commit Tamarin to JUnit XML
+function writeJUnit2() {
+	tcnum=0
+	tcnum=$(echo "$1" | grep 'PASSED!\|FAILED!' \
+	| { while read L
+	do
+		tcnum=`expr $tcnum + 1`
+		#Escape <>& and remove non-printable characters
+		xml_l=`echo -e "$L" | sed -e 's/[^[:print:]]//g' -e 's/\&/\&/g' -e 's/</\</g' -e 's/>/\>/g'`
+		if echo "$L" | grep 'FAILED!' > /dev/null ; then
+		    echo  "<testcase classname=\"$2\" name=\"${3}_tc${tcnum}\"><failure type=\"testfailure\">$xml_l</failure></testcase>" >> "$JUNITFILE"
+		else
+		    echo "<testcase classname=\"$2\" name=\"${3}_tc${tcnum}\"/>" >> "$JUNITFILE"
+		fi
+	done
+	echo $tcnum
+	})
+
+	if [[ "$tcnum" != "$4" ]]; then
+		echo -e "\nError parsing test output of $test: Not enough testcases seen"
+		exit 1
+	fi
+}
+
 if ! `which timeout > /dev/null`; then
 	echo "Warning: 'timeout' command not found"
 	TIMEOUTCMD=""
@@ -182,7 +232,7 @@ if [ $COMPILE -eq 1 ]; then
 	echo -e "\n" 1>&2;
 fi
 
-FAILURECOUNT=0; SUCCESSCOUNT=0; TESTCOUNT=0;
+FAILURECOUNT=0; SUCCESSCOUNT=0; TESTCOUNT=0; EXITEDCOUNT=0; ALLSUCCESSCOUNT=0; NOSUMMARYCOUNT=0;
 
 #Colors used for colorization
 CLEAR='\\\e[0m';
@@ -283,15 +333,21 @@ for test in $TESTS; do
 			fi
 		fi
 		if [[ -n "$JUNITFILE" ]]; then
-			echo "<testcase classname=\"$testclass\" name=\"$testname\"><failure type=\"exitvalue\">Exit Value $ev</failure></testcase>" >> "$JUNITFILE"
+			if [[ "$ev" = "124" ]]; then
+				echo "<testcase classname=\"$testclass\" name=\"$testname\"><failure type=\"timeout\">Timeout</failure></testcase>" >> "$JUNITFILE"
+			else
+				echo "<testcase classname=\"$testclass\" name=\"$testname\"><failure type=\"exitvalue\">Exit Value $ev</failure></testcase>" >> "$JUNITFILE"
+			fi
 		fi
 		FAILURECOUNT=`expr $FAILURECOUNT + 1`;
 		FAILED_TESTS="$FAILED_TESTS $test"
+		EXITEDCOUNT=`expr $EXITEDCOUNT + 1`
 		continue
 	fi
 	#Remove the RANDR error when running under xvfb, convert control characters to something like \303
 	lines=`sed -e '/Xlib:  extension "RANDR" missing on display.*/d' -e 's/[[:cntrl:]]//' $LOGFILE`
 	if [ "`echo $lines | grep '==Failures'`" != "" ]; then
+		# local tests and Tamarin before commit 7555 
 		THISFAILEDCOUNT=`echo "$lines" | sed -n -e 's/.*=Failures (\(.*\)\/.*)=.*/\1/p'`
 		THISNUMTESTS=`echo "$lines" | sed -n -e 's/.*=Failures (.*\/\(.*\))=.*/\1/p'`
 		THISSUCCESSCOUNT=`expr $THISNUMTESTS - $THISFAILEDCOUNT`
@@ -299,9 +355,22 @@ for test in $TESTS; do
 		SUCCESSCOUNT=`expr $SUCCESSCOUNT + $THISSUCCESSCOUNT`;
 		FAILED_TESTS="$FAILED_TESTS $test"
 	elif [ "`echo $lines | grep '==No failures'`" != "" ]; then
+		# local tests and Tamarin before commit 7555 
 		THISSUCCESSCOUNT=`echo "$lines" | sed -n -e 's/.*=No failures (\(.*\))=.*/\1/p'`
 		THISNUMTESTS="$THISSUCCESSCOUNT"
 		SUCCESSCOUNT=`expr $SUCCESSCOUNT + $THISSUCCESSCOUNT`;
+		ALLSUCCESSCOUNT=`expr $ALLSUCCESSCOUNT + 1`
+	elif [ "`echo $lines | grep 'PASSED!\|FAILED!'`" != "" ]; then
+		# Tamarin commit 7555 and later
+		THISSUCCESSCOUNT=`echo "$lines" | grep -c 'PASSED!'`
+		THISFAILEDCOUNT=`echo "$lines" | grep -c 'FAILED!'`
+		THISNUMTESTS=`expr $THISSUCCESSCOUNT + $THISFAILEDCOUNT`
+		FAILURECOUNT=`expr $FAILURECOUNT + $THISFAILEDCOUNT`;
+		SUCCESSCOUNT=`expr $SUCCESSCOUNT + $THISSUCCESSCOUNT`;
+		FAILED_TESTS="$FAILED_TESTS $test"
+		if [ $THISFAILEDCOUNT -eq 0 ]; then
+			ALLSUCCESSCOUNT=`expr $ALLSUCCESSCOUNT + 1`
+		fi
 	else
 		if [ $COLORS -eq 1 ]; then
 			echo -e "\\e[0;31m$test printed no test summary!\\e[0m"
@@ -313,31 +382,15 @@ for test in $TESTS; do
 		fi
 		FAILURECOUNT=`expr $FAILURECOUNT + 1`;
 		FAILED_TESTS="$FAILED_TESTS $test"
+		NOSUMMARYCOUNT=`expr $NOSUMMARYCOUNT + 1`
 		continue
 	fi
 
 	if [[ -n "$JUNITFILE" ]]; then
-		#For xml output
-		tcnum=0
-		#Find all lines that start with '. [' or 'F [' or 'A ..F.. ['
-		tcnum=$(echo "$lines" | sed -n -e "/^\(A \)\?[F\.]\+ \[.*/p" \
-		| { while read L
-		do
-			tcnum=`expr $tcnum + 1`
-			#Escape <>& and remove non-printable characters
-			xml_l=`echo -e "$L" | sed -e 's/[^[:print:]]//g' -e 's/\&/\&/g' -e 's/</\</g' -e 's/>/\>/g'`
-			#Check if L starts with an 'F' or with 'A ...F'
-			if echo -e "$L" | grep -e "^\(A \.*\)\?F" > /dev/null ; then
-				echo "<testcase classname=\"$testclass\" name=\"${testname}_tc${tcnum}\"><failure type=\"testfailure\">$xml_l</failure></testcase>" >> "$JUNITFILE"
-			else
-				echo "<testcase classname=\"$testclass\" name=\"${testname}_tc${tcnum}\"/>" >> "$JUNITFILE"
-			fi
-		done
-		echo $tcnum
-		})
-		if [[ "$tcnum" != "$THISNUMTESTS" ]]; then
-			echo -e "\nError parsing test output of $test: Not enough testcases seen"
-			exit 1
+		if [[ "`echo $lines | grep '==Failures\|==No failures'`" != "" ]]; then
+			writeJUnit1 "$lines" "$testclass" "$testname" "$THISNUMTESTS"
+		else
+			writeJUnit2 "$lines" "$testclass" "$testname" "$THISNUMTESTS"
 		fi
 	fi
 
@@ -399,7 +452,13 @@ if [ $PROPRIETARY -eq 0 ]; then
 fi
 
 if [ $COLORS -eq 1 ]; then
-	echo -e "Tests run: $TESTCOUNT, \e[1;32m$SUCCESSCOUNT successful\e[0m and \e[1;31m$FAILURECOUNT failed\e[0m" 1>&2
+	echo -e "\e[1;36mTEST SUMMARY:" 1>&2
+	echo -e "$TESTCOUNT tests\e[0m were run, of which \e[1;32m`expr $TESTCOUNT - $EXITEDCOUNT` finished\e[0m and \e[1;31m$EXITEDCOUNT exited prematurely\e[0m." 1>&2
+	echo -e "\e[1;36m`expr $SUCCESSCOUNT + $FAILURECOUNT` single test cases\e[0m were performed: \e[1;32m$SUCCESSCOUNT were successful\e[0m and \e[1;31m$FAILURECOUNT failed\e[0m (\e[1;36m`expr $SUCCESSCOUNT \* 100 / \( $SUCCESSCOUNT + $FAILURECOUNT \)`% success rate\e[0m)." 1>&2
+	echo -e "\e[1;32m$ALLSUCCESSCOUNT tests passed every single test case\e[0m, while \e[1;31m$NOSUMMARYCOUNT didn't print a test summary\e[0m." 1>&2
 else
-	echo -e "Tests run: $TESTCOUNT, $SUCCESSCOUNT successful and $FAILURECOUNT failed" 1>&2
+	echo -e "TEST SUMMARY:" 1>&2
+	echo -e "$TESTCOUNT tests were run, of which `expr $TESTCOUNT - $EXITEDCOUNT` finished and $EXITEDCOUNT exited prematurely." 1>&2
+	echo -e "`expr $SUCCESSCOUNT + $FAILURECOUNT` single test cases were performed: $SUCCESSCOUNT were successful and $FAILURECOUNT failed (`expr $SUCCESSCOUNT \* 100 / \( $SUCCESSCOUNT + $FAILURECOUNT \)`% success rate)." 1>&2
+	echo -e "$ALLSUCCESSCOUNT tests passed every single test case, while $NOSUMMARYCOUNT didn't print a test summary." 1>&2
 fi
diff --git a/tools/langref_parser b/tools/langref_parser
index 88849c9..5d470cd 100755
--- a/tools/langref_parser
+++ b/tools/langref_parser
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python2
 #This greps the source for SET_NAMESPACE, REGISTER_CLASS_NAME2,
 #sinit definition and the following ->set{Getter,Setter,Method}ByQName calls
 
@@ -21,7 +21,7 @@ if len(sys.argv) < 2:
 	print("Call by langref_parser langref-directory")
 	print("If you do not have a langref directory,")
 	print("please download http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/standalone.zip")
-        print("and unpack it.")
+	print("and unpack it.")
 	exit(1)
 
 langref = sys.argv[1]
@@ -71,10 +71,11 @@ for dirpath, dirnames, filenames in os.walk(langref):
 				if m:
 					if dirpath==langref:
 						curClass = m.group(1)
+						isConst = False
 					else:
 						curClass = dirpath.replace("langref/","").replace("/",".") +"."+ m.group(1)
-			                dclasses.add(curClass)
-			                isConst = False
+						dclasses.add(curClass)
+						isConst = False
 					break
 				m = regconst.search(line)
 				if m:
@@ -84,7 +85,7 @@ for dirpath, dirnames, filenames in os.walk(langref):
 					#there may be another match on this line
 				m = regproperty.search(line)
 				if m:
-					name = m.group(1)
+					name = m.group(1).replace("#","").replace("(","").replace(")","")
 					isOverride = m.group(2) != None
 					isStatic = m.group(3) != None
 					isReadOnly = m.group(4) != None
@@ -94,7 +95,7 @@ for dirpath, dirnames, filenames in os.walk(langref):
 					continue
 				m = regmethod.search(line)
 				if m:
-					name = m.group(1)
+					name = m.group(1).replace("#","").replace("(","").replace(")","")
 					dmethods.add((curClass,name))
 					line = line[m.end():]
 					continue
diff --git a/tools/mergeABCtoSWF b/tools/mergeABCtoSWF
new file mode 100755
index 0000000..9e2b5be
--- /dev/null
+++ b/tools/mergeABCtoSWF
@@ -0,0 +1,134 @@
+#!/usr/bin/python
+
+# Copyright (C) 2013 Antti Ajanki (antti.ajanki at iki.fi)
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# This script merges one or more ABC files into a simple SWF wrapper.
+#
+# Usage: mergeABCtoSWF abcFile1 [abcFile2 ...] [-o outputSWFFile]
+#
+# The ABC files should be in dependency order, files that provide
+# functions should be listed before files that use those functions.
+
+import struct
+import sys
+import os.path
+from optparse import OptionParser
+
+class SWFFile:
+    TAG_END = 0
+    TAG_SHOW_FRAME = 1
+    TAG_FILE_ATTRIBUTES = 69
+    TAG_DOABC = 82
+
+    ATTR_HAS_AS3 = 8
+
+    # RECT 8000x6000
+    DEFAULT_RECT = '\x78\x00\x03\xe8\x00\x00\x0b\xb8\x00'
+    
+    def __init__(self, filename):
+        self.file = open(filename, 'wb')
+        self.writeSWFHeader()
+
+    def writeSWFHeader(self):
+        self.file.write('FWS')
+        # version
+        self.file.write(chr(9))
+        # length, will be set in finalize
+        self.file.write('\0'*4)
+        # rect size in twips
+        self.file.write(self.DEFAULT_RECT)
+        # framerate
+        self.writeUI16(20 << 8)
+        # frame count
+        self.writeUI16(1)
+        self.addFileAttributesTag()
+
+    def finalize(self):
+        self.addShowFrameTag()
+        self.addEndTag()
+        self.updateSize()
+        self.file.close()
+        self.file = None
+
+    def addFileAttributesTag(self):
+        body = chr(self.ATTR_HAS_AS3) + '\0'*3
+        self.writeTag(self.TAG_FILE_ATTRIBUTES, body)
+        
+    def addABCBlock(self, abc):
+        body = '\0'*4 # flags
+        body += '\0' # name
+        body += abc
+        self.writeTag(self.TAG_DOABC, body)
+
+    def addShowFrameTag(self):
+        self.writeTag(self.TAG_SHOW_FRAME, '')
+
+    def addEndTag(self):
+        self.file.write('\0\0')
+
+    def writeTag(self, tagType, body):
+        #print 'tag %d at %d length %s' % (tagType, self.file.tell(), len(body))
+        self.writeTagHeader(tagType, len(body))
+        self.file.write(body)
+        
+    def writeTagHeader(self, tagType, tagLength):
+        assert (tagType & 0x3FF) == tagType
+        if tagLength >= 0x3F:
+            self.writeUI16((tagType << 6) | 0x3F)
+            self.writeSI32(tagLength)
+        else:
+            self.writeUI16((tagType << 6) | tagLength)
+        
+    def updateSize(self):
+        size = self.file.tell()
+        self.file.seek(4, 0)
+        self.writeSI32(size)
+        self.file.seek(0, 2)
+
+    def writeUI16(self, value):
+        self.file.write(struct.pack('<H', value))
+
+    def writeSI32(self, value):
+        self.file.write(struct.pack('<i', value))
+
+
+def parseParameters():
+    usage = 'usage: %prog abcFile1 [abcFile2 ...] [-o outputSWFFile]'
+    parser = OptionParser(usage=usage)
+    parser.add_option('-o', dest='output',
+                      help='Name of the output SWF file')
+    (options, abcFiles) = parser.parse_args()
+
+    if not abcFiles:
+        print 'ABC filenames required'
+        sys.exit(1)
+    
+    if options.output:
+        SWF = options.output
+    else:
+        SWF = os.path.splitext(abcFiles[-1])[0] + '.swf'
+    
+    return (abcFiles, SWF)
+
+def main():
+    abcfiles, swfFileName = parseParameters()
+    swf = SWFFile(swfFileName)
+    for abc in abcfiles:
+        swf.addABCBlock(open(abc).read())
+    swf.finalize()
+
+if __name__ == '__main__':
+    main()
diff --git a/tools/pygil b/tools/pygil
index c6c0cd5..02e3662 100755
--- a/tools/pygil
+++ b/tools/pygil
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python2
 #This greps the source for SET_NAMESPACE, REGISTER_CLASS_NAME2,
 #sinit definition and the following ->set{Getter,Setter,Method}ByQName calls
 
@@ -13,9 +13,10 @@ import pickle
 
 #These regexp are used for finding important pieces in the source
 sinit = re.compile('.*void\s*(\w*)::sinit\(.*')
-rconstructor = re.compile('[^/]*->setConstructor\(NULL|Class<IFunction>::getFunction\([^)]*\)\).*')
+rconstructor = re.compile('[^/]*ASFUNCTIONBODY\([^,]*, *\_constructor\)')
 #looks like builtin->registerBuiltin("Capabilities","flash.system",Class<Capabilities>::getRef());
 rclass          = re.compile('.*builtin->registerBuiltin\( *"([^"]*)", *"([^"]*)", *Class<([^>]*)>::getRef\(\)\)')
+rtemplateclass  = re.compile('.*builtin->registerBuiltin\( *"([^"]*)", *"([^"]*)", *_MR\(Template<([^>]*)>::getTemplate\(\)\)\)')
 rinterfaceclass = re.compile('.*builtin->registerBuiltin\( *"([^"]*)", *"([^"]*)", *InterfaceClass<([^>]*)>::getRef\(\)\)')
 #looks like builtin->registerBuiltin("Socket","flash.net",Class<ASObject>::getStubClass(QName("Socket","flash.net")));
 rstupclass = re.compile('.*builtin->registerBuiltin\( *"([^"]*)", *"([^"]*)", *Class<ASObject>::getStubClass\(QName.*')
@@ -27,7 +28,8 @@ rget2 = re.compile('.*REGISTER_GETTER\([^,]*, *(.*)\)')
 rset2 = re.compile('.*REGISTER_SETTER\([^,]*, *(.*)\)')
 rgetset2 = re.compile('.*REGISTER_GETTER_SETTER\([^,]*, *(.*)\)')
 #Constant names do not contain lower-case letters
-rconst = re.compile('[^/]*->setVariableByQName\("([A-Z_]*)",.*_TRAIT');
+rconst = re.compile('[^/]*->setVariableByQName\("([A-Z_0-9]*)",.*_TRAIT');
+rcomment = re.compile('[ \t]*/')
 
 def getFullname(cls,name):
 	if cls != "":
@@ -54,10 +56,15 @@ curClass = ""
 f = open('../src/scripting/abc.cpp','r')
 for line in f.read().replace("\n","").replace("\t"," ").split(";"):
 	m = rclass.match(line)
-        if m:
+	if m:
 		fullname = getFullname(m.group(2),m.group(1))
 		internalToExternal[m.group(3)] = fullname
 		classes.add(fullname)
+	m = rtemplateclass.match(line)
+	if m:
+		fullname = getFullname("",m.group(1))
+		internalToExternal[m.group(3)] = fullname
+		classes.add(fullname)
 	m = rinterfaceclass.match(line)
 	if m:
 		fullname = getFullname(m.group(2),m.group(1))
@@ -81,7 +88,14 @@ p1 = Popen(["find", "..", "-name",'*.cpp'], stdout=PIPE)
 p2 = Popen(["xargs","cat"], stdin=p1.stdout, stdout=PIPE);
 p1.stdout.close() 
 
-for line in p2.communicate()[0].split(";"):
+ptmp =""
+for line in p2.communicate()[0].split("\n"):
+	m = rcomment.match(line)
+	if m:
+		continue
+	ptmp = ptmp + line
+	
+for line in ptmp.split(";"):
 	line = line.replace("\n","").rstrip().rstrip();
 	m = sinit.match(line)
 	if m:

-- 
Alioth's hooks/post-receive on /srv/git.debian.org/git/pkg-flash/lightspark.git



More information about the pkg-flash-devel mailing list