[Swfdec-commits] 15 commits - doc/swfdec.types swfdec/Makefile.am swfdec/swfdec_amf.c swfdec/swfdec_as_array.c swfdec/swfdec_as_array.h swfdec/swfdec_as_boolean.c swfdec/swfdec_as_boolean.h swfdec/swfdec_as_context.c swfdec/swfdec_as_context.h swfdec/swfdec_as_date.c swfdec/swfdec_as_date.h swfdec/swfdec_as_frame.c swfdec/swfdec_as_gcable.c swfdec/swfdec_as_gcable.h swfdec/swfdec_as_internal.h swfdec/swfdec_as_interpret.c swfdec/swfdec_as_math.c swfdec/swfdec_as_native_function.c swfdec/swfdec_as_number.c swfdec/swfdec_as_number.h swfdec/swfdec_as_object.c swfdec/swfdec_as_object.h swfdec/swfdec_as_relay.c swfdec/swfdec_as_relay.h swfdec/swfdec_as_string.c swfdec/swfdec_as_string.h swfdec/swfdec_as_strings.c swfdec/swfdec_as_string_value.c swfdec/swfdec_as_string_value.h swfdec/swfdec_as_types.c swfdec/swfdec_as_types.h swfdec/swfdec_bitmap_data.c swfdec/swfdec_blur_filter_as.c swfdec/swfdec_color_as.c swfdec/swfdec_color_matrix_filter_as.c swfdec/swfdec_color_transform_as.c swfdec/swfdec_gc_object.c swfdec/swfdec_key_as.c swfdec/swfdec_load_object_as.c swfdec/swfdec_mouse_as.c swfdec/swfdec_movie_asprops.c swfdec/swfdec_movie_clip_loader.c swfdec/swfdec_net_connection.c swfdec/swfdec_net_stream.c swfdec/swfdec_player_as.c swfdec/swfdec_resource.c swfdec/swfdec_selection.c swfdec/swfdec_sound_object.c swfdec/swfdec_sprite_movie_as.c swfdec/swfdec_sprite_movie.c swfdec/swfdec_stage_as.c swfdec/swfdec_style_sheet.c swfdec/swfdec_system_as.c swfdec/swfdec_text_field_movie_as.c swfdec/swfdec_text_field_movie.c swfdec/swfdec_text_field_movie_html.c swfdec/swfdec_text_format.c swfdec/swfdec_transform_as.c swfdec/swfdec_video_movie.c swfdec/swfdec_xml.c swfdec/swfdec_xml_node.c swfdec/swfdec_xml_node.h test/swfdec_test_buffer.c test/swfdec_test.c test/swfdec_test_function.c test/swfdec_test_http_request.c test/swfdec_test_http_server.c test/swfdec_test_socket.c test/swfdec_test_test.c test/trace vivified/core

Benjamin Otte company at kemper.freedesktop.org
Tue Oct 21 04:35:44 PDT 2008


 doc/swfdec.types                         |    1 
 swfdec/Makefile.am                       |   11 
 swfdec/swfdec_amf.c                      |   22 
 swfdec/swfdec_as_array.c                 |  271 ++++-------
 swfdec/swfdec_as_array.h                 |   39 -
 swfdec/swfdec_as_boolean.c               |   31 -
 swfdec/swfdec_as_boolean.h               |    7 
 swfdec/swfdec_as_context.c               |  128 ++---
 swfdec/swfdec_as_context.h               |    4 
 swfdec/swfdec_as_date.c                  |   51 --
 swfdec/swfdec_as_date.h                  |   13 
 swfdec/swfdec_as_frame.c                 |    2 
 swfdec/swfdec_as_gcable.c                |  108 ++++
 swfdec/swfdec_as_gcable.h                |   59 ++
 swfdec/swfdec_as_internal.h              |   18 
 swfdec/swfdec_as_interpret.c             |   95 ++--
 swfdec/swfdec_as_math.c                  |   36 -
 swfdec/swfdec_as_native_function.c       |   10 
 swfdec/swfdec_as_number.c                |   19 
 swfdec/swfdec_as_number.h                |    7 
 swfdec/swfdec_as_object.c                |  149 +++++-
 swfdec/swfdec_as_object.h                |    8 
 swfdec/swfdec_as_relay.c                 |  122 +++++
 swfdec/swfdec_as_relay.h                 |   59 ++
 swfdec/swfdec_as_string.c                |  165 +++----
 swfdec/swfdec_as_string.h                |    7 
 swfdec/swfdec_as_string_value.c          |  727 +++++++++++++++++++++++++++++++
 swfdec/swfdec_as_string_value.h          |   37 +
 swfdec/swfdec_as_strings.c               |   12 
 swfdec/swfdec_as_types.c                 |   71 +--
 swfdec/swfdec_as_types.h                 |   48 +-
 swfdec/swfdec_bitmap_data.c              |   20 
 swfdec/swfdec_blur_filter_as.c           |    6 
 swfdec/swfdec_color_as.c                 |    6 
 swfdec/swfdec_color_matrix_filter_as.c   |    6 
 swfdec/swfdec_color_transform_as.c       |   18 
 swfdec/swfdec_gc_object.c                |    2 
 swfdec/swfdec_key_as.c                   |    4 
 swfdec/swfdec_load_object_as.c           |   12 
 swfdec/swfdec_mouse_as.c                 |    4 
 swfdec/swfdec_movie_asprops.c            |   24 -
 swfdec/swfdec_movie_clip_loader.c        |   10 
 swfdec/swfdec_net_connection.c           |    2 
 swfdec/swfdec_net_stream.c               |   14 
 swfdec/swfdec_player_as.c                |    4 
 swfdec/swfdec_resource.c                 |   12 
 swfdec/swfdec_selection.c                |   12 
 swfdec/swfdec_sound_object.c             |   14 
 swfdec/swfdec_sprite_movie.c             |    7 
 swfdec/swfdec_sprite_movie_as.c          |   36 -
 swfdec/swfdec_stage_as.c                 |    8 
 swfdec/swfdec_style_sheet.c              |    2 
 swfdec/swfdec_system_as.c                |    8 
 swfdec/swfdec_text_field_movie.c         |    7 
 swfdec/swfdec_text_field_movie_as.c      |   30 -
 swfdec/swfdec_text_field_movie_html.c    |    8 
 swfdec/swfdec_text_format.c              |   28 -
 swfdec/swfdec_transform_as.c             |   14 
 swfdec/swfdec_video_movie.c              |    8 
 swfdec/swfdec_xml.c                      |    2 
 swfdec/swfdec_xml_node.c                 |    8 
 swfdec/swfdec_xml_node.h                 |    4 
 test/swfdec_test.c                       |    4 
 test/swfdec_test_buffer.c                |    4 
 test/swfdec_test_function.c              |    2 
 test/swfdec_test_http_request.c          |    2 
 test/swfdec_test_http_server.c           |    2 
 test/swfdec_test_socket.c                |    2 
 test/swfdec_test_test.c                  |    2 
 test/trace/Makefile.am                   |   18 
 test/trace/constructor-relay-5.swf       |binary
 test/trace/constructor-relay-5.swf.trace |   20 
 test/trace/constructor-relay-6.swf       |binary
 test/trace/constructor-relay-6.swf.trace |   20 
 test/trace/constructor-relay-7.swf       |binary
 test/trace/constructor-relay-7.swf.trace |   20 
 test/trace/constructor-relay-8.swf       |binary
 test/trace/constructor-relay-8.swf.trace |   20 
 test/trace/constructor-relay.as          |   46 +
 test/trace/equality-nan-5.swf            |binary
 test/trace/equality-nan-5.swf.trace      |   90 +++
 test/trace/equality-nan-6.swf            |binary
 test/trace/equality-nan-6.swf.trace      |   90 +++
 test/trace/equality-nan-7.swf            |binary
 test/trace/equality-nan-7.swf.trace      |   90 +++
 test/trace/equality-nan-8.swf            |binary
 test/trace/equality-nan-8.swf.trace      |   90 +++
 test/trace/equality-nan.as               |   14 
 vivified/core/vivi_function.c            |    8 
 89 files changed, 2431 insertions(+), 790 deletions(-)

New commits:
commit e0054632190f18d024c6cb440ec032e77f4fc75c
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Oct 21 13:32:50 2008 +0200

    make String a relay

diff --git a/swfdec/swfdec_as_string.c b/swfdec/swfdec_as_string.c
index e0465d5..9c3a795 100644
--- a/swfdec/swfdec_as_string.c
+++ b/swfdec/swfdec_as_string.c
@@ -32,7 +32,7 @@
 #include "swfdec_as_strings.h"
 #include "swfdec_debug.h"
 
-G_DEFINE_TYPE (SwfdecAsString, swfdec_as_string, SWFDEC_TYPE_AS_OBJECT)
+G_DEFINE_TYPE (SwfdecAsString, swfdec_as_string, SWFDEC_TYPE_AS_RELAY)
 
 static void
 swfdec_as_string_do_mark (SwfdecGcObject *object)
@@ -44,23 +44,12 @@ swfdec_as_string_do_mark (SwfdecGcObject *object)
   SWFDEC_GC_OBJECT_CLASS (swfdec_as_string_parent_class)->mark (object);
 }
 
-static char *
-swfdec_as_string_debug (SwfdecAsObject *object)
-{
-  SwfdecAsString *string = SWFDEC_AS_STRING (object);
-
-  return g_strdup (string->string);
-}
-
 static void
 swfdec_as_string_class_init (SwfdecAsStringClass *klass)
 {
   SwfdecGcObjectClass *gc_class = SWFDEC_GC_OBJECT_CLASS (klass);
-  SwfdecAsObjectClass *asobject_class = SWFDEC_AS_OBJECT_CLASS (klass);
 
   gc_class->mark = swfdec_as_string_do_mark;
-
-  asobject_class->debug = swfdec_as_string_debug;
 }
 
 static void
@@ -71,23 +60,17 @@ swfdec_as_string_init (SwfdecAsString *string)
 
 /*** AS CODE ***/
 
-static const char *
-swfdec_as_string_object_to_string (SwfdecAsContext *context,
-    SwfdecAsObject *object)
-{
-  SwfdecAsValue val;
-
-  g_return_val_if_fail (object == NULL || SWFDEC_IS_AS_OBJECT (object),
-      SWFDEC_AS_STR_EMPTY);
-
-  if (object == NULL) {
-    SWFDEC_AS_VALUE_SET_UNDEFINED (&val);
-  } else {
-    SWFDEC_AS_VALUE_SET_OBJECT (&val, object);
-  }
-
-  return swfdec_as_value_to_string (context, &val);
-}
+#define SWFDEC_AS_STRING_CHECK(result,...) G_STMT_START {\
+  if (object) {\
+    SwfdecAsValue _tmp; \
+    SWFDEC_AS_VALUE_SET_OBJECT (&_tmp, object); \
+    *(result) = swfdec_as_value_to_string (cx, &_tmp);\
+  } else {\
+    *(result) = SWFDEC_AS_STR_undefined; \
+  }\
+  if (!swfdec_as_native_function_check (cx, object, 0, NULL, argc, argv, __VA_ARGS__)) \
+    return; \
+}G_STMT_END
 
 static const char *
 swfdec_as_str_nth_char (const char *s, guint n)
@@ -102,14 +85,12 @@ void
 swfdec_as_string_lastIndexOf (SwfdecAsContext *cx, SwfdecAsObject *object,
     guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
 {
-  const char *string = swfdec_as_string_object_to_string (cx, object);
+  const char *string;
   gsize len;
   const char *s;
 
-  if (argc < 1)
-    return;
+  SWFDEC_AS_STRING_CHECK (&string, "s", &s);
 
-  s = swfdec_as_value_to_string (cx, &argv[0]);
   if (argc == 2) {
     int offset = swfdec_as_value_to_integer (cx, &argv[1]);
     if (offset < 0) {
@@ -133,14 +114,12 @@ void
 swfdec_as_string_indexOf (SwfdecAsContext *cx, SwfdecAsObject *object,
     guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
 {
-  const char *string = swfdec_as_string_object_to_string (cx, object);
+  const char *string;
   int offset=0, len, i=-1;
   const char *s, *t = NULL;
 
-  if (argc < 1)
-    return;
+  SWFDEC_AS_STRING_CHECK (&string, "s", &s);
 
-  s = swfdec_as_value_to_string (cx, &argv[0]);
   if (argc == 2)
     offset = swfdec_as_value_to_integer (cx, &argv[1]);
   if (offset < 0)
@@ -161,14 +140,12 @@ void
 swfdec_as_string_charAt (SwfdecAsContext *cx, SwfdecAsObject *object,
     guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
 {
-  const char *string = swfdec_as_string_object_to_string (cx, object);
+  const char *string;
   int i;
   const char *s, *t;
 
-  if (argc < 1)
-    return;
+  SWFDEC_AS_STRING_CHECK (&string, "i", &i);
 
-  i = swfdec_as_value_to_integer (cx, &argv[0]);
   if (i < 0) {
     SWFDEC_AS_VALUE_SET_STRING (ret, SWFDEC_AS_STR_EMPTY);
     return;
@@ -188,15 +165,13 @@ void
 swfdec_as_string_charCodeAt (SwfdecAsContext *cx, SwfdecAsObject *object,
     guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
 {
-  const char *string = swfdec_as_string_object_to_string (cx, object);
+  const char *string;
   int i;
   const char *s;
   gunichar c;
 
-  if (argc < 1)
-    return;
+  SWFDEC_AS_STRING_CHECK (&string, "i", &i);
 
-  i = swfdec_as_value_to_integer (cx, &argv[0]);
   if (i < 0) {
     swfdec_as_value_set_number (cx, ret, NAN);
     return;
@@ -242,8 +217,7 @@ swfdec_as_string_fromCharCode_5 (SwfdecAsContext *cx, SwfdecAsObject *object,
   }
 
   if (s) {
-    SWFDEC_AS_VALUE_SET_STRING (ret, swfdec_as_context_get_string (cx, s));
-    g_free (s);
+    SWFDEC_AS_VALUE_SET_STRING (ret, swfdec_as_context_give_string (cx, s));
   } else {
     SWFDEC_ERROR ("%s", error->message);
     g_error_free (error);
@@ -295,7 +269,7 @@ swfdec_as_string_fromCharCode (SwfdecAsContext *cx, SwfdecAsObject *object,
   }
 }
 
-SWFDEC_AS_CONSTRUCTOR (251, 0, swfdec_as_string_construct, swfdec_as_string_get_type)
+SWFDEC_AS_NATIVE (251, 0, swfdec_as_string_construct)
 void
 swfdec_as_string_construct (SwfdecAsContext *cx, SwfdecAsObject *object,
     guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
@@ -309,13 +283,16 @@ swfdec_as_string_construct (SwfdecAsContext *cx, SwfdecAsObject *object,
   }
 
   if (swfdec_as_context_is_constructing (cx)) {
-    SwfdecAsString *string = SWFDEC_AS_STRING (object);
+    SwfdecAsString *string = g_object_new (SWFDEC_TYPE_AS_STRING, "context", cx, NULL);
     SwfdecAsValue val;
 
     string->string = s;
+    swfdec_as_object_set_relay (object, SWFDEC_AS_RELAY (string));
+
     swfdec_as_value_set_integer (cx, &val, g_utf8_strlen (string->string, -1));
     swfdec_as_object_set_variable_and_flags (object, SWFDEC_AS_STR_length,
 	&val, SWFDEC_AS_VARIABLE_HIDDEN | SWFDEC_AS_VARIABLE_PERMANENT);
+
     SWFDEC_AS_VALUE_SET_OBJECT (ret, object);
   } else {
     SWFDEC_AS_VALUE_SET_STRING (ret, s);
@@ -327,10 +304,11 @@ void
 swfdec_as_string_toString (SwfdecAsContext *cx, SwfdecAsObject *object,
     guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
 {
-  if (!SWFDEC_IS_AS_STRING (object))
-    return;
+  SwfdecAsString *string;
+
+  SWFDEC_AS_CHECK (SWFDEC_TYPE_AS_STRING, &string, "");
 
-  SWFDEC_AS_VALUE_SET_STRING (ret, SWFDEC_AS_STRING (object)->string);
+  SWFDEC_AS_VALUE_SET_STRING (ret, string->string);
 }
 
 SWFDEC_AS_NATIVE (251, 1, swfdec_as_string_valueOf)
@@ -338,18 +316,11 @@ void
 swfdec_as_string_valueOf (SwfdecAsContext *cx, SwfdecAsObject *object,
     guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
 {
-  if (object == NULL)
-    return;
+  const char *string;
 
-  if (SWFDEC_IS_AS_STRING (object)) {
-    SWFDEC_AS_VALUE_SET_STRING (ret, SWFDEC_AS_STRING (object)->string);
-  } else {
-    SwfdecAsValue val;
-
-    SWFDEC_AS_VALUE_SET_OBJECT (&val, object);
-    SWFDEC_AS_VALUE_SET_STRING (ret, swfdec_as_value_to_string (cx, &val));
-  }
+  SWFDEC_AS_STRING_CHECK (&string, "");
 
+  SWFDEC_AS_VALUE_SET_STRING (ret, string);
 }
 
 static void
@@ -361,7 +332,8 @@ swfdec_as_string_split_5 (SwfdecAsContext *cx, SwfdecAsObject *object,
   const char *str, *end, *delim;
   int count;
 
-  str = swfdec_as_string_object_to_string (cx, object);
+  SWFDEC_AS_STRING_CHECK (&str, "");
+
   arr = swfdec_as_array_new (cx);
   SWFDEC_AS_VALUE_SET_OBJECT (ret, SWFDEC_AS_OBJECT (arr));
   /* hi, i'm the special case */
@@ -412,7 +384,8 @@ swfdec_as_string_split_6 (SwfdecAsContext *cx, SwfdecAsObject *object,
   int count;
   guint len;
 
-  str = swfdec_as_string_object_to_string (cx, object);
+  SWFDEC_AS_STRING_CHECK (&str, "");
+
   arr = swfdec_as_array_new (cx);
   SWFDEC_AS_VALUE_SET_OBJECT (ret, SWFDEC_AS_OBJECT (arr));
   /* hi, i'm the special case */
@@ -477,13 +450,10 @@ swfdec_as_string_slice (SwfdecAsContext *cx, SwfdecAsObject *object,
   int start, end, length;
   const char *str;
 
-  if (argc == 0)
-    return;
+  SWFDEC_AS_STRING_CHECK (&str, "i", &start);
 
-  str = swfdec_as_string_object_to_string (cx, object);
   length = g_utf8_strlen (str, -1);
 
-  start = swfdec_as_value_to_integer (cx, &argv[0]);
   if (start < 0)
     start += length;
   start = CLAMP (start, 0, length);
@@ -508,8 +478,11 @@ swfdec_as_string_concat (SwfdecAsContext *cx, SwfdecAsObject *object,
 {
   guint i;
   GString *string;
+  const char *s;
 
-  string = g_string_new (swfdec_as_string_object_to_string (cx, object));
+  SWFDEC_AS_STRING_CHECK (&s, "");
+
+  string = g_string_new (s);
 
   for (i = 0; i < argc; i++) {
     string = g_string_append (string, swfdec_as_value_to_string (cx, &argv[i]));
@@ -535,13 +508,11 @@ void
 swfdec_as_string_substr (SwfdecAsContext *cx, SwfdecAsObject *object,
     guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
 {
-  const char *string = swfdec_as_string_object_to_string (cx, object);
+  const char *string;
   int from, to, len;
 
-  if (argc < 1)
-    return;
+  SWFDEC_AS_STRING_CHECK (&string, "i", &from);
 
-  from = swfdec_as_value_to_integer (cx, &argv[0]);
   len = g_utf8_strlen (string, -1);
   
   if (argc > 1 && !SWFDEC_AS_VALUE_IS_UNDEFINED (&argv[1])) {
@@ -572,14 +543,12 @@ void
 swfdec_as_string_substring (SwfdecAsContext *cx, SwfdecAsObject *object,
     guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
 {
-  const char *string = swfdec_as_string_object_to_string (cx, object);
+  const char *string;
   int from, to, len;
 
-  if (argc < 1)
-    return;
+  SWFDEC_AS_STRING_CHECK (&string, "i", &from);
 
   len = g_utf8_strlen (string, -1);
-  from = swfdec_as_value_to_integer (cx, &argv[0]);
   if (argc > 1 && !SWFDEC_AS_VALUE_IS_UNDEFINED (&argv[1])) {
     to = swfdec_as_value_to_integer (cx, &argv[1]);
   } else {
@@ -604,9 +573,11 @@ void
 swfdec_as_string_toLowerCase (SwfdecAsContext *cx, SwfdecAsObject *object,
     guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
 {
-  const char *string = swfdec_as_string_object_to_string (cx, object);
+  const char *string;
   char *s;
 
+  SWFDEC_AS_STRING_CHECK (&string, "");
+
   s = g_utf8_strdown (string, -1);
   SWFDEC_AS_VALUE_SET_STRING (ret, swfdec_as_context_give_string (cx, s));
 }
@@ -616,9 +587,11 @@ void
 swfdec_as_string_toUpperCase (SwfdecAsContext *cx, SwfdecAsObject *object,
     guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
 {
-  const char *string = swfdec_as_string_object_to_string (cx, object);
+  const char *string;
   char *s;
 
+  SWFDEC_AS_STRING_CHECK (&string, "");
+
   s = g_utf8_strup (string, -1);
   SWFDEC_AS_VALUE_SET_STRING (ret, swfdec_as_context_give_string (cx, s));
 }
@@ -629,9 +602,11 @@ void
 swfdec_as_string_old_toLowerCase (SwfdecAsContext *cx, SwfdecAsObject *object,
     guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
 {
-  const char *string = swfdec_as_string_object_to_string (cx, object);
+  const char *string;
   char *s;
 
+  SWFDEC_AS_STRING_CHECK (&string, "");
+
   s = g_ascii_strdown (string, -1);
   SWFDEC_AS_VALUE_SET_STRING (ret, swfdec_as_context_give_string (cx, s));
 }
@@ -642,9 +617,11 @@ void
 swfdec_as_string_old_toUpperCase (SwfdecAsContext *cx, SwfdecAsObject *object,
     guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
 {
-  const char *string = swfdec_as_string_object_to_string (cx, object);
+  const char *string;
   char *s;
 
+  SWFDEC_AS_STRING_CHECK (&string, "");
+
   s = g_ascii_strup (string, -1);
   SWFDEC_AS_VALUE_SET_STRING (ret, swfdec_as_context_give_string (cx, s));
 }
diff --git a/swfdec/swfdec_as_string.h b/swfdec/swfdec_as_string.h
index 915ced0..f9a2f0e 100644
--- a/swfdec/swfdec_as_string.h
+++ b/swfdec/swfdec_as_string.h
@@ -20,8 +20,7 @@
 #ifndef _SWFDEC_AS_STRING_H_
 #define _SWFDEC_AS_STRING_H_
 
-#include <swfdec/swfdec_as_object.h>
-#include <swfdec/swfdec_as_types.h>
+#include <swfdec/swfdec_as_relay.h>
 
 G_BEGIN_DECLS
 
@@ -36,13 +35,13 @@ typedef struct _SwfdecAsStringClass SwfdecAsStringClass;
 #define SWFDEC_AS_STRING_GET_CLASS(obj)          (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFDEC_TYPE_AS_STRING, SwfdecAsStringClass))
 
 struct _SwfdecAsString {
-  SwfdecAsObject	object;
+  SwfdecAsRelay		relay;
 
   const char *		string;		/* string represented by this string object */
 };
 
 struct _SwfdecAsStringClass {
-  SwfdecAsObjectClass	object_class;
+  SwfdecAsRelayClass	relay_class;
 };
 
 GType		swfdec_as_string_get_type	(void);
diff --git a/swfdec/swfdec_as_types.c b/swfdec/swfdec_as_types.c
index 036b919..d99eaf2 100644
--- a/swfdec/swfdec_as_types.c
+++ b/swfdec/swfdec_as_types.c
@@ -412,8 +412,8 @@ swfdec_as_value_to_string (SwfdecAsContext *context, const SwfdecAsValue *value)
 	    char *str = swfdec_movie_get_path (SWFDEC_MOVIE (object), TRUE);
 	    return swfdec_as_context_give_string (context, str);
 	  }
-	} else if (SWFDEC_IS_AS_STRING (object)) {
-	  return SWFDEC_AS_STRING (object)->string;
+	} else if (SWFDEC_IS_AS_STRING (object->relay)) {
+	  return SWFDEC_AS_STRING (object->relay)->string;
 	} else {
 	  SwfdecAsValue ret;
 	  swfdec_as_object_call (object, SWFDEC_AS_STR_toString, 0, NULL, &ret);
commit 186787deffdc53ad360593209aacd542cb1dd3cf
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Oct 21 13:32:22 2008 +0200

    no need for workarounds for string objects anymore
    
    swfdec_as_value_to_string() does the right thing

diff --git a/swfdec/swfdec_as_array.c b/swfdec/swfdec_as_array.c
index 060e4d3..0b38a86 100644
--- a/swfdec/swfdec_as_array.c
+++ b/swfdec/swfdec_as_array.c
@@ -1241,13 +1241,7 @@ swfdec_as_array_sortOn (SwfdecAsContext *cx, SwfdecAsObject *object,
     fields = g_new (const char *, num_fields + 1);
     for (i = 0; i < num_fields; i++) {
       swfdec_as_array_get_value (array, i, &val);
-      if (SWFDEC_AS_VALUE_IS_OBJECT (&val) &&
-	  SWFDEC_IS_AS_STRING (SWFDEC_AS_VALUE_GET_OBJECT (&val))) {
-	fields[i] =
-	  SWFDEC_AS_STRING (SWFDEC_AS_VALUE_GET_OBJECT (&val))->string;
-      } else {
-	fields[i] = swfdec_as_value_to_string (cx, &val);
-      }
+      fields[i] = swfdec_as_value_to_string (cx, &val);
     }
 
     fields[i] = NULL;
commit ca76fa38864b4132428e391998339cf9540409be
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Oct 21 12:48:52 2008 +0200

    make number a relay

diff --git a/swfdec/swfdec_as_number.c b/swfdec/swfdec_as_number.c
index d6926c2..240a46c 100644
--- a/swfdec/swfdec_as_number.c
+++ b/swfdec/swfdec_as_number.c
@@ -31,7 +31,7 @@
 #include "swfdec_as_strings.h"
 #include "swfdec_debug.h"
 
-G_DEFINE_TYPE (SwfdecAsNumber, swfdec_as_number, SWFDEC_TYPE_AS_OBJECT)
+G_DEFINE_TYPE (SwfdecAsNumber, swfdec_as_number, SWFDEC_TYPE_AS_RELAY)
 
 static void
 swfdec_as_number_class_init (SwfdecAsNumberClass *klass)
@@ -45,7 +45,7 @@ swfdec_as_number_init (SwfdecAsNumber *number)
 
 /*** AS CODE ***/
 
-SWFDEC_AS_CONSTRUCTOR (106, 2, swfdec_as_number_construct, swfdec_as_number_get_type)
+SWFDEC_AS_NATIVE (106, 2, swfdec_as_number_construct)
 void
 swfdec_as_number_construct (SwfdecAsContext *cx, SwfdecAsObject *object,
     guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
@@ -53,14 +53,15 @@ swfdec_as_number_construct (SwfdecAsContext *cx, SwfdecAsObject *object,
   double d;
 
   if (argc > 0) {
-    d = swfdec_as_value_to_number (swfdec_gc_object_get_context (object), &argv[0]);
+    d = swfdec_as_value_to_number (cx, &argv[0]);
   } else {
     d = NAN;
   }
 
   if (swfdec_as_context_is_constructing (cx)) {
-    SwfdecAsNumber *num = SWFDEC_AS_NUMBER (object);
+    SwfdecAsNumber *num = g_object_new (SWFDEC_TYPE_AS_NUMBER, "context", cx, NULL);
     num->number = d;
+    swfdec_as_object_set_relay (object, SWFDEC_AS_RELAY (num));
     SWFDEC_AS_VALUE_SET_OBJECT (ret, object);
   } else {
     swfdec_as_value_set_number (cx, ret, d);
@@ -140,10 +141,8 @@ swfdec_as_number_valueOf (SwfdecAsContext *cx, SwfdecAsObject *object,
 {
   SwfdecAsNumber *num;
 
-  if (!SWFDEC_IS_AS_NUMBER (object))
-    return;
+  SWFDEC_AS_CHECK (SWFDEC_TYPE_AS_NUMBER, &num, "");
 
-  num = SWFDEC_AS_NUMBER (object);
   swfdec_as_value_set_number (cx, ret, num->number);
 }
 
diff --git a/swfdec/swfdec_as_number.h b/swfdec/swfdec_as_number.h
index eeb1c1c..9290715 100644
--- a/swfdec/swfdec_as_number.h
+++ b/swfdec/swfdec_as_number.h
@@ -20,8 +20,7 @@
 #ifndef _SWFDEC_AS_NUMBER_H_
 #define _SWFDEC_AS_NUMBER_H_
 
-#include <swfdec/swfdec_as_object.h>
-#include <swfdec/swfdec_as_types.h>
+#include <swfdec/swfdec_as_relay.h>
 
 G_BEGIN_DECLS
 
@@ -36,13 +35,13 @@ typedef struct _SwfdecAsNumberClass SwfdecAsNumberClass;
 #define SWFDEC_AS_NUMBER_GET_CLASS(obj)          (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFDEC_TYPE_AS_NUMBER, SwfdecAsNumberClass))
 
 struct _SwfdecAsNumber {
-  SwfdecAsObject	object;
+  SwfdecAsRelay		relay;
 
   double		number;		/* number represented by this number object */
 };
 
 struct _SwfdecAsNumberClass {
-  SwfdecAsObjectClass	object_class;
+  SwfdecAsRelayClass	relay_class;
 };
 
 GType		swfdec_as_number_get_type	(void);
commit 16f1daeef19b30589882f79f7ad581b773e0018f
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Oct 21 12:26:17 2008 +0200

    make booleans relayed

diff --git a/swfdec/swfdec_as_boolean.c b/swfdec/swfdec_as_boolean.c
index 65a1ec7..fda7519 100644
--- a/swfdec/swfdec_as_boolean.c
+++ b/swfdec/swfdec_as_boolean.c
@@ -28,9 +28,10 @@
 #include "swfdec_as_internal.h"
 #include "swfdec_as_native_function.h"
 #include "swfdec_as_strings.h"
+#include "swfdec_as_types.h"
 #include "swfdec_debug.h"
 
-G_DEFINE_TYPE (SwfdecAsBoolean, swfdec_as_boolean, SWFDEC_TYPE_AS_OBJECT)
+G_DEFINE_TYPE (SwfdecAsBoolean, swfdec_as_boolean, SWFDEC_TYPE_AS_RELAY)
 
 static void
 swfdec_as_boolean_class_init (SwfdecAsBooleanClass *klass)
@@ -44,25 +45,19 @@ swfdec_as_boolean_init (SwfdecAsBoolean *boolean)
 
 /*** AS CODE ***/
 
-SWFDEC_AS_CONSTRUCTOR (107, 2, swfdec_as_boolean_construct, swfdec_as_boolean_get_type)
+SWFDEC_AS_NATIVE (107, 2, swfdec_as_boolean_construct)
 void
 swfdec_as_boolean_construct (SwfdecAsContext *cx, SwfdecAsObject *object,
     guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
 {
-  gboolean b;
-
-  if (argc > 0) {
-    b = swfdec_as_value_to_boolean (swfdec_gc_object_get_context (object), &argv[0]);
-  } else {
-    if (!swfdec_as_context_is_constructing (cx))
-      return;
-    b = FALSE;
-  }
-
   if (swfdec_as_context_is_constructing (cx)) {
-    SWFDEC_AS_BOOLEAN (object)->boolean = b;
+    SwfdecAsBoolean *b = g_object_new (SWFDEC_TYPE_AS_BOOLEAN, "context", cx, NULL);
+    b->boolean = argc > 0 ? swfdec_as_value_to_boolean (cx, &argv[0]) : FALSE;
+    swfdec_as_object_set_relay (object, SWFDEC_AS_RELAY (b));
     SWFDEC_AS_VALUE_SET_OBJECT (ret, object);
   } else {
+    gboolean b;
+    SWFDEC_AS_CHECK (0, NULL, "b", &b);
     SWFDEC_AS_VALUE_SET_BOOLEAN (ret, b);
   }
 }
@@ -74,10 +69,8 @@ swfdec_as_boolean_toString (SwfdecAsContext *cx, SwfdecAsObject *object,
 {
   SwfdecAsBoolean *b;
   
-  if (!SWFDEC_IS_AS_BOOLEAN (object))
-    return;
-  b = SWFDEC_AS_BOOLEAN (object);
-  
+  SWFDEC_AS_CHECK (SWFDEC_TYPE_AS_BOOLEAN, &b, "");
+
   SWFDEC_AS_VALUE_SET_STRING (ret, b->boolean ? SWFDEC_AS_STR_true : SWFDEC_AS_STR_false);
 }
 
@@ -88,9 +81,7 @@ swfdec_as_boolean_valueOf (SwfdecAsContext *cx, SwfdecAsObject *object,
 {
   SwfdecAsBoolean *b;
 
-  if (!SWFDEC_IS_AS_BOOLEAN (object))
-    return;
-  b = SWFDEC_AS_BOOLEAN (object);
+  SWFDEC_AS_CHECK (SWFDEC_TYPE_AS_BOOLEAN, &b, "");
   
   SWFDEC_AS_VALUE_SET_BOOLEAN (ret, b->boolean);
 }
diff --git a/swfdec/swfdec_as_boolean.h b/swfdec/swfdec_as_boolean.h
index 7206da2..2fb3c0c 100644
--- a/swfdec/swfdec_as_boolean.h
+++ b/swfdec/swfdec_as_boolean.h
@@ -20,8 +20,7 @@
 #ifndef _SWFDEC_AS_BOOLEAN_H_
 #define _SWFDEC_AS_BOOLEAN_H_
 
-#include <swfdec/swfdec_as_object.h>
-#include <swfdec/swfdec_as_types.h>
+#include <swfdec/swfdec_as_relay.h>
 
 G_BEGIN_DECLS
 
@@ -36,13 +35,13 @@ typedef struct _SwfdecAsBooleanClass SwfdecAsBooleanClass;
 #define SWFDEC_AS_BOOLEAN_GET_CLASS(obj)          (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFDEC_TYPE_AS_BOOLEAN, SwfdecAsBooleanClass))
 
 struct _SwfdecAsBoolean {
-  SwfdecAsObject	object;
+  SwfdecAsRelay		relay;
 
   gboolean		boolean;		/* boolean represented by this boolean object */
 };
 
 struct _SwfdecAsBooleanClass {
-  SwfdecAsObjectClass	object_class;
+  SwfdecAsRelayClass	relay_class;
 };
 
 GType		swfdec_as_boolean_get_type	(void);
commit b879956bcf77bb393394d55ad34cc910671457bf
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Oct 21 12:11:56 2008 +0200

    add test for constructor madness

diff --git a/test/trace/Makefile.am b/test/trace/Makefile.am
index 446538c..d9fc249 100644
--- a/test/trace/Makefile.am
+++ b/test/trace/Makefile.am
@@ -752,6 +752,15 @@ EXTRA_DIST = \
 	constructor-madness-8.swf.trace \
 	constructor-prototype.swf \
 	constructor-prototype.swf.trace \
+	constructor-relay-5.swf \
+	constructor-relay-5.swf.trace \
+	constructor-relay-6.swf \
+	constructor-relay-6.swf.trace \
+	constructor-relay-7.swf \
+	constructor-relay-7.swf.trace \
+	constructor-relay-8.swf \
+	constructor-relay-8.swf.trace \
+	constructor-relay.as \
 	context-menu.as \
 	context-menu-5.swf \
 	context-menu-5.swf.trace \
diff --git a/test/trace/constructor-relay-5.swf b/test/trace/constructor-relay-5.swf
new file mode 100644
index 0000000..18751eb
Binary files /dev/null and b/test/trace/constructor-relay-5.swf differ
diff --git a/test/trace/constructor-relay-5.swf.trace b/test/trace/constructor-relay-5.swf.trace
new file mode 100644
index 0000000..3abf595
--- /dev/null
+++ b/test/trace/constructor-relay-5.swf.trace
@@ -0,0 +1,20 @@
+undefined
+undefined
+42
+42
+undefined
+42
+undefined
+42
+undefined
+42
+undefined
+42
+undefined
+undefined
+undefined
+true
+true
+undefined
+undefined
+undefined
diff --git a/test/trace/constructor-relay-6.swf b/test/trace/constructor-relay-6.swf
new file mode 100644
index 0000000..9a55c03
Binary files /dev/null and b/test/trace/constructor-relay-6.swf differ
diff --git a/test/trace/constructor-relay-6.swf.trace b/test/trace/constructor-relay-6.swf.trace
new file mode 100644
index 0000000..ce49fa4
--- /dev/null
+++ b/test/trace/constructor-relay-6.swf.trace
@@ -0,0 +1,20 @@
+undefined
+undefined
+42
+42
+1035840244000
+42
+1035840244000
+42
+1035840244000
+42
+1035840244000
+42
+1035840244000
+1035840244000
+undefined
+true
+true
+undefined
+undefined
+undefined
diff --git a/test/trace/constructor-relay-7.swf b/test/trace/constructor-relay-7.swf
new file mode 100644
index 0000000..32e8d8f
Binary files /dev/null and b/test/trace/constructor-relay-7.swf differ
diff --git a/test/trace/constructor-relay-7.swf.trace b/test/trace/constructor-relay-7.swf.trace
new file mode 100644
index 0000000..ce49fa4
--- /dev/null
+++ b/test/trace/constructor-relay-7.swf.trace
@@ -0,0 +1,20 @@
+undefined
+undefined
+42
+42
+1035840244000
+42
+1035840244000
+42
+1035840244000
+42
+1035840244000
+42
+1035840244000
+1035840244000
+undefined
+true
+true
+undefined
+undefined
+undefined
diff --git a/test/trace/constructor-relay-8.swf b/test/trace/constructor-relay-8.swf
new file mode 100644
index 0000000..ee3474a
Binary files /dev/null and b/test/trace/constructor-relay-8.swf differ
diff --git a/test/trace/constructor-relay-8.swf.trace b/test/trace/constructor-relay-8.swf.trace
new file mode 100644
index 0000000..ce49fa4
--- /dev/null
+++ b/test/trace/constructor-relay-8.swf.trace
@@ -0,0 +1,20 @@
+undefined
+undefined
+42
+42
+1035840244000
+42
+1035840244000
+42
+1035840244000
+42
+1035840244000
+42
+1035840244000
+1035840244000
+undefined
+true
+true
+undefined
+undefined
+undefined
diff --git a/test/trace/constructor-relay.as b/test/trace/constructor-relay.as
new file mode 100644
index 0000000..4e3587b
--- /dev/null
+++ b/test/trace/constructor-relay.as
@@ -0,0 +1,46 @@
+// makeswf -v 7 -s 200x150 -r 1 -o constructor-relay.swf constructor-relay.as
+
+extends = function (child, parent) {
+  asm {
+    push "child"
+    getvariable
+    push "parent"
+    getvariable
+    extends
+  };
+};
+
+Foo = function () {
+  before = this;
+  trace (this.getTime ());
+  this.__proto__.__constructor__ = Date;
+  trace (this.getTime ());
+  this.x = 42;
+  trace (this.x);
+  for (i = 0; i < 5; i++) {
+    super ();
+    trace (this.x);
+    trace (this.getTime ());
+  }
+  this.__proto__.__constructor__ = Array;
+  trace (this.getTime ());
+  super ();
+  trace (this.getTime ());
+  after = this;
+};
+
+//extends (Foo, Date);
+Foo.prototype.getTime = Date.prototype.getTime;
+x = new Foo ();
+trace (before == after);
+trace (before == x);
+trace (before.getTime ());
+trace (after.getTime ());
+
+x = new Object ();
+x.getTime = Date.prototype.getTime;
+x.construct = Date;
+x.construct ();
+trace (x.getTime ());
+
+getURL ("fscommand:quit", "");
commit 12cc7dedc42b60a76ccdf61cac6ca566b49a2751
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Oct 21 12:11:40 2008 +0200

    add forgotten files (oops)

diff --git a/swfdec/swfdec_as_relay.c b/swfdec/swfdec_as_relay.c
new file mode 100644
index 0000000..1339275
--- /dev/null
+++ b/swfdec/swfdec_as_relay.c
@@ -0,0 +1,122 @@
+/* Swfdec
+ * Copyright (C) 2008 Benjamin Otte <otte at gnome.org>
+ *
+ * This library 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 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#include "swfdec_as_relay.h"
+#include "swfdec_as_context.h"
+#include "swfdec_as_function.h"
+
+G_DEFINE_ABSTRACT_TYPE (SwfdecAsRelay, swfdec_as_relay, SWFDEC_TYPE_GC_OBJECT)
+
+static void
+swfdec_as_relay_mark (SwfdecGcObject *object)
+{
+  SwfdecAsRelay *relay = SWFDEC_AS_RELAY (object);
+
+  if (relay->relay)
+    swfdec_gc_object_mark (relay->relay);
+}
+
+static void
+swfdec_as_relay_class_init (SwfdecAsRelayClass *klass)
+{
+  SwfdecGcObjectClass *gc_class = SWFDEC_GC_OBJECT_CLASS (klass);
+
+  gc_class->mark = swfdec_as_relay_mark;
+}
+
+static void
+swfdec_as_relay_init (SwfdecAsRelay *object)
+{
+}
+
+#if 0
+/**
+ * swfdec_as_relay_get_as_object:
+ * @object: a #SwfdecAsRelay. This function takes a gpointer argument only to
+ *          save you from having to cast it manually. For language bindings, 
+ *          please treat this argument as having the #SwfdecAsRelay type.
+ *
+ * Gets the Actionscript object associated with this object.
+ *
+ * Returns: The #SwfdecAsObject associated with this relay.
+ **/
+static SwfdecAsObject *
+swfdec_as_relay_get_as_object (gpointer object)
+{
+  SwfdecAsRelay *relay = object;
+
+  g_return_val_if_fail (SWFDEC_IS_AS_RELAY (object), NULL);
+  g_return_val_if_fail (relay->relay != NULL, NULL);
+
+  return relay->relay;
+}
+#endif
+
+/**
+ * swfdec_as_relay_call:
+ * @object: a #SwfdecAsRelay
+ * @name: garbage-collected string naming the function to call. 
+ * @argc: number of arguments to provide to function
+ * @argv: arguments or %NULL when @argc is 0
+ * @return_value: location to take the return value of the call or %NULL to 
+ *                ignore the return value.
+ *
+ * Calls the function named @name on the given object. This function is 
+ * essentially equal to the folloeing Actionscript code: 
+ * <informalexample><programlisting>
+ * @return_value = @object. at name (@argv[0], ..., @argv[argc-1]);
+ * </programlisting></informalexample>
+ *
+ * Returns: %TRUE if @object had a function with the given name, %FALSE otherwise
+ **/
+gboolean
+swfdec_as_relay_call (SwfdecAsRelay *relay, const char *name, guint argc, 
+    SwfdecAsValue *argv, SwfdecAsValue *return_value)
+{
+  SwfdecAsValue tmp;
+  SwfdecAsFunction *fun;
+
+  g_return_val_if_fail (SWFDEC_IS_AS_RELAY (relay), TRUE);
+  g_return_val_if_fail (name != NULL, TRUE);
+  g_return_val_if_fail (argc == 0 || argv != NULL, TRUE);
+  g_return_val_if_fail (swfdec_gc_object_get_context (relay)->global != NULL, TRUE); /* for SwfdecPlayer */
+
+  /* If this doesn't hold, we need to use swfdec_as_relay_get_as_object()
+   * and have that function create the relay on demand. */
+  g_assert (relay->relay);
+
+  if (return_value)
+    SWFDEC_AS_VALUE_SET_UNDEFINED (return_value);
+  swfdec_as_object_get_variable (relay->relay, name, &tmp);
+  if (!SWFDEC_AS_VALUE_IS_OBJECT (&tmp))
+    return FALSE;
+  fun = (SwfdecAsFunction *) SWFDEC_AS_VALUE_GET_OBJECT (&tmp);
+  if (!SWFDEC_IS_AS_FUNCTION (fun))
+    return FALSE;
+  swfdec_as_function_call (fun, relay->relay, argc, argv, return_value ? return_value : &tmp);
+
+  return TRUE;
+}
+
diff --git a/swfdec/swfdec_as_relay.h b/swfdec/swfdec_as_relay.h
new file mode 100644
index 0000000..6afa9c5
--- /dev/null
+++ b/swfdec/swfdec_as_relay.h
@@ -0,0 +1,59 @@
+/* Swfdec
+ * Copyright (C) 2008 Benjamin Otte <otte at gnome.org>
+ *
+ * This library 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 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+
+#ifndef _SWFDEC_AS_RELAY_H_
+#define _SWFDEC_AS_RELAY_H_
+
+#include <swfdec/swfdec_as_types.h>
+#include <swfdec/swfdec_gc_object.h>
+
+G_BEGIN_DECLS
+
+typedef struct _SwfdecAsRelayClass SwfdecAsRelayClass;
+
+#define SWFDEC_TYPE_AS_RELAY                    (swfdec_as_relay_get_type())
+#define SWFDEC_IS_AS_RELAY(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFDEC_TYPE_AS_RELAY))
+#define SWFDEC_IS_AS_RELAY_CLASS(klass)         (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFDEC_TYPE_AS_RELAY))
+#define SWFDEC_AS_RELAY(obj)                    (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFDEC_TYPE_AS_RELAY, SwfdecAsRelay))
+#define SWFDEC_AS_RELAY_CLASS(klass)            (G_TYPE_CHECK_CLASS_CAST ((klass), SWFDEC_TYPE_AS_RELAY, SwfdecAsRelayClass))
+#define SWFDEC_AS_RELAY_GET_CLASS(obj)          (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFDEC_TYPE_AS_RELAY, SwfdecAsRelayClass))
+
+struct _SwfdecAsRelay {
+  /*< protected >*/
+  SwfdecGcObject	object;
+  SwfdecAsObject *	relay;
+};
+
+struct _SwfdecAsRelayClass {
+  /*< private >*/
+  SwfdecGcObjectClass	object_class;
+};
+
+GType		swfdec_as_relay_get_type	(void);
+
+
+gboolean	swfdec_as_relay_call		(SwfdecAsRelay *	relay,
+						 const char *		name,
+						 guint			argc,
+						 SwfdecAsValue *	argv,
+						 SwfdecAsValue *	return_value);
+
+
+G_END_DECLS
+#endif
commit 689c41d2484547b2bb920ce45745f22a30d3f219
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Oct 21 11:30:50 2008 +0200

    make Arrays a special type of normal objects

diff --git a/doc/swfdec.types b/doc/swfdec.types
index 2bbfe83..20386bf 100644
--- a/doc/swfdec.types
+++ b/doc/swfdec.types
@@ -1,7 +1,6 @@
 #include <swfdec/swfdec.h>
 #include <swfdec-gtk/swfdec-gtk.h>
 
-swfdec_as_array_get_type
 swfdec_as_context_get_type
 swfdec_as_debugger_get_type
 swfdec_as_function_get_type
diff --git a/swfdec/swfdec_amf.c b/swfdec/swfdec_amf.c
index c3ef012..c7c8245 100644
--- a/swfdec/swfdec_amf.c
+++ b/swfdec/swfdec_amf.c
@@ -138,7 +138,7 @@ swfdec_amf_parse_array (SwfdecAsContext *context, SwfdecBits *bits, SwfdecAsValu
     }
     if (!func (context, bits, &tmp))
       goto fail;
-    swfdec_as_array_push (SWFDEC_AS_ARRAY (array), &tmp);
+    swfdec_as_array_push (array, &tmp);
   }
 
   SWFDEC_AS_VALUE_SET_OBJECT (val, array);
diff --git a/swfdec/swfdec_as_array.c b/swfdec/swfdec_as_array.c
index dd18c59..060e4d3 100644
--- a/swfdec/swfdec_as_array.c
+++ b/swfdec/swfdec_as_array.c
@@ -37,23 +37,15 @@
 #include "swfdec_utils.h"
 #include "swfdec_debug.h"
 
-G_DEFINE_TYPE (SwfdecAsArray, swfdec_as_array, SWFDEC_TYPE_AS_OBJECT)
-
 /**
- * SECTION:SwfdecAsArray
- * @title: SwfdecAsArray
+ * SECTION:Arrays
+ * @title: arrays
  * @short_description: the array object
  *
  * The array object provides some convenience functions for creating and
  * modifying arrays.
  */
 
-/**
- * SwfdecAsArray
- *
- * This is the type of the array object.
- */
-
 /*
  * Internal helper functions
  */
@@ -89,65 +81,61 @@ swfdec_as_array_length_as_integer (SwfdecAsObject *object)
   return length;
 }
 
-static gint32
-swfdec_as_array_length (SwfdecAsObject *object)
-{
-  gint32 length;
-
-  length = swfdec_as_array_length_as_integer (object);
-
-  if (length < 0)
-    return 0;
-
-  return length;
-}
-
 /**
  * swfdec_as_array_get_length:
- * @array: a #SwfdecAsArray
+ * @array: the array
  *
  * Gets the current length of the @array.
  *
  * Returns: Current length of the @array, always >= 0
  **/
 gint32
-swfdec_as_array_get_length (SwfdecAsArray *array)
+swfdec_as_array_get_length (SwfdecAsObject *array)
 {
-  return swfdec_as_array_length (SWFDEC_AS_OBJECT (array));
+  gint32 length;
+
+  g_return_val_if_fail (SWFDEC_IS_AS_OBJECT (array), 0);
+
+  length = swfdec_as_array_length_as_integer (array);
+
+  if (length < 0)
+    return 0;
+
+  return length;
 }
 
 static void
 swfdec_as_array_set_length_object (SwfdecAsObject *object, gint32 length)
 {
   SwfdecAsValue val;
+  gboolean was_array;
 
   g_return_if_fail (SWFDEC_IS_AS_OBJECT (object));
 
-  if (SWFDEC_IS_AS_ARRAY (object))
-    SWFDEC_AS_ARRAY (object)->check_length = FALSE;
+  was_array = object->array;
+  object->array = FALSE;
 
   swfdec_as_value_set_integer (swfdec_gc_object_get_context (object), &val, length);
   swfdec_as_object_set_variable_and_flags (object, SWFDEC_AS_STR_length, &val,
       SWFDEC_AS_VARIABLE_HIDDEN | SWFDEC_AS_VARIABLE_PERMANENT);
 
-  if (SWFDEC_IS_AS_ARRAY (object))
-    SWFDEC_AS_ARRAY (object)->check_length = TRUE;
+  object->array = was_array;
 }
 
 /**
  * swfdec_as_array_set_length:
- * @array: a #SwfdecAsArray
+ * @array: the array
  * @length: the new length
  *
  * Sets the length of the @array. Values outside the new length will be
  * removed.
  **/
 void
-swfdec_as_array_set_length (SwfdecAsArray *array, gint32 length)
+swfdec_as_array_set_length (SwfdecAsObject *array, gint32 length)
 {
   SwfdecAsValue val;
 
-  g_return_if_fail (SWFDEC_IS_AS_ARRAY (array));
+  g_return_if_fail (SWFDEC_IS_AS_OBJECT (array));
   g_return_if_fail (length >= 0);
 
   swfdec_as_value_set_integer (swfdec_gc_object_get_context (array), &val, length);
@@ -181,7 +169,7 @@ swfdec_as_array_foreach_remove_range (SwfdecAsObject *object,
   return FALSE;
 }
 
-static void
+void
 swfdec_as_array_remove_range (SwfdecAsObject *object, gint32 start_index,
     gint32 num)
 {
@@ -247,7 +235,7 @@ swfdec_as_array_move_range (SwfdecAsObject *object, gint32 from_index,
       &fdata);
 
   // only changes length if it becomes bigger, not if it becomes smaller
-  if (to_index + num > swfdec_as_array_length (object))
+  if (to_index + num > swfdec_as_array_get_length (object))
     swfdec_as_array_set_length_object (object, to_index + num);
 }
 
@@ -288,7 +276,7 @@ swfdec_as_array_append_internal (SwfdecAsObject *object, guint n,
 
 /**
  * swfdec_as_array_push:
- * @array: a #SwfdecAsArray
+ * @array: the array
  * @value: the value to add
  *
  * Adds the given @value to the @array. This is a macro that just calls
@@ -297,7 +285,7 @@ swfdec_as_array_append_internal (SwfdecAsObject *object, guint n,
 
 /**
  * swfdec_as_array_push_with_flags:
- * @array: a #SwfdecAsArray
+ * @array: the array
  * @value: the value to add
  * @flags: the #SwfdecAsVariableFlag flags to use
  *
@@ -307,7 +295,7 @@ swfdec_as_array_append_internal (SwfdecAsObject *object, guint n,
 
 /**
  * swfdec_as_array_append:
- * @array: a #SwfdecAsArray
+ * @array: the array
  * @n: number of values to add
  * @values: the values to add
  *
@@ -317,7 +305,7 @@ swfdec_as_array_append_internal (SwfdecAsObject *object, guint n,
 
 /**
  * swfdec_as_array_append_with_flags:
- * @array: a #SwfdecAsArray
+ * @array: the array
  * @n: number of values to add
  * @values: the values to add
  * @flags: the #SwfdecAsVariableFlag flags to use
@@ -325,20 +313,20 @@ swfdec_as_array_append_internal (SwfdecAsObject *object, guint n,
  * Appends the given @values to the @array using the given @flags.
  **/
 void
-swfdec_as_array_append_with_flags (SwfdecAsArray *array, guint n,
+swfdec_as_array_append_with_flags (SwfdecAsObject *array, guint n,
     const SwfdecAsValue *value, SwfdecAsVariableFlag flags)
 {
-  g_return_if_fail (SWFDEC_IS_AS_ARRAY (array));
+  g_return_if_fail (SWFDEC_IS_AS_OBJECT (array));
   g_return_if_fail (n == 0 || value != NULL);
 
   // don't allow negative length
   swfdec_as_array_set_range_with_flags (SWFDEC_AS_OBJECT (array),
-      swfdec_as_array_length (SWFDEC_AS_OBJECT (array)), n, value, flags);
+      swfdec_as_array_get_length (SWFDEC_AS_OBJECT (array)), n, value, flags);
 }
 
 /**
  * swfdec_as_array_insert:
- * @array: a #SwfdecAsArray
+ * @array: the array
  * @idx: index to insert the value to
  * @value: a #SwfdecAsValue
  *
@@ -348,7 +336,7 @@ swfdec_as_array_append_with_flags (SwfdecAsArray *array, guint n,
  **/
 /**
  * swfdec_as_array_insert_with_flags:
- * @array: a #SwfdecAsArray
+ * @array: the array
  * @idx: index to insert the value to
  * @value: a #SwfdecAsValue
  * @flags: the #SwfdecAsVariableFlag flags to use
@@ -357,18 +345,18 @@ swfdec_as_array_append_with_flags (SwfdecAsArray *array, guint n,
  * it by moving elements to bigger indexes if necessary.
  **/
 void
-swfdec_as_array_insert_with_flags (SwfdecAsArray *array, gint32 idx,
+swfdec_as_array_insert_with_flags (SwfdecAsObject *array, gint32 idx,
     const SwfdecAsValue *value, SwfdecAsVariableFlag flags)
 {
   gint32 length;
   SwfdecAsObject *object;
 
-  g_return_if_fail (SWFDEC_IS_AS_ARRAY (array));
+  g_return_if_fail (SWFDEC_IS_AS_OBJECT (array));
   g_return_if_fail (idx >= 0);
   g_return_if_fail (SWFDEC_IS_AS_VALUE (value));
 
   object = SWFDEC_AS_OBJECT (array);
-  length = swfdec_as_array_length (object);
+  length = swfdec_as_array_get_length (object);
 
   if (idx < length)
     swfdec_as_array_move_range (object, idx, length - idx, idx + 1);
@@ -377,23 +365,23 @@ swfdec_as_array_insert_with_flags (SwfdecAsArray *array, gint32 idx,
 
 /**
  * swfdec_as_array_remove:
- * @array: a #SwfdecAsArray
+ * @array: the array
  * @idx: index of the value to remove
  *
  * Removes value at given index from the @array, elements with higher indexes
  * will be moved towards the start of the @array.
  **/
 void
-swfdec_as_array_remove (SwfdecAsArray *array, gint32 idx)
+swfdec_as_array_remove (SwfdecAsObject *array, gint32 idx)
 {
   gint32 length;
   SwfdecAsObject *object;
 
-  g_return_if_fail (SWFDEC_IS_AS_ARRAY (array));
+  g_return_if_fail (SWFDEC_IS_AS_OBJECT (array));
   g_return_if_fail (idx >= 0);
 
   object = SWFDEC_AS_OBJECT (array);
-  length = swfdec_as_array_length (object);
+  length = swfdec_as_array_get_length (object);
 
   if (idx >= length)
     return;
@@ -404,7 +392,7 @@ swfdec_as_array_remove (SwfdecAsArray *array, gint32 idx)
 
 /**
  * swfdec_as_array_get_value:
- * @array: a #SwfdecAsArray
+ * @array: the array
  * @idx: index of the value to get
  * @value: a pointer to #SwfdecAsValue that will be set
  *
@@ -412,12 +400,12 @@ swfdec_as_array_remove (SwfdecAsArray *array, gint32 idx)
  * value is set.
  **/
 void
-swfdec_as_array_get_value (SwfdecAsArray *array, gint32 idx,
+swfdec_as_array_get_value (SwfdecAsObject *array, gint32 idx,
     SwfdecAsValue *value)
 {
   const char *var;
 
-  g_assert (SWFDEC_IS_AS_ARRAY (array));
+  g_assert (SWFDEC_IS_AS_OBJECT (array));
   g_assert (idx >= 0);
   g_assert (value != NULL);
 
@@ -427,7 +415,7 @@ swfdec_as_array_get_value (SwfdecAsArray *array, gint32 idx,
 
 /**
  * swfdec_as_array_set_value:
- * @array: a #SwfdecAsArray
+ * @array: the array
  * @idx: index of the value to set
  * @value: a pointer to #SwfdecAsValue
  *
@@ -435,12 +423,12 @@ swfdec_as_array_get_value (SwfdecAsArray *array, gint32 idx,
  * necessary.
  **/
 void
-swfdec_as_array_set_value (SwfdecAsArray *array, gint32 idx,
+swfdec_as_array_set_value (SwfdecAsObject *array, gint32 idx,
     SwfdecAsValue *value)
 {
   const char *var;
 
-  g_assert (SWFDEC_IS_AS_ARRAY (array));
+  g_assert (SWFDEC_IS_AS_OBJECT (array));
   g_assert (idx >= 0);
   g_assert (SWFDEC_IS_AS_VALUE (value));
 
@@ -474,12 +462,12 @@ swfdec_as_array_foreach_append_array_range (SwfdecAsObject *object,
 }
 
 static void
-swfdec_as_array_append_array_range (SwfdecAsArray *array_to,
+swfdec_as_array_append_array_range (SwfdecAsObject *array_to,
     SwfdecAsObject *object_from, gint32 start_index, gint32 num)
 {
   ForeachAppendArrayRangeData fdata;
 
-  g_return_if_fail (SWFDEC_IS_AS_ARRAY (array_to));
+  g_return_if_fail (SWFDEC_IS_AS_OBJECT (array_to));
   g_return_if_fail (SWFDEC_IS_AS_OBJECT (object_from));
   g_return_if_fail (start_index >= 0);
 
@@ -487,7 +475,7 @@ swfdec_as_array_append_array_range (SwfdecAsArray *array_to,
     return;
 
   fdata.object_to = SWFDEC_AS_OBJECT (array_to);
-  fdata.offset = swfdec_as_array_length (SWFDEC_AS_OBJECT (array_to));
+  fdata.offset = swfdec_as_array_get_length (SWFDEC_AS_OBJECT (array_to));
   fdata.start_index = start_index;
   fdata.num = num;
 
@@ -498,64 +486,11 @@ swfdec_as_array_append_array_range (SwfdecAsArray *array_to,
 }
 
 static void
-swfdec_as_array_append_array (SwfdecAsArray *array_to,
+swfdec_as_array_append_array (SwfdecAsObject *array_to,
     SwfdecAsObject *object_from)
 {
   swfdec_as_array_append_array_range (array_to, object_from, 0,
-      swfdec_as_array_length (object_from));
-}
-
-/*
- * Class functions
- */
-
-static void
-swfdec_as_array_set (SwfdecAsObject *object, const char *variable,
-    const SwfdecAsValue *val, guint flags)
-{
-  gboolean indexvar;
-  char *end;
-  gint32 l;
-
-  // we have to allow negative values here
-  l = strtoul (variable, &end, 10);
-  indexvar = (*end == 0);
-
-  // if we changed to smaller length, destroy all values that are outside it
-  //
-  if (SWFDEC_AS_ARRAY (object)->check_length &&
-      !swfdec_strcmp (swfdec_gc_object_get_context (object)->version, variable,
-	SWFDEC_AS_STR_length))
-  {
-    gint32 length_old = swfdec_as_array_length (object);
-    gint32 length_new = swfdec_as_value_to_integer (swfdec_gc_object_get_context (object), val);
-    length_new = MAX (0, length_new);
-    if (length_old > length_new) {
-      swfdec_as_array_remove_range (object, length_new,
-	  length_old - length_new);
-    }
-  }
-
-  SWFDEC_AS_OBJECT_CLASS (swfdec_as_array_parent_class)->set (object, variable,
-      val, flags);
-
-  // if we added new value outside the current length, set a bigger length
-  if (indexvar && ++l > swfdec_as_array_length_as_integer (object))
-    swfdec_as_array_set_length_object (object, l);
-}
-
-static void
-swfdec_as_array_class_init (SwfdecAsArrayClass *klass)
-{
-  SwfdecAsObjectClass *asobject_class = SWFDEC_AS_OBJECT_CLASS (klass);
-
-  asobject_class->set = swfdec_as_array_set;
-}
-
-static void
-swfdec_as_array_init (SwfdecAsArray *array)
-{
-  array->check_length = TRUE;
+      swfdec_as_array_get_length (object_from));
 }
 
 /*
@@ -566,7 +501,7 @@ swfdec_as_array_init (SwfdecAsArray *array)
  * swfdec_as_array_new:
  * @context: a #SwfdecAsContext
  *
- * Creates a new #SwfdecAsArray. 
+ * Creates a new array.
  *
  * Returns: the new array
  **/
@@ -577,7 +512,8 @@ swfdec_as_array_new (SwfdecAsContext *context)
 
   g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), NULL);
 
-  ret = g_object_new (SWFDEC_TYPE_AS_ARRAY, "context", context, NULL);
+  ret = swfdec_as_object_new (context, NULL);
+  ret->array = TRUE;
   swfdec_as_object_set_constructor_by_name (ret, SWFDEC_AS_STR_Array, NULL);
 
   swfdec_as_array_set_length_object (ret, 0);
@@ -606,12 +542,12 @@ swfdec_as_array_join (SwfdecAsContext *cx, SwfdecAsObject *object, guint argc,
   }
 
   // note: we don't cache length
-  if (swfdec_as_array_length (object) > 0) {
+  if (swfdec_as_array_get_length (object) > 0) {
     GString *string;
     swfdec_as_object_get_variable (object, SWFDEC_AS_STR_0, &val);
     str = swfdec_as_value_to_string (cx, &val);
     string = g_string_new (str);
-    for (i = 1; i < swfdec_as_array_length (object); i++) {
+    for (i = 1; i < swfdec_as_array_get_length (object); i++) {
       var = swfdec_as_integer_to_string (cx, i);
       swfdec_as_object_get_variable (object, var, &val);
       var = swfdec_as_value_to_string (cx, &val);
@@ -679,7 +615,7 @@ swfdec_as_array_do_pop (SwfdecAsContext *cx, SwfdecAsObject *object,
 
   // if Array, the length is reduced by one
   // else the length is not reduced at all, but the variable is still deleted
-  if (SWFDEC_IS_AS_ARRAY (object))
+  if (object->array)
     swfdec_as_array_set_length_object (object, length - 1);
 }
 
@@ -695,15 +631,15 @@ swfdec_as_array_do_unshift (SwfdecAsContext *cx, SwfdecAsObject *object,
 
   if (argc) {
     // don't allow negative length
-    length = swfdec_as_array_length (object);
+    length = swfdec_as_array_get_length (object);
     swfdec_as_array_move_range (object, 0, length, argc);
     swfdec_as_array_set_range (object, 0, argc, argv);
     // if not Array, leave the length unchanged
-    if (!SWFDEC_IS_AS_ARRAY (object))
+    if (!object->array)
       swfdec_as_array_set_length_object (object, length);
   }
 
-  swfdec_as_value_set_integer (cx, ret, swfdec_as_array_length (object));
+  swfdec_as_value_set_integer (cx, ret, swfdec_as_array_get_length (object));
 }
 
 SWFDEC_AS_NATIVE (252, 4, swfdec_as_array_do_shift)
@@ -718,7 +654,7 @@ swfdec_as_array_do_shift (SwfdecAsContext *cx, SwfdecAsObject *object,
     return;
 
   // don't allow negative length
-  length = swfdec_as_array_length (object);
+  length = swfdec_as_array_get_length (object);
   if (length <= 0)
     return;
 
@@ -727,7 +663,7 @@ swfdec_as_array_do_shift (SwfdecAsContext *cx, SwfdecAsObject *object,
   swfdec_as_array_move_range (object, 1, length - 1, 0);
 
   // if not Array, leave the length unchanged, and don't remove the element
-  if (SWFDEC_IS_AS_ARRAY (object)) {
+  if (object->array) {
     swfdec_as_array_set_length_object (object, length - 1);
   } else {
     // we have to put the last element back, because we used move, not copy
@@ -767,7 +703,7 @@ swfdec_as_array_reverse (SwfdecAsContext *cx, SwfdecAsObject *object,
   if (object == NULL || SWFDEC_IS_MOVIE (object))
     return;
 
-  length = swfdec_as_array_length (object);
+  length = swfdec_as_array_get_length (object);
   swfdec_as_object_foreach_rename (object, swfdec_as_array_foreach_reverse,
       &length);
 
@@ -780,23 +716,19 @@ swfdec_as_array_concat (SwfdecAsContext *cx, SwfdecAsObject *object,
     guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
 {
   guint j;
-  SwfdecAsObject *object_new;
-  SwfdecAsArray *array_new;
+  SwfdecAsObject *array_new;
   const char *var;
 
   if (object == NULL || SWFDEC_IS_MOVIE (object))
     return;
 
-  object_new = swfdec_as_array_new (cx);
-  if (object_new == NULL)
-    return;
-  array_new = SWFDEC_AS_ARRAY (object_new);
+  array_new = swfdec_as_array_new (cx);
 
   swfdec_as_array_append_array (array_new, object);
 
   for (j = 0; j < argc; j++) {
     if (SWFDEC_AS_VALUE_IS_OBJECT (&argv[j]) &&
-	SWFDEC_IS_AS_ARRAY (SWFDEC_AS_VALUE_GET_OBJECT (&argv[j])))
+	SWFDEC_AS_VALUE_GET_OBJECT (&argv[j])->array)
     {
       swfdec_as_array_append_array (array_new,
 	  SWFDEC_AS_VALUE_GET_OBJECT (&argv[j]));
@@ -804,12 +736,12 @@ swfdec_as_array_concat (SwfdecAsContext *cx, SwfdecAsObject *object,
     else
     {
       var = swfdec_as_integer_to_string (swfdec_gc_object_get_context (object),
-	  swfdec_as_array_length (object_new));
-      swfdec_as_object_set_variable (object_new, var, &argv[j]);
+	  swfdec_as_array_get_length (array_new));
+      swfdec_as_object_set_variable (array_new, var, &argv[j]);
     }
   }
 
-  SWFDEC_AS_VALUE_SET_OBJECT (ret, object_new);
+  SWFDEC_AS_VALUE_SET_OBJECT (ret, array_new);
 }
 
 SWFDEC_AS_NATIVE (252, 6, swfdec_as_array_slice)
@@ -818,12 +750,12 @@ swfdec_as_array_slice (SwfdecAsContext *cx, SwfdecAsObject *object, guint argc,
     SwfdecAsValue *argv, SwfdecAsValue *ret)
 {
   gint32 length, start_index, num;
-  SwfdecAsArray *array_new;
+  SwfdecAsObject *array_new;
 
   if (object == NULL || SWFDEC_IS_MOVIE (object))
     return;
 
-  length = swfdec_as_array_length (object);
+  length = swfdec_as_array_get_length (object);
 
   if (argc > 0) {
     start_index = swfdec_as_value_to_integer (cx, &argv[0]);
@@ -844,13 +776,11 @@ swfdec_as_array_slice (SwfdecAsContext *cx, SwfdecAsObject *object, guint argc,
     num = length - start_index;
   }
 
-  array_new = SWFDEC_AS_ARRAY (swfdec_as_array_new (cx));
-  if (array_new == NULL)
-    return;
+  array_new = swfdec_as_array_new (cx);
 
   swfdec_as_array_append_array_range (array_new, object, start_index, num);
 
-  SWFDEC_AS_VALUE_SET_OBJECT (ret, SWFDEC_AS_OBJECT (array_new));
+  SWFDEC_AS_VALUE_SET_OBJECT (ret, array_new);
 }
 
 SWFDEC_AS_NATIVE (252, 8, swfdec_as_array_splice)
@@ -859,12 +789,12 @@ swfdec_as_array_splice (SwfdecAsContext *cx, SwfdecAsObject *object,
     guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
 {
   gint32 length, start_index, num_remove, num_add, at_end;
-  SwfdecAsArray *array_new;
+  SwfdecAsObject *array_new;
 
   if (object == NULL || SWFDEC_IS_MOVIE (object) || argc == 0)
     return;
 
-  length = swfdec_as_array_length (object);
+  length = swfdec_as_array_get_length (object);
 
   start_index = swfdec_as_value_to_integer (cx, &argv[0]);
   if (start_index < 0)
@@ -884,10 +814,10 @@ swfdec_as_array_splice (SwfdecAsContext *cx, SwfdecAsObject *object,
   at_end = length - num_remove - start_index;
 
   /* create return value */
-  array_new = SWFDEC_AS_ARRAY (swfdec_as_array_new (cx));
+  array_new = swfdec_as_array_new (cx);
   swfdec_as_array_append_array_range (array_new, object, start_index,
       num_remove);
-  SWFDEC_AS_VALUE_SET_OBJECT (ret, SWFDEC_AS_OBJECT (array_new));
+  SWFDEC_AS_VALUE_SET_OBJECT (ret, array_new);
 
   /* move old data to the right spot */
   swfdec_as_array_move_range (object, start_index + num_remove,
@@ -1136,7 +1066,7 @@ swfdec_as_array_do_sort (SwfdecAsContext *cx, SwfdecAsObject *object,
       SWFDEC_IS_AS_FUNCTION (custom_function));
   g_return_if_fail (fields == NULL || fields[0] != NULL);
 
-  length = swfdec_as_array_length (object);
+  length = swfdec_as_array_get_length (object);
   if (length == 0) {
     // special case for empty array, because g_try_new0 would return NULL
     SWFDEC_AS_VALUE_SET_OBJECT (ret, object);
@@ -1297,12 +1227,12 @@ swfdec_as_array_sortOn (SwfdecAsContext *cx, SwfdecAsObject *object,
   if (SWFDEC_AS_VALUE_IS_OBJECT (&argv[0])) {
 
     array = SWFDEC_AS_VALUE_GET_OBJECT (&argv[0]);
-    if (!SWFDEC_IS_AS_ARRAY (array)) {
+    if (!array->array) {
       SWFDEC_AS_VALUE_SET_OBJECT (ret, object);
       return;
     }
 
-    num_fields = swfdec_as_array_get_length (SWFDEC_AS_ARRAY (array));
+    num_fields = swfdec_as_array_get_length (array);
     if (num_fields <= 0) {
       SWFDEC_AS_VALUE_SET_OBJECT (ret, object);
       return;
@@ -1310,7 +1240,7 @@ swfdec_as_array_sortOn (SwfdecAsContext *cx, SwfdecAsObject *object,
 
     fields = g_new (const char *, num_fields + 1);
     for (i = 0; i < num_fields; i++) {
-      swfdec_as_array_get_value (SWFDEC_AS_ARRAY (array), i, &val);
+      swfdec_as_array_get_value (array, i, &val);
       if (SWFDEC_AS_VALUE_IS_OBJECT (&val) &&
 	  SWFDEC_IS_AS_STRING (SWFDEC_AS_VALUE_GET_OBJECT (&val))) {
 	fields[i] =
@@ -1334,10 +1264,10 @@ swfdec_as_array_sortOn (SwfdecAsContext *cx, SwfdecAsObject *object,
     if (SWFDEC_AS_VALUE_IS_OBJECT (&argv[1])) {
       array = SWFDEC_AS_VALUE_GET_OBJECT (&argv[1]);
 
-      if (SWFDEC_IS_AS_ARRAY (array) &&
-	swfdec_as_array_get_length (SWFDEC_AS_ARRAY (array)) == num_fields) {
+      if (array->array &&
+	swfdec_as_array_get_length (array) == num_fields) {
 	for (i = 0; i < num_fields; i++) {
-	  swfdec_as_array_get_value (SWFDEC_AS_ARRAY (array), i, &val);
+	  swfdec_as_array_get_value (array, i, &val);
 	  options[i] =
 	    swfdec_as_value_to_integer (cx, &val) & MASK_SORT_OPTION;
 	}
@@ -1359,26 +1289,25 @@ swfdec_as_array_sortOn (SwfdecAsContext *cx, SwfdecAsObject *object,
 
 // Constructor
 
-SWFDEC_AS_CONSTRUCTOR (252, 0, swfdec_as_array_construct, swfdec_as_array_get_type)
+SWFDEC_AS_NATIVE (252, 0, swfdec_as_array_construct)
 void
 swfdec_as_array_construct (SwfdecAsContext *cx, SwfdecAsObject *object,
     guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
 {
-  SwfdecAsArray *array;
-
   if (!cx->frame->construct) {
-    object = g_object_new (SWFDEC_TYPE_AS_ARRAY, "context", cx, NULL);
+    object = swfdec_as_object_new (cx, NULL);
     swfdec_as_object_set_constructor_by_name (object, SWFDEC_AS_STR_Array, NULL);
   }
+  swfdec_as_object_set_relay (object, NULL);
+  object->array = TRUE;
 
-  array = SWFDEC_AS_ARRAY (object);
   if (argc == 1 && SWFDEC_AS_VALUE_IS_NUMBER (&argv[0])) {
     int l = swfdec_as_value_to_integer (cx, &argv[0]);
-    swfdec_as_array_set_length (array, l < 0 ? 0 : l);
+    swfdec_as_array_set_length (object, l < 0 ? 0 : l);
   } else if (argc > 0) {
-    swfdec_as_array_append (array, argc, argv);
+    swfdec_as_array_append (object, argc, argv);
   } else {
-    swfdec_as_array_set_length (array, 0);
+    swfdec_as_array_set_length (object, 0);
   }
 
   SWFDEC_AS_VALUE_SET_OBJECT (ret, object);
diff --git a/swfdec/swfdec_as_array.h b/swfdec/swfdec_as_array.h
index 2d422d8..34f91ce 100644
--- a/swfdec/swfdec_as_array.h
+++ b/swfdec/swfdec_as_array.h
@@ -26,29 +26,6 @@
 
 G_BEGIN_DECLS
 
-typedef struct _SwfdecAsArrayClass SwfdecAsArrayClass;
-
-#define SWFDEC_TYPE_AS_ARRAY                    (swfdec_as_array_get_type())
-#define SWFDEC_IS_AS_ARRAY(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFDEC_TYPE_AS_ARRAY))
-#define SWFDEC_IS_AS_ARRAY_CLASS(klass)         (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFDEC_TYPE_AS_ARRAY))
-#define SWFDEC_AS_ARRAY(obj)                    (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFDEC_TYPE_AS_ARRAY, SwfdecAsArray))
-#define SWFDEC_AS_ARRAY_CLASS(klass)            (G_TYPE_CHECK_CLASS_CAST ((klass), SWFDEC_TYPE_AS_ARRAY, SwfdecAsArrayClass))
-#define SWFDEC_AS_ARRAY_GET_CLASS(obj)          (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFDEC_TYPE_AS_ARRAY, SwfdecAsArrayClass))
-
-struct _SwfdecAsArray {
-  /*< private >*/
-  SwfdecAsObject	object;
-
-  // whether to remove elements if length property is changed
-  // disabled internally sometimes to not create extra valueOf calls
-  gboolean		check_length;
-};
-
-struct _SwfdecAsArrayClass {
-  SwfdecAsObjectClass	object_class;
-};
-
-GType		swfdec_as_array_get_type	(void);
 
 SwfdecAsObject *swfdec_as_array_new		(SwfdecAsContext *	context);
 
@@ -58,29 +35,29 @@ SwfdecAsObject *swfdec_as_array_new		(SwfdecAsContext *	context);
   swfdec_as_array_append_with_flags ((array), 1, (value), (flags))
 #define		swfdec_as_array_append(array,n,values) \
   swfdec_as_array_append_with_flags ((array), (n), (values), 0)
-void		swfdec_as_array_append_with_flags (SwfdecAsArray *	array,
+void		swfdec_as_array_append_with_flags (SwfdecAsObject *	array,
 						 guint			n,
 						 const SwfdecAsValue *	values,
 						 SwfdecAsVariableFlag	flags);
-void		swfdec_as_array_insert		(SwfdecAsArray *	array,
+void		swfdec_as_array_insert		(SwfdecAsObject *	array,
 						 gint32			idx,
 						 SwfdecAsValue *	value);
 #define		swfdec_as_array_insert(array,idx,value) \
   swfdec_as_array_insert_with_flags ((array), (idx), (value), 0)
-void		swfdec_as_array_insert_with_flags (SwfdecAsArray *	array,
+void		swfdec_as_array_insert_with_flags (SwfdecAsObject *	array,
 						 gint32			idx,
 						 const SwfdecAsValue *	value,
 						 SwfdecAsVariableFlag	flags);
-gint32		swfdec_as_array_get_length	(SwfdecAsArray *	array);
-void		swfdec_as_array_set_length	(SwfdecAsArray *	array,
+gint32		swfdec_as_array_get_length	(SwfdecAsObject *	array);
+void		swfdec_as_array_set_length	(SwfdecAsObject *	array,
 						 gint32			length);
-void		swfdec_as_array_get_value	(SwfdecAsArray *	array,
+void		swfdec_as_array_get_value	(SwfdecAsObject *	array,
 						 gint32			idx,
 						 SwfdecAsValue *	value);
-void		swfdec_as_array_set_value	(SwfdecAsArray *	array,
+void		swfdec_as_array_set_value	(SwfdecAsObject *	array,
 						 gint32			idx,
 						 SwfdecAsValue *	value);
-void		swfdec_as_array_remove		(SwfdecAsArray *	array,
+void		swfdec_as_array_remove		(SwfdecAsObject *	array,
 						 gint32			idx);
 
 
diff --git a/swfdec/swfdec_as_frame.c b/swfdec/swfdec_as_frame.c
index cca50a7..1c8d265 100644
--- a/swfdec/swfdec_as_frame.c
+++ b/swfdec/swfdec_as_frame.c
@@ -590,7 +590,7 @@ swfdec_as_frame_preload (SwfdecAsFrame *frame)
     args = swfdec_as_array_new (context);
     for (cur = swfdec_as_stack_iterator_init_arguments (&iter, frame); cur != NULL;
 	cur = swfdec_as_stack_iterator_next (&iter)) {
-      swfdec_as_array_push (SWFDEC_AS_ARRAY (args), cur);
+      swfdec_as_array_push (args, cur);
     }
 
     next = frame->next;
diff --git a/swfdec/swfdec_as_internal.h b/swfdec/swfdec_as_internal.h
index a9d7973..ad79b87 100644
--- a/swfdec/swfdec_as_internal.h
+++ b/swfdec/swfdec_as_internal.h
@@ -80,6 +80,11 @@ SwfdecAsObject * swfdec_as_object_set_constructor_by_namev
 						 const char *		name,
 						 va_list		args);
 
+/* swfdec_as_array.h */
+void		swfdec_as_array_remove_range	(SwfdecAsObject *	object,
+						 gint32			start_index,
+						 gint32			num);
+
 
 G_END_DECLS
 #endif
diff --git a/swfdec/swfdec_as_interpret.c b/swfdec/swfdec_as_interpret.c
index 186b8d0..35ee098 100644
--- a/swfdec/swfdec_as_interpret.c
+++ b/swfdec/swfdec_as_interpret.c
@@ -1814,7 +1814,7 @@ swfdec_action_init_array (SwfdecAsContext *cx, guint action, const guint8 *data,
   /* NB: we can't increase the stack here, as the number can easily be MAXINT */
   for (i = 0; i < n && swfdec_as_stack_get_size (cx) > 0; i++) {
     swfdec_as_stack_ensure_size (cx, 1);
-    swfdec_as_array_push (SWFDEC_AS_ARRAY (array), swfdec_as_stack_pop (cx));
+    swfdec_as_array_push (array, swfdec_as_stack_pop (cx));
   }
   if (i != n) {
     SwfdecAsValue val;
diff --git a/swfdec/swfdec_as_object.c b/swfdec/swfdec_as_object.c
index 065fbd4..e25b716 100644
--- a/swfdec/swfdec_as_object.c
+++ b/swfdec/swfdec_as_object.c
@@ -21,9 +21,12 @@
 #include "config.h"
 #endif
 
+#include <stdlib.h>
 #include <string.h>
 
 #include "swfdec_as_object.h"
+
+#include "swfdec_as_array.h"
 #include "swfdec_as_context.h"
 #include "swfdec_as_frame_internal.h"
 #include "swfdec_as_internal.h"
@@ -35,6 +38,7 @@
 #include "swfdec_as_super.h"
 #include "swfdec_debug.h"
 #include "swfdec_movie.h"
+#include "swfdec_utils.h"
 
 /**
  * SECTION:SwfdecAsObject
@@ -445,6 +449,14 @@ swfdec_as_object_hash_lookup_with_prototype (SwfdecAsObject *object,
   return var;
 }
 
+#if 0
+static void
+swfdec_as_array_set (SwfdecAsObject *object, const char *variable,
+    const SwfdecAsValue *val, guint flags)
+{
+}
+#endif
+
 static void
 swfdec_as_object_do_set (SwfdecAsObject *object, const char *variable, 
     const SwfdecAsValue *val, guint flags)
@@ -452,17 +464,18 @@ swfdec_as_object_do_set (SwfdecAsObject *object, const char *variable,
   SwfdecAsVariable *var;
   SwfdecAsWatch *watch;
   SwfdecAsObject *proto;
+  SwfdecAsContext *context;
 
   if (!swfdec_as_variable_name_is_valid (variable))
     return;
 
+  context = swfdec_gc_object_get_context (object);
   var = swfdec_as_object_hash_lookup_with_prototype (object, variable, &proto);
-  if (swfdec_as_context_is_aborted (swfdec_gc_object_get_context (object)))
+  if (swfdec_as_context_is_aborted (context))
     return;
 
   // if variable is disabled in this version
-  if (var != NULL && !swfdec_as_object_variable_enabled_in_version (var,
-	swfdec_gc_object_get_context (object)->version)) {
+  if (var != NULL && !swfdec_as_object_variable_enabled_in_version (var, context->version)) {
     if (proto == NULL) {
       // it's at the top level, remove getter and setter plus overwrite
       var->get = NULL;
@@ -481,7 +494,7 @@ swfdec_as_object_do_set (SwfdecAsObject *object, const char *variable,
     if (var->flags & SWFDEC_AS_VARIABLE_CONSTANT)
       return;
     // remove the flags that could make this variable hidden
-    if (swfdec_gc_object_get_context (object)->version == 6) {
+    if (context->version == 6) {
       // version 6, so let's forget SWFDEC_AS_VARIABLE_VERSION_7_UP flag, oops!
       // we will still set the value though, even if that flag is set
       var->flags &= ~(SWFDEC_AS_VARIABLE_VERSION_6_UP |
@@ -509,7 +522,7 @@ swfdec_as_object_do_set (SwfdecAsObject *object, const char *variable,
       swfdec_as_watch_unref (watch);
       var = swfdec_as_object_hash_lookup_with_prototype (object, variable,
 	  NULL);
-      if (swfdec_as_context_is_aborted (swfdec_gc_object_get_context (object)))
+      if (swfdec_as_context_is_aborted (context))
 	return;
       if (var == NULL) {
 	SWFDEC_INFO ("watch removed variable %s", variable);
@@ -521,6 +534,22 @@ swfdec_as_object_do_set (SwfdecAsObject *object, const char *variable,
   } else {
     watch = NULL;
   }
+
+  if (object->array) {
+    /* if we changed to smaller length, destroy all values that are outside it */
+    if (!swfdec_strcmp (context->version, variable,
+	  SWFDEC_AS_STR_length))
+    {
+      gint32 length_old = swfdec_as_array_get_length (object);
+      gint32 length_new = swfdec_as_value_to_integer (context, val);
+      length_new = MAX (0, length_new);
+      if (length_old > length_new) {
+	swfdec_as_array_remove_range (object, length_new,
+	    length_old - length_new);
+      }
+    }
+  }
+
   if (var->get) {
     if (var->set) {
       SwfdecAsValue tmp;
@@ -540,6 +569,28 @@ swfdec_as_object_do_set (SwfdecAsObject *object, const char *variable,
       object->prototype_flags = 0;
     }
   }
+
+  /* If we are an array, do the special magic now */
+  if (object->array) {
+    char *end;
+    gint32 l;
+
+    /* if we added new value outside the current length, set a bigger length */
+    l = strtoul (variable, &end, 10);
+    if (*end == '\0') {
+      SwfdecAsValue tmp;
+      gint32 length;
+      swfdec_as_object_get_variable (object, SWFDEC_AS_STR_length, &tmp);
+      length = swfdec_as_value_to_integer (context, &tmp);
+      if (l >= length) {
+	object->array = FALSE;
+	swfdec_as_value_set_integer (swfdec_gc_object_get_context (object), &tmp, l + 1);
+	swfdec_as_object_set_variable_and_flags (object, SWFDEC_AS_STR_length, &tmp,
+	    SWFDEC_AS_VARIABLE_HIDDEN | SWFDEC_AS_VARIABLE_PERMANENT);
+	object->array = TRUE;
+      }
+    }
+  }
 }
 
 static void
@@ -1835,13 +1886,17 @@ void
 swfdec_as_object_set_relay (SwfdecAsObject *object, SwfdecAsRelay *relay)
 {
   g_return_if_fail (SWFDEC_IS_AS_OBJECT (object));
-  g_return_if_fail (SWFDEC_IS_AS_RELAY (relay));
-  g_return_if_fail (relay->relay == NULL);
+  if (relay) {
+    g_return_if_fail (SWFDEC_IS_AS_RELAY (relay));
+    g_return_if_fail (relay->relay == NULL);
+  }
 
   if (object->relay) {
     object->relay->relay = NULL;
   }
   object->relay = relay;
-  relay->relay = object;
+  object->array = FALSE;
+  if (relay)
+    relay->relay = object;
 }
 
diff --git a/swfdec/swfdec_as_object.h b/swfdec/swfdec_as_object.h
index d426390..214d951 100644
--- a/swfdec/swfdec_as_object.h
+++ b/swfdec/swfdec_as_object.h
@@ -60,6 +60,7 @@ struct _SwfdecAsObject {
   /*< protected >*/
   SwfdecGcObject      	object;
   /*< private >*/
+  gboolean		array:1;	/* TRUE if object is an array */
   SwfdecAsObject *	prototype;	/* prototype object (referred to as __proto__) */
   guint			prototype_flags; /* propflags for the prototype object */
   GHashTable *		properties;	/* string->SwfdecAsVariable mapping or NULL when not in GC */
diff --git a/swfdec/swfdec_as_string.c b/swfdec/swfdec_as_string.c
index 8a0c726..e0465d5 100644
--- a/swfdec/swfdec_as_string.c
+++ b/swfdec/swfdec_as_string.c
@@ -356,13 +356,13 @@ static void
 swfdec_as_string_split_5 (SwfdecAsContext *cx, SwfdecAsObject *object,
     guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
 {
-  SwfdecAsArray *arr;
+  SwfdecAsObject *arr;
   SwfdecAsValue val;
   const char *str, *end, *delim;
   int count;
 
   str = swfdec_as_string_object_to_string (cx, object);
-  arr = SWFDEC_AS_ARRAY (swfdec_as_array_new (cx));
+  arr = swfdec_as_array_new (cx);
   SWFDEC_AS_VALUE_SET_OBJECT (ret, SWFDEC_AS_OBJECT (arr));
   /* hi, i'm the special case */
   if (argc < 1 || SWFDEC_AS_VALUE_IS_UNDEFINED (&argv[0])) {
@@ -406,14 +406,14 @@ static void
 swfdec_as_string_split_6 (SwfdecAsContext *cx, SwfdecAsObject *object,
     guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
 {
-  SwfdecAsArray *arr;
+  SwfdecAsObject *arr;
   SwfdecAsValue val;
   const char *str, *end, *delim;
   int count;
   guint len;
 
   str = swfdec_as_string_object_to_string (cx, object);
-  arr = SWFDEC_AS_ARRAY (swfdec_as_array_new (cx));
+  arr = swfdec_as_array_new (cx);
   SWFDEC_AS_VALUE_SET_OBJECT (ret, SWFDEC_AS_OBJECT (arr));
   /* hi, i'm the special case */
   if (argc < 1 || SWFDEC_AS_VALUE_IS_UNDEFINED (&argv[0])) {
diff --git a/swfdec/swfdec_as_types.h b/swfdec/swfdec_as_types.h
index 84f853f..5b80456 100644
--- a/swfdec/swfdec_as_types.h
+++ b/swfdec/swfdec_as_types.h
@@ -36,7 +36,6 @@ typedef enum {
   SWFDEC_AS_TYPE_OBJECT
 } SwfdecAsValueType;
 
-typedef struct _SwfdecAsArray SwfdecAsArray;
 typedef struct _SwfdecAsContext SwfdecAsContext;
 typedef struct _SwfdecAsDebugger SwfdecAsDebugger;
 typedef struct _SwfdecAsDoubleValue SwfdecAsDoubleValue;
diff --git a/swfdec/swfdec_color_matrix_filter_as.c b/swfdec/swfdec_color_matrix_filter_as.c
index 235e3c4..5c38d68 100644
--- a/swfdec/swfdec_color_matrix_filter_as.c
+++ b/swfdec/swfdec_color_matrix_filter_as.c
@@ -48,7 +48,7 @@ swfdec_color_matrix_filter_get_matrix (SwfdecAsContext *cx,
     swfdec_as_value_set_number (cx, &val[i], cm->matrix[i]);
   }
   array = swfdec_as_array_new (cx);
-  swfdec_as_array_append (SWFDEC_AS_ARRAY (array), 20, val);
+  swfdec_as_array_append (array, 20, val);
   SWFDEC_AS_VALUE_SET_OBJECT (ret, array);
 }
 
@@ -60,7 +60,7 @@ swfdec_color_matrix_filter_do_set_matrix (SwfdecColorMatrixFilter *cm,
   SwfdecAsValue val;
   int i;
 
-  if (!SWFDEC_IS_AS_ARRAY (array)) {
+  if (!array->array) {
     memset (cm->matrix, 0, sizeof (double) * 20);
     return;
   }
diff --git a/swfdec/swfdec_movie_clip_loader.c b/swfdec/swfdec_movie_clip_loader.c
index 19e1afa..902f2e2 100644
--- a/swfdec/swfdec_movie_clip_loader.c
+++ b/swfdec/swfdec_movie_clip_loader.c
@@ -56,7 +56,7 @@ swfdec_movie_clip_loader_construct (SwfdecAsContext *cx, SwfdecAsObject *object,
 
   array = swfdec_as_array_new (cx);
   SWFDEC_AS_VALUE_SET_OBJECT (&val, object);
-  swfdec_as_array_push (SWFDEC_AS_ARRAY (array), &val);
+  swfdec_as_array_push (array, &val);
   SWFDEC_AS_VALUE_SET_OBJECT (&val, array);
   swfdec_as_object_set_variable_and_flags (object, SWFDEC_AS_STR__listeners, 
       &val, SWFDEC_AS_VARIABLE_HIDDEN | SWFDEC_AS_VARIABLE_PERMANENT);
diff --git a/swfdec/swfdec_text_field_movie.c b/swfdec/swfdec_text_field_movie.c
index feaf4f0..bbebe17 100644
--- a/swfdec/swfdec_text_field_movie.c
+++ b/swfdec/swfdec_text_field_movie.c
@@ -404,7 +404,7 @@ swfdec_text_field_movie_init_movie (SwfdecMovie *movie)
   /* create _listeners array */
   array = swfdec_as_array_new (cx);
   SWFDEC_AS_VALUE_SET_OBJECT (&val, SWFDEC_AS_OBJECT (movie));
-  swfdec_as_array_push (SWFDEC_AS_ARRAY (array), &val);
+  swfdec_as_array_push (array, &val);
   SWFDEC_AS_VALUE_SET_OBJECT (&val, array);
   swfdec_as_object_set_variable_and_flags (SWFDEC_AS_OBJECT (movie), SWFDEC_AS_STR__listeners, 
       &val, SWFDEC_AS_VARIABLE_HIDDEN | SWFDEC_AS_VARIABLE_PERMANENT);
diff --git a/swfdec/swfdec_text_field_movie_as.c b/swfdec/swfdec_text_field_movie_as.c
index 9d04b72..18c4c35 100644
--- a/swfdec/swfdec_text_field_movie_as.c
+++ b/swfdec/swfdec_text_field_movie_as.c
@@ -1273,7 +1273,7 @@ swfdec_text_field_movie_getFontList (SwfdecAsContext *cx,
     SwfdecAsObject *object, guint argc, SwfdecAsValue *argv,
     SwfdecAsValue *ret)
 {
-  SwfdecAsArray *array;
+  SwfdecAsObject *array;
   SwfdecAsValue val;
   PangoFontFamily **families;
   int i, n_families;
@@ -1281,7 +1281,7 @@ swfdec_text_field_movie_getFontList (SwfdecAsContext *cx,
   pango_font_map_list_families (pango_cairo_font_map_get_default (),
       &families, &n_families);
 
-  array = SWFDEC_AS_ARRAY (swfdec_as_array_new (cx));
+  array = swfdec_as_array_new (cx);
   for (i = 0; i < n_families; i++) {
     SWFDEC_AS_VALUE_SET_STRING (&val, swfdec_as_context_get_string (cx,
 	  pango_font_family_get_name (families[i])));
diff --git a/swfdec/swfdec_text_format.c b/swfdec/swfdec_text_format.c
index 401201c..c45379d 100644
--- a/swfdec/swfdec_text_format.c
+++ b/swfdec/swfdec_text_format.c
@@ -677,7 +677,7 @@ swfdec_text_format_do_get_tab_stops (SwfdecAsContext *cx,
   array = swfdec_as_array_new (cx);
   for (i = 0; i < format->attr.n_tab_stops; i++) {
     swfdec_as_value_set_integer (cx, &val, format->attr.tab_stops[i]);
-    swfdec_as_array_push (SWFDEC_AS_ARRAY (array), &val);
+    swfdec_as_array_push (array, &val);
   }
   SWFDEC_AS_VALUE_SET_OBJECT (ret, array);
 }
@@ -709,14 +709,14 @@ swfdec_text_format_do_set_tab_stops (SwfdecAsContext *cx,
     SWFDEC_TEXT_ATTRIBUTE_UNSET (format->values_set, SWFDEC_TEXT_ATTRIBUTE_TAB_STOPS);
   }
   else if (SWFDEC_AS_VALUE_IS_OBJECT (&argv[0]) &&
-	SWFDEC_IS_AS_ARRAY (SWFDEC_AS_VALUE_GET_OBJECT (&argv[0])))
+	SWFDEC_AS_VALUE_GET_OBJECT (&argv[0])->array)
   {
-    SwfdecAsArray *array;
+    SwfdecAsObject *array;
     SwfdecAsValue val;
     guint i;
     int len;
 
-    array = SWFDEC_AS_ARRAY (SWFDEC_AS_VALUE_GET_OBJECT (&argv[0]));
+    array = SWFDEC_AS_VALUE_GET_OBJECT (&argv[0]);
     len = swfdec_as_array_get_length (array);
 
     if (!SWFDEC_TEXT_ATTRIBUTE_IS_SET (format->values_set, SWFDEC_TEXT_ATTRIBUTE_TAB_STOPS)) {
diff --git a/swfdec/swfdec_xml_node.c b/swfdec/swfdec_xml_node.c
index 2beccf8..019ae6f 100644
--- a/swfdec/swfdec_xml_node.c
+++ b/swfdec/swfdec_xml_node.c
@@ -980,7 +980,7 @@ swfdec_xml_node_init_values (SwfdecXmlNode *node, int type, const char* value)
 
   node->valid = TRUE;
   node->parent = NULL;
-  node->children = SWFDEC_AS_ARRAY (swfdec_as_array_new (swfdec_gc_object_get_context (object)));
+  node->children = swfdec_as_array_new (swfdec_gc_object_get_context (object));
   node->attributes = swfdec_as_object_new_empty (swfdec_gc_object_get_context (object));
   node->type = type;
   if (node->type == SWFDEC_XML_NODE_ELEMENT) {
@@ -989,7 +989,7 @@ swfdec_xml_node_init_values (SwfdecXmlNode *node, int type, const char* value)
     node->value = value;
   }
 
-  node->child_nodes = SWFDEC_AS_ARRAY (swfdec_as_array_new (swfdec_gc_object_get_context (object)));
+  node->child_nodes = swfdec_as_array_new (swfdec_gc_object_get_context (object));
 }
 
 static void
diff --git a/swfdec/swfdec_xml_node.h b/swfdec/swfdec_xml_node.h
index 49b5d48..59c1f8e 100644
--- a/swfdec/swfdec_xml_node.h
+++ b/swfdec/swfdec_xml_node.h
@@ -65,13 +65,13 @@ struct _SwfdecXmlNode {
   const char		*value;		// for type != element
 
   SwfdecXmlNode		*parent;
-  SwfdecAsArray		*children;
+  SwfdecAsObject	*children;
   SwfdecAsObject	*attributes;
 
   // visible trough childNodes property, if modified by the user directly, the
   // changes are not visible in children and will get overwritten by next
   // internal change
-  SwfdecAsArray		*child_nodes;
+  SwfdecAsObject	*child_nodes;
 };
 
 struct _SwfdecXmlNodeClass {
diff --git a/test/swfdec_test.c b/test/swfdec_test.c
index 2da4af0..f7a499b 100644
--- a/test/swfdec_test.c
+++ b/test/swfdec_test.c
@@ -200,13 +200,13 @@ main (int argc, char **argv)
       if (!g_str_has_suffix (file, ".swf"))
 	continue;
       SWFDEC_AS_VALUE_SET_STRING (&val, swfdec_as_context_get_string (context, file));
-      swfdec_as_array_push (SWFDEC_AS_ARRAY (array), &val);
+      swfdec_as_array_push (array, &val);
     }
     g_dir_close (dir);
   } else {
     for (i = 1; i < argc; i++) {
       SWFDEC_AS_VALUE_SET_STRING (&val, swfdec_as_context_get_string (context, argv[i]));
-      swfdec_as_array_push (SWFDEC_AS_ARRAY (array), &val);
+      swfdec_as_array_push (array, &val);
     }
   }
   SWFDEC_AS_VALUE_SET_OBJECT (&val, array);
diff --git a/test/swfdec_test_function.c b/test/swfdec_test_function.c
index fafde52..aa997e5 100644
--- a/test/swfdec_test_function.c
+++ b/test/swfdec_test_function.c
@@ -57,7 +57,7 @@ swfdec_test_function_init_context (SwfdecAsContext *cx)
   SwfdecAsValue val;
   guint i;
 
-  obj = swfdec_as_object_new (cx);
+  obj = swfdec_as_object_new (cx, NULL);
   if (obj == NULL)
     return;
   SWFDEC_AS_VALUE_SET_OBJECT (&val, obj);
diff --git a/vivified/core/vivi_function.c b/vivified/core/vivi_function.c
index a44c9aa..f61ce9a 100644
--- a/vivified/core/vivi_function.c
+++ b/vivified/core/vivi_function.c
@@ -58,9 +58,7 @@ vivi_function_init_context (ViviApplication *app)
   SwfdecAsValue val;
   guint i;
 
-  obj = swfdec_as_object_new (cx);
-  if (obj == NULL)
-    return;
+  obj = swfdec_as_object_new (cx, NULL);
   SWFDEC_AS_VALUE_SET_OBJECT (&val, obj);
   swfdec_as_object_set_variable (cx->global, 
       swfdec_as_context_get_string (cx, "Native"), &val);
@@ -76,9 +74,7 @@ vivi_function_init_context (ViviApplication *app)
     functions[i].fun);
   swfdec_as_native_function_set_construct_type (SWFDEC_AS_NATIVE_FUNCTION (fun),
       VIVI_TYPE_BREAKPOINT);
-  obj = swfdec_as_object_new (cx);
-  if (obj == NULL)
-    return;
+  obj = swfdec_as_object_new (cx, NULL);
   SWFDEC_AS_VALUE_SET_OBJECT (&val, obj);
   swfdec_as_object_set_variable (SWFDEC_AS_OBJECT (fun), 
       swfdec_as_context_get_string (cx, "prototype"), &val);
commit 46c72b029902d5ccfc5702d39984d64a93fb0c3f
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Oct 20 22:44:15 2008 +0200

    make date construction work again in AMF code

diff --git a/swfdec/Makefile.am b/swfdec/Makefile.am
index b2ee9c5..1a86942 100644
--- a/swfdec/Makefile.am
+++ b/swfdec/Makefile.am
@@ -27,6 +27,7 @@ libswfdec_source_files = \
 	swfdec_as_native_function.c \
 	swfdec_as_number.c \
 	swfdec_as_object.c \
+	swfdec_as_relay.c \
 	swfdec_as_script_function.c \
 	swfdec_as_stack.c \
 	swfdec_as_string.c \
@@ -243,6 +244,7 @@ noinst_HEADERS = \
 	swfdec_as_gcable.h \
 	swfdec_as_interpret.h \
 	swfdec_as_number.h \
+	swfdec_as_relay.h \
 	swfdec_as_script_function.h \
 	swfdec_as_stack.h \
 	swfdec_as_string.h \
diff --git a/swfdec/swfdec_amf.c b/swfdec/swfdec_amf.c
index 6ce65d6..c3ef012 100644
--- a/swfdec/swfdec_amf.c
+++ b/swfdec/swfdec_amf.c
@@ -24,6 +24,7 @@
 #include "swfdec_amf.h"
 #include "swfdec_as_array.h"
 #include "swfdec_as_date.h"
+#include "swfdec_as_strings.h"
 #include "swfdec_debug.h"
 
 typedef gboolean (* SwfdecAmfParseFunc) (SwfdecAsContext *cx, SwfdecBits *bits, SwfdecAsValue *val);
@@ -96,7 +97,7 @@ swfdec_amf_parse_object (SwfdecAsContext *context, SwfdecBits *bits, SwfdecAsVal
 {
   SwfdecAsObject *object;
   
-  object = swfdec_as_object_new (context);
+  object = swfdec_as_object_new (context, SWFDEC_AS_STR_Object, NULL);
   if (!swfdec_amf_parse_properties (context, bits, object))
     return FALSE;
   SWFDEC_AS_VALUE_SET_OBJECT (val, object);
@@ -151,14 +152,17 @@ fail:
 static gboolean
 swfdec_amf_parse_date (SwfdecAsContext *context, SwfdecBits *bits, SwfdecAsValue *val)
 {
-  double milliseconds = swfdec_bits_get_bdouble (bits);
-  int utc_offset = swfdec_bits_get_bu16 (bits);
+  SwfdecAsDate *date;
+  SwfdecAsObject *object;
 
-  if (utc_offset > 12 * 60)
-    utc_offset -= 12 * 60;
+  object = swfdec_as_object_new (context, SWFDEC_AS_STR_Date, NULL);
+  date = SWFDEC_AS_DATE (object->relay);
+  date->milliseconds = swfdec_bits_get_bdouble (bits);
+  date->utc_offset = swfdec_bits_get_bu16 (bits);
+  if (date->utc_offset > 12 * 60)
+    date->utc_offset -= 12 * 60;
+  SWFDEC_AS_VALUE_SET_OBJECT (val, object);
 
-  SWFDEC_AS_VALUE_SET_OBJECT (val,
-      swfdec_as_date_new (context, milliseconds, utc_offset));
   return TRUE;
 }
 
diff --git a/swfdec/swfdec_as_date.c b/swfdec/swfdec_as_date.c
index c86aa5d..1d17aac 100644
--- a/swfdec/swfdec_as_date.c
+++ b/swfdec/swfdec_as_date.c
@@ -1,5 +1,5 @@
 /* Swfdec
- * Copyright (C) 2007 Benjamin Otte <otte at gnome.org>
+ * Copyright (C) 2007-2008 Benjamin Otte <otte at gnome.org>
  *               2007 Pekka Lampila <pekka.lampila at iki.fi>
  *
  * This library is free software; you can redistribute it and/or
@@ -38,7 +38,7 @@
 #include "swfdec_player_internal.h"
 #include "swfdec_debug.h"
 
-G_DEFINE_TYPE (SwfdecAsDate, swfdec_as_date, SWFDEC_TYPE_AS_OBJECT)
+G_DEFINE_TYPE (SwfdecAsDate, swfdec_as_date, SWFDEC_TYPE_AS_RELAY)
 
 /*
  * Class functions
@@ -1048,7 +1048,7 @@ swfdec_as_date_UTC (SwfdecAsContext *cx, SwfdecAsObject *object, guint argc,
 
 // Constructor
 
-SWFDEC_AS_CONSTRUCTOR (103, 256, swfdec_as_date_construct, swfdec_as_date_get_type)
+SWFDEC_AS_NATIVE (103, 256, swfdec_as_date_construct)
 void
 swfdec_as_date_construct (SwfdecAsContext *cx, SwfdecAsObject *object,
     guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
@@ -1057,11 +1057,12 @@ swfdec_as_date_construct (SwfdecAsContext *cx, SwfdecAsObject *object,
   SwfdecAsDate *date;
 
   if (!cx->frame->construct) {
-    object = g_object_new (SWFDEC_TYPE_AS_DATE, "context", cx, NULL);
+    object = swfdec_as_object_new_empty (cx);
     swfdec_as_object_set_constructor_by_name (object, SWFDEC_AS_STR_Date, NULL);
   }
 
-  date = SWFDEC_AS_DATE (object);
+  date = g_object_new (SWFDEC_TYPE_AS_DATE, "context", cx, NULL);
+  swfdec_as_object_set_relay (object, SWFDEC_AS_RELAY (date));
 
   /* FIXME: find a general solution here */
   if (SWFDEC_IS_PLAYER (swfdec_gc_object_get_context (date))) {
@@ -1194,19 +1195,3 @@ swfdec_as_date_construct (SwfdecAsContext *cx, SwfdecAsObject *object,
   SWFDEC_AS_VALUE_SET_OBJECT (ret, object);
 }
 
-SwfdecAsObject *
-swfdec_as_date_new (SwfdecAsContext *context, double milliseconds,
-    int utc_offset)
-{
-  SwfdecAsObject *ret;
-
-  g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), NULL);
-
-  ret = g_object_new (SWFDEC_TYPE_AS_DATE, "context", context, NULL);
-  swfdec_as_object_set_constructor_by_name (ret, SWFDEC_AS_STR_Date, NULL);
-
-  SWFDEC_AS_DATE (ret)->milliseconds = milliseconds;
-  SWFDEC_AS_DATE (ret)->utc_offset = utc_offset;
-
-  return ret;
-}
diff --git a/swfdec/swfdec_as_date.h b/swfdec/swfdec_as_date.h
index ceacce0..3cfabde 100644
--- a/swfdec/swfdec_as_date.h
+++ b/swfdec/swfdec_as_date.h
@@ -1,5 +1,5 @@
 /* Swfdec
- * Copyright (C) 2007 Benjamin Otte <otte at gnome.org>
+ * Copyright (C) 2007-2008 Benjamin Otte <otte at gnome.org>
  *               2007 Pekka Lampila <pekka.lampila at iki.fi>
  *
  * This library is free software; you can redistribute it and/or
@@ -21,9 +21,8 @@
 #ifndef _SWFDEC_AS_DATE_H_
 #define _SWFDEC_AS_DATE_H_
 
-#include <swfdec/swfdec_as_object.h>
+#include <swfdec/swfdec_as_relay.h>
 #include <swfdec/swfdec_as_types.h>
-#include <swfdec/swfdec_script.h>
 
 G_BEGIN_DECLS
 
@@ -38,7 +37,7 @@ typedef struct _SwfdecAsDateClass SwfdecAsDateClass;
 #define SWFDEC_AS_DATE_GET_CLASS(obj)          (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFDEC_TYPE_AS_DATE, SwfdecAsDateClass))
 
 struct _SwfdecAsDate {
-  SwfdecAsObject	object;
+  SwfdecAsRelay		relay;
 
   // time from epoch in UTC
   double		milliseconds;
@@ -48,15 +47,11 @@ struct _SwfdecAsDate {
 };
 
 struct _SwfdecAsDateClass {
-  SwfdecAsObjectClass	object_class;
+  SwfdecAsRelayClass	relay_class;
 };
 
 GType		swfdec_as_date_get_type	(void);
 
-SwfdecAsObject *swfdec_as_date_new		(SwfdecAsContext *	context,
-						 double			milliseconds,
-						 int			utc_offset);
-
 
 G_END_DECLS
 #endif
diff --git a/swfdec/swfdec_as_internal.h b/swfdec/swfdec_as_internal.h
index 749ebc2..a9d7973 100644
--- a/swfdec/swfdec_as_internal.h
+++ b/swfdec/swfdec_as_internal.h
@@ -71,10 +71,14 @@ void		swfdec_as_object_add_native_variable (SwfdecAsObject *	object,
 						 const char *		variable,
 						 SwfdecAsNative		get,
 						 SwfdecAsNative		set);
-void		swfdec_as_object_set_constructor_by_name 
+SwfdecAsObject * swfdec_as_object_set_constructor_by_name 
 						(SwfdecAsObject *	object,
 						 const char *		name,
 						 ...) G_GNUC_NULL_TERMINATED;
+SwfdecAsObject * swfdec_as_object_set_constructor_by_namev 
+						(SwfdecAsObject *	object,
+						 const char *		name,
+						 va_list		args);
 
 
 G_END_DECLS
diff --git a/swfdec/swfdec_as_interpret.c b/swfdec/swfdec_as_interpret.c
index 6957db3..186b8d0 100644
--- a/swfdec/swfdec_as_interpret.c
+++ b/swfdec/swfdec_as_interpret.c
@@ -938,7 +938,7 @@ swfdec_action_add2_to_primitive (SwfdecAsValue *value)
   if (SWFDEC_IS_MOVIE (object))
     return;
 
-  if (SWFDEC_IS_AS_DATE (object) && swfdec_gc_object_get_context (object)->version > 5)
+  if (SWFDEC_IS_AS_DATE (object->relay) && swfdec_gc_object_get_context (object)->version > 5)
     name = SWFDEC_AS_STR_toString;
   else
     name = SWFDEC_AS_STR_valueOf;
@@ -1790,7 +1790,8 @@ swfdec_action_init_object (SwfdecAsContext *cx, guint action, const guint8 *data
     size = 0;
   }
 
-  object = swfdec_as_object_new (cx);
+  object = swfdec_as_object_new (cx, NULL);
+  swfdec_as_object_set_constructor (object, cx->Object);
   for (i = 0; i < n_args; i++) {
     const char *s = swfdec_as_value_to_string (cx, swfdec_as_stack_peek (cx, 2));
     swfdec_as_object_set_variable (object, s, swfdec_as_stack_peek (cx, 1));
diff --git a/swfdec/swfdec_as_native_function.c b/swfdec/swfdec_as_native_function.c
index 7fbe5b2..0bac0e3 100644
--- a/swfdec/swfdec_as_native_function.c
+++ b/swfdec/swfdec_as_native_function.c
@@ -325,9 +325,13 @@ swfdec_as_native_function_checkv (SwfdecAsContext *cx, SwfdecAsObject *object,
 
   /* check that we got a valid type */
   if (type) {
-    if (!G_TYPE_CHECK_INSTANCE_TYPE (object, type))
-      return FALSE;
-    *result = object;
+    if (G_TYPE_CHECK_INSTANCE_TYPE (object, type)) {
+      *result = object;
+    } else if (object && G_TYPE_CHECK_INSTANCE_TYPE (object->relay, type)) {
+      *result = object->relay;
+    } else {
+	return FALSE;
+    }
   }
   for (i = 0; *args && i < argc; i++, args++) {
     switch (*args) {
diff --git a/swfdec/swfdec_as_object.c b/swfdec/swfdec_as_object.c
index 2e92e08..065fbd4 100644
--- a/swfdec/swfdec_as_object.c
+++ b/swfdec/swfdec_as_object.c
@@ -28,6 +28,7 @@
 #include "swfdec_as_frame_internal.h"
 #include "swfdec_as_internal.h"
 #include "swfdec_as_native_function.h"
+#include "swfdec_as_relay.h"
 #include "swfdec_as_stack.h"
 #include "swfdec_as_string.h"
 #include "swfdec_as_strings.h"
@@ -765,35 +766,45 @@ swfdec_as_object_new_empty (SwfdecAsContext *context)
 {
   g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), NULL);
   
-  return g_object_new (SWFDEC_TYPE_AS_OBJECT, "context", context, NULL);
+  return swfdec_as_object_new (context, NULL);
 }
 
 /**
  * swfdec_as_object_new:
  * @context: a #SwfdecAsContext
+ * @...: %NULL-terminated list of names of the constructor or %NULL for an 
+ *       empty object.
  *
- * Allocates a new Object. This does the same as the Actionscript code 
- * "new Object()".
+ * Allocates a new object and if @name is not %NULL, runs the constructor.
+ * Name is a list of variables to get from the global context as the 
+ * constructor.
  *
  * Returns: the new object
  **/
 SwfdecAsObject *
-swfdec_as_object_new (SwfdecAsContext *context)
+swfdec_as_object_new (SwfdecAsContext *context, ...)
 {
-  SwfdecAsObject *object;
-  SwfdecAsValue val;
+  SwfdecAsObject *object, *fun;
+  SwfdecAsValue rval;
+  const char *name;
+  va_list args;
 
   g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), NULL);
-  g_assert (context->Object);
-  g_assert (context->Object_prototype);
   
-  object = swfdec_as_object_new_empty (context);
-  SWFDEC_AS_VALUE_SET_OBJECT (&val, context->Object);
-  swfdec_as_object_set_variable_and_flags (object, SWFDEC_AS_STR_constructor,
-      &val, SWFDEC_AS_VARIABLE_HIDDEN | SWFDEC_AS_VARIABLE_PERMANENT);
-  SWFDEC_AS_VALUE_SET_OBJECT (&val, context->Object_prototype);
-  swfdec_as_object_set_variable_and_flags (object, SWFDEC_AS_STR___proto__,
-      &val, SWFDEC_AS_VARIABLE_HIDDEN | SWFDEC_AS_VARIABLE_PERMANENT);
+  object = g_object_new (SWFDEC_TYPE_AS_OBJECT, "context", context, NULL);
+  va_start (args, context);
+  name = va_arg (args, const char *);
+  if (name == NULL)
+    return object;
+
+  g_return_val_if_fail (context->global, NULL);
+
+  fun = swfdec_as_object_set_constructor_by_namev (object, name, args);
+  va_end (args);
+  if (SWFDEC_IS_AS_FUNCTION (fun)) {
+    swfdec_as_function_call_full (SWFDEC_AS_FUNCTION (fun), object,
+	TRUE, object->prototype, 0, NULL, &rval);
+  }
   return object;
 }
 
@@ -1320,31 +1331,45 @@ swfdec_as_object_create (SwfdecAsFunction *fun, guint n_args,
   swfdec_as_function_call_full (fun, new, TRUE, new->prototype, n_args, args, return_value);
 }
 
-void
+SwfdecAsObject *
 swfdec_as_object_set_constructor_by_name (SwfdecAsObject *object, const char *name, ...)
 {
+  SwfdecAsObject *ret;
+  va_list args;
+
+  g_return_val_if_fail (SWFDEC_IS_AS_OBJECT (object), NULL);
+  g_return_val_if_fail (name != NULL, NULL);
+
+  va_start (args, name);
+  ret = swfdec_as_object_set_constructor_by_namev (object, name, args);
+  va_end (args);
+  return ret;
+}
+
+SwfdecAsObject *
+swfdec_as_object_set_constructor_by_namev (SwfdecAsObject *object, 
+    const char *name, va_list args)
+{
   SwfdecAsContext *context;
   SwfdecAsObject *cur;
   SwfdecAsValue val;
-  va_list args;
 
-  g_return_if_fail (SWFDEC_IS_AS_OBJECT (object));
-  g_return_if_fail (name != NULL);
+  g_return_val_if_fail (SWFDEC_IS_AS_OBJECT (object), NULL);
+  g_return_val_if_fail (name != NULL, NULL);
 
   context = swfdec_gc_object_get_context (object);
-  va_start (args, name);
   cur = context->global;
   do {
     if (!swfdec_as_object_get_variable (cur, name, &val) || 
 	!SWFDEC_AS_VALUE_IS_OBJECT (&val)) {
       SWFDEC_WARNING ("could not find constructor %s", name);
-      return;
+      return NULL;
     }
     cur = SWFDEC_AS_VALUE_GET_OBJECT (&val);
     name = va_arg (args, const char *);
   } while (name != NULL);
-  va_end (args);
   swfdec_as_object_set_constructor (object, cur);
+  return cur;
 }
 
 /**
@@ -1805,3 +1830,18 @@ swfdec_as_object_resolve (SwfdecAsObject *object)
 
   return klass->resolve (object);
 }
+
+void
+swfdec_as_object_set_relay (SwfdecAsObject *object, SwfdecAsRelay *relay)
+{
+  g_return_if_fail (SWFDEC_IS_AS_OBJECT (object));
+  g_return_if_fail (SWFDEC_IS_AS_RELAY (relay));
+  g_return_if_fail (relay->relay == NULL);
+
+  if (object->relay) {
+    object->relay->relay = NULL;
+  }
+  object->relay = relay;
+  relay->relay = object;
+}
+
diff --git a/swfdec/swfdec_as_object.h b/swfdec/swfdec_as_object.h
index 9293cfa..d426390 100644
--- a/swfdec/swfdec_as_object.h
+++ b/swfdec/swfdec_as_object.h
@@ -65,6 +65,7 @@ struct _SwfdecAsObject {
   GHashTable *		properties;	/* string->SwfdecAsVariable mapping or NULL when not in GC */
   GHashTable *		watches;	/* string->WatchData mapping or NULL when not watching anything */
   GSList *		interfaces;	/* list of interfaces this object implements */
+  SwfdecAsRelay	*	relay;		/* object we relay data to */
 };
 
 struct _SwfdecAsObjectClass {
@@ -101,7 +102,8 @@ struct _SwfdecAsObjectClass {
 
 GType		swfdec_as_object_get_type	(void);
 
-SwfdecAsObject *swfdec_as_object_new		(SwfdecAsContext *    	context);
+SwfdecAsObject *swfdec_as_object_new		(SwfdecAsContext *    	context,
+						 ...) G_GNUC_NULL_TERMINATED;
 SwfdecAsObject *swfdec_as_object_new_empty    	(SwfdecAsContext *    	context);
 void		swfdec_as_object_create		(SwfdecAsFunction *	fun,
 						 guint			n_args,
@@ -112,6 +114,9 @@ void		swfdec_as_object_set_constructor(SwfdecAsObject *	object,
 SwfdecAsObject *swfdec_as_object_resolve	(SwfdecAsObject *	object);
 char *		swfdec_as_object_get_debug	(SwfdecAsObject *	object);
 
+void		swfdec_as_object_set_relay	(SwfdecAsObject *	object,
+						 SwfdecAsRelay *	relay);
+
 /* I'd like to name these [gs]et_property, but binding authors will complain
  * about overlap with g_object_[gs]et_property then */
 #define swfdec_as_object_set_variable(object, variable, value) \
diff --git a/swfdec/swfdec_as_types.h b/swfdec/swfdec_as_types.h
index d5f0d54..84f853f 100644
--- a/swfdec/swfdec_as_types.h
+++ b/swfdec/swfdec_as_types.h
@@ -44,6 +44,7 @@ typedef struct _SwfdecAsFrame SwfdecAsFrame;
 typedef struct _SwfdecAsFunction SwfdecAsFunction;
 typedef struct _SwfdecAsGcable SwfdecAsGcable;
 typedef struct _SwfdecAsObject SwfdecAsObject;
+typedef struct _SwfdecAsRelay SwfdecAsRelay;
 typedef struct _SwfdecAsScope SwfdecAsScope;
 typedef struct _SwfdecAsStack SwfdecAsStack;
 typedef struct _SwfdecAsValue SwfdecAsValue;
diff --git a/swfdec/swfdec_color_as.c b/swfdec/swfdec_color_as.c
index 1a2f410..c90ad70 100644
--- a/swfdec/swfdec_color_as.c
+++ b/swfdec/swfdec_color_as.c
@@ -92,7 +92,7 @@ swfdec_movie_color_getTransform (SwfdecAsContext *cx, SwfdecAsObject *obj,
   if (movie == NULL)
     return;
 
-  ret = swfdec_as_object_new (cx);
+  ret = swfdec_as_object_new (cx, SWFDEC_AS_STR_Object, NULL);
 
   add_variable (ret, SWFDEC_AS_STR_ra, movie->color_transform.ra * 100.0 / 256.0);
   add_variable (ret, SWFDEC_AS_STR_ga, movie->color_transform.ga * 100.0 / 256.0);
diff --git a/swfdec/swfdec_gc_object.c b/swfdec/swfdec_gc_object.c
index db14c01..f3016cc 100644
--- a/swfdec/swfdec_gc_object.c
+++ b/swfdec/swfdec_gc_object.c
@@ -174,7 +174,7 @@ swfdec_gc_object_init (SwfdecGcObject *object)
  *          save you from having to cast it manually. For language bindings, 
  *          please treat this argument as having the #SwfdecGcObject type.
  *
- * Gets the cotext that garbage-collects this object.
+ * Gets the context that garbage-collects this object.
  *
  * Returns: the context this object belongs to
  **/
diff --git a/swfdec/swfdec_net_connection.c b/swfdec/swfdec_net_connection.c
index 8feb65a..d826502 100644
--- a/swfdec/swfdec_net_connection.c
+++ b/swfdec/swfdec_net_connection.c
@@ -66,7 +66,7 @@ swfdec_net_connection_onstatus (SwfdecNetConnection *conn, const char *code,
   SwfdecAsValue value;
   SwfdecAsObject *info;
 
-  info = swfdec_as_object_new (swfdec_gc_object_get_context (conn));
+  info = swfdec_as_object_new (swfdec_gc_object_get_context (conn), SWFDEC_AS_STR_Object, NULL);
   SWFDEC_AS_VALUE_SET_STRING (&value, code);
   swfdec_as_object_set_variable (info, SWFDEC_AS_STR_code, &value);
   SWFDEC_AS_VALUE_SET_STRING (&value, level);
diff --git a/swfdec/swfdec_net_stream.c b/swfdec/swfdec_net_stream.c
index b863997..0884975 100644
--- a/swfdec/swfdec_net_stream.c
+++ b/swfdec/swfdec_net_stream.c
@@ -46,7 +46,7 @@ swfdec_net_stream_onstatus (SwfdecNetStream *stream, const char *code, const cha
   SwfdecAsObject *object;
 
   swfdec_sandbox_use (stream->sandbox);
-  object = swfdec_as_object_new (swfdec_gc_object_get_context (stream));
+  object = swfdec_as_object_new (swfdec_gc_object_get_context (stream), SWFDEC_AS_STR_Object, NULL);
   SWFDEC_INFO ("emitting onStatus for %s %s", level, code);
   SWFDEC_AS_VALUE_SET_STRING (&val, code);
   swfdec_as_object_set_variable (object, SWFDEC_AS_STR_code, &val);
diff --git a/swfdec/swfdec_player_as.c b/swfdec/swfdec_player_as.c
index 4a792ea..0845931 100644
--- a/swfdec/swfdec_player_as.c
+++ b/swfdec/swfdec_player_as.c
@@ -206,7 +206,7 @@ swfdec_player_ASconstructor (SwfdecAsContext *cx, SwfdecAsObject *object,
 
   func = swfdec_get_asnative (cx, x, y);
   if (func) {
-    proto = swfdec_as_object_new (cx);
+    proto = swfdec_as_object_new (cx, SWFDEC_AS_STR_Object, NULL);
 
     SWFDEC_AS_VALUE_SET_OBJECT (&val, proto);
     swfdec_as_object_set_variable_and_flags (SWFDEC_AS_OBJECT (func),
diff --git a/swfdec/swfdec_sound_object.c b/swfdec/swfdec_sound_object.c
index 02756cc..f7dc144 100644
--- a/swfdec/swfdec_sound_object.c
+++ b/swfdec/swfdec_sound_object.c
@@ -156,7 +156,7 @@ swfdec_sound_object_getTransform (SwfdecAsContext *cx, SwfdecAsObject *object,
   if (matrix == NULL)
     return;
 
-  obj = swfdec_as_object_new (cx);
+  obj = swfdec_as_object_new (cx, SWFDEC_AS_STR_Object, NULL);
 
   swfdec_as_value_set_integer (cx, &val, matrix->ll);
   swfdec_as_object_set_variable (obj, SWFDEC_AS_STR_ll, &val);
diff --git a/swfdec/swfdec_sprite_movie_as.c b/swfdec/swfdec_sprite_movie_as.c
index 2d6f76b..17dc8b7 100644
--- a/swfdec/swfdec_sprite_movie_as.c
+++ b/swfdec/swfdec_sprite_movie_as.c
@@ -992,7 +992,7 @@ swfdec_sprite_movie_init_context (SwfdecPlayer *player)
   movie = SWFDEC_AS_OBJECT (swfdec_as_object_add_function (context->global, 
       SWFDEC_AS_STR_MovieClip, NULL));
   SWFDEC_SANDBOX (context->global)->MovieClip = movie;
-  proto = swfdec_as_object_new (context);
+  proto = swfdec_as_object_new (context, SWFDEC_AS_STR_Object, NULL);
   SWFDEC_AS_VALUE_SET_OBJECT (&val, proto);
   swfdec_as_object_set_variable_and_flags (movie,
       SWFDEC_AS_STR_prototype, &val, SWFDEC_AS_VARIABLE_HIDDEN |
commit 3fb4eb3eba80b7a306fa3dd137a990e9b8959177
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Oct 20 01:06:51 2008 +0200

    add length of the string to the SwfdecAsStringValue

diff --git a/swfdec/swfdec_as_context.c b/swfdec/swfdec_as_context.c
index d6ecc2a..adda5b8 100644
--- a/swfdec/swfdec_as_context.c
+++ b/swfdec/swfdec_as_context.c
@@ -272,11 +272,9 @@ static void
 swfdec_as_context_collect_string (SwfdecAsContext *context, gpointer gc)
 {
   SwfdecAsStringValue *string;
-  gsize size;
 
   string = gc;
-  size = strlen (string->string) + 1 + sizeof (SwfdecAsStringValue);
-  swfdec_as_gcable_free (context, gc, size);
+  swfdec_as_gcable_free (context, gc, sizeof (SwfdecAsStringValue) + string->length + 1);
 }
 
 static void
@@ -581,7 +579,7 @@ swfdec_as_context_init (SwfdecAsContext *context)
   context->constant_pools = g_hash_table_new (g_direct_hash, g_direct_equal);
 
   for (s = swfdec_as_strings; s->next; s = (const SwfdecAsStringValue *) 
-      ((const guint8 *) (s + 1) + strlen (s->string) + 1)) {
+      ((const guint8 *) (s + 1) + s->length + 1)) {
     g_hash_table_insert (context->interned_strings, (gpointer) s->string, (gpointer) s);
   }
   context->rand = g_rand_new ();
@@ -594,12 +592,10 @@ static const char *
 swfdec_as_context_create_string (SwfdecAsContext *context, const char *string, gsize len)
 {
   SwfdecAsStringValue *new;
-  gsize size;
 
-  size = sizeof (SwfdecAsStringValue) + len + 1;
-  new = swfdec_as_gcable_alloc (context, size);
-  memcpy (new->string, string, len + 1);
-  g_assert (sizeof (SwfdecAsStringValue) == ((guint8 *) new->string - (guint8 *) new));
+  new = swfdec_as_gcable_alloc (context, sizeof (SwfdecAsStringValue) + len + 1);
+  new->length = len;
+  memcpy (new->string, string, new->length + 1);
   g_hash_table_insert (context->interned_strings, new->string, new);
   SWFDEC_AS_GCABLE_SET_NEXT (new, context->strings);
   context->strings = new;
diff --git a/swfdec/swfdec_as_string_value.c b/swfdec/swfdec_as_string_value.c
new file mode 100644
index 0000000..036b919
--- /dev/null
+++ b/swfdec/swfdec_as_string_value.c
@@ -0,0 +1,727 @@
+/* Swfdec
+ * Copyright (C) 2007-2008 Benjamin Otte <otte at gnome.org>
+ *
+ * This library 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 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <math.h>
+#include <string.h>
+
+#include "swfdec_as_types.h"
+#include "swfdec_as_context.h"
+#include "swfdec_as_function.h"
+#include "swfdec_as_gcable.h"
+#include "swfdec_as_number.h"
+#include "swfdec_as_object.h"
+#include "swfdec_as_stack.h"
+#include "swfdec_as_string.h"
+#include "swfdec_as_strings.h"
+#include "swfdec_as_super.h"
+#include "swfdec_debug.h"
+#include "swfdec_internal.h"
+#include "swfdec_movie.h"
+
+/*** GTK-DOC ***/
+
+/**
+ * SECTION:SwfdecAsValue
+ * @title: SwfdecAsValue
+ * @short_description: exchanging values with the Actionscript engine
+ *
+ * This section describes how values are handled inside the Actionscript 
+ * engine. Since Actionscript is a dynamically typed language, the variable type 
+ * has to be carried with every value. #SwfdecAsValue accomplishes that. Swfdec
+ * allows two possible ways of accessing these values: The common method is to
+ * use the provided functions to explicitly convert the values to a given type
+ * with a function such as swfdec_as_value_to_string (). This is convenient, 
+ * but can be very slow as it can call back into the Actionscript engine when
+ * converting various objects. So it can be unsuitable in some cases.
+ * A different possibiltiy is accessing the values directly using the accessor
+ * macros. You must check the type before doing so though. For setting values,
+ * there only exist macros, since type conversion is not necessary.
+ */
+
+/**
+ * SwfdecAsValueType:
+ * @SWFDEC_AS_TYPE_UNDEFINED: the special undefined value
+ * @SWFDEC_AS_TYPE_BOOLEAN: a boolean value - true or false
+ * @SWFDEC_AS_TYPE_INT: reserved value for integers. Should the need arise for
+ *                      performance enhancements - especially on embedded 
+ *                      devices - it might be useful to implement this type.
+ *                      For now, this type will never appear in Swfdec. Using 
+ *                      it will cause Swfdec to crash.
+ * @SWFDEC_AS_TYPE_NUMBER: a double value - also used for integer numbers
+ * @SWFDEC_AS_TYPE_STRING: a string. Strings are garbage-collected and unique.
+ * @SWFDEC_AS_TYPE_NULL: the spaecial null value
+ * @SWFDEC_AS_TYPE_OBJECT: an object - must be of type #SwfdecAsObject
+ *
+ * These are the possible values the Swfdec Actionscript engine knows about.
+ */
+
+/**
+ * SwfdecAsValue:
+ * @type: the type of this value.
+ *
+ * This is the type used to present an opaque value in the Actionscript 
+ * engine. See #SwfdecAsValueType for possible types. It's similar in 
+ * spirit to #GValue. The value held is garbage-collected. Apart from the type 
+ * member, use the provided macros to access this structure.
+ * <note>If you memset a SwfdecAsValue to 0, it is a valid undefined value.</note>
+ */
+
+/**
+ * SWFDEC_AS_VALUE_SET_UNDEFINED:
+ * @val: value to set as undefined
+ *
+ * Sets @val to the special undefined value. If you create a temporary value, 
+ * you can instead use code such as |[ SwfdecAsValue val = { 0, }; ]|
+ */
+
+/**
+ * SWFDEC_AS_VALUE_GET_BOOLEAN:
+ * @val: value to get, the value must reference a boolean
+ *
+ * Gets the boolean associated with value. If you are not sure if the value is
+ * a boolean, use swfdec_as_value_to_boolean () instead.
+ *
+ * Returns: %TRUE or %FALSE
+ */
+
+/**
+ * SWFDEC_AS_VALUE_SET_BOOLEAN:
+ * @val: value to set
+ * @b: boolean value to set, must be either %TRUE or %FALSE
+ *
+ * Sets @val to the specified boolean value.
+ */
+
+/**
+ * SWFDEC_AS_VALUE_GET_NUMBER:
+ * @val: value to get, the value must reference a number
+ *
+ * Gets the number associated with @val. If you are not sure that the value is
+ * a valid number value, consider using swfdec_as_value_to_number() or 
+ * swfdec_as_value_to_int() instead.
+ *
+ * Returns: a double. It can be NaN or +-Infinity, but not -0.0
+ */
+
+/**
+ * SWFDEC_AS_VALUE_GET_STRING:
+ * @val: value to get, the value must reference a string
+ *
+ * Gets the string associated with @val. If you are not sure that the value is
+ * a string value, consider using swfdec_as_value_to_string() instead.
+ *
+ * Returns: a garbage-collected string.
+ */
+
+/**
+ * SWFDEC_AS_VALUE_SET_STRING:
+ * @val: value to set
+ * @s: garbage-collected string to use
+ *
+ * Sets @val to the given string value.
+ */
+
+/**
+ * SWFDEC_AS_VALUE_SET_NULL:
+ * @val: value to set
+ *
+ * Sets @val to the special null value.
+ */
+
+/**
+ * SWFDEC_AS_VALUE_GET_OBJECT:
+ * @val: value to get, the value must reference an object
+ *
+ * Gets the object associated with @val. If you are not sure that the value is
+ * an object value, consider using swfdec_as_value_to_object() instead.
+ *
+ * Returns: a #SwfdecAsObject
+ */
+
+/**
+ * SWFDEC_AS_VALUE_SET_OBJECT:
+ * @val: value to set
+ * @o: garbage-collected #SwfdecAsObject to use
+ *
+ * Sets @val to the given object. The object must have been added to the 
+ * garbage collector via swfdec_as_object_add() previously.
+ */
+
+/*** actual code ***/
+
+/**
+ * swfdec_as_value_set_int:
+ * @val: value to set
+ * @i: integer value to set
+ *
+ * Sets @val to the given value. Currently this function is a macro that calls
+ * swfdec_as_value_set_number(), but this may change in future versions of
+ * Swfdec.
+ */
+
+/**
+ * swfdec_as_value_set_number:
+ * @context: The context to use
+ * @val: value to set
+ * @number: double value to set
+ *
+ * Sets @val to the given value. If you are sure the value is a valid
+ * integer value, use wfdec_as_value_set_int() instead.
+ */
+void
+swfdec_as_value_set_number (SwfdecAsContext *context, SwfdecAsValue *val,
+    double d)
+{
+  SwfdecAsDoubleValue *dval;
+
+  g_return_if_fail (SWFDEC_IS_AS_CONTEXT (context));
+  g_return_if_fail (val != NULL);
+
+  dval = swfdec_as_gcable_new (context, SwfdecAsDoubleValue);
+  dval->number = d;
+  SWFDEC_AS_GCABLE_SET_NEXT (dval, context->numbers);
+  context->numbers = dval;
+
+  val->type = SWFDEC_AS_TYPE_NUMBER;
+  val->value.number = dval;
+}
+
+/**
+ * swfdec_as_str_concat:
+ * @cx: a #SwfdecAsContext
+ * @s1: first string
+ * @s2: second string
+ *
+ * Convenience function to concatenate two garbage-collected strings. This
+ * function is equivalent to g_strconcat ().
+ *
+ * Returns: A new garbage-collected string
+ **/
+const char *
+swfdec_as_str_concat (SwfdecAsContext *cx, const char * s1, const char *s2)
+{
+  const char *ret;
+  char *s;
+
+  g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (cx), SWFDEC_AS_STR_EMPTY);
+  g_return_val_if_fail (s1, SWFDEC_AS_STR_EMPTY);
+  g_return_val_if_fail (s2, SWFDEC_AS_STR_EMPTY);
+
+  s = g_strconcat (s1, s2, NULL);
+  ret = swfdec_as_context_get_string (cx, s);
+  g_free (s);
+
+  return ret;
+}
+
+/**
+ * swfdec_as_integer_to_string:
+ * @context: a #SwfdecAsContext
+ * @i: an integer that fits into 32 bits
+ *
+ * Converts @d into a string using the same conversion algorithm as the 
+ * official Flash player.
+ *
+ * Returns: a garbage-collected string
+ **/
+const char *
+swfdec_as_integer_to_string (SwfdecAsContext *context, int i)
+{
+  return swfdec_as_context_give_string (context, g_strdup_printf ("%d", i));
+}
+
+/**
+ * swfdec_as_double_to_string:
+ * @context: a #SwfdecAsContext
+ * @d: a double
+ *
+ * Converts @d into a string using the same conversion algorithm as the 
+ * official Flash player.
+ *
+ * Returns: a garbage-collected string
+ **/
+/* FIXME: this function is still buggy - and it's ugly as hell.
+ * Someone with the right expertise should rewrite it 
+ * Some pointers:
+ * http://www.cs.indiana.edu/~burger/FP-Printing-PLDI96.pdf
+ * http://lxr.mozilla.org/mozilla/source/js/tamarin/core/MathUtils.cpp
+ */
+const char *
+swfdec_as_double_to_string (SwfdecAsContext *context, double d)
+{
+  gboolean found = FALSE, gotdot = FALSE;
+  guint digits = 15;
+  char tmp[50], *end, *start, *s;
+
+  g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), SWFDEC_AS_STR_EMPTY);
+
+  if (isnan (d))
+    return SWFDEC_AS_STR_NaN;
+  if (isinf (d))
+    return d < 0 ? SWFDEC_AS_STR__Infinity : SWFDEC_AS_STR_Infinity;
+  /* stupid -0.0 */
+  if (fabs (d) == 0.0)
+    return SWFDEC_AS_STR_0;
+
+  tmp[0] = ' ';
+  s = &tmp[1];
+  if (ABS (d) > 0.00001 && ABS (d) < 1e+15) {
+    g_ascii_formatd (s, 50, "%.22f", d);
+  } else {
+    g_ascii_formatd (s, 50, "%.25e", d);
+  }
+  start = s;
+  /* skip - sign */
+  if (*start == '-')
+    start++;
+  /* count digits (maximum allowed is 15) */
+  while (digits) {
+    if (*start == '.') {
+      start++;
+      gotdot = TRUE;
+      continue;
+    }
+    if (*start < '0' || *start > '9')
+      break;
+    if (found || *start != '0') {
+      digits--;
+      found = TRUE;
+    }
+    start++;
+  }
+  end = start;
+  /* go to end of string */
+  while (*end != 'e' && *end != 0)
+    end++;
+  /* round using the next digit */
+  if (*start >= '5' && *start <= '9') {
+    char *finish = NULL;
+    /* skip all 9s at the end */
+    while (start[-1] == '9')
+      start--;
+    /* if we're before the dot, replace 9s with 0s */
+    if (start[-1] == '.') {
+      finish = start;
+      start--;
+    }
+    while (start[-1] == '9') {
+      start[-1] = '0';
+      start--;
+    }
+    /* write out correct number */
+    if (start[-1] == '-') {
+      s--;
+      start[-2] = '-';
+      start[-1] = '1';
+    } else if (start[-1] == ' ') {
+      s--;
+      start[-1] = '1';
+    } else {
+      start[-1]++;
+    }
+    /* reposition cursor at end */
+    if (finish)
+      start = finish;
+  }
+  /* remove trailing zeros (note we skipped zero above, so there will be non-0 bytes left) */
+  if (gotdot) {
+    while (start[-1] == '0')
+      start--;
+    if (start[-1] == '.')
+      start--;
+  }
+  /* add exponent */
+  if (*end == 'e') {
+    /* 'e' */
+    *start++ = *end++;
+    /* + or - */
+    *start++ = *end++;
+    /* skip 0s */
+    while (*end == '0')
+      end++;
+    /* add rest */
+    while (*end != 0)
+      *start++ = *end++;
+  }
+  /* end string */
+  *start = 0;
+  return swfdec_as_context_get_string (context, s);
+}
+
+/**
+ * swfdec_as_value_to_string:
+ * @context: a #SwfdecAsContext
+ * @value: value to be expressed as string
+ *
+ * Converts @value to a string according to the rules of Flash. This might 
+ * cause calling back into the script engine if the @value is an object. In
+ * that case, the object's valueOf function is called. 
+ * <warning>Never use this function for debugging purposes.</warning>
+ *
+ * Returns: a garbage-collected string representing @value. The value will 
+ *          never be %NULL.
+ **/
+const char *
+swfdec_as_value_to_string (SwfdecAsContext *context, const SwfdecAsValue *value)
+{
+  g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), SWFDEC_AS_STR_EMPTY);
+  g_return_val_if_fail (SWFDEC_IS_AS_VALUE (value), SWFDEC_AS_STR_EMPTY);
+
+  switch (SWFDEC_AS_VALUE_GET_TYPE (value)) {
+    case SWFDEC_AS_TYPE_STRING:
+      return SWFDEC_AS_VALUE_GET_STRING (value);
+    case SWFDEC_AS_TYPE_UNDEFINED:
+      if (context->version > 6)
+	return SWFDEC_AS_STR_undefined;
+      else
+	return SWFDEC_AS_STR_EMPTY;
+    case SWFDEC_AS_TYPE_BOOLEAN:
+      return SWFDEC_AS_VALUE_GET_BOOLEAN (value) ? SWFDEC_AS_STR_true : SWFDEC_AS_STR_false;
+    case SWFDEC_AS_TYPE_NULL:
+      return SWFDEC_AS_STR_null;
+    case SWFDEC_AS_TYPE_NUMBER:
+      return swfdec_as_double_to_string (context, SWFDEC_AS_VALUE_GET_NUMBER (value));
+    case SWFDEC_AS_TYPE_OBJECT:
+      {
+	SwfdecAsObject *object = SWFDEC_AS_VALUE_GET_OBJECT (value);
+	if (SWFDEC_IS_MOVIE (object)) {
+	  SwfdecMovie *movie = swfdec_movie_resolve (SWFDEC_MOVIE (object));
+	  if (movie == NULL) {
+	    return SWFDEC_AS_STR_EMPTY;
+	  } else {
+	    char *str = swfdec_movie_get_path (SWFDEC_MOVIE (object), TRUE);
+	    return swfdec_as_context_give_string (context, str);
+	  }
+	} else if (SWFDEC_IS_AS_STRING (object)) {
+	  return SWFDEC_AS_STRING (object)->string;
+	} else {
+	  SwfdecAsValue ret;
+	  swfdec_as_object_call (object, SWFDEC_AS_STR_toString, 0, NULL, &ret);
+	  if (SWFDEC_AS_VALUE_IS_STRING (&ret))
+	    return SWFDEC_AS_VALUE_GET_STRING (&ret);
+	  else if (SWFDEC_IS_AS_SUPER (SWFDEC_AS_VALUE_GET_OBJECT (value)))
+	    return SWFDEC_AS_STR__type_Object_;
+	  else if (SWFDEC_IS_AS_FUNCTION (SWFDEC_AS_VALUE_GET_OBJECT (value)))
+	    return SWFDEC_AS_STR__type_Function_;
+	  else
+	    return SWFDEC_AS_STR__type_Object_;
+	}
+      }
+    case SWFDEC_AS_TYPE_INT:
+    default:
+      g_assert_not_reached ();
+      return SWFDEC_AS_STR_EMPTY;
+  }
+}
+
+/**
+ * swfdec_as_value_to_debug:
+ * @value: a #SwfdecAsValue
+ *
+ * Converts the given @value to a string in a safe way. It will not call into
+ * the scripting engine. Its intended use is for output in debuggers.
+ *
+ * Returns: a newly allocated string. Free with g_free().
+ **/
+char *
+swfdec_as_value_to_debug (const SwfdecAsValue *value)
+{
+  g_return_val_if_fail (SWFDEC_IS_AS_VALUE (value), NULL);
+
+  switch (SWFDEC_AS_VALUE_GET_TYPE (value)) {
+    case SWFDEC_AS_TYPE_STRING:
+      return g_shell_quote (SWFDEC_AS_VALUE_GET_STRING (value));
+    case SWFDEC_AS_TYPE_UNDEFINED:
+      return g_strdup ("undefined");
+    case SWFDEC_AS_TYPE_BOOLEAN:
+      return g_strdup (SWFDEC_AS_VALUE_GET_BOOLEAN (value) ? "true" : "false");
+    case SWFDEC_AS_TYPE_NULL:
+      return g_strdup ("null");
+    case SWFDEC_AS_TYPE_NUMBER:
+      return g_strdup_printf ("%g", SWFDEC_AS_VALUE_GET_NUMBER (value));
+    case SWFDEC_AS_TYPE_OBJECT:
+      return swfdec_as_object_get_debug (SWFDEC_AS_VALUE_GET_OBJECT (value));
+    case SWFDEC_AS_TYPE_INT:
+    default:
+      g_assert_not_reached ();
+      return NULL;
+  }
+}
+
+/**
+ * swfdec_as_value_to_number:
+ * @context: a #SwfdecAsContext
+ * @value: a #SwfdecAsValue used by context
+ *
+ * Converts the value to a number according to Flash's conversion routines and
+ * the current Flash version. This conversion routine is similar, but not equal
+ * to ECMAScript. For objects, it can call back into the script engine by 
+ * calling the object's valueOf function.
+ *
+ * Returns: a double value. It can be NaN or +-Infinity. It will not be -0.0.
+ **/
+double
+swfdec_as_value_to_number (SwfdecAsContext *context, const SwfdecAsValue *value)
+{
+  SwfdecAsValue tmp;
+
+  g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), 0.0);
+  g_return_val_if_fail (SWFDEC_IS_AS_VALUE (value), 0.0);
+
+  tmp = *value;
+  swfdec_as_value_to_primitive (&tmp);
+
+  switch (tmp.type) {
+    case SWFDEC_AS_TYPE_UNDEFINED:
+    case SWFDEC_AS_TYPE_NULL:
+      return (context->version >= 7) ? NAN : 0.0;
+    case SWFDEC_AS_TYPE_BOOLEAN:
+      return SWFDEC_AS_VALUE_GET_BOOLEAN (&tmp) ? 1 : 0;
+    case SWFDEC_AS_TYPE_NUMBER:
+      return SWFDEC_AS_VALUE_GET_NUMBER (&tmp);
+    case SWFDEC_AS_TYPE_STRING:
+      {
+	const char *s;
+	char *end;
+	double d;
+	
+	// FIXME: We should most likely copy Tamarin's code here (MathUtils.cpp)
+	s = SWFDEC_AS_VALUE_GET_STRING (&tmp);
+	if (s == SWFDEC_AS_STR_EMPTY)
+	  return (context->version >= 5) ? NAN : 0.0;
+	if (context->version > 5 && s[0] == '0' &&
+	    (s[1] == 'x' || s[1] == 'X')) {
+	  d = g_ascii_strtoll (s + 2, &end, 16);
+	} else if (context->version > 5 &&
+	    (s[0] == '0' || ((s[0] == '+' || s[0] == '-') && s[1] == '0')) &&
+	    s[strspn (s+1, "01234567")+1] == '\0') {
+	  d = g_ascii_strtoll (s, &end, 8);
+	} else {
+	  if (strpbrk (s, "xXiI") != NULL)
+	    return (context->version >= 5) ? NAN : 0.0;
+	  d = g_ascii_strtod (s, &end);
+	}
+	if (*end == '\0' || context->version < 5)
+	  return d == -0.0 ? 0.0 : d;
+	else
+	  return NAN;
+      }
+    case SWFDEC_AS_TYPE_OBJECT:
+      return (context->version >= 5) ? NAN : 0.0;
+    case SWFDEC_AS_TYPE_INT:
+    default:
+      g_assert_not_reached ();
+      return NAN;
+  }
+}
+
+/**
+ * swfdec_as_double_to_integer:
+ * @d: any double
+ *
+ * Converts the given double to an integer using the same rules as the Flash
+ * player.
+ *
+ * Returns: an integer
+ **/
+int
+swfdec_as_double_to_integer (double d)
+{
+  if (!isfinite (d))
+    return 0;
+  if (d < 0) {
+    d = fmod (-d, 4294967296.0);
+    return - (guint) d;
+  } else {
+    d = fmod (d, 4294967296.0);
+    return (guint) d;
+  }
+}
+
+/**
+ * swfdec_as_value_to_integer:
+ * @context: a #SwfdecAsContext
+ * @value: value to convert
+ *
+ * Converts the given value to an integer. This is done similar to the 
+ * conversion used by swfdec_as_value_to_number().
+ *
+ * Returns: An Integer that can be represented in 32 bits.
+ **/
+int
+swfdec_as_value_to_integer (SwfdecAsContext *context, const SwfdecAsValue *value)
+{
+  double d;
+  
+  d = swfdec_as_value_to_number (context, value);
+  return swfdec_as_double_to_integer (d);
+}
+
+/**
+ * swfdec_as_value_to_object:
+ * @context: a #SwfdecAsContext
+ * @value: value to convert
+ *
+ * Converts a given value to its representation as an object. The object 
+ * representation for primitive types is a wrapper object of the corresponding 
+ * class (Number for numbers, String for strings, Boolean for bools). If the 
+ * value does not have an object representing it, such as undefined and null 
+ * values, %NULL is returned.
+ *
+ * Returns: object representing @value or %NULL.
+ **/
+SwfdecAsObject *
+swfdec_as_value_to_object (SwfdecAsContext *context, const SwfdecAsValue *value)
+{
+  SwfdecAsFunction *fun;
+  SwfdecAsValue val;
+  const char *s;
+
+  g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), NULL);
+  g_return_val_if_fail (SWFDEC_IS_AS_VALUE (value), NULL);
+
+  switch (SWFDEC_AS_VALUE_GET_TYPE (value)) {
+    case SWFDEC_AS_TYPE_UNDEFINED:
+    case SWFDEC_AS_TYPE_NULL:
+      return NULL;
+    case SWFDEC_AS_TYPE_NUMBER:
+      s = SWFDEC_AS_STR_Number;
+      break;
+    case SWFDEC_AS_TYPE_STRING:
+      s = SWFDEC_AS_STR_String;
+      break;
+    case SWFDEC_AS_TYPE_BOOLEAN:
+      s = SWFDEC_AS_STR_Boolean;
+      break;
+    case SWFDEC_AS_TYPE_OBJECT:
+      return SWFDEC_AS_VALUE_GET_OBJECT (value);
+    case SWFDEC_AS_TYPE_INT:
+    default:
+      g_assert_not_reached ();
+      return NULL;
+  }
+
+  swfdec_as_object_get_variable (context->global, s, &val);
+  if (!SWFDEC_AS_VALUE_IS_OBJECT (&val) ||
+      !SWFDEC_IS_AS_FUNCTION (fun = (SwfdecAsFunction *) SWFDEC_AS_VALUE_GET_OBJECT (&val)))
+    return NULL;
+  swfdec_as_object_create (fun, 1, value, &val);
+  if (SWFDEC_AS_VALUE_IS_OBJECT (&val)) {
+    return SWFDEC_AS_VALUE_GET_OBJECT (&val);
+  } else {
+    SWFDEC_ERROR ("did not construct an object");
+    return NULL;
+  }
+}
+
+/**
+* swfdec_as_value_to_boolean:
+* @context: a #SwfdecAsContext
+* @value: value to convert
+*
+* Converts the given value to a boolean according to Flash's rules. Note that
+* these rules changed significantly for strings between Flash 6 and 7.
+*
+* Returns: either %TRUE or %FALSE.
+**/
+gboolean
+swfdec_as_value_to_boolean (SwfdecAsContext *context, const SwfdecAsValue *value)
+{
+  g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), FALSE);
+  g_return_val_if_fail (SWFDEC_IS_AS_VALUE (value), FALSE);
+
+  /* FIXME: what do we do when called in flash 4? */
+  switch (SWFDEC_AS_VALUE_GET_TYPE (value)) {
+    case SWFDEC_AS_TYPE_UNDEFINED:
+    case SWFDEC_AS_TYPE_NULL:
+      return FALSE;
+    case SWFDEC_AS_TYPE_BOOLEAN:
+      return SWFDEC_AS_VALUE_GET_BOOLEAN (value);
+    case SWFDEC_AS_TYPE_NUMBER:
+      {
+	double d = SWFDEC_AS_VALUE_GET_NUMBER (value);
+	return d != 0.0 && !isnan (d);
+      }
+    case SWFDEC_AS_TYPE_STRING:
+      if (context->version <= 6) {
+	double d = swfdec_as_value_to_number (context, value);
+	return d != 0.0 && !isnan (d);
+      } else {
+	return SWFDEC_AS_VALUE_GET_STRING (value) != SWFDEC_AS_STR_EMPTY;
+      }
+    case SWFDEC_AS_TYPE_OBJECT:
+      return TRUE;
+    case SWFDEC_AS_TYPE_INT:
+    default:
+      g_assert_not_reached ();
+      return FALSE;
+  }
+}
+
+/**
+* swfdec_as_value_to_primitive:
+* @value: value to convert
+*
+* Tries to convert the given @value inline to its primitive value. Primitive 
+* values are values that are not objects. If the value is an object, the 
+* object's valueOf function is called. If the result of that function is still 
+* an object, it is returned nonetheless.
+**/
+void
+swfdec_as_value_to_primitive (SwfdecAsValue *value)
+{
+  g_return_if_fail (SWFDEC_IS_AS_VALUE (value));
+
+  if (SWFDEC_AS_VALUE_IS_OBJECT (value) && !SWFDEC_IS_MOVIE (SWFDEC_AS_VALUE_GET_OBJECT (value))) {
+    swfdec_as_object_call (SWFDEC_AS_VALUE_GET_OBJECT (value), SWFDEC_AS_STR_valueOf,
+	0, NULL, value);
+  }
+}
+
+/* from swfdec_internal.h */
+gboolean
+swfdec_as_value_to_twips (SwfdecAsContext *context, const SwfdecAsValue *val, 
+    gboolean is_length, SwfdecTwips *result)
+{
+  double d;
+
+  g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), FALSE);
+  g_return_val_if_fail (val != NULL, FALSE);
+  g_return_val_if_fail (result != NULL, FALSE);
+
+  if (SWFDEC_AS_VALUE_IS_UNDEFINED (val) || SWFDEC_AS_VALUE_IS_NULL (val))
+    return FALSE;
+
+  d = swfdec_as_value_to_number (context, val);
+  if (isnan (d))
+    return FALSE;
+  if (is_length && d < 0)
+    return FALSE;
+
+  d *= SWFDEC_TWIPS_SCALE_FACTOR;
+  *result = swfdec_as_double_to_integer (d);
+  if (is_length)
+    *result = ABS (*result);
+  return TRUE;
+}
+
diff --git a/swfdec/swfdec_as_string_value.h b/swfdec/swfdec_as_string_value.h
new file mode 100644
index 0000000..f2b85a8
--- /dev/null
+++ b/swfdec/swfdec_as_string_value.h
@@ -0,0 +1,37 @@
+/* Swfdec
+ * Copyright (C) 2008 Benjamin Otte <otte at gnome.org>
+ *
+ * This library 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 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+
+#ifndef _SWFDEC_AS_STRING_VALUE_H_
+#define _SWFDEC_AS_STRING_VALUE_H_
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+typedef struct _SwfdecAsStringValue SwfdecAsStringValue;
+struct _SwfdecAsStringValue {
+  SwfdecAsStringValue *	next;
+  gsize			length;
+  char			string[];
+};
+
+
+
+G_END_DECLS
+#endif
diff --git a/swfdec/swfdec_as_strings.c b/swfdec/swfdec_as_strings.c
index 0d7d661..2d9eede 100644
--- a/swfdec/swfdec_as_strings.c
+++ b/swfdec/swfdec_as_strings.c
@@ -26,7 +26,7 @@
 #include "swfdec_as_gcable.h"
 
 
-#define SWFDEC_AS_CONSTANT_STRING(str) { GSIZE_TO_POINTER (SWFDEC_AS_GC_ROOT), str },
+#define SWFDEC_AS_CONSTANT_STRING(str) { GSIZE_TO_POINTER (SWFDEC_AS_GC_ROOT), sizeof (str) - 1, str },
 const SwfdecAsStringValue swfdec_as_strings[] = {
   SWFDEC_AS_CONSTANT_STRING ("")
   SWFDEC_AS_CONSTANT_STRING ("__proto__")
@@ -537,5 +537,5 @@ const SwfdecAsStringValue swfdec_as_strings[] = {
   SWFDEC_AS_CONSTANT_STRING ("auto")
   SWFDEC_AS_CONSTANT_STRING ("Matrix")
   /* add more here */
-  { 0, "" }
+  { 0, 0, "" }
 };
commit fcb918e7b15737a18907429901afd4833a2dd456
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Oct 20 00:44:00 2008 +0200

    make strings Gcables

diff --git a/swfdec/Makefile.am b/swfdec/Makefile.am
index 5d4daf1..b2ee9c5 100644
--- a/swfdec/Makefile.am
+++ b/swfdec/Makefile.am
@@ -190,7 +190,7 @@ libswfdec_ at SWFDEC_MAJORMINOR@_la_SOURCES = \
 
 libswfdec_ at SWFDEC_MAJORMINOR@_la_CFLAGS = \
 	$(GLOBAL_CFLAGS) $(CAIRO_CFLAGS) $(GLIB_CFLAGS) $(PANGO_CFLAGS) \
-	-I$(top_srcdir) -I$(srcdir)/jpeg/ $(LIBOIL_CFLAGS) $(GST_CFLAGS) \ 
+	-I$(top_srcdir) -I$(srcdir)/jpeg/ $(LIBOIL_CFLAGS) $(GST_CFLAGS) \
 	-DG_LOG_DOMAIN=\"Swfdec\"
 libswfdec_ at SWFDEC_MAJORMINOR@_la_LDFLAGS = \
 	$(SYMBOLIC_LDFLAGS) \
@@ -432,11 +432,12 @@ swfdec_as_strings.h: swfdec_as_strings.c
 	( cd $(srcdir) && echo "/* This is a generated file. See swfdec_as_strings.c for details. */" \
 	  && echo "#ifndef _SWFDEC_AS_STRINGS_H_" \
 	  && echo "#define _SWFDEC_AS_STRINGS_H_" \
+	  && echo "#include <swfdec/swfdec_as_types.h>" \
 	  && echo "G_BEGIN_DECLS" \
-	  && echo "extern const char swfdec_as_strings[];" \
+	  && echo "extern const SwfdecAsStringValue swfdec_as_strings[];" \
 	  && grep "  SWFDEC_AS_CONSTANT_STRING" swfdec_as_strings.c \
 	  | sed "s/.*(\"\(.*\)\").*/\1/" \
-	  | LC_ALL="C" $(AWK) '{ if ($$0 == "") name = "EMPTY"; else if ($$0 == ",") name = "COMMA"; else if ($$0 == "/") name = "SLASH"; else name = $$0; gsub("[^a-zA-Z0-9]","_",name); print "#define SWFDEC_AS_STR_" name " &swfdec_as_strings[" x + 1 "]"; x = x + length ($$0) + 2 }' \
+	  | LC_ALL="C" $(AWK) '{ if ($$0 == "") name = "EMPTY"; else if ($$0 == ",") name = "COMMA"; else if ($$0 == "/") name = "SLASH"; else name = $$0; gsub("[^a-zA-Z0-9]","_",name); print "#define SWFDEC_AS_STR_" name " (((SwfdecAsStringValue *) &((guint8 *) swfdec_as_strings)[" (x + 0) " * sizeof (SwfdecAsStringValue) + " (y + 0) "])->string)"; x = x + 1; y = y + length ($$0) + 1 }' \
 	  && echo "G_END_DECLS" \
 	  && echo "#endif" ) > xgen-sas \
 	&& (cmp -s xgen-sas swfdec_as_strings.h || cp xgen-sas swfdec_as_strings.h ) \
diff --git a/swfdec/swfdec_as_context.c b/swfdec/swfdec_as_context.c
index 11f0874..d6ecc2a 100644
--- a/swfdec/swfdec_as_context.c
+++ b/swfdec/swfdec_as_context.c
@@ -250,31 +250,6 @@ swfdec_as_context_unuse_mem (SwfdecAsContext *context, gsize bytes)
 /*** GC ***/
 
 static gboolean
-swfdec_as_context_remove_strings (gpointer key, gpointer value, gpointer data)
-{
-  SwfdecAsContext *context = data;
-  char *string;
-
-  string = (char *) value;
-  /* it doesn't matter that rooted strings aren't destroyed, they're constant */
-  if (string[0] & SWFDEC_AS_GC_ROOT) {
-    SWFDEC_LOG ("rooted: %s", (char *) key);
-    return FALSE;
-  } else if (string[0] & SWFDEC_AS_GC_MARK) {
-    SWFDEC_LOG ("marked: %s", (char *) key);
-    string[0] &= ~SWFDEC_AS_GC_MARK;
-    return FALSE;
-  } else {
-    gsize len;
-    SWFDEC_LOG ("deleted: %s", (char *) key);
-    len = (strlen ((char *) key) + 2);
-    swfdec_as_context_unuse_mem (context, len);
-    g_slice_free1 (len, value);
-    return TRUE;
-  }
-}
-
-static gboolean
 swfdec_as_context_remove_objects (gpointer key, gpointer value, gpointer debugger)
 {
   SwfdecGcObject *gc;
@@ -294,6 +269,17 @@ swfdec_as_context_remove_objects (gpointer key, gpointer value, gpointer debugge
 }
 
 static void
+swfdec_as_context_collect_string (SwfdecAsContext *context, gpointer gc)
+{
+  SwfdecAsStringValue *string;
+  gsize size;
+
+  string = gc;
+  size = strlen (string->string) + 1 + sizeof (SwfdecAsStringValue);
+  swfdec_as_gcable_free (context, gc, size);
+}
+
+static void
 swfdec_as_context_collect_double (SwfdecAsContext *context, gpointer gc)
 {
   swfdec_as_gcable_free (context, gc, sizeof (SwfdecAsDoubleValue));
@@ -305,11 +291,11 @@ swfdec_as_context_collect (SwfdecAsContext *context)
   /* NB: This functions is called without GC from swfdec_as_context_dispose */
   SWFDEC_INFO (">> collecting garbage");
   
-  g_hash_table_foreach_remove (context->strings, 
-    swfdec_as_context_remove_strings, context);
   g_hash_table_foreach_remove (context->objects, 
     swfdec_as_context_remove_objects, context->debugger);
 
+  context->strings = swfdec_as_gcable_collect (context, context->strings,
+      swfdec_as_context_collect_string);
   context->numbers = swfdec_as_gcable_collect (context, context->numbers,
       swfdec_as_context_collect_double);
 
@@ -326,13 +312,13 @@ swfdec_as_context_collect (SwfdecAsContext *context)
 void
 swfdec_as_string_mark (const char *string)
 {
-  char *str;
+  SwfdecAsStringValue *value;
 
   g_return_if_fail (string != NULL);
 
-  str = (char *) string - 1;
-  if (*str == 0)
-    *str = SWFDEC_AS_GC_MARK;
+  value = (SwfdecAsStringValue *) ((guint8 *) string - G_STRUCT_OFFSET (SwfdecAsStringValue, string));
+  if (!SWFDEC_AS_GCABLE_FLAG_IS_SET (value, SWFDEC_AS_GC_ROOT))
+    SWFDEC_AS_GCABLE_SET_FLAG (value, SWFDEC_AS_GC_MARK);
 }
 
 /**
@@ -351,7 +337,8 @@ swfdec_as_value_mark (SwfdecAsValue *value)
   if (SWFDEC_AS_VALUE_IS_OBJECT (value)) {
     swfdec_gc_object_mark (SWFDEC_AS_VALUE_GET_OBJECT (value));
   } else if (SWFDEC_AS_VALUE_IS_STRING (value)) {
-    swfdec_as_string_mark (SWFDEC_AS_VALUE_GET_STRING (value));
+    if (!SWFDEC_AS_GCABLE_FLAG_IS_SET (value->value.string, SWFDEC_AS_GC_ROOT))
+      SWFDEC_AS_GCABLE_SET_FLAG (value->value.string, SWFDEC_AS_GC_MARK);
   } else if (SWFDEC_AS_VALUE_IS_NUMBER (value)) {
     SWFDEC_AS_GCABLE_SET_FLAG (value->value.number, SWFDEC_AS_GC_MARK);
   }
@@ -527,11 +514,13 @@ swfdec_as_context_dispose (GObject *object)
   if (context->memory != 0) {
     g_critical ("%zu bytes of memory left over\n", context->memory);
   }
-  g_assert (g_hash_table_size (context->objects) == 0);
+  g_assert (context->strings == NULL);
+  g_assert (context->numbers == NULL);
   g_assert (g_hash_table_size (context->constant_pools) == 0);
+  g_assert (g_hash_table_size (context->objects) == 0);
   g_hash_table_destroy (context->constant_pools);
   g_hash_table_destroy (context->objects);
-  g_hash_table_destroy (context->strings);
+  g_hash_table_destroy (context->interned_strings);
   g_rand_free (context->rand);
   if (context->debugger) {
     g_object_unref (context->debugger);
@@ -583,18 +572,18 @@ swfdec_as_context_class_init (SwfdecAsContextClass *klass)
 static void
 swfdec_as_context_init (SwfdecAsContext *context)
 {
-  const char *s;
+  const SwfdecAsStringValue *s;
 
   context->version = G_MAXUINT;
 
-  context->strings = g_hash_table_new (g_str_hash, g_str_equal);
+  context->interned_strings = g_hash_table_new (g_str_hash, g_str_equal);
   context->objects = g_hash_table_new (g_direct_hash, g_direct_equal);
   context->constant_pools = g_hash_table_new (g_direct_hash, g_direct_equal);
 
-  for (s = swfdec_as_strings; *s == '\2'; s += strlen (s) + 1) {
-    g_hash_table_insert (context->strings, (char *) s + 1, (char *) s);
+  for (s = swfdec_as_strings; s->next; s = (const SwfdecAsStringValue *) 
+      ((const guint8 *) (s + 1) + strlen (s->string) + 1)) {
+    g_hash_table_insert (context->interned_strings, (gpointer) s->string, (gpointer) s);
   }
-  g_assert (*s == 0);
   context->rand = g_rand_new ();
   g_get_current_time (&context->start_time);
 }
@@ -604,20 +593,18 @@ swfdec_as_context_init (SwfdecAsContext *context)
 static const char *
 swfdec_as_context_create_string (SwfdecAsContext *context, const char *string, gsize len)
 {
-  char *new;
-  
-  if (!swfdec_as_context_try_use_mem (context, sizeof (char) * (2 + len))) {
-    swfdec_as_context_abort (context, "Out of memory");
-    return SWFDEC_AS_STR_EMPTY;
-  }
-
-  new = g_slice_alloc (2 + len);
-  memcpy (&new[1], string, len);
-  new[len + 1] = 0;
-  new[0] = 0; /* GC flags */
-  g_hash_table_insert (context->strings, new + 1, new);
-
-  return new + 1;
+  SwfdecAsStringValue *new;
+  gsize size;
+
+  size = sizeof (SwfdecAsStringValue) + len + 1;
+  new = swfdec_as_gcable_alloc (context, size);
+  memcpy (new->string, string, len + 1);
+  g_assert (sizeof (SwfdecAsStringValue) == ((guint8 *) new->string - (guint8 *) new));
+  g_hash_table_insert (context->interned_strings, new->string, new);
+  SWFDEC_AS_GCABLE_SET_NEXT (new, context->strings);
+  context->strings = new;
+
+  return new->string;
 }
 
 /**
@@ -634,14 +621,15 @@ swfdec_as_context_create_string (SwfdecAsContext *context, const char *string, g
 const char *
 swfdec_as_context_get_string (SwfdecAsContext *context, const char *string)
 {
-  const char *ret;
+  const SwfdecAsStringValue *ret;
   gsize len;
 
   g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), NULL);
   g_return_val_if_fail (string != NULL, NULL);
 
-  if (g_hash_table_lookup_extended (context->strings, string, (gpointer) &ret, NULL))
-    return ret;
+  ret = g_hash_table_lookup (context->interned_strings, string);
+  if (ret)
+    return ret->string;
 
   len = strlen (string);
   return swfdec_as_context_create_string (context, string, len);
diff --git a/swfdec/swfdec_as_context.h b/swfdec/swfdec_as_context.h
index c4e170a..f3f41ee 100644
--- a/swfdec/swfdec_as_context.h
+++ b/swfdec/swfdec_as_context.h
@@ -56,8 +56,9 @@ struct _SwfdecAsContext {
   /* bookkeeping for GC */
   gsize			memory;		/* total memory currently in use */
   gsize			memory_since_gc;/* memory allocated since last GC run */
-  GHashTable *		strings;	/* string => memory mapping the context manages */
+  GHashTable *		interned_strings;/* string => memory mapping the context manages */
   GHashTable *		objects;	/* all objects the context manages */
+  gpointer		strings;	/* all numbers the context manages */
   gpointer		numbers;	/* all numbers the context manages */
   GHashTable *		constant_pools;	/* memory address => SwfdecConstantPool for all gc'ed pools */
 
diff --git a/swfdec/swfdec_as_gcable.c b/swfdec/swfdec_as_gcable.c
index 5eadb0d..3a02d7c 100644
--- a/swfdec/swfdec_as_gcable.c
+++ b/swfdec/swfdec_as_gcable.c
@@ -84,8 +84,9 @@ swfdec_as_gcable_collect (SwfdecAsContext *context, SwfdecAsGcable *gc,
   cur = gc;
   for (;;) {
     while (cur) {
-      if (SWFDEC_AS_GCABLE_FLAG_IS_SET (cur, SWFDEC_AS_GC_MARK)) {
-	SWFDEC_AS_GCABLE_UNSET_FLAG (cur, SWFDEC_AS_GC_MARK);
+      if (SWFDEC_AS_GCABLE_FLAG_IS_SET (cur, SWFDEC_AS_GC_MARK | SWFDEC_AS_GC_ROOT)) {
+	if (SWFDEC_AS_GCABLE_FLAG_IS_SET (cur, SWFDEC_AS_GC_MARK))
+	  SWFDEC_AS_GCABLE_UNSET_FLAG (cur, SWFDEC_AS_GC_MARK);
 	break;
       }
       tmp = SWFDEC_AS_GCABLE_NEXT (cur);
diff --git a/swfdec/swfdec_as_strings.c b/swfdec/swfdec_as_strings.c
index 44f95a9..0d7d661 100644
--- a/swfdec/swfdec_as_strings.c
+++ b/swfdec/swfdec_as_strings.c
@@ -21,8 +21,13 @@
 #include "config.h"
 #endif
 
-#define SWFDEC_AS_CONSTANT_STRING(str) "\2" str "\0"
-const char swfdec_as_strings[] = 
+#include "swfdec_as_strings.h"
+
+#include "swfdec_as_gcable.h"
+
+
+#define SWFDEC_AS_CONSTANT_STRING(str) { GSIZE_TO_POINTER (SWFDEC_AS_GC_ROOT), str },
+const SwfdecAsStringValue swfdec_as_strings[] = {
   SWFDEC_AS_CONSTANT_STRING ("")
   SWFDEC_AS_CONSTANT_STRING ("__proto__")
   SWFDEC_AS_CONSTANT_STRING ("this")
@@ -532,4 +537,5 @@ const char swfdec_as_strings[] =
   SWFDEC_AS_CONSTANT_STRING ("auto")
   SWFDEC_AS_CONSTANT_STRING ("Matrix")
   /* add more here */
-;
+  { 0, "" }
+};
diff --git a/swfdec/swfdec_as_types.h b/swfdec/swfdec_as_types.h
index 499d15a..d5f0d54 100644
--- a/swfdec/swfdec_as_types.h
+++ b/swfdec/swfdec_as_types.h
@@ -1,5 +1,5 @@
 /* Swfdec
- * Copyright (C) 2007 Benjamin Otte <otte at gnome.org>
+ * Copyright (C) 2007-2008 Benjamin Otte <otte at gnome.org>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -21,6 +21,7 @@
 #define _SWFDEC_AS_TYPES_H_
 
 #include <glib-object.h>
+#include <swfdec/swfdec_as_string_value.h>
 
 G_BEGIN_DECLS
 
@@ -62,7 +63,7 @@ struct _SwfdecAsValue {
   union {
     gboolean		boolean;
     SwfdecAsDoubleValue *number;
-    const char *	string;
+    SwfdecAsStringValue *string;
     SwfdecAsObject *	object;
   } value;
 };
@@ -92,10 +93,10 @@ struct _SwfdecAsDoubleValue {
 #define SWFDEC_AS_VALUE_GET_NUMBER(val) ((val)->value.number->number)
 
 #define SWFDEC_AS_VALUE_IS_STRING(val) (SWFDEC_AS_VALUE_GET_TYPE (val) == SWFDEC_AS_TYPE_STRING)
-#define SWFDEC_AS_VALUE_GET_STRING(val) ((val)->value.string)
+#define SWFDEC_AS_VALUE_GET_STRING(val) ((val)->value.string->string)
 #define SWFDEC_AS_VALUE_SET_STRING(val,s) G_STMT_START { \
   SwfdecAsValue *__val = (val); \
-  (__val)->value.string = s; \
+  (__val)->value.string = (SwfdecAsStringValue *) ((guint8 *) (s) - G_STRUCT_OFFSET (SwfdecAsStringValue, string)); \
   (__val)->type = SWFDEC_AS_TYPE_STRING; \
 } G_STMT_END
 
commit 70baee5192097ec06b0fa9cdd3eaecf233aab99d
Author: Benjamin Otte <otte at gnome.org>
Date:   Sun Oct 19 14:52:55 2008 +0200

    add a eneric Gcable type and use it for doubles
    
    Makes the code cleaner and prepares it for moving of all SwfdecAsValue types
    to be Gcables.

diff --git a/swfdec/Makefile.am b/swfdec/Makefile.am
index e4a3842..5d4daf1 100644
--- a/swfdec/Makefile.am
+++ b/swfdec/Makefile.am
@@ -21,6 +21,7 @@ libswfdec_source_files = \
 	swfdec_as_debugger.c \
 	swfdec_as_frame.c \
 	swfdec_as_function.c \
+	swfdec_as_gcable.c \
 	swfdec_as_interpret.c \
 	swfdec_as_math.c \
 	swfdec_as_native_function.c \
@@ -239,6 +240,7 @@ noinst_HEADERS = \
 	swfdec_as_initialize.h \
 	swfdec_as_internal.h \
 	swfdec_as_date.h \
+	swfdec_as_gcable.h \
 	swfdec_as_interpret.h \
 	swfdec_as_number.h \
 	swfdec_as_script_function.h \
diff --git a/swfdec/swfdec_as_context.c b/swfdec/swfdec_as_context.c
index 2314168..11f0874 100644
--- a/swfdec/swfdec_as_context.c
+++ b/swfdec/swfdec_as_context.c
@@ -28,6 +28,7 @@
 #include "swfdec_as_array.h"
 #include "swfdec_as_frame_internal.h"
 #include "swfdec_as_function.h"
+#include "swfdec_as_gcable.h"
 #include "swfdec_as_initialize.h"
 #include "swfdec_as_internal.h"
 #include "swfdec_as_interpret.h"
@@ -293,10 +294,14 @@ swfdec_as_context_remove_objects (gpointer key, gpointer value, gpointer debugge
 }
 
 static void
-swfdec_as_context_collect (SwfdecAsContext *context)
+swfdec_as_context_collect_double (SwfdecAsContext *context, gpointer gc)
 {
-  SwfdecAsDoubleValue *prev, *cur;
+  swfdec_as_gcable_free (context, gc, sizeof (SwfdecAsDoubleValue));
+}
 
+static void
+swfdec_as_context_collect (SwfdecAsContext *context)
+{
   /* NB: This functions is called without GC from swfdec_as_context_dispose */
   SWFDEC_INFO (">> collecting garbage");
   
@@ -305,32 +310,8 @@ swfdec_as_context_collect (SwfdecAsContext *context)
   g_hash_table_foreach_remove (context->objects, 
     swfdec_as_context_remove_objects, context->debugger);
 
-  prev = NULL;
-  cur = context->numbers;
-  for (;;) {
-    while (cur) {
-      gsize next = GPOINTER_TO_SIZE (cur->next);
-      if (next & SWFDEC_AS_GC_MARK) {
-	cur->next = GSIZE_TO_POINTER (next & ~SWFDEC_AS_GC_MARK);
-	break;
-      }
-      g_slice_free (SwfdecAsDoubleValue, cur);
-      cur = GSIZE_TO_POINTER (next);
-    }
-    if (prev)
-      prev->next = cur;
-    else
-      context->numbers = cur;
-    prev = cur;
-    if (prev == NULL)
-      break;
-    cur = cur->next;
-  }
-  prev = context->numbers;
-  while (prev) {
-    g_assert ((GPOINTER_TO_SIZE (prev) & 3) == 0);
-    prev = prev->next;
-  }
+  context->numbers = swfdec_as_gcable_collect (context, context->numbers,
+      swfdec_as_context_collect_double);
 
   SWFDEC_INFO (">> done collecting garbage");
 }
@@ -372,8 +353,7 @@ swfdec_as_value_mark (SwfdecAsValue *value)
   } else if (SWFDEC_AS_VALUE_IS_STRING (value)) {
     swfdec_as_string_mark (SWFDEC_AS_VALUE_GET_STRING (value));
   } else if (SWFDEC_AS_VALUE_IS_NUMBER (value)) {
-    value->value.number->next = GSIZE_TO_POINTER (
-	GPOINTER_TO_SIZE (value->value.number->next) | SWFDEC_AS_GC_MARK);
+    SWFDEC_AS_GCABLE_SET_FLAG (value->value.number, SWFDEC_AS_GC_MARK);
   }
 }
 
diff --git a/swfdec/swfdec_as_context.h b/swfdec/swfdec_as_context.h
index 6951e3b..c4e170a 100644
--- a/swfdec/swfdec_as_context.h
+++ b/swfdec/swfdec_as_context.h
@@ -58,7 +58,7 @@ struct _SwfdecAsContext {
   gsize			memory_since_gc;/* memory allocated since last GC run */
   GHashTable *		strings;	/* string => memory mapping the context manages */
   GHashTable *		objects;	/* all objects the context manages */
-  SwfdecAsDoubleValue *	numbers;	/* all numbers the context manages */
+  gpointer		numbers;	/* all numbers the context manages */
   GHashTable *		constant_pools;	/* memory address => SwfdecConstantPool for all gc'ed pools */
 
   /* execution state */
diff --git a/swfdec/swfdec_as_gcable.c b/swfdec/swfdec_as_gcable.c
new file mode 100644
index 0000000..5eadb0d
--- /dev/null
+++ b/swfdec/swfdec_as_gcable.c
@@ -0,0 +1,107 @@
+/* Swfdec
+ * Copyright (C) 2008 Benjamin Otte <otte at gnome.org>
+ *
+ * This library 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 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "swfdec_as_gcable.h"
+
+#include "swfdec_as_context.h"
+
+gpointer
+swfdec_as_gcable_alloc (SwfdecAsContext *context, gsize size)
+{
+  SwfdecAsGcable *mem;
+  guint8 diff;
+
+  g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), NULL);
+  g_return_val_if_fail (size > sizeof (SwfdecAsGcable), NULL);
+
+  swfdec_as_context_use_mem (context, size);
+  mem = g_slice_alloc0 (size);
+  if (G_LIKELY ((GPOINTER_TO_SIZE (mem) & SWFDEC_AS_GC_FLAG_MASK) == 0))
+    return mem;
+
+  g_slice_free1 (size, mem);
+  mem = g_slice_alloc0 (size + SWFDEC_AS_GC_FLAG_MASK);
+  diff = GPOINTER_TO_SIZE (mem) & SWFDEC_AS_GC_FLAG_MASK;
+  if (diff == 0)
+    return mem;
+
+  diff = SWFDEC_AS_GC_FLAG_MASK + 1 - diff;
+  mem += diff;
+  g_assert ((GPOINTER_TO_SIZE (mem) & SWFDEC_AS_GC_FLAG_MASK) == 0);
+  SWFDEC_AS_GCABLE_SET_FLAG (mem, SWFDEC_AS_GC_ALIGN);
+  ((guint8 *) mem)[-1] = diff;
+
+  return mem;
+}
+
+void
+swfdec_as_gcable_free (SwfdecAsContext *context, gpointer mem, gsize size)
+{
+  SwfdecAsGcable *gc;
+
+  g_return_if_fail (SWFDEC_IS_AS_CONTEXT (context));
+  g_return_if_fail (mem != NULL);
+  g_return_if_fail (size > sizeof (SwfdecAsGcable));
+
+  gc = mem;
+  swfdec_as_context_unuse_mem (context, size);
+  if (G_UNLIKELY (SWFDEC_AS_GCABLE_FLAG_IS_SET (gc, SWFDEC_AS_GC_ALIGN))) {
+    mem = ((guint8 *) mem) - ((guint8 *) mem)[-1];
+    size += SWFDEC_AS_GC_FLAG_MASK;
+  }
+  g_slice_free1 (size, mem);
+}
+
+SwfdecAsGcable *
+swfdec_as_gcable_collect (SwfdecAsContext *context, SwfdecAsGcable *gc,
+    SwfdecAsGcableDestroyNotify notify)
+{
+  SwfdecAsGcable *prev, *cur, *tmp;
+
+  g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), NULL);
+
+  prev = NULL;
+  cur = gc;
+  for (;;) {
+    while (cur) {
+      if (SWFDEC_AS_GCABLE_FLAG_IS_SET (cur, SWFDEC_AS_GC_MARK)) {
+	SWFDEC_AS_GCABLE_UNSET_FLAG (cur, SWFDEC_AS_GC_MARK);
+	break;
+      }
+      tmp = SWFDEC_AS_GCABLE_NEXT (cur);
+      notify (context, cur);
+      cur = tmp;
+    }
+    if (prev)
+      SWFDEC_AS_GCABLE_SET_NEXT (prev, cur);
+    else
+      gc = cur;
+    prev = cur;
+    if (prev == NULL)
+      break;
+    cur = SWFDEC_AS_GCABLE_NEXT (cur);
+  }
+
+  return gc;
+}
+
diff --git a/swfdec/swfdec_as_gcable.h b/swfdec/swfdec_as_gcable.h
new file mode 100644
index 0000000..2c7a27c
--- /dev/null
+++ b/swfdec/swfdec_as_gcable.h
@@ -0,0 +1,59 @@
+/* Swfdec
+ * Copyright (C) 2008 Benjamin Otte <otte at gnome.org>
+ *
+ * This library 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 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library 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 library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+
+#ifndef _SWFDEC_AS_GCABLE_H_
+#define _SWFDEC_AS_GCABLE_H_
+
+#include <swfdec/swfdec_as_types.h>
+
+G_BEGIN_DECLS
+
+#define SWFDEC_AS_GC_FLAG_MASK 7
+
+#define SWFDEC_AS_GC_MARK (1 << 0)
+#define SWFDEC_AS_GC_ROOT (1 << 1)
+#define SWFDEC_AS_GC_ALIGN (1 << 2)
+
+struct _SwfdecAsGcable {
+  SwfdecAsGcable *	next;
+};
+
+typedef void (* SwfdecAsGcableDestroyNotify) (SwfdecAsContext *context, gpointer mem);
+
+#define SWFDEC_AS_GCABLE_FLAG_IS_SET(gc,flag) (GPOINTER_TO_SIZE((gc)->next) & (flag))
+#define SWFDEC_AS_GCABLE_SET_FLAG(gc,flag) (gc)->next = GSIZE_TO_POINTER (GPOINTER_TO_SIZE((gc)->next) | (flag))
+#define SWFDEC_AS_GCABLE_UNSET_FLAG(gc,flag) (gc)->next = GSIZE_TO_POINTER (GPOINTER_TO_SIZE((gc)->next) & ~(flag))
+
+#define SWFDEC_AS_GCABLE_NEXT(gc) ((SwfdecAsGcable *) GSIZE_TO_POINTER (GPOINTER_TO_SIZE((gc)->next) & ~7))
+#define SWFDEC_AS_GCABLE_SET_NEXT(gc, val) (gc)->next = GSIZE_TO_POINTER (GPOINTER_TO_SIZE (val) | (GPOINTER_TO_SIZE((gc)->next) & 7))
+
+gpointer	swfdec_as_gcable_alloc		(SwfdecAsContext *	context,
+						 gsize			size);
+#define swfdec_as_gcable_new(cx,type) ((type *) swfdec_as_gcable_alloc (cx, sizeof (type)))
+void		swfdec_as_gcable_free		(SwfdecAsContext *	context,
+						 gpointer		mem,
+						 gsize			size);
+
+SwfdecAsGcable *swfdec_as_gcable_collect	(SwfdecAsContext *	context,
+						 SwfdecAsGcable *	gc,
+						 SwfdecAsGcableDestroyNotify notify);
+
+
+G_END_DECLS
+#endif
diff --git a/swfdec/swfdec_as_internal.h b/swfdec/swfdec_as_internal.h
index 04d88f3..749ebc2 100644
--- a/swfdec/swfdec_as_internal.h
+++ b/swfdec/swfdec_as_internal.h
@@ -20,6 +20,7 @@
 #ifndef _SWFDEC_AS_INTERNAL_H_
 #define _SWFDEC_AS_INTERNAL_H_
 
+#include <swfdec/swfdec_as_gcable.h>
 #include <swfdec/swfdec_as_object.h>
 #include <swfdec/swfdec_as_types.h>
 
@@ -34,9 +35,6 @@ G_BEGIN_DECLS
 
 #define SWFDEC_AS_OBJECT_PROTOTYPE_RECURSION_LIMIT 256
 
-#define SWFDEC_AS_GC_MARK (1 << 0)		/* only valid during GC */
-#define SWFDEC_AS_GC_ROOT (1 << 1)		/* for objects: rooted, for strings: static */
-
 void		swfdec_as_function_set_constructor	(SwfdecAsFunction *	fun);
 void		swfdec_as_function_init_context		(SwfdecAsContext *	context);
 
@@ -47,6 +45,9 @@ void		swfdec_as_context_run_init_script (SwfdecAsContext *	context,
 						 const guint8 *		data,
 						 gsize			length,
 						 guint			version);
+void		swfdec_as_context_gc_alloc	(SwfdecAsContext *	context,
+						 gsize			size);
+#define swfdec_as_context_gc_new(context,type) ((type *)swfdec_as_context_gc_alloc ((context), sizeof (type)))
 
 /* swfdec_as_object.c */
 typedef SwfdecAsVariableForeach SwfdecAsVariableForeachRemove;
diff --git a/swfdec/swfdec_as_types.c b/swfdec/swfdec_as_types.c
index b9ef9a8..036b919 100644
--- a/swfdec/swfdec_as_types.c
+++ b/swfdec/swfdec_as_types.c
@@ -25,10 +25,11 @@
 #include <string.h>
 
 #include "swfdec_as_types.h"
-#include "swfdec_as_object.h"
 #include "swfdec_as_context.h"
 #include "swfdec_as_function.h"
+#include "swfdec_as_gcable.h"
 #include "swfdec_as_number.h"
+#include "swfdec_as_object.h"
 #include "swfdec_as_stack.h"
 #include "swfdec_as_string.h"
 #include "swfdec_as_strings.h"
@@ -191,11 +192,18 @@ void
 swfdec_as_value_set_number (SwfdecAsContext *context, SwfdecAsValue *val,
     double d)
 {
+  SwfdecAsDoubleValue *dval;
+
+  g_return_if_fail (SWFDEC_IS_AS_CONTEXT (context));
+  g_return_if_fail (val != NULL);
+
+  dval = swfdec_as_gcable_new (context, SwfdecAsDoubleValue);
+  dval->number = d;
+  SWFDEC_AS_GCABLE_SET_NEXT (dval, context->numbers);
+  context->numbers = dval;
+
   val->type = SWFDEC_AS_TYPE_NUMBER;
-  val->value.number = g_slice_new (SwfdecAsDoubleValue);
-  val->value.number->number = d;
-  val->value.number->next = context->numbers;
-  context->numbers = val->value.number;
+  val->value.number = dval;
 }
 
 /**
diff --git a/swfdec/swfdec_as_types.h b/swfdec/swfdec_as_types.h
index bd82697..499d15a 100644
--- a/swfdec/swfdec_as_types.h
+++ b/swfdec/swfdec_as_types.h
@@ -41,6 +41,7 @@ typedef struct _SwfdecAsDebugger SwfdecAsDebugger;
 typedef struct _SwfdecAsDoubleValue SwfdecAsDoubleValue;
 typedef struct _SwfdecAsFrame SwfdecAsFrame;
 typedef struct _SwfdecAsFunction SwfdecAsFunction;
+typedef struct _SwfdecAsGcable SwfdecAsGcable;
 typedef struct _SwfdecAsObject SwfdecAsObject;
 typedef struct _SwfdecAsScope SwfdecAsScope;
 typedef struct _SwfdecAsStack SwfdecAsStack;
@@ -83,7 +84,7 @@ struct _SwfdecAsValue {
 } G_STMT_END
 
 struct _SwfdecAsDoubleValue {
-  SwfdecAsDoubleValue *	next;
+  SwfdecAsGcable *	next;
   double		number;
 };
 
commit 1642740d6743011d5a8955dc766fbd51f08a7020
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Oct 17 16:52:04 2008 +0200

    introduce a SWFDEC_AS_VALUE_GET_TYPE macro

diff --git a/swfdec/swfdec_as_interpret.c b/swfdec/swfdec_as_interpret.c
index 0788cd2..6957db3 100644
--- a/swfdec/swfdec_as_interpret.c
+++ b/swfdec/swfdec_as_interpret.c
@@ -753,7 +753,7 @@ swfdec_action_trace (SwfdecAsContext *cx, guint action, const guint8 *data, guin
   const char *s;
 
   val = swfdec_as_stack_peek (cx, 1);
-  if (val->type == SWFDEC_AS_TYPE_UNDEFINED) {
+  if (SWFDEC_AS_VALUE_IS_UNDEFINED (val)) {
     s = SWFDEC_AS_STR_undefined;
   } else {
     s = swfdec_as_value_to_string (cx, val);
@@ -1398,7 +1398,7 @@ swfdec_action_equals2_5 (SwfdecAsContext *cx, guint action, const guint8 *data,
       ro = SWFDEC_AS_OBJECT (swfdec_movie_resolve (SWFDEC_MOVIE (ro)));
     } else if (SWFDEC_IS_MOVIE (lo)) {
       swfdec_as_value_to_primitive (rval);
-      rtype = rval->type;
+      rtype = SWFDEC_AS_VALUE_GET_TYPE (rval);
       if (rtype != SWFDEC_AS_TYPE_OBJECT) {
 	cond = FALSE;
 	goto out;
@@ -1406,7 +1406,7 @@ swfdec_action_equals2_5 (SwfdecAsContext *cx, guint action, const guint8 *data,
       ro = SWFDEC_AS_VALUE_GET_OBJECT (rval);
     } else if (SWFDEC_IS_MOVIE (ro)) {
       swfdec_as_value_to_primitive (lval);
-      ltype = lval->type;
+      ltype = SWFDEC_AS_VALUE_GET_TYPE (lval);
       if (ltype != SWFDEC_AS_TYPE_OBJECT) {
 	cond = FALSE;
 	goto out;
@@ -1471,8 +1471,8 @@ swfdec_action_equals2_6 (SwfdecAsContext *cx, guint action, const guint8 *data,
 
   rval = swfdec_as_stack_peek (cx, 1);
   lval = swfdec_as_stack_peek (cx, 2);
-  ltype = lval->type;
-  rtype = rval->type;
+  ltype = SWFDEC_AS_VALUE_GET_TYPE (lval);
+  rtype = SWFDEC_AS_VALUE_GET_TYPE (rval);
   
   /* get objects compared */
   if (ltype == SWFDEC_AS_TYPE_OBJECT && rtype == SWFDEC_AS_TYPE_OBJECT) {
@@ -1484,7 +1484,7 @@ swfdec_action_equals2_6 (SwfdecAsContext *cx, guint action, const guint8 *data,
       ro = SWFDEC_AS_OBJECT (swfdec_movie_resolve (SWFDEC_MOVIE (ro)));
     } else if (SWFDEC_IS_MOVIE (lo)) {
       swfdec_as_value_to_primitive (rval);
-      rtype = rval->type;
+      rtype = SWFDEC_AS_VALUE_GET_TYPE (rval);
       if (rtype != SWFDEC_AS_TYPE_OBJECT) {
 	cond = FALSE;
 	goto out;
@@ -1492,7 +1492,7 @@ swfdec_action_equals2_6 (SwfdecAsContext *cx, guint action, const guint8 *data,
       ro = SWFDEC_AS_VALUE_GET_OBJECT (rval);
     } else if (SWFDEC_IS_MOVIE (ro)) {
       swfdec_as_value_to_primitive (lval);
-      ltype = lval->type;
+      ltype = SWFDEC_AS_VALUE_GET_TYPE (lval);
       if (ltype != SWFDEC_AS_TYPE_OBJECT) {
 	cond = FALSE;
 	goto out;
@@ -1506,13 +1506,13 @@ swfdec_action_equals2_6 (SwfdecAsContext *cx, guint action, const guint8 *data,
   /* if one of the values is an object, call valueOf. 
    * If it's still an object, return FALSE */
   swfdec_as_value_to_primitive (lval);
-  ltype = lval->type;
+  ltype = SWFDEC_AS_VALUE_GET_TYPE (lval);
   if (ltype == SWFDEC_AS_TYPE_OBJECT) {
     cond = FALSE;
     goto out;
   }
   swfdec_as_value_to_primitive (rval);
-  rtype = rval->type;
+  rtype = SWFDEC_AS_VALUE_GET_TYPE (rval);
   if (rtype == SWFDEC_AS_TYPE_OBJECT) {
     cond = FALSE;
     goto out;
@@ -1570,10 +1570,10 @@ swfdec_action_strict_equals (SwfdecAsContext *cx, guint action, const guint8 *da
   rval = swfdec_as_stack_peek (cx, 1);
   lval = swfdec_as_stack_peek (cx, 2);
 
-  if (rval->type != lval->type) {
+  if (SWFDEC_AS_VALUE_GET_TYPE (rval) != SWFDEC_AS_VALUE_GET_TYPE (lval)) {
     cond = FALSE;
   } else {
-    switch (rval->type) {
+    switch (SWFDEC_AS_VALUE_GET_TYPE (rval)) {
       case SWFDEC_AS_TYPE_UNDEFINED:
       case SWFDEC_AS_TYPE_NULL:
 	cond = TRUE;
@@ -2155,7 +2155,7 @@ swfdec_action_type_of (SwfdecAsContext *cx, guint action, const guint8 *data, gu
   const char *type;
 
   val = swfdec_as_stack_peek (cx, 1);
-  switch (val->type) {
+  switch (SWFDEC_AS_VALUE_GET_TYPE (val)) {
     case SWFDEC_AS_TYPE_NUMBER:
       type = SWFDEC_AS_STR_number;
       break;
diff --git a/swfdec/swfdec_as_types.c b/swfdec/swfdec_as_types.c
index c69486e..b9ef9a8 100644
--- a/swfdec/swfdec_as_types.c
+++ b/swfdec/swfdec_as_types.c
@@ -379,7 +379,7 @@ swfdec_as_value_to_string (SwfdecAsContext *context, const SwfdecAsValue *value)
   g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), SWFDEC_AS_STR_EMPTY);
   g_return_val_if_fail (SWFDEC_IS_AS_VALUE (value), SWFDEC_AS_STR_EMPTY);
 
-  switch (value->type) {
+  switch (SWFDEC_AS_VALUE_GET_TYPE (value)) {
     case SWFDEC_AS_TYPE_STRING:
       return SWFDEC_AS_VALUE_GET_STRING (value);
     case SWFDEC_AS_TYPE_UNDEFINED:
@@ -440,7 +440,7 @@ swfdec_as_value_to_debug (const SwfdecAsValue *value)
 {
   g_return_val_if_fail (SWFDEC_IS_AS_VALUE (value), NULL);
 
-  switch (value->type) {
+  switch (SWFDEC_AS_VALUE_GET_TYPE (value)) {
     case SWFDEC_AS_TYPE_STRING:
       return g_shell_quote (SWFDEC_AS_VALUE_GET_STRING (value));
     case SWFDEC_AS_TYPE_UNDEFINED:
@@ -592,7 +592,7 @@ swfdec_as_value_to_object (SwfdecAsContext *context, const SwfdecAsValue *value)
   g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), NULL);
   g_return_val_if_fail (SWFDEC_IS_AS_VALUE (value), NULL);
 
-  switch (value->type) {
+  switch (SWFDEC_AS_VALUE_GET_TYPE (value)) {
     case SWFDEC_AS_TYPE_UNDEFINED:
     case SWFDEC_AS_TYPE_NULL:
       return NULL;
@@ -643,7 +643,7 @@ swfdec_as_value_to_boolean (SwfdecAsContext *context, const SwfdecAsValue *value
   g_return_val_if_fail (SWFDEC_IS_AS_VALUE (value), FALSE);
 
   /* FIXME: what do we do when called in flash 4? */
-  switch (value->type) {
+  switch (SWFDEC_AS_VALUE_GET_TYPE (value)) {
     case SWFDEC_AS_TYPE_UNDEFINED:
     case SWFDEC_AS_TYPE_NULL:
       return FALSE;
diff --git a/swfdec/swfdec_as_types.h b/swfdec/swfdec_as_types.h
index 36b353a..bd82697 100644
--- a/swfdec/swfdec_as_types.h
+++ b/swfdec/swfdec_as_types.h
@@ -66,12 +66,13 @@ struct _SwfdecAsValue {
   } value;
 };
 
-#define SWFDEC_IS_AS_VALUE(val) ((val) != NULL && (val)->type <= SWFDEC_TYPE_AS_OBJECT)
+#define SWFDEC_IS_AS_VALUE(val) ((val) != NULL && SWFDEC_AS_VALUE_GET_TYPE (val) <= SWFDEC_TYPE_AS_OBJECT)
+#define SWFDEC_AS_VALUE_GET_TYPE(val) ((val)->type)
 
-#define SWFDEC_AS_VALUE_IS_UNDEFINED(val) ((val)->type == SWFDEC_AS_TYPE_UNDEFINED)
+#define SWFDEC_AS_VALUE_IS_UNDEFINED(val) (SWFDEC_AS_VALUE_GET_TYPE (val) == SWFDEC_AS_TYPE_UNDEFINED)
 #define SWFDEC_AS_VALUE_SET_UNDEFINED(val) (val)->type = SWFDEC_AS_TYPE_UNDEFINED
 
-#define SWFDEC_AS_VALUE_IS_BOOLEAN(val) ((val)->type == SWFDEC_AS_TYPE_BOOLEAN)
+#define SWFDEC_AS_VALUE_IS_BOOLEAN(val) (SWFDEC_AS_VALUE_GET_TYPE (val) == SWFDEC_AS_TYPE_BOOLEAN)
 #define SWFDEC_AS_VALUE_GET_BOOLEAN(val) ((val)->value.boolean)
 #define SWFDEC_AS_VALUE_SET_BOOLEAN(val,b) G_STMT_START { \
   SwfdecAsValue *__val = (val); \
@@ -86,10 +87,10 @@ struct _SwfdecAsDoubleValue {
   double		number;
 };
 
-#define SWFDEC_AS_VALUE_IS_NUMBER(val) ((val)->type == SWFDEC_AS_TYPE_NUMBER)
+#define SWFDEC_AS_VALUE_IS_NUMBER(val) (SWFDEC_AS_VALUE_GET_TYPE (val) == SWFDEC_AS_TYPE_NUMBER)
 #define SWFDEC_AS_VALUE_GET_NUMBER(val) ((val)->value.number->number)
 
-#define SWFDEC_AS_VALUE_IS_STRING(val) ((val)->type == SWFDEC_AS_TYPE_STRING)
+#define SWFDEC_AS_VALUE_IS_STRING(val) (SWFDEC_AS_VALUE_GET_TYPE (val) == SWFDEC_AS_TYPE_STRING)
 #define SWFDEC_AS_VALUE_GET_STRING(val) ((val)->value.string)
 #define SWFDEC_AS_VALUE_SET_STRING(val,s) G_STMT_START { \
   SwfdecAsValue *__val = (val); \
@@ -97,10 +98,10 @@ struct _SwfdecAsDoubleValue {
   (__val)->type = SWFDEC_AS_TYPE_STRING; \
 } G_STMT_END
 
-#define SWFDEC_AS_VALUE_IS_NULL(val) ((val)->type == SWFDEC_AS_TYPE_NULL)
+#define SWFDEC_AS_VALUE_IS_NULL(val) (SWFDEC_AS_VALUE_GET_TYPE (val) == SWFDEC_AS_TYPE_NULL)
 #define SWFDEC_AS_VALUE_SET_NULL(val) (val)->type = SWFDEC_AS_TYPE_NULL
 
-#define SWFDEC_AS_VALUE_IS_OBJECT(val) ((val)->type == SWFDEC_AS_TYPE_OBJECT)
+#define SWFDEC_AS_VALUE_IS_OBJECT(val) (SWFDEC_AS_VALUE_GET_TYPE (val) == SWFDEC_AS_TYPE_OBJECT)
 #define SWFDEC_AS_VALUE_GET_OBJECT(val) ((val)->value.object)
 #define SWFDEC_AS_VALUE_SET_OBJECT(val,o) G_STMT_START { \
   SwfdecAsValue *__val = (val); \
commit 7fc2912c87658aa16097b917b17346cff9b53cf7
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Oct 17 16:18:03 2008 +0200

    add a test for recent fix

diff --git a/test/trace/Makefile.am b/test/trace/Makefile.am
index eb6651b..446538c 100644
--- a/test/trace/Makefile.am
+++ b/test/trace/Makefile.am
@@ -1340,6 +1340,15 @@ EXTRA_DIST = \
 	equality-7.swf.trace \
 	equality-8.swf \
 	equality-8.swf.trace \
+	equality-nan-5.swf \
+	equality-nan-5.swf.trace \
+	equality-nan-6.swf \
+	equality-nan-6.swf.trace \
+	equality-nan-7.swf \
+	equality-nan-7.swf.trace \
+	equality-nan-8.swf \
+	equality-nan-8.swf.trace \
+	equality-nan.as \
 	equality-old.as \
 	equality-old-5.swf \
 	equality-old-5.swf.trace \
diff --git a/test/trace/equality-nan-5.swf b/test/trace/equality-nan-5.swf
new file mode 100644
index 0000000..3648c1f
Binary files /dev/null and b/test/trace/equality-nan-5.swf differ
diff --git a/test/trace/equality-nan-5.swf.trace b/test/trace/equality-nan-5.swf.trace
new file mode 100644
index 0000000..9b63072
--- /dev/null
+++ b/test/trace/equality-nan-5.swf.trace
@@ -0,0 +1,90 @@
+NaN
+0 == 0 => true
+0 == 1 => false
+0 == 2 => false
+0 == 3 => false
+0 == 4 => false
+0 == 5 => false
+0 == 6 => false
+0 == 7 => false
+0 == 8 => false
+NaN
+1 == 0 => false
+1 == 1 => true
+1 == 2 => false
+1 == 3 => false
+1 == 4 => false
+1 == 5 => false
+1 == 6 => false
+1 == 7 => false
+1 == 8 => false
+NaN
+2 == 0 => false
+2 == 1 => false
+2 == 2 => true
+2 == 3 => true
+2 == 4 => false
+2 == 5 => false
+2 == 6 => false
+2 == 7 => false
+2 == 8 => false
+NaN
+3 == 0 => false
+3 == 1 => false
+3 == 2 => true
+3 == 3 => true
+3 == 4 => false
+3 == 5 => false
+3 == 6 => false
+3 == 7 => false
+3 == 8 => false
+NaN
+4 == 0 => false
+4 == 1 => false
+4 == 2 => false
+4 == 3 => false
+4 == 4 => true
+4 == 5 => false
+4 == 6 => false
+4 == 7 => false
+4 == 8 => false
+asdf
+5 == 0 => false
+5 == 1 => false
+5 == 2 => false
+5 == 3 => false
+5 == 4 => false
+5 == 5 => true
+5 == 6 => true
+5 == 7 => false
+5 == 8 => false
+asdf
+6 == 0 => false
+6 == 1 => false
+6 == 2 => false
+6 == 3 => false
+6 == 4 => false
+6 == 5 => true
+6 == 6 => true
+6 == 7 => false
+6 == 8 => false
+NaN
+7 == 0 => false
+7 == 1 => false
+7 == 2 => false
+7 == 3 => false
+7 == 4 => false
+7 == 5 => false
+7 == 6 => false
+7 == 7 => true
+7 == 8 => true
+NaN
+8 == 0 => false
+8 == 1 => false
+8 == 2 => false
+8 == 3 => false
+8 == 4 => false
+8 == 5 => false
+8 == 6 => false
+8 == 7 => true
+8 == 8 => true
diff --git a/test/trace/equality-nan-6.swf b/test/trace/equality-nan-6.swf
new file mode 100644
index 0000000..9c16913
Binary files /dev/null and b/test/trace/equality-nan-6.swf differ
diff --git a/test/trace/equality-nan-6.swf.trace b/test/trace/equality-nan-6.swf.trace
new file mode 100644
index 0000000..9b63072
--- /dev/null
+++ b/test/trace/equality-nan-6.swf.trace
@@ -0,0 +1,90 @@
+NaN
+0 == 0 => true
+0 == 1 => false
+0 == 2 => false
+0 == 3 => false
+0 == 4 => false
+0 == 5 => false
+0 == 6 => false
+0 == 7 => false
+0 == 8 => false
+NaN
+1 == 0 => false
+1 == 1 => true
+1 == 2 => false
+1 == 3 => false
+1 == 4 => false
+1 == 5 => false
+1 == 6 => false
+1 == 7 => false
+1 == 8 => false
+NaN
+2 == 0 => false
+2 == 1 => false
+2 == 2 => true
+2 == 3 => true
+2 == 4 => false
+2 == 5 => false
+2 == 6 => false
+2 == 7 => false
+2 == 8 => false
+NaN
+3 == 0 => false
+3 == 1 => false
+3 == 2 => true
+3 == 3 => true
+3 == 4 => false
+3 == 5 => false
+3 == 6 => false
+3 == 7 => false
+3 == 8 => false
+NaN
+4 == 0 => false
+4 == 1 => false
+4 == 2 => false
+4 == 3 => false
+4 == 4 => true
+4 == 5 => false
+4 == 6 => false
+4 == 7 => false
+4 == 8 => false
+asdf
+5 == 0 => false
+5 == 1 => false
+5 == 2 => false
+5 == 3 => false
+5 == 4 => false
+5 == 5 => true
+5 == 6 => true
+5 == 7 => false
+5 == 8 => false
+asdf
+6 == 0 => false
+6 == 1 => false
+6 == 2 => false
+6 == 3 => false
+6 == 4 => false
+6 == 5 => true
+6 == 6 => true
+6 == 7 => false
+6 == 8 => false
+NaN
+7 == 0 => false
+7 == 1 => false
+7 == 2 => false
+7 == 3 => false
+7 == 4 => false
+7 == 5 => false
+7 == 6 => false
+7 == 7 => true
+7 == 8 => true
+NaN
+8 == 0 => false
+8 == 1 => false
+8 == 2 => false
+8 == 3 => false
+8 == 4 => false
+8 == 5 => false
+8 == 6 => false
+8 == 7 => true
+8 == 8 => true
diff --git a/test/trace/equality-nan-7.swf b/test/trace/equality-nan-7.swf
new file mode 100644
index 0000000..7306dcf
Binary files /dev/null and b/test/trace/equality-nan-7.swf differ
diff --git a/test/trace/equality-nan-7.swf.trace b/test/trace/equality-nan-7.swf.trace
new file mode 100644
index 0000000..9b63072
--- /dev/null
+++ b/test/trace/equality-nan-7.swf.trace
@@ -0,0 +1,90 @@
+NaN
+0 == 0 => true
+0 == 1 => false
+0 == 2 => false
+0 == 3 => false
+0 == 4 => false
+0 == 5 => false
+0 == 6 => false
+0 == 7 => false
+0 == 8 => false
+NaN
+1 == 0 => false
+1 == 1 => true
+1 == 2 => false
+1 == 3 => false
+1 == 4 => false
+1 == 5 => false
+1 == 6 => false
+1 == 7 => false
+1 == 8 => false
+NaN
+2 == 0 => false
+2 == 1 => false
+2 == 2 => true
+2 == 3 => true
+2 == 4 => false
+2 == 5 => false
+2 == 6 => false
+2 == 7 => false
+2 == 8 => false
+NaN
+3 == 0 => false
+3 == 1 => false
+3 == 2 => true
+3 == 3 => true
+3 == 4 => false
+3 == 5 => false
+3 == 6 => false
+3 == 7 => false
+3 == 8 => false
+NaN
+4 == 0 => false
+4 == 1 => false
+4 == 2 => false
+4 == 3 => false
+4 == 4 => true
+4 == 5 => false
+4 == 6 => false
+4 == 7 => false
+4 == 8 => false
+asdf
+5 == 0 => false
+5 == 1 => false
+5 == 2 => false
+5 == 3 => false
+5 == 4 => false
+5 == 5 => true
+5 == 6 => true
+5 == 7 => false
+5 == 8 => false
+asdf
+6 == 0 => false
+6 == 1 => false
+6 == 2 => false
+6 == 3 => false
+6 == 4 => false
+6 == 5 => true
+6 == 6 => true
+6 == 7 => false
+6 == 8 => false
+NaN
+7 == 0 => false
+7 == 1 => false
+7 == 2 => false
+7 == 3 => false
+7 == 4 => false
+7 == 5 => false
+7 == 6 => false
+7 == 7 => true
+7 == 8 => true
+NaN
+8 == 0 => false
+8 == 1 => false
+8 == 2 => false
+8 == 3 => false
+8 == 4 => false
+8 == 5 => false
+8 == 6 => false
+8 == 7 => true
+8 == 8 => true
diff --git a/test/trace/equality-nan-8.swf b/test/trace/equality-nan-8.swf
new file mode 100644
index 0000000..34e0676
Binary files /dev/null and b/test/trace/equality-nan-8.swf differ
diff --git a/test/trace/equality-nan-8.swf.trace b/test/trace/equality-nan-8.swf.trace
new file mode 100644
index 0000000..9b63072
--- /dev/null
+++ b/test/trace/equality-nan-8.swf.trace
@@ -0,0 +1,90 @@
+NaN
+0 == 0 => true
+0 == 1 => false
+0 == 2 => false
+0 == 3 => false
+0 == 4 => false
+0 == 5 => false
+0 == 6 => false
+0 == 7 => false
+0 == 8 => false
+NaN
+1 == 0 => false
+1 == 1 => true
+1 == 2 => false
+1 == 3 => false
+1 == 4 => false
+1 == 5 => false
+1 == 6 => false
+1 == 7 => false
+1 == 8 => false
+NaN
+2 == 0 => false
+2 == 1 => false
+2 == 2 => true
+2 == 3 => true
+2 == 4 => false
+2 == 5 => false
+2 == 6 => false
+2 == 7 => false
+2 == 8 => false
+NaN
+3 == 0 => false
+3 == 1 => false
+3 == 2 => true
+3 == 3 => true
+3 == 4 => false
+3 == 5 => false
+3 == 6 => false
+3 == 7 => false
+3 == 8 => false
+NaN
+4 == 0 => false
+4 == 1 => false
+4 == 2 => false
+4 == 3 => false
+4 == 4 => true
+4 == 5 => false
+4 == 6 => false
+4 == 7 => false
+4 == 8 => false
+asdf
+5 == 0 => false
+5 == 1 => false
+5 == 2 => false
+5 == 3 => false
+5 == 4 => false
+5 == 5 => true
+5 == 6 => true
+5 == 7 => false
+5 == 8 => false
+asdf
+6 == 0 => false
+6 == 1 => false
+6 == 2 => false
+6 == 3 => false
+6 == 4 => false
+6 == 5 => true
+6 == 6 => true
+6 == 7 => false
+6 == 8 => false
+NaN
+7 == 0 => false
+7 == 1 => false
+7 == 2 => false
+7 == 3 => false
+7 == 4 => false
+7 == 5 => false
+7 == 6 => false
+7 == 7 => true
+7 == 8 => true
+NaN
+8 == 0 => false
+8 == 1 => false
+8 == 2 => false
+8 == 3 => false
+8 == 4 => false
+8 == 5 => false
+8 == 6 => false
+8 == 7 => true
+8 == 8 => true
diff --git a/test/trace/equality-nan.as b/test/trace/equality-nan.as
new file mode 100644
index 0000000..24c1b05
--- /dev/null
+++ b/test/trace/equality-nan.as
@@ -0,0 +1,14 @@
+// makeswf -v 7 -s 200x150 -r 1 -o equality-nan.swf equality-nan.as
+
+x = 0/0;
+nans = [ 0/0, 0/0, NaN, NaN, Number ("asdf"), "asdf", "asdf", x, x];
+
+for (i = 0; i < nans.length; i++) {
+  trace (nans[i]);
+  for (j = 0; j < nans.length; j++) {
+    trace (i + " == " + j + " => " + (nans[i] == nans[j]));
+  }
+}
+
+
+getURL ("fscommand:quit", "");
commit 4629eb29049a64fff77d972b9b3c47763acb3889
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Oct 17 16:13:31 2008 +0200

    compare the garbage-collected value for NaN comparisons

diff --git a/swfdec/swfdec_as_interpret.c b/swfdec/swfdec_as_interpret.c
index 9b6b51e..0788cd2 100644
--- a/swfdec/swfdec_as_interpret.c
+++ b/swfdec/swfdec_as_interpret.c
@@ -1449,10 +1449,12 @@ swfdec_action_equals2_5 (SwfdecAsContext *cx, guint action, const guint8 *data,
   }
 
   /* else compare as numbers */
-  if (isnan (l) && isnan (r))
-    cond = ltype == rtype;
-  else
+  if (isnan (l) && isnan (r)) {
+    cond = (ltype == rtype && ltype == SWFDEC_AS_TYPE_NUMBER &&
+	lval->value.number == rval->value.number);
+  } else {
     cond = l == r;
+  }
 
 out:
   swfdec_as_stack_pop (cx);
@@ -1537,10 +1539,12 @@ swfdec_action_equals2_6 (SwfdecAsContext *cx, guint action, const guint8 *data,
   l = swfdec_as_value_to_number (cx, lval);
   r = swfdec_as_value_to_number (cx, rval);
 
-  if (isnan (l) && isnan (r))
-    cond = ltype == rtype;
-  else
+  if (isnan (l) && isnan (r)) {
+    cond = (ltype == rtype && ltype == SWFDEC_AS_TYPE_NUMBER &&
+	lval->value.number == rval->value.number);
+  } else {
     cond = l == r;
+  }
 
 out:
   swfdec_as_stack_pop (cx);
commit 12381932c7efdd1818f5d319ea5bf4c7d728842f
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Oct 17 15:45:31 2008 +0200

    make numbers garbage-collected objects
    
    This is the first step in a reorganization of the script engine to fix
    bugs that surfaced during the end of the 0.8 development cycle.
    Note that most of these fixes are from going
    SWFDEC_AS_VALUE_SET_NUMBER() to swfdec_as_value_set_number(), which
    takes the context as an argument.

diff --git a/swfdec/swfdec_amf.c b/swfdec/swfdec_amf.c
index 251a764..6ce65d6 100644
--- a/swfdec/swfdec_amf.c
+++ b/swfdec/swfdec_amf.c
@@ -39,7 +39,7 @@ swfdec_amf_parse_boolean (SwfdecAsContext *context, SwfdecBits *bits, SwfdecAsVa
 static gboolean
 swfdec_amf_parse_number (SwfdecAsContext *context, SwfdecBits *bits, SwfdecAsValue *val)
 {
-  SWFDEC_AS_VALUE_SET_NUMBER (val, swfdec_bits_get_bdouble (bits));
+  swfdec_as_value_set_number (context, val, swfdec_bits_get_bdouble (bits));
   return TRUE;
 }
 
diff --git a/swfdec/swfdec_as_array.c b/swfdec/swfdec_as_array.c
index 6926ebf..dd18c59 100644
--- a/swfdec/swfdec_as_array.c
+++ b/swfdec/swfdec_as_array.c
@@ -126,7 +126,7 @@ swfdec_as_array_set_length_object (SwfdecAsObject *object, gint32 length)
   if (SWFDEC_IS_AS_ARRAY (object))
     SWFDEC_AS_ARRAY (object)->check_length = FALSE;
 
-  SWFDEC_AS_VALUE_SET_INT (&val, length);
+  swfdec_as_value_set_integer (swfdec_gc_object_get_context (object), &val, length);
   swfdec_as_object_set_variable_and_flags (object, SWFDEC_AS_STR_length, &val,
       SWFDEC_AS_VARIABLE_HIDDEN | SWFDEC_AS_VARIABLE_PERMANENT);
 
@@ -150,7 +150,7 @@ swfdec_as_array_set_length (SwfdecAsArray *array, gint32 length)
   g_return_if_fail (SWFDEC_IS_AS_ARRAY (array));
   g_return_if_fail (length >= 0);
 
-  SWFDEC_AS_VALUE_SET_INT (&val, length);
+  swfdec_as_value_set_integer (swfdec_gc_object_get_context (array), &val, length);
   swfdec_as_object_set_variable_and_flags (SWFDEC_AS_OBJECT (array),
       SWFDEC_AS_STR_length, &val,
       SWFDEC_AS_VARIABLE_HIDDEN | SWFDEC_AS_VARIABLE_PERMANENT);
@@ -653,7 +653,7 @@ swfdec_as_array_do_push (SwfdecAsContext *cx, SwfdecAsObject *object,
     swfdec_as_array_set_length_object (object, length + argc);
   }
 
-  SWFDEC_AS_VALUE_SET_INT (ret, swfdec_as_array_length_as_integer (object));
+  swfdec_as_value_set_integer (cx, ret, swfdec_as_array_length_as_integer (object));
 }
 
 SWFDEC_AS_NATIVE (252, 2, swfdec_as_array_do_pop)
@@ -703,7 +703,7 @@ swfdec_as_array_do_unshift (SwfdecAsContext *cx, SwfdecAsObject *object,
       swfdec_as_array_set_length_object (object, length);
   }
 
-  SWFDEC_AS_VALUE_SET_INT (ret, swfdec_as_array_length (object));
+  swfdec_as_value_set_integer (cx, ret, swfdec_as_array_length (object));
 }
 
 SWFDEC_AS_NATIVE (252, 4, swfdec_as_array_do_shift)
@@ -1201,11 +1201,11 @@ swfdec_as_array_do_sort (SwfdecAsContext *cx, SwfdecAsObject *object,
 	  break;
       }
       if (i < length - 1) {
-	SWFDEC_AS_VALUE_SET_INT (ret, 0);
+	swfdec_as_value_set_integer (cx, ret, 0);
 	goto done;
       }
     } else if (compare_data.equal_found) {
-      SWFDEC_AS_VALUE_SET_INT (ret, 0);
+      swfdec_as_value_set_integer (cx, ret, 0);
       goto done;
     }
   }
@@ -1228,7 +1228,7 @@ swfdec_as_array_do_sort (SwfdecAsContext *cx, SwfdecAsObject *object,
 
     var = swfdec_as_integer_to_string (cx, (descending ? length - i - 1 : i));
     if (options[0] & SORT_OPTION_RETURNINDEXEDARRAY) {
-      SWFDEC_AS_VALUE_SET_INT (&val, entry->index_);
+      swfdec_as_value_set_integer (cx, &val, entry->index_);
       swfdec_as_object_set_variable (target, var, &val);
     } else {
       swfdec_as_object_set_variable (target, var, &entry->value);
diff --git a/swfdec/swfdec_as_context.c b/swfdec/swfdec_as_context.c
index fd15d4b..2314168 100644
--- a/swfdec/swfdec_as_context.c
+++ b/swfdec/swfdec_as_context.c
@@ -295,12 +295,43 @@ swfdec_as_context_remove_objects (gpointer key, gpointer value, gpointer debugge
 static void
 swfdec_as_context_collect (SwfdecAsContext *context)
 {
-  SWFDEC_INFO (">> collecting garbage");
+  SwfdecAsDoubleValue *prev, *cur;
+
   /* NB: This functions is called without GC from swfdec_as_context_dispose */
+  SWFDEC_INFO (">> collecting garbage");
+  
   g_hash_table_foreach_remove (context->strings, 
     swfdec_as_context_remove_strings, context);
   g_hash_table_foreach_remove (context->objects, 
     swfdec_as_context_remove_objects, context->debugger);
+
+  prev = NULL;
+  cur = context->numbers;
+  for (;;) {
+    while (cur) {
+      gsize next = GPOINTER_TO_SIZE (cur->next);
+      if (next & SWFDEC_AS_GC_MARK) {
+	cur->next = GSIZE_TO_POINTER (next & ~SWFDEC_AS_GC_MARK);
+	break;
+      }
+      g_slice_free (SwfdecAsDoubleValue, cur);
+      cur = GSIZE_TO_POINTER (next);
+    }
+    if (prev)
+      prev->next = cur;
+    else
+      context->numbers = cur;
+    prev = cur;
+    if (prev == NULL)
+      break;
+    cur = cur->next;
+  }
+  prev = context->numbers;
+  while (prev) {
+    g_assert ((GPOINTER_TO_SIZE (prev) & 3) == 0);
+    prev = prev->next;
+  }
+
   SWFDEC_INFO (">> done collecting garbage");
 }
 
@@ -340,6 +371,9 @@ swfdec_as_value_mark (SwfdecAsValue *value)
     swfdec_gc_object_mark (SWFDEC_AS_VALUE_GET_OBJECT (value));
   } else if (SWFDEC_AS_VALUE_IS_STRING (value)) {
     swfdec_as_string_mark (SWFDEC_AS_VALUE_GET_STRING (value));
+  } else if (SWFDEC_AS_VALUE_IS_NUMBER (value)) {
+    value->value.number->next = GSIZE_TO_POINTER (
+	GPOINTER_TO_SIZE (value->value.number->next) | SWFDEC_AS_GC_MARK);
   }
 }
 
@@ -1059,14 +1093,14 @@ swfdec_as_context_parseInt (SwfdecAsContext *cx, SwfdecAsObject *object,
   SWFDEC_AS_CHECK (0, NULL, "s|i", &s, &radix);
 
   if (argc >= 2 && (radix < 2 || radix > 36)) {
-    SWFDEC_AS_VALUE_SET_NUMBER (retval, NAN);
+    swfdec_as_value_set_number (cx, retval, NAN);
     return;
   }
 
   // special case, don't allow sign in front of the 0x
   if ((s[0] == '-' || s[0] == '+') && s[1] == '0' &&
       (s[2] == 'x' || s[2] == 'X')) {
-    SWFDEC_AS_VALUE_SET_NUMBER (retval, NAN);
+    swfdec_as_value_set_number (cx, retval, NAN);
     return;
   }
 
@@ -1092,7 +1126,7 @@ swfdec_as_context_parseInt (SwfdecAsContext *cx, SwfdecAsObject *object,
     if (skip != s && (skip[0] == '-' || skip[0] == '+'))
       skip++;
     if (skip != s && skip[0] == '0' && (skip[1] == 'x' || skip[1] == 'X')) {
-      SWFDEC_AS_VALUE_SET_NUMBER (retval, 0);
+      swfdec_as_value_set_number (cx, retval, 0);
       return;
     }
   }
@@ -1100,14 +1134,14 @@ swfdec_as_context_parseInt (SwfdecAsContext *cx, SwfdecAsObject *object,
   i = g_ascii_strtoll (s, &tail, radix);
 
   if (tail == s) {
-    SWFDEC_AS_VALUE_SET_NUMBER (retval, NAN);
+    swfdec_as_value_set_number (cx, retval, NAN);
     return;
   }
 
   if (i > G_MAXINT32 || i < G_MININT32) {
-    SWFDEC_AS_VALUE_SET_NUMBER (retval, i);
+    swfdec_as_value_set_number (cx, retval, i);
   } else {
-    SWFDEC_AS_VALUE_SET_INT (retval, i);
+    swfdec_as_value_set_integer (cx, retval, i);
   }
 }
 
@@ -1132,9 +1166,9 @@ swfdec_as_context_parseFloat (SwfdecAsContext *cx, SwfdecAsObject *object,
   d = g_ascii_strtod (s, &tail);
 
   if (tail == s) {
-    SWFDEC_AS_VALUE_SET_NUMBER (retval, NAN);
+    swfdec_as_value_set_number (cx, retval, NAN);
   } else {
-    SWFDEC_AS_VALUE_SET_NUMBER (retval, d);
+    swfdec_as_value_set_number (cx, retval, d);
   }
 
   g_free (s);
@@ -1145,9 +1179,9 @@ swfdec_as_context_init_global (SwfdecAsContext *context)
 {
   SwfdecAsValue val;
 
-  SWFDEC_AS_VALUE_SET_NUMBER (&val, NAN);
+  swfdec_as_value_set_number (context, &val, NAN);
   swfdec_as_object_set_variable (context->global, SWFDEC_AS_STR_NaN, &val);
-  SWFDEC_AS_VALUE_SET_NUMBER (&val, HUGE_VAL);
+  swfdec_as_value_set_number (context, &val, HUGE_VAL);
   swfdec_as_object_set_variable (context->global, SWFDEC_AS_STR_Infinity, &val);
 }
 
diff --git a/swfdec/swfdec_as_context.h b/swfdec/swfdec_as_context.h
index 41b5651..6951e3b 100644
--- a/swfdec/swfdec_as_context.h
+++ b/swfdec/swfdec_as_context.h
@@ -58,6 +58,7 @@ struct _SwfdecAsContext {
   gsize			memory_since_gc;/* memory allocated since last GC run */
   GHashTable *		strings;	/* string => memory mapping the context manages */
   GHashTable *		objects;	/* all objects the context manages */
+  SwfdecAsDoubleValue *	numbers;	/* all numbers the context manages */
   GHashTable *		constant_pools;	/* memory address => SwfdecConstantPool for all gc'ed pools */
 
   /* execution state */
diff --git a/swfdec/swfdec_as_date.c b/swfdec/swfdec_as_date.c
index b8b73d7..c86aa5d 100644
--- a/swfdec/swfdec_as_date.c
+++ b/swfdec/swfdec_as_date.c
@@ -508,7 +508,7 @@ swfdec_as_date_set_field (SwfdecAsContext *cx, SwfdecAsObject *object,
     }
   }
 
-  SWFDEC_AS_VALUE_SET_NUMBER (ret, date->milliseconds);
+  swfdec_as_value_set_number (cx, ret, date->milliseconds);
 }
 
 static void
@@ -522,7 +522,7 @@ swfdec_as_date_get_field (SwfdecAsContext *cx, SwfdecAsObject *object,
   SWFDEC_AS_CHECK (SWFDEC_TYPE_AS_DATE, &date, "");
 
   if (!swfdec_as_date_is_valid (date)) {
-    SWFDEC_AS_VALUE_SET_NUMBER (ret, NAN);
+    swfdec_as_value_set_number (cx, ret, NAN);
     return;
   }
 
@@ -532,7 +532,7 @@ swfdec_as_date_get_field (SwfdecAsContext *cx, SwfdecAsObject *object,
   if (field == FIELD_FULL_YEAR)
     number += 1900;
 
-  SWFDEC_AS_VALUE_SET_INT (ret, number);
+  swfdec_as_value_set_integer (cx, ret, number);
 }
 
 /*** AS CODE ***/
@@ -580,7 +580,7 @@ swfdec_as_date_getTime (SwfdecAsContext *cx, SwfdecAsObject *object,
 
   SWFDEC_AS_CHECK (SWFDEC_TYPE_AS_DATE, &date, "");
 
-  SWFDEC_AS_VALUE_SET_NUMBER (ret, date->milliseconds);
+  swfdec_as_value_set_number (cx, ret, date->milliseconds);
 }
 
 SWFDEC_AS_NATIVE (103, 18, swfdec_as_date_getTimezoneOffset)
@@ -593,7 +593,7 @@ swfdec_as_date_getTimezoneOffset (SwfdecAsContext *cx, SwfdecAsObject *object,
   SWFDEC_AS_CHECK (SWFDEC_TYPE_AS_DATE, &date, "");
 
   // reverse of utc_offset
-  SWFDEC_AS_VALUE_SET_NUMBER (ret, -(date->utc_offset));
+  swfdec_as_value_set_number (cx, ret, -(date->utc_offset));
 }
 
 // get* functions
@@ -774,7 +774,7 @@ swfdec_as_date_setTime (SwfdecAsContext *cx, SwfdecAsObject *object,
     swfdec_as_date_set_milliseconds_utc (date, NAN);
   }
 
-  SWFDEC_AS_VALUE_SET_NUMBER (ret, date->milliseconds);
+  swfdec_as_value_set_number (cx, ret, date->milliseconds);
 }
 
 SWFDEC_AS_NATIVE (103, 15, swfdec_as_date_setMilliseconds)
@@ -989,7 +989,7 @@ swfdec_as_date_UTC (SwfdecAsContext *cx, SwfdecAsObject *object, guint argc,
 	  &num)) {
       brokentime.day_of_month = num;
     } else {
-      SWFDEC_AS_VALUE_SET_NUMBER (ret, d);
+      swfdec_as_value_set_number (cx, ret, d);
       return;
     }
   } else {
@@ -1001,7 +1001,7 @@ swfdec_as_date_UTC (SwfdecAsContext *cx, SwfdecAsObject *object, guint argc,
 	  &num)) {
       brokentime.hours = num;
     } else {
-      SWFDEC_AS_VALUE_SET_NUMBER (ret, d);
+      swfdec_as_value_set_number (cx, ret, d);
       return;
     }
   }
@@ -1011,7 +1011,7 @@ swfdec_as_date_UTC (SwfdecAsContext *cx, SwfdecAsObject *object, guint argc,
 	  &num)) {
       brokentime.minutes = num;
     } else {
-      SWFDEC_AS_VALUE_SET_NUMBER (ret, d);
+      swfdec_as_value_set_number (cx, ret, d);
       return;
     }
   }
@@ -1021,7 +1021,7 @@ swfdec_as_date_UTC (SwfdecAsContext *cx, SwfdecAsObject *object, guint argc,
 	  &num)) {
       brokentime.seconds = num;
     } else {
-      SWFDEC_AS_VALUE_SET_NUMBER (ret, d);
+      swfdec_as_value_set_number (cx, ret, d);
       return;
     }
   }
@@ -1037,12 +1037,12 @@ swfdec_as_date_UTC (SwfdecAsContext *cx, SwfdecAsObject *object, guint argc,
 	  &num)) {
       brokentime.milliseconds = num;
     } else {
-      SWFDEC_AS_VALUE_SET_NUMBER (ret, d);
+      swfdec_as_value_set_number (cx, ret, d);
       return;
     }
   }
 
-  SWFDEC_AS_VALUE_SET_NUMBER (ret,
+  swfdec_as_value_set_number (cx, ret,
       swfdec_as_date_brokentime_to_milliseconds (&brokentime));
 }
 
diff --git a/swfdec/swfdec_as_interpret.c b/swfdec/swfdec_as_interpret.c
index b29ca50..9b6b51e 100644
--- a/swfdec/swfdec_as_interpret.c
+++ b/swfdec/swfdec_as_interpret.c
@@ -328,7 +328,7 @@ swfdec_action_push (SwfdecAsContext *cx, guint action, const guint8 *data, guint
 	  break;
 	}
       case 1: /* float */
-	SWFDEC_AS_VALUE_SET_NUMBER (swfdec_as_stack_push (cx), 
+	swfdec_as_value_set_number (cx, swfdec_as_stack_push (cx), 
 	    swfdec_bits_get_float (&bits));
 	break;
       case 2: /* null */
@@ -353,11 +353,11 @@ swfdec_action_push (SwfdecAsContext *cx, guint action, const guint8 *data, guint
 	    swfdec_bits_get_u8 (&bits) ? TRUE : FALSE);
 	break;
       case 6: /* double */
-	SWFDEC_AS_VALUE_SET_NUMBER (swfdec_as_stack_push (cx), 
+	swfdec_as_value_set_number (cx, swfdec_as_stack_push (cx), 
 	    swfdec_bits_get_double (&bits));
 	break;
       case 7: /* 32bit int */
-	SWFDEC_AS_VALUE_SET_INT (swfdec_as_stack_push (cx), 
+	swfdec_as_value_set_integer (cx, swfdec_as_stack_push (cx), 
 	    swfdec_bits_get_s32 (&bits));
 	break;
       case 8: /* 8bit ConstantPool address */
@@ -923,7 +923,7 @@ swfdec_action_binary (SwfdecAsContext *cx, guint action, const guint8 *data, gui
       break;
   }
   swfdec_as_stack_pop (cx);
-  SWFDEC_AS_VALUE_SET_NUMBER (swfdec_as_stack_peek (cx, 1), l);
+  swfdec_as_value_set_number (cx, swfdec_as_stack_peek (cx, 1), l);
 }
 
 static void
@@ -974,7 +974,7 @@ swfdec_action_add2 (SwfdecAsContext *cx, guint action, const guint8 *data, guint
     d2 = swfdec_as_value_to_number (cx, rval);
     d += d2;
     swfdec_as_stack_pop (cx);
-    SWFDEC_AS_VALUE_SET_NUMBER (swfdec_as_stack_peek (cx, 1), d);
+    swfdec_as_value_set_number (cx, swfdec_as_stack_peek (cx, 1), d);
   }
 }
 
@@ -1050,7 +1050,7 @@ swfdec_action_not (SwfdecAsContext *cx, guint action, const guint8 *data, guint
 {
   if (cx->version <= 4) {
     double d = swfdec_as_value_to_number (cx, swfdec_as_stack_peek (cx, 1));
-    SWFDEC_AS_VALUE_SET_NUMBER (swfdec_as_stack_peek (cx, 1), d == 0 ? 1 : 0);
+    swfdec_as_value_set_number (cx, swfdec_as_stack_peek (cx, 1), d == 0 ? 1 : 0);
   } else {
     SWFDEC_AS_VALUE_SET_BOOLEAN (swfdec_as_stack_peek (cx, 1), 
 	!swfdec_as_value_to_boolean (cx, swfdec_as_stack_peek (cx, 1)));
@@ -1090,7 +1090,7 @@ swfdec_action_decrement (SwfdecAsContext *cx, guint action, const guint8 *data,
   SwfdecAsValue *val;
 
   val = swfdec_as_stack_peek (cx, 1);
-  SWFDEC_AS_VALUE_SET_NUMBER (val, swfdec_as_value_to_number (cx, val) - 1);
+  swfdec_as_value_set_number (cx, val, swfdec_as_value_to_number (cx, val) - 1);
 }
 
 static void
@@ -1099,7 +1099,7 @@ swfdec_action_increment (SwfdecAsContext *cx, guint action, const guint8 *data,
   SwfdecAsValue *val;
 
   val = swfdec_as_stack_peek (cx, 1);
-  SWFDEC_AS_VALUE_SET_NUMBER (val, swfdec_as_value_to_number (cx, val) + 1);
+  swfdec_as_value_set_number (cx, val, swfdec_as_value_to_number (cx, val) + 1);
 }
 
 static void
@@ -1269,9 +1269,9 @@ swfdec_action_random_number (SwfdecAsContext *cx, guint action, const guint8 *da
   max = swfdec_as_value_to_integer (cx, val);
   
   if (max <= 0)
-    SWFDEC_AS_VALUE_SET_NUMBER (val, 0);
+    swfdec_as_value_set_number (cx, val, 0);
   else
-    SWFDEC_AS_VALUE_SET_NUMBER (val, g_rand_int_range (cx->rand, 0, max));
+    swfdec_as_value_set_number (cx, val, g_rand_int_range (cx->rand, 0, max));
 }
 
 static void
@@ -1295,7 +1295,7 @@ swfdec_action_old_compare (SwfdecAsContext *cx, guint action, const guint8 *data
   }
   swfdec_as_stack_pop (cx);
   if (cx->version < 5) {
-    SWFDEC_AS_VALUE_SET_NUMBER (swfdec_as_stack_peek (cx, 1), cond ? 1 : 0);
+    swfdec_as_value_set_number (cx, swfdec_as_stack_peek (cx, 1), cond ? 1 : 0);
   } else {
     SWFDEC_AS_VALUE_SET_BOOLEAN (swfdec_as_stack_peek (cx, 1), cond);
   }
@@ -1336,7 +1336,7 @@ swfdec_action_string_length (SwfdecAsContext *cx, guint action, const guint8 *da
 
   v = swfdec_as_stack_peek (cx, 1);
   s = swfdec_as_value_to_string (cx, v);
-  SWFDEC_AS_VALUE_SET_INT (v, g_utf8_strlen (s, -1));  
+  swfdec_as_value_set_integer (cx, v, g_utf8_strlen (s, -1));  
 }
 
 static void
@@ -1364,7 +1364,7 @@ swfdec_action_string_compare (SwfdecAsContext *cx, guint action, const guint8 *d
   }
   swfdec_as_stack_pop (cx);
   if (cx->version < 5) {
-    SWFDEC_AS_VALUE_SET_NUMBER (swfdec_as_stack_peek (cx, 1), cond ? 1 : 0);
+    swfdec_as_value_set_number (cx, swfdec_as_stack_peek (cx, 1), cond ? 1 : 0);
   } else {
     SWFDEC_AS_VALUE_SET_BOOLEAN (swfdec_as_stack_peek (cx, 1), cond);
   }
@@ -1813,7 +1813,7 @@ swfdec_action_init_array (SwfdecAsContext *cx, guint action, const guint8 *data,
   }
   if (i != n) {
     SwfdecAsValue val;
-    SWFDEC_AS_VALUE_SET_INT (&val, n);
+    swfdec_as_value_set_integer (cx, &val, n);
     swfdec_as_object_set_variable (array, SWFDEC_AS_STR_length, &val);
   }
   SWFDEC_AS_VALUE_SET_OBJECT (swfdec_as_stack_push (cx), array);
@@ -1969,7 +1969,7 @@ swfdec_action_bitwise (SwfdecAsContext *cx, guint action, const guint8 *data, gu
   }
 
   swfdec_as_stack_pop (cx);
-  SWFDEC_AS_VALUE_SET_INT (swfdec_as_stack_peek (cx, 1), a);
+  swfdec_as_value_set_integer (cx, swfdec_as_stack_peek (cx, 1), a);
 }
 
 static void
@@ -1996,7 +1996,7 @@ swfdec_action_shift (SwfdecAsContext *cx, guint action, const guint8 *data, guin
   }
 
   swfdec_as_stack_pop (cx);
-  SWFDEC_AS_VALUE_SET_INT (swfdec_as_stack_peek (cx, 1), value);
+  swfdec_as_value_set_integer (cx, swfdec_as_stack_peek (cx, 1), value);
 }
 
 static void
@@ -2004,7 +2004,7 @@ swfdec_action_to_integer (SwfdecAsContext *cx, guint action, const guint8 *data,
 {
   SwfdecAsValue *val = swfdec_as_stack_peek (cx, 1);
 
-  SWFDEC_AS_VALUE_SET_INT (val, swfdec_as_value_to_integer (cx, val));
+  swfdec_as_value_set_integer (cx, val, swfdec_as_value_to_integer (cx, val));
 }
 
 static void
@@ -2121,7 +2121,7 @@ swfdec_action_modulo (SwfdecAsContext *cx, guint action, const guint8 *data, gui
     }
   }
   swfdec_as_stack_pop (cx);
-  SWFDEC_AS_VALUE_SET_NUMBER (swfdec_as_stack_peek (cx, 1), x);
+  swfdec_as_value_set_number (cx, swfdec_as_stack_peek (cx, 1), x);
 }
 
 static void
@@ -2133,7 +2133,7 @@ swfdec_action_swap (SwfdecAsContext *cx, guint action, const guint8 *data, guint
 static void
 swfdec_action_to_number (SwfdecAsContext *cx, guint action, const guint8 *data, guint len)
 {
-  SWFDEC_AS_VALUE_SET_NUMBER (swfdec_as_stack_peek (cx, 1),
+  swfdec_as_value_set_number (cx, swfdec_as_stack_peek (cx, 1),
       swfdec_as_value_to_number (cx, swfdec_as_stack_peek (cx, 1)));
 }
 
@@ -2206,7 +2206,7 @@ swfdec_action_get_time (SwfdecAsContext *cx, guint action, const guint8 *data, g
   diff *= 1000;
   diff += (tv.tv_usec - cx->start_time.tv_usec) / 1000;
 
-  SWFDEC_AS_VALUE_SET_NUMBER (swfdec_as_stack_push (cx), diff);
+  swfdec_as_value_set_number (cx, swfdec_as_stack_push (cx), diff);
 }
 
 static gboolean
@@ -2489,9 +2489,9 @@ swfdec_action_char_to_ascii (SwfdecAsContext *cx, guint action, const guint8 *da
     if (ascii == NULL) {
       /* This can happen if a Flash 5 movie gets loaded into a Flash 7 movie */
       SWFDEC_FIXME ("Someone threw unconvertible text %s at Flash <= 5", s);
-      SWFDEC_AS_VALUE_SET_INT (val, 0); /* FIXME: what to return??? */
+      swfdec_as_value_set_integer (cx, val, 0); /* FIXME: what to return??? */
     } else {
-      SWFDEC_AS_VALUE_SET_INT (val, (guchar) ascii[0]);
+      swfdec_as_value_set_integer (cx, val, (guchar) ascii[0]);
       g_free (ascii);
     }
   } else {
@@ -2500,9 +2500,9 @@ swfdec_action_char_to_ascii (SwfdecAsContext *cx, guint action, const guint8 *da
     if (uni == NULL) {
       /* This should never happen, everything is valid UTF-8 in here */
       g_warning ("conversion of character %s failed", s);
-      SWFDEC_AS_VALUE_SET_INT (val, 0);
+      swfdec_as_value_set_integer (cx, val, 0);
     } else {
-      SWFDEC_AS_VALUE_SET_INT (val, uni[0]);
+      swfdec_as_value_set_integer (cx, val, uni[0]);
       g_free (uni);
     }
   }
diff --git a/swfdec/swfdec_as_math.c b/swfdec/swfdec_as_math.c
index 5ec53a8..db07415 100644
--- a/swfdec/swfdec_as_math.c
+++ b/swfdec/swfdec_as_math.c
@@ -42,11 +42,11 @@ swfdec_as_math_ ## name (SwfdecAsContext *cx, SwfdecAsObject *object, \
 { \
   double d, unused; \
 \
-  SWFDEC_AS_VALUE_SET_NUMBER (ret, NAN); \
+  swfdec_as_value_set_number (cx, ret, NAN); \
   SWFDEC_AS_CHECK (0, NULL, "n|n", &d, &unused); \
 \
   d = name (d); \
-  SWFDEC_AS_VALUE_SET_NUMBER (ret, d); \
+  swfdec_as_value_set_number (cx, ret, d); \
 }
 
 SWFDEC_AS_NATIVE (200, 16, swfdec_as_math_acos)
@@ -79,10 +79,10 @@ swfdec_as_math_abs (SwfdecAsContext *cx, SwfdecAsObject *object,
 {
   double d, unused;
 
-  SWFDEC_AS_VALUE_SET_NUMBER (ret, NAN);
+  swfdec_as_value_set_number (cx, ret, NAN);
   SWFDEC_AS_CHECK (0, NULL, "n|n", &d, &unused);
 
-  SWFDEC_AS_VALUE_SET_NUMBER (ret, fabs (d));
+  swfdec_as_value_set_number (cx, ret, fabs (d));
 }
 
 SWFDEC_AS_NATIVE (200, 5, swfdec_as_math_atan2)
@@ -92,10 +92,10 @@ swfdec_as_math_atan2 (SwfdecAsContext *cx, SwfdecAsObject *object,
 {
   double x, y;
 
-  SWFDEC_AS_VALUE_SET_NUMBER (ret, NAN);
+  swfdec_as_value_set_number (cx, ret, NAN);
   SWFDEC_AS_CHECK (0, NULL, "nn", &y, &x);
 
-  SWFDEC_AS_VALUE_SET_NUMBER (ret, atan2 (y, x));
+  swfdec_as_value_set_number (cx, ret, atan2 (y, x));
 }
 
 SWFDEC_AS_NATIVE (200, 2, swfdec_as_math_max)
@@ -106,13 +106,13 @@ swfdec_as_math_max (SwfdecAsContext *cx, SwfdecAsObject *object,
   double x, y;
 
   if (argc == 0) {
-    SWFDEC_AS_VALUE_SET_NUMBER (ret, -HUGE_VAL);
+    swfdec_as_value_set_number (cx, ret, -HUGE_VAL);
   } else {
-    SWFDEC_AS_VALUE_SET_NUMBER (ret, NAN);
+    swfdec_as_value_set_number (cx, ret, NAN);
   }
   SWFDEC_AS_CHECK (0, NULL, "nn", &x, &y);
 
-  SWFDEC_AS_VALUE_SET_NUMBER (ret, isnan (x) || isnan (y) ? NAN : MAX (x, y));
+  swfdec_as_value_set_number (cx, ret, isnan (x) || isnan (y) ? NAN : MAX (x, y));
 }
 
 SWFDEC_AS_NATIVE (200, 1, swfdec_as_math_min)
@@ -123,13 +123,13 @@ swfdec_as_math_min (SwfdecAsContext *cx, SwfdecAsObject *object,
   double x, y;
 
   if (argc == 0) {
-    SWFDEC_AS_VALUE_SET_NUMBER (ret, HUGE_VAL);
+    swfdec_as_value_set_number (cx, ret, HUGE_VAL);
   } else {
-    SWFDEC_AS_VALUE_SET_NUMBER (ret, NAN);
+    swfdec_as_value_set_number (cx, ret, NAN);
   }
   SWFDEC_AS_CHECK (0, NULL, "nn", &x, &y);
 
-  SWFDEC_AS_VALUE_SET_NUMBER (ret, isnan (x) || isnan (y) ? NAN : MIN (x, y));
+  swfdec_as_value_set_number (cx, ret, isnan (x) || isnan (y) ? NAN : MIN (x, y));
 }
 
 SWFDEC_AS_NATIVE (200, 17, swfdec_as_math_pow)
@@ -139,10 +139,10 @@ swfdec_as_math_pow (SwfdecAsContext *cx, SwfdecAsObject *object,
 {
   double x, y;
 
-  SWFDEC_AS_VALUE_SET_NUMBER (ret, NAN);
+  swfdec_as_value_set_number (cx, ret, NAN);
   SWFDEC_AS_CHECK (0, NULL, "nn", &x, &y);
 
-  SWFDEC_AS_VALUE_SET_NUMBER (ret, isfinite (x) ? pow (x, y): NAN);
+  swfdec_as_value_set_number (cx, ret, isfinite (x) ? pow (x, y): NAN);
 }
 
 SWFDEC_AS_NATIVE (200, 11, swfdec_as_math_random)
@@ -152,10 +152,10 @@ swfdec_as_math_random (SwfdecAsContext *cx, SwfdecAsObject *object,
 {
   double unused, unused2;
 
-  SWFDEC_AS_VALUE_SET_NUMBER (ret, NAN);
+  swfdec_as_value_set_number (cx, ret, NAN);
   SWFDEC_AS_CHECK (0, NULL, "|nn", &unused, &unused2);
 
-  SWFDEC_AS_VALUE_SET_NUMBER (ret, g_rand_double (cx->rand));
+  swfdec_as_value_set_number (cx, ret, g_rand_double (cx->rand));
 }
 
 SWFDEC_AS_NATIVE (200, 10, swfdec_as_math_round)
@@ -165,8 +165,8 @@ swfdec_as_math_round (SwfdecAsContext *cx, SwfdecAsObject *object,
 {
   double d, unused;
 
-  SWFDEC_AS_VALUE_SET_NUMBER (ret, NAN);
+  swfdec_as_value_set_number (cx, ret, NAN);
   SWFDEC_AS_CHECK (0, NULL, "n|n", &d, &unused);
 
-  SWFDEC_AS_VALUE_SET_NUMBER (ret, floor (d + 0.5));
+  swfdec_as_value_set_number (cx, ret, floor (d + 0.5));
 }
diff --git a/swfdec/swfdec_as_number.c b/swfdec/swfdec_as_number.c
index 75d0cb5..d6926c2 100644
--- a/swfdec/swfdec_as_number.c
+++ b/swfdec/swfdec_as_number.c
@@ -63,7 +63,7 @@ swfdec_as_number_construct (SwfdecAsContext *cx, SwfdecAsObject *object,
     num->number = d;
     SWFDEC_AS_VALUE_SET_OBJECT (ret, object);
   } else {
-    SWFDEC_AS_VALUE_SET_NUMBER (ret, d);
+    swfdec_as_value_set_number (cx, ret, d);
   }
 }
 
@@ -125,7 +125,7 @@ swfdec_as_number_toString (SwfdecAsContext *cx, SwfdecAsObject *object,
 
   if (radix == 10 || radix < 2 || radix > 36 || isinf (num->number) ||
       isnan (num->number)) {
-    SWFDEC_AS_VALUE_SET_NUMBER (&val, num->number);
+    swfdec_as_value_set_number (cx, &val, num->number);
     s = swfdec_as_value_to_string (cx, &val);
   } else {
     s = swfdec_as_number_toStringRadix (cx, num->number, radix);
@@ -144,7 +144,7 @@ swfdec_as_number_valueOf (SwfdecAsContext *cx, SwfdecAsObject *object,
     return;
 
   num = SWFDEC_AS_NUMBER (object);
-  SWFDEC_AS_VALUE_SET_NUMBER (ret, num->number);
+  swfdec_as_value_set_number (cx, ret, num->number);
 }
 
 // only available as ASnative
diff --git a/swfdec/swfdec_as_string.c b/swfdec/swfdec_as_string.c
index e9ba518..8a0c726 100644
--- a/swfdec/swfdec_as_string.c
+++ b/swfdec/swfdec_as_string.c
@@ -113,7 +113,7 @@ swfdec_as_string_lastIndexOf (SwfdecAsContext *cx, SwfdecAsObject *object,
   if (argc == 2) {
     int offset = swfdec_as_value_to_integer (cx, &argv[1]);
     if (offset < 0) {
-      SWFDEC_AS_VALUE_SET_INT (ret, -1);
+      swfdec_as_value_set_integer (cx, ret, -1);
       return;
     }
     len = g_utf8_offset_to_pointer (string, offset + 1) - string;
@@ -122,9 +122,9 @@ swfdec_as_string_lastIndexOf (SwfdecAsContext *cx, SwfdecAsObject *object,
   }
   s = g_strrstr_len (string, len, s);
   if (s) {
-    SWFDEC_AS_VALUE_SET_INT (ret, g_utf8_pointer_to_offset (string, s));
+    swfdec_as_value_set_integer (cx, ret, g_utf8_pointer_to_offset (string, s));
   } else {
-    SWFDEC_AS_VALUE_SET_INT (ret, -1);
+    swfdec_as_value_set_integer (cx, ret, -1);
   }
 }
 
@@ -153,7 +153,7 @@ swfdec_as_string_indexOf (SwfdecAsContext *cx, SwfdecAsObject *object,
     i = g_utf8_pointer_to_offset (string, t);
   }
 
-  SWFDEC_AS_VALUE_SET_INT (ret, i);
+  swfdec_as_value_set_integer (cx, ret, i);
 }
 
 SWFDEC_AS_NATIVE (251, 5, swfdec_as_string_charAt)
@@ -198,20 +198,20 @@ swfdec_as_string_charCodeAt (SwfdecAsContext *cx, SwfdecAsObject *object,
 
   i = swfdec_as_value_to_integer (cx, &argv[0]);
   if (i < 0) {
-    SWFDEC_AS_VALUE_SET_NUMBER (ret, NAN);
+    swfdec_as_value_set_number (cx, ret, NAN);
     return;
   }
   s = swfdec_as_str_nth_char (string, i);
   if (*s == 0) {
     if (cx->version > 5) {
-      SWFDEC_AS_VALUE_SET_NUMBER (ret, NAN);
+      swfdec_as_value_set_number (cx, ret, NAN);
     } else {
-      SWFDEC_AS_VALUE_SET_INT (ret, 0);
+      swfdec_as_value_set_integer (cx, ret, 0);
     }
     return;
   }
   c = g_utf8_get_char (s);
-  SWFDEC_AS_VALUE_SET_NUMBER (ret, c);
+  swfdec_as_value_set_number (cx, ret, c);
 }
 
 static void
@@ -313,7 +313,7 @@ swfdec_as_string_construct (SwfdecAsContext *cx, SwfdecAsObject *object,
     SwfdecAsValue val;
 
     string->string = s;
-    SWFDEC_AS_VALUE_SET_INT (&val, g_utf8_strlen (string->string, -1));
+    swfdec_as_value_set_integer (cx, &val, g_utf8_strlen (string->string, -1));
     swfdec_as_object_set_variable_and_flags (object, SWFDEC_AS_STR_length,
 	&val, SWFDEC_AS_VARIABLE_HIDDEN | SWFDEC_AS_VARIABLE_PERMANENT);
     SWFDEC_AS_VALUE_SET_OBJECT (ret, object);
diff --git a/swfdec/swfdec_as_types.c b/swfdec/swfdec_as_types.c
index d609d62..c69486e 100644
--- a/swfdec/swfdec_as_types.c
+++ b/swfdec/swfdec_as_types.c
@@ -123,25 +123,6 @@
  */
 
 /**
- * SWFDEC_AS_VALUE_SET_NUMBER:
- * @val: value to set
- * @d: double value to set
- *
- * Sets @val to the given value. If you are sure the value is a valid
- * integer value, use SWFDEC_AS_VALUE_SET_INT() instead.
- */
-
-/**
- * SWFDEC_AS_VALUE_SET_INT:
- * @val: value to set
- * @d: integer value to set
- *
- * Sets @val to the given value. Currently this macro is equivalent to
- * SWFDEC_AS_VALUE_SET_NUMBER(), but this may change in future versions of
- * Swfdec.
- */
-
-/**
  * SWFDEC_AS_VALUE_GET_STRING:
  * @val: value to get, the value must reference a string
  *
@@ -188,6 +169,36 @@
 /*** actual code ***/
 
 /**
+ * swfdec_as_value_set_int:
+ * @val: value to set
+ * @i: integer value to set
+ *
+ * Sets @val to the given value. Currently this function is a macro that calls
+ * swfdec_as_value_set_number(), but this may change in future versions of
+ * Swfdec.
+ */
+
+/**
+ * swfdec_as_value_set_number:
+ * @context: The context to use
+ * @val: value to set
+ * @number: double value to set
+ *
+ * Sets @val to the given value. If you are sure the value is a valid
+ * integer value, use wfdec_as_value_set_int() instead.
+ */
+void
+swfdec_as_value_set_number (SwfdecAsContext *context, SwfdecAsValue *val,
+    double d)
+{
+  val->type = SWFDEC_AS_TYPE_NUMBER;
+  val->value.number = g_slice_new (SwfdecAsDoubleValue);
+  val->value.number->number = d;
+  val->value.number->next = context->numbers;
+  context->numbers = val->value.number;
+}
+
+/**
  * swfdec_as_str_concat:
  * @cx: a #SwfdecAsContext
  * @s1: first string
diff --git a/swfdec/swfdec_as_types.h b/swfdec/swfdec_as_types.h
index 44e0e8a..36b353a 100644
--- a/swfdec/swfdec_as_types.h
+++ b/swfdec/swfdec_as_types.h
@@ -38,6 +38,7 @@ typedef enum {
 typedef struct _SwfdecAsArray SwfdecAsArray;
 typedef struct _SwfdecAsContext SwfdecAsContext;
 typedef struct _SwfdecAsDebugger SwfdecAsDebugger;
+typedef struct _SwfdecAsDoubleValue SwfdecAsDoubleValue;
 typedef struct _SwfdecAsFrame SwfdecAsFrame;
 typedef struct _SwfdecAsFunction SwfdecAsFunction;
 typedef struct _SwfdecAsObject SwfdecAsObject;
@@ -59,7 +60,7 @@ struct _SwfdecAsValue {
   /*< private >*/
   union {
     gboolean		boolean;
-    double		number;
+    SwfdecAsDoubleValue *number;
     const char *	string;
     SwfdecAsObject *	object;
   } value;
@@ -80,15 +81,13 @@ struct _SwfdecAsValue {
   (__val)->type = SWFDEC_AS_TYPE_BOOLEAN; \
 } G_STMT_END
 
-#define SWFDEC_AS_VALUE_IS_NUMBER(val) ((val)->type == SWFDEC_AS_TYPE_NUMBER)
-#define SWFDEC_AS_VALUE_GET_NUMBER(val) ((val)->value.number)
-#define SWFDEC_AS_VALUE_SET_NUMBER(val,d) G_STMT_START { \
-  SwfdecAsValue *__val = (val); \
-  (__val)->value.number = (d); \
-  (__val)->type = SWFDEC_AS_TYPE_NUMBER; \
-} G_STMT_END
+struct _SwfdecAsDoubleValue {
+  SwfdecAsDoubleValue *	next;
+  double		number;
+};
 
-#define SWFDEC_AS_VALUE_SET_INT(val,d) SWFDEC_AS_VALUE_SET_NUMBER(val,(int) (d))
+#define SWFDEC_AS_VALUE_IS_NUMBER(val) ((val)->type == SWFDEC_AS_TYPE_NUMBER)
+#define SWFDEC_AS_VALUE_GET_NUMBER(val) ((val)->value.number->number)
 
 #define SWFDEC_AS_VALUE_IS_STRING(val) ((val)->type == SWFDEC_AS_TYPE_STRING)
 #define SWFDEC_AS_VALUE_GET_STRING(val) ((val)->value.string)
@@ -111,6 +110,12 @@ struct _SwfdecAsValue {
   (__val)->value.object = __o; \
 } G_STMT_END
 
+/* value setters */
+#define swfdec_as_value_set_integer(cx, val, i) swfdec_as_value_set_number((cx), (val), (int) (i))
+void		swfdec_as_value_set_number	(SwfdecAsContext *	context,
+						 SwfdecAsValue *	value,
+						 double			number);
+
 /* value conversion functions */
 gboolean	swfdec_as_value_to_boolean	(SwfdecAsContext *	context,
 						 const SwfdecAsValue *	value);
diff --git a/swfdec/swfdec_bitmap_data.c b/swfdec/swfdec_bitmap_data.c
index 4ed1964..4aaf3c2 100644
--- a/swfdec/swfdec_bitmap_data.c
+++ b/swfdec/swfdec_bitmap_data.c
@@ -181,7 +181,7 @@ swfdec_bitmap_data_do_get_width (SwfdecAsContext *cx, SwfdecAsObject *object,
 
   SWFDEC_AS_CHECK (SWFDEC_TYPE_BITMAP_DATA, &bitmap, "");
 
-  SWFDEC_AS_VALUE_SET_INT (ret, bitmap->surface ? (int) bitmap->width : -1);
+  swfdec_as_value_set_integer (cx, ret, bitmap->surface ? (int) bitmap->width : -1);
 }
 
 SWFDEC_AS_NATIVE (1100, 101, swfdec_bitmap_data_set_width)
@@ -201,7 +201,7 @@ swfdec_bitmap_data_do_get_height (SwfdecAsContext *cx, SwfdecAsObject *object,
 
   SWFDEC_AS_CHECK (SWFDEC_TYPE_BITMAP_DATA, &bitmap, "");
 
-  SWFDEC_AS_VALUE_SET_INT (ret, bitmap->surface ? (int) bitmap->height : -1);
+  swfdec_as_value_set_integer (cx, ret, bitmap->surface ? (int) bitmap->height : -1);
 }
 
 SWFDEC_AS_NATIVE (1100, 103, swfdec_bitmap_data_set_height)
@@ -223,7 +223,7 @@ swfdec_bitmap_data_get_rectangle (SwfdecAsContext *cx, SwfdecAsObject *object,
 
   SWFDEC_AS_CHECK (SWFDEC_TYPE_BITMAP_DATA, &bitmap, "");
 
-  SWFDEC_AS_VALUE_SET_INT (ret, -1);
+  swfdec_as_value_set_integer (cx, ret, -1);
   if (bitmap->surface == NULL)
     return;
   
@@ -242,10 +242,10 @@ swfdec_bitmap_data_get_rectangle (SwfdecAsContext *cx, SwfdecAsObject *object,
   if (!SWFDEC_IS_AS_FUNCTION (o))
     return;
 
-  SWFDEC_AS_VALUE_SET_INT (&args[0], 0);
-  SWFDEC_AS_VALUE_SET_INT (&args[1], 0);
-  SWFDEC_AS_VALUE_SET_INT (&args[2], bitmap->width);
-  SWFDEC_AS_VALUE_SET_INT (&args[3], bitmap->height);
+  swfdec_as_value_set_integer (cx, &args[0], 0);
+  swfdec_as_value_set_integer (cx, &args[1], 0);
+  swfdec_as_value_set_integer (cx, &args[2], bitmap->width);
+  swfdec_as_value_set_integer (cx, &args[3], bitmap->height);
   swfdec_as_object_create (SWFDEC_AS_FUNCTION (o), 4, args, ret);
 }
 
@@ -271,7 +271,7 @@ swfdec_bitmap_data_get_transparent (SwfdecAsContext *cx,
     SWFDEC_AS_VALUE_SET_BOOLEAN (ret, 
 	swfdec_surface_has_alpha (bitmap->surface) ? TRUE : FALSE);
   } else {
-    SWFDEC_AS_VALUE_SET_INT (ret, -1);
+    swfdec_as_value_set_integer (cx, ret, -1);
   }
 }
 
@@ -314,7 +314,7 @@ swfdec_bitmap_data_getPixel (SwfdecAsContext *cx, SwfdecAsObject *object,
   color = swfdec_bitmap_data_get_pixel (bitmap, x, y);
   color = SWFDEC_COLOR_UNMULTIPLY (color);
   color &= SWFDEC_COLOR_COMBINE (0xFF, 0xFF, 0xFF, 0);
-  SWFDEC_AS_VALUE_SET_INT (ret, color);
+  swfdec_as_value_set_integer (cx, ret, color);
 }
 
 SWFDEC_AS_NATIVE (1100, 2, swfdec_bitmap_data_setPixel)
@@ -561,7 +561,7 @@ swfdec_bitmap_data_getPixel32 (SwfdecAsContext *cx, SwfdecAsObject *object,
 
   color = swfdec_bitmap_data_get_pixel (bitmap, x, y);
   color = SWFDEC_COLOR_UNMULTIPLY (color);
-  SWFDEC_AS_VALUE_SET_INT (ret, color);
+  swfdec_as_value_set_integer (cx, ret, color);
 }
 
 SWFDEC_AS_NATIVE (1100, 11, swfdec_bitmap_data_setPixel32)
diff --git a/swfdec/swfdec_blur_filter_as.c b/swfdec/swfdec_blur_filter_as.c
index 7732261..e0ddc13 100644
--- a/swfdec/swfdec_blur_filter_as.c
+++ b/swfdec/swfdec_blur_filter_as.c
@@ -35,7 +35,7 @@ swfdec_blur_filter_get_blurX (SwfdecAsContext *cx, SwfdecAsObject *object,
 
   SWFDEC_AS_CHECK (SWFDEC_TYPE_BLUR_FILTER, &filter, "");
 
-  SWFDEC_AS_VALUE_SET_NUMBER (ret, filter->x);
+  swfdec_as_value_set_number (cx, ret, filter->x);
 }
 
 SWFDEC_AS_NATIVE (1102, 2, swfdec_blur_filter_set_blurX)
@@ -61,7 +61,7 @@ swfdec_blur_filter_get_blurY (SwfdecAsContext *cx, SwfdecAsObject *object,
 
   SWFDEC_AS_CHECK (SWFDEC_TYPE_BLUR_FILTER, &filter, "");
 
-  SWFDEC_AS_VALUE_SET_NUMBER (ret, filter->y);
+  swfdec_as_value_set_number (cx, ret, filter->y);
 }
 
 SWFDEC_AS_NATIVE (1102, 4, swfdec_blur_filter_set_blurY)
@@ -87,7 +87,7 @@ swfdec_blur_filter_get_quality (SwfdecAsContext *cx, SwfdecAsObject *object,
 
   SWFDEC_AS_CHECK (SWFDEC_TYPE_BLUR_FILTER, &filter, "");
 
-  SWFDEC_AS_VALUE_SET_INT (ret, filter->quality);
+  swfdec_as_value_set_integer (cx, ret, filter->quality);
 }
 
 SWFDEC_AS_NATIVE (1102, 6, swfdec_blur_filter_set_quality)
diff --git a/swfdec/swfdec_color_as.c b/swfdec/swfdec_color_as.c
index b76de66..1a2f410 100644
--- a/swfdec/swfdec_color_as.c
+++ b/swfdec/swfdec_color_as.c
@@ -67,7 +67,7 @@ swfdec_movie_color_getRGB (SwfdecAsContext *cx, SwfdecAsObject *obj,
   result = (movie->color_transform.rb << 16) |
 	   ((movie->color_transform.gb % 256) << 8) | 
 	   (movie->color_transform.bb % 256);
-  SWFDEC_AS_VALUE_SET_INT (ret, result);
+  swfdec_as_value_set_integer (cx, ret, result);
 }
 
 static void
@@ -75,7 +75,7 @@ add_variable (SwfdecAsObject *obj, const char *name, double value)
 {
   SwfdecAsValue val;
 
-  SWFDEC_AS_VALUE_SET_NUMBER (&val, value);
+  swfdec_as_value_set_number (swfdec_gc_object_get_context (obj), &val, value);
   swfdec_as_object_set_variable (obj, name, &val);
 }
 
diff --git a/swfdec/swfdec_color_matrix_filter_as.c b/swfdec/swfdec_color_matrix_filter_as.c
index f87810e..235e3c4 100644
--- a/swfdec/swfdec_color_matrix_filter_as.c
+++ b/swfdec/swfdec_color_matrix_filter_as.c
@@ -45,7 +45,7 @@ swfdec_color_matrix_filter_get_matrix (SwfdecAsContext *cx,
   SWFDEC_AS_CHECK (SWFDEC_TYPE_COLOR_MATRIX_FILTER, &cm, "");
 
   for (i = 0; i < 20; i++) {
-    SWFDEC_AS_VALUE_SET_NUMBER (&val[i], cm->matrix[i]);
+    swfdec_as_value_set_number (cx, &val[i], cm->matrix[i]);
   }
   array = swfdec_as_array_new (cx);
   swfdec_as_array_append (SWFDEC_AS_ARRAY (array), 20, val);
diff --git a/swfdec/swfdec_color_transform_as.c b/swfdec/swfdec_color_transform_as.c
index 95c949d..1b7b6ff 100644
--- a/swfdec/swfdec_color_transform_as.c
+++ b/swfdec/swfdec_color_transform_as.c
@@ -58,7 +58,7 @@ swfdec_color_transform_as_get_alphaMultiplier (SwfdecAsContext *cx,
 
   SWFDEC_AS_CHECK (SWFDEC_TYPE_COLOR_TRANSFORM_AS, &transform, "");
 
-  SWFDEC_AS_VALUE_SET_NUMBER (ret, transform->aa);
+  swfdec_as_value_set_number (cx, ret, transform->aa);
 }
 
 SWFDEC_AS_NATIVE (1105, 102, swfdec_color_transform_as_set_alphaMultiplier)
@@ -85,7 +85,7 @@ swfdec_color_transform_as_get_redMultiplier (SwfdecAsContext *cx,
 
   SWFDEC_AS_CHECK (SWFDEC_TYPE_COLOR_TRANSFORM_AS, &transform, "");
 
-  SWFDEC_AS_VALUE_SET_NUMBER (ret, transform->ra);
+  swfdec_as_value_set_number (cx, ret, transform->ra);
 }
 
 SWFDEC_AS_NATIVE (1105, 104, swfdec_color_transform_as_set_redMultiplier)
@@ -112,7 +112,7 @@ swfdec_color_transform_as_get_greenMultiplier (SwfdecAsContext *cx,
 
   SWFDEC_AS_CHECK (SWFDEC_TYPE_COLOR_TRANSFORM_AS, &transform, "");
 
-  SWFDEC_AS_VALUE_SET_NUMBER (ret, transform->ga);
+  swfdec_as_value_set_number (cx, ret, transform->ga);
 }
 
 SWFDEC_AS_NATIVE (1105, 106, swfdec_color_transform_as_set_greenMultiplier)
@@ -139,7 +139,7 @@ swfdec_color_transform_as_get_blueMultiplier (SwfdecAsContext *cx,
 
   SWFDEC_AS_CHECK (SWFDEC_TYPE_COLOR_TRANSFORM_AS, &transform, "");
 
-  SWFDEC_AS_VALUE_SET_NUMBER (ret, transform->ba);
+  swfdec_as_value_set_number (cx, ret, transform->ba);
 }
 
 SWFDEC_AS_NATIVE (1105, 108, swfdec_color_transform_as_set_blueMultiplier)
@@ -166,7 +166,7 @@ swfdec_color_transform_as_get_alphaOffset (SwfdecAsContext *cx,
 
   SWFDEC_AS_CHECK (SWFDEC_TYPE_COLOR_TRANSFORM_AS, &transform, "");
 
-  SWFDEC_AS_VALUE_SET_NUMBER (ret, transform->ab);
+  swfdec_as_value_set_number (cx, ret, transform->ab);
 }
 
 SWFDEC_AS_NATIVE (1105, 110, swfdec_color_transform_as_set_alphaOffset)
@@ -193,7 +193,7 @@ swfdec_color_transform_as_get_redOffset (SwfdecAsContext *cx,
 
   SWFDEC_AS_CHECK (SWFDEC_TYPE_COLOR_TRANSFORM_AS, &transform, "");
 
-  SWFDEC_AS_VALUE_SET_NUMBER (ret, transform->rb);
+  swfdec_as_value_set_number (cx, ret, transform->rb);
 }
 
 SWFDEC_AS_NATIVE (1105, 112, swfdec_color_transform_as_set_redOffset)
@@ -220,7 +220,7 @@ swfdec_color_transform_as_get_greenOffset (SwfdecAsContext *cx,
 
   SWFDEC_AS_CHECK (SWFDEC_TYPE_COLOR_TRANSFORM_AS, &transform, "");
 
-  SWFDEC_AS_VALUE_SET_NUMBER (ret, transform->gb);
+  swfdec_as_value_set_number (cx, ret, transform->gb);
 }
 
 SWFDEC_AS_NATIVE (1105, 114, swfdec_color_transform_as_set_greenOffset)
@@ -247,7 +247,7 @@ swfdec_color_transform_as_get_blueOffset (SwfdecAsContext *cx,
 
   SWFDEC_AS_CHECK (SWFDEC_TYPE_COLOR_TRANSFORM_AS, &transform, "");
 
-  SWFDEC_AS_VALUE_SET_NUMBER (ret, transform->bb);
+  swfdec_as_value_set_number (cx, ret, transform->bb);
 }
 
 SWFDEC_AS_NATIVE (1105, 116, swfdec_color_transform_as_set_blueOffset)
@@ -281,7 +281,7 @@ swfdec_color_transform_as_get_rgb (SwfdecAsContext *cx,
   value |= swfdec_as_double_to_integer (transform->gb) << 8;
   value |= swfdec_as_double_to_integer (transform->bb);
 
-  SWFDEC_AS_VALUE_SET_INT (ret, value);
+  swfdec_as_value_set_integer (cx, ret, value);
 }
 
 SWFDEC_AS_NATIVE (1105, 118, swfdec_color_transform_as_set_rgb)
diff --git a/swfdec/swfdec_key_as.c b/swfdec/swfdec_key_as.c
index f89b2b8..c8cb8f8 100644
--- a/swfdec/swfdec_key_as.c
+++ b/swfdec/swfdec_key_as.c
@@ -34,7 +34,7 @@ swfdec_key_getAscii (SwfdecAsContext *cx, SwfdecAsObject *object,
 {
   SwfdecPlayer *player = SWFDEC_PLAYER (cx);
 
-  SWFDEC_AS_VALUE_SET_INT (retval, player->priv->last_character);
+  swfdec_as_value_set_integer (cx, retval, player->priv->last_character);
 }
 
 SWFDEC_AS_NATIVE (800, 1, swfdec_key_getCode)
@@ -44,7 +44,7 @@ swfdec_key_getCode (SwfdecAsContext *cx, SwfdecAsObject *object,
 {
   SwfdecPlayer *player = SWFDEC_PLAYER (cx);
 
-  SWFDEC_AS_VALUE_SET_INT (retval, player->priv->last_keycode);
+  swfdec_as_value_set_integer (cx, retval, player->priv->last_keycode);
 }
 
 SWFDEC_AS_NATIVE (800, 2, swfdec_key_isDown)
diff --git a/swfdec/swfdec_load_object_as.c b/swfdec/swfdec_load_object_as.c
index 235f013..d25b3a2 100644
--- a/swfdec/swfdec_load_object_as.c
+++ b/swfdec/swfdec_load_object_as.c
@@ -48,16 +48,18 @@ static void
 swfdec_load_object_on_progress (SwfdecAsObject *target, glong size,
     glong loaded)
 {
+  SwfdecAsContext *cx;
   SwfdecAsValue val;
 
-  SWFDEC_AS_VALUE_SET_NUMBER (&val, loaded);
+  cx = swfdec_gc_object_get_context (target);
+  swfdec_as_value_set_number (cx, &val, loaded);
   swfdec_as_object_set_variable_and_flags (target, SWFDEC_AS_STR__bytesLoaded,
       &val, SWFDEC_AS_VARIABLE_HIDDEN);
 
   if (size >= 0) {
-    SWFDEC_AS_VALUE_SET_NUMBER (&val, size);
+    swfdec_as_value_set_number (cx, &val, size);
   } else {
-    SWFDEC_AS_VALUE_SET_NUMBER (&val, loaded);
+    swfdec_as_value_set_number (cx, &val, loaded);
   }
   swfdec_as_object_set_variable_and_flags (target, SWFDEC_AS_STR__bytesTotal,
       &val, SWFDEC_AS_VARIABLE_HIDDEN);
@@ -77,7 +79,7 @@ swfdec_load_object_as_load (SwfdecAsContext *cx, SwfdecAsObject *object, guint a
   swfdec_load_object_create (object, url, NULL, 0, NULL, NULL,
       swfdec_load_object_on_progress, swfdec_load_object_on_finish);
 
-  SWFDEC_AS_VALUE_SET_INT (&val, 0);
+  swfdec_as_value_set_integer (cx, &val, 0);
   swfdec_as_object_set_variable_and_flags (object, SWFDEC_AS_STR__bytesLoaded,
       &val, SWFDEC_AS_VARIABLE_HIDDEN);
   SWFDEC_AS_VALUE_SET_UNDEFINED (&val);
@@ -245,7 +247,7 @@ swfdec_load_object_as_sendAndLoad (SwfdecAsContext *cx, SwfdecAsObject *object,
       header_values, swfdec_load_object_on_progress,
       swfdec_load_object_on_finish);
 
-  SWFDEC_AS_VALUE_SET_INT (&val, 0);
+  swfdec_as_value_set_integer (cx, &val, 0);
   swfdec_as_object_set_variable_and_flags (target, SWFDEC_AS_STR__bytesLoaded,
       &val, SWFDEC_AS_VARIABLE_HIDDEN);
   SWFDEC_AS_VALUE_SET_UNDEFINED (&val);
diff --git a/swfdec/swfdec_mouse_as.c b/swfdec/swfdec_mouse_as.c
index 88ee046..9169b45 100644
--- a/swfdec/swfdec_mouse_as.c
+++ b/swfdec/swfdec_mouse_as.c
@@ -34,7 +34,7 @@ swfdec_mouse_show (SwfdecAsContext *cx, SwfdecAsObject *object,
 {
   SwfdecPlayer *player = SWFDEC_PLAYER (cx);
 
-  SWFDEC_AS_VALUE_SET_INT (retval, player->priv->mouse_visible ? 1 : 0);
+  swfdec_as_value_set_integer (cx, retval, player->priv->mouse_visible ? 1 : 0);
   player->priv->mouse_visible = TRUE;
 }
 
@@ -45,7 +45,7 @@ swfdec_mouse_hide (SwfdecAsContext *cx, SwfdecAsObject *object,
 {
   SwfdecPlayer *player = SWFDEC_PLAYER (cx);
 
-  SWFDEC_AS_VALUE_SET_INT (retval, player->priv->mouse_visible ? 1 : 0);
+  swfdec_as_value_set_integer (cx, retval, player->priv->mouse_visible ? 1 : 0);
   player->priv->mouse_visible = FALSE;
 }
 
diff --git a/swfdec/swfdec_movie_asprops.c b/swfdec/swfdec_movie_asprops.c
index 2a885a4..23fe3a9 100644
--- a/swfdec/swfdec_movie_asprops.c
+++ b/swfdec/swfdec_movie_asprops.c
@@ -43,7 +43,7 @@ mc_x_get (SwfdecMovie *movie, SwfdecAsValue *rval)
 
   swfdec_movie_update (movie);
   d = SWFDEC_TWIPS_TO_DOUBLE (movie->matrix.x0);
-  SWFDEC_AS_VALUE_SET_NUMBER (rval, d);
+  swfdec_as_value_set_number (swfdec_gc_object_get_context (movie), rval, d);
 }
 
 static void
@@ -68,7 +68,7 @@ mc_y_get (SwfdecMovie *movie, SwfdecAsValue *rval)
 
   swfdec_movie_update (movie);
   d = SWFDEC_TWIPS_TO_DOUBLE (movie->matrix.y0);
-  SWFDEC_AS_VALUE_SET_NUMBER (rval, d);
+  swfdec_as_value_set_number (swfdec_gc_object_get_context (movie), rval, d);
 }
 
 static void
@@ -89,7 +89,7 @@ mc_y_set (SwfdecMovie *movie, const SwfdecAsValue *val)
 static void
 mc_xscale_get (SwfdecMovie *movie, SwfdecAsValue *rval)
 {
-  SWFDEC_AS_VALUE_SET_NUMBER (rval, movie->xscale);
+  swfdec_as_value_set_number (swfdec_gc_object_get_context (movie), rval, movie->xscale);
 }
 
 static void
@@ -113,7 +113,7 @@ mc_xscale_set (SwfdecMovie *movie, const SwfdecAsValue *val)
 static void
 mc_yscale_get (SwfdecMovie *movie, SwfdecAsValue *rval)
 {
-  SWFDEC_AS_VALUE_SET_NUMBER (rval, movie->yscale);
+  swfdec_as_value_set_number (swfdec_gc_object_get_context (movie), rval, movie->yscale);
 }
 
 static void
@@ -149,7 +149,7 @@ mc_name_set (SwfdecMovie *movie, const SwfdecAsValue *val)
 static void
 mc_alpha_get (SwfdecMovie *movie, SwfdecAsValue *rval)
 {
-  SWFDEC_AS_VALUE_SET_NUMBER (rval,
+  swfdec_as_value_set_number (swfdec_gc_object_get_context (movie), rval,
       movie->color_transform.aa * 100.0 / 256.0);
 }
 
@@ -197,7 +197,7 @@ mc_width_get (SwfdecMovie *movie, SwfdecAsValue *rval)
   swfdec_movie_update (movie);
   d = rint (movie->extents.x1 - movie->extents.x0);
   d = SWFDEC_TWIPS_TO_DOUBLE ((SwfdecTwips) d);
-  SWFDEC_AS_VALUE_SET_NUMBER (rval, d);
+  swfdec_as_value_set_number (swfdec_gc_object_get_context (movie), rval, d);
 }
 
 static void
@@ -239,7 +239,7 @@ mc_height_get (SwfdecMovie *movie, SwfdecAsValue *rval)
   swfdec_movie_update (movie);
   d = rint (movie->extents.y1 - movie->extents.y0);
   d = SWFDEC_TWIPS_TO_DOUBLE ((SwfdecTwips) d);
-  SWFDEC_AS_VALUE_SET_NUMBER (rval, d);
+  swfdec_as_value_set_number (swfdec_gc_object_get_context (movie), rval, d);
 }
 
 static void
@@ -276,7 +276,7 @@ mc_height_set (SwfdecMovie *movie, const SwfdecAsValue *val)
 static void
 mc_rotation_get (SwfdecMovie *movie, SwfdecAsValue *rval)
 {
-  SWFDEC_AS_VALUE_SET_NUMBER (rval, movie->rotation);
+  swfdec_as_value_set_number (swfdec_gc_object_get_context (movie), rval, movie->rotation);
 }
 
 static void
@@ -315,7 +315,7 @@ mc_xmouse_get (SwfdecMovie *movie, SwfdecAsValue *rval)
 
   swfdec_movie_get_mouse (movie, &x, &y);
   x = SWFDEC_TWIPS_TO_DOUBLE (rint (x));
-  SWFDEC_AS_VALUE_SET_NUMBER (rval, x);
+  swfdec_as_value_set_number (swfdec_gc_object_get_context (movie), rval, x);
 }
 
 static void
@@ -325,7 +325,7 @@ mc_ymouse_get (SwfdecMovie *movie, SwfdecAsValue *rval)
 
   swfdec_movie_get_mouse (movie, &x, &y);
   y = SWFDEC_TWIPS_TO_DOUBLE (rint (y));
-  SWFDEC_AS_VALUE_SET_NUMBER (rval, y);
+  swfdec_as_value_set_number (swfdec_gc_object_get_context (movie), rval, y);
 }
 
 static void
@@ -391,13 +391,13 @@ mc_focusrect_get (SwfdecMovie *movie, SwfdecAsValue *rval)
       if (cx->version > 5)
 	SWFDEC_AS_VALUE_SET_BOOLEAN (rval, TRUE);
       else
-	SWFDEC_AS_VALUE_SET_INT (rval, 1);
+	swfdec_as_value_set_integer (cx, rval, 1);
       break;
     case SWFDEC_FLASH_NO:
       if (cx->version > 5)
 	SWFDEC_AS_VALUE_SET_BOOLEAN (rval, FALSE);
       else
-	SWFDEC_AS_VALUE_SET_INT (rval, 0);
+	swfdec_as_value_set_integer (cx, rval, 0);
       break;
     case SWFDEC_FLASH_MAYBE:
       SWFDEC_AS_VALUE_SET_NULL (rval);
diff --git a/swfdec/swfdec_movie_clip_loader.c b/swfdec/swfdec_movie_clip_loader.c
index c56aec1..19e1afa 100644
--- a/swfdec/swfdec_movie_clip_loader.c
+++ b/swfdec/swfdec_movie_clip_loader.c
@@ -113,11 +113,11 @@ swfdec_movie_clip_loader_getProgress (SwfdecAsContext *cx, SwfdecAsObject *objec
   SWFDEC_AS_VALUE_SET_OBJECT (rval, ret);
   resource = swfdec_movie_get_own_resource (movie);
   if (resource == NULL || resource->decoder == NULL) {
-    SWFDEC_AS_VALUE_SET_INT (&loaded, 0);
-    SWFDEC_AS_VALUE_SET_INT (&total, 0);
+    swfdec_as_value_set_integer (cx, &loaded, 0);
+    swfdec_as_value_set_integer (cx, &total, 0);
   } else {
-    SWFDEC_AS_VALUE_SET_INT (&loaded, resource->decoder->bytes_loaded);
-    SWFDEC_AS_VALUE_SET_INT (&total, resource->decoder->bytes_total);
+    swfdec_as_value_set_integer (cx, &loaded, resource->decoder->bytes_loaded);
+    swfdec_as_value_set_integer (cx, &total, resource->decoder->bytes_total);
   }
   swfdec_as_object_set_variable (ret, SWFDEC_AS_STR_bytesLoaded, &loaded);
   swfdec_as_object_set_variable (ret, SWFDEC_AS_STR_bytesTotal, &total);
diff --git a/swfdec/swfdec_net_stream.c b/swfdec/swfdec_net_stream.c
index 422a4a3..b863997 100644
--- a/swfdec/swfdec_net_stream.c
+++ b/swfdec/swfdec_net_stream.c
@@ -533,31 +533,33 @@ swfdec_net_stream_get_variable (SwfdecAsObject *object, SwfdecAsObject *orig,
     const char *variable, SwfdecAsValue *val, guint *flags)
 {
   SwfdecNetStream *stream;
+  SwfdecAsContext *cx;
 
   if (SWFDEC_AS_OBJECT_CLASS (swfdec_net_stream_parent_class)->get (object, orig, variable, val, flags))
     return TRUE;
 
+  cx = swfdec_gc_object_get_context (object);
   stream = SWFDEC_NET_STREAM (object);
   /* FIXME: need case insensitive comparisons? */
   if (variable == SWFDEC_AS_STR_time) {
     guint msecs;
     if (stream->flvdecoder == NULL ||
 	!swfdec_flv_decoder_get_video_info (stream->flvdecoder, &msecs, NULL)) {
-      SWFDEC_AS_VALUE_SET_INT (val, 0);
+      swfdec_as_value_set_integer (cx, val, 0);
     } else {
       if (msecs >= stream->current_time)
 	msecs = 0;
       else 
 	msecs = stream->current_time - msecs;
-      SWFDEC_AS_VALUE_SET_NUMBER (val, msecs / 1000.);
+      swfdec_as_value_set_number (cx, val, msecs / 1000.);
     }
     *flags = 0;
     return TRUE;
   } else if (variable == SWFDEC_AS_STR_bytesLoaded) {
     if (stream->loader == NULL)
-      SWFDEC_AS_VALUE_SET_INT (val, 0);
+      swfdec_as_value_set_integer (cx, val, 0);
     else
-      SWFDEC_AS_VALUE_SET_NUMBER (val, swfdec_loader_get_loaded (stream->loader));
+      swfdec_as_value_set_number (cx, val, swfdec_loader_get_loaded (stream->loader));
     *flags = 0;
     return TRUE;
   } else if (variable == SWFDEC_AS_STR_bytesTotal) {
@@ -569,7 +571,7 @@ swfdec_net_stream_get_variable (SwfdecAsObject *object, SwfdecAsObject *orig,
       if (bytes < 0)
 	bytes = swfdec_loader_get_loaded (stream->loader);
     }
-    SWFDEC_AS_VALUE_SET_NUMBER (val, bytes);
+    swfdec_as_value_set_number (cx, val, bytes);
     *flags = 0;
     return TRUE;
   } else if (variable == SWFDEC_AS_STR_bufferLength) {
diff --git a/swfdec/swfdec_player_as.c b/swfdec/swfdec_player_as.c
index 2455156..4a792ea 100644
--- a/swfdec/swfdec_player_as.c
+++ b/swfdec/swfdec_player_as.c
@@ -78,7 +78,7 @@ swfdec_player_do_set_interval (gboolean repeat, SwfdecAsContext *cx, guint argc,
     }
     id = swfdec_interval_new_object (player, msecs, repeat, object, name, argc - 3, &argv[3]);
   }
-  SWFDEC_AS_VALUE_SET_INT (rval, id);
+  swfdec_as_value_set_integer (cx, rval, id);
 }
 
 SWFDEC_AS_NATIVE (2, 0, swfdec_player_ASnew)
diff --git a/swfdec/swfdec_resource.c b/swfdec/swfdec_resource.c
index 67a5c9c..51e1b2a 100644
--- a/swfdec/swfdec_resource.c
+++ b/swfdec/swfdec_resource.c
@@ -146,11 +146,11 @@ swfdec_resource_emit_signal (SwfdecResource *resource, const char *name, gboolea
       res = NULL;
     if (res && res->decoder) {
       SwfdecDecoder *dec = res->decoder;
-      SWFDEC_AS_VALUE_SET_INT (&vals[2], dec->bytes_loaded);
-      SWFDEC_AS_VALUE_SET_INT (&vals[3], dec->bytes_total);
+      swfdec_as_value_set_integer (cx, &vals[2], dec->bytes_loaded);
+      swfdec_as_value_set_integer (cx, &vals[3], dec->bytes_total);
     } else {
-      SWFDEC_AS_VALUE_SET_INT (&vals[2], 0);
-      SWFDEC_AS_VALUE_SET_INT (&vals[3], 0);
+      swfdec_as_value_set_integer (cx, &vals[2], 0);
+      swfdec_as_value_set_integer (cx, &vals[3], 0);
     }
   }
   if (n_args)
@@ -168,7 +168,7 @@ swfdec_resource_emit_error (SwfdecResource *resource, const char *message)
   SwfdecAsValue vals[2];
 
   SWFDEC_AS_VALUE_SET_STRING (&vals[0], message);
-  SWFDEC_AS_VALUE_SET_INT (&vals[1], 0);
+  swfdec_as_value_set_integer (swfdec_gc_object_get_context (resource), &vals[1], 0);
 
   swfdec_resource_emit_signal (resource, SWFDEC_AS_STR_onLoadError, FALSE, vals, 2);
 }
@@ -320,7 +320,7 @@ swfdec_resource_stream_target_close (SwfdecStreamTarget *target, SwfdecStream *s
       swfdec_loader_set_data_type (SWFDEC_LOADER (stream), dec->data_type);
   }
 
-  SWFDEC_AS_VALUE_SET_INT (&val, 0); /* FIXME */
+  swfdec_as_value_set_integer (swfdec_gc_object_get_context (resource), &val, 0); /* FIXME */
   swfdec_resource_emit_signal (resource, SWFDEC_AS_STR_onLoadComplete, FALSE, &val, 1);
   resource->state = SWFDEC_RESOURCE_COMPLETE;
   if (swfdec_resource_abort_if_not_initialized (resource))
diff --git a/swfdec/swfdec_selection.c b/swfdec/swfdec_selection.c
index 853f2b4..9f4ecfc 100644
--- a/swfdec/swfdec_selection.c
+++ b/swfdec/swfdec_selection.c
@@ -44,13 +44,13 @@ swfdec_selection_getBeginIndex (SwfdecAsContext *cx, SwfdecAsObject *object,
   const char *s;
 
   if (!SWFDEC_IS_TEXT_FIELD_MOVIE (priv->focus)) {
-    SWFDEC_AS_VALUE_SET_INT (ret, -1);
+    swfdec_as_value_set_integer (cx, ret, -1);
     return;
   }
   text = SWFDEC_TEXT_FIELD_MOVIE (priv->focus);
   swfdec_text_buffer_get_selection (text->text, &start, &end);
   s = swfdec_text_buffer_get_text (text->text);
-  SWFDEC_AS_VALUE_SET_INT (ret, g_utf8_pointer_to_offset (s, s + start));
+  swfdec_as_value_set_integer (cx, ret, g_utf8_pointer_to_offset (s, s + start));
 }
 
 SWFDEC_AS_NATIVE (600, 1, swfdec_selection_getEndIndex)
@@ -64,13 +64,13 @@ swfdec_selection_getEndIndex (SwfdecAsContext *cx, SwfdecAsObject *object,
   const char *s;
 
   if (!SWFDEC_IS_TEXT_FIELD_MOVIE (priv->focus)) {
-    SWFDEC_AS_VALUE_SET_INT (ret, -1);
+    swfdec_as_value_set_integer (cx, ret, -1);
     return;
   }
   text = SWFDEC_TEXT_FIELD_MOVIE (priv->focus);
   swfdec_text_buffer_get_selection (text->text, &start, &end);
   s = swfdec_text_buffer_get_text (text->text);
-  SWFDEC_AS_VALUE_SET_INT (ret, g_utf8_pointer_to_offset (s, s + end));
+  swfdec_as_value_set_integer (cx, ret, g_utf8_pointer_to_offset (s, s + end));
 }
 
 SWFDEC_AS_NATIVE (600, 2, swfdec_selection_getCaretIndex)
@@ -83,12 +83,12 @@ swfdec_selection_getCaretIndex (SwfdecAsContext *cx, SwfdecAsObject *object,
   const char *s;
 
   if (!SWFDEC_IS_TEXT_FIELD_MOVIE (priv->focus)) {
-    SWFDEC_AS_VALUE_SET_INT (ret, -1);
+    swfdec_as_value_set_integer (cx, ret, -1);
     return;
   }
   text = SWFDEC_TEXT_FIELD_MOVIE (priv->focus);
   s = swfdec_text_buffer_get_text (text->text);
-  SWFDEC_AS_VALUE_SET_INT (ret, g_utf8_pointer_to_offset (s, 
+  swfdec_as_value_set_integer (cx, ret, g_utf8_pointer_to_offset (s, 
 	s + swfdec_text_buffer_get_cursor (text->text)));
 }
 
diff --git a/swfdec/swfdec_sound_object.c b/swfdec/swfdec_sound_object.c
index d5f959b..02756cc 100644
--- a/swfdec/swfdec_sound_object.c
+++ b/swfdec/swfdec_sound_object.c
@@ -137,7 +137,7 @@ swfdec_sound_object_getPan (SwfdecAsContext *cx, SwfdecAsObject *object,
   if (matrix == NULL)
     return;
 
-  SWFDEC_AS_VALUE_SET_INT (ret, swfdec_sound_matrix_get_pan (matrix));
+  swfdec_as_value_set_integer (cx, ret, swfdec_sound_matrix_get_pan (matrix));
 }
 
 SWFDEC_AS_NATIVE (500, 1, swfdec_sound_object_getTransform)
@@ -158,13 +158,13 @@ swfdec_sound_object_getTransform (SwfdecAsContext *cx, SwfdecAsObject *object,
 
   obj = swfdec_as_object_new (cx);
 
-  SWFDEC_AS_VALUE_SET_INT (&val, matrix->ll);
+  swfdec_as_value_set_integer (cx, &val, matrix->ll);
   swfdec_as_object_set_variable (obj, SWFDEC_AS_STR_ll, &val);
-  SWFDEC_AS_VALUE_SET_INT (&val, matrix->lr);
+  swfdec_as_value_set_integer (cx, &val, matrix->lr);
   swfdec_as_object_set_variable (obj, SWFDEC_AS_STR_lr, &val);
-  SWFDEC_AS_VALUE_SET_INT (&val, matrix->rl);
+  swfdec_as_value_set_integer (cx, &val, matrix->rl);
   swfdec_as_object_set_variable (obj, SWFDEC_AS_STR_rl, &val);
-  SWFDEC_AS_VALUE_SET_INT (&val, matrix->rr);
+  swfdec_as_value_set_integer (cx, &val, matrix->rr);
   swfdec_as_object_set_variable (obj, SWFDEC_AS_STR_rr, &val);
 
   SWFDEC_AS_VALUE_SET_OBJECT (ret, obj);
@@ -184,7 +184,7 @@ swfdec_sound_object_getVolume (SwfdecAsContext *cx, SwfdecAsObject *object,
   if (matrix == NULL)
     return;
 
-  SWFDEC_AS_VALUE_SET_INT (ret, matrix->volume);
+  swfdec_as_value_set_integer (cx, ret, matrix->volume);
 }
 
 SWFDEC_AS_NATIVE (500, 3, swfdec_sound_object_setPan)
diff --git a/swfdec/swfdec_sprite_movie.c b/swfdec/swfdec_sprite_movie.c
index 2e9c34b..20d65f0 100644
--- a/swfdec/swfdec_sprite_movie.c
+++ b/swfdec/swfdec_sprite_movie.c
@@ -779,16 +779,17 @@ static void
 swfdec_sprite_movie_property_get (SwfdecMovie *mov, guint prop_id, SwfdecAsValue *val)
 {
   SwfdecSpriteMovie *movie = SWFDEC_SPRITE_MOVIE (mov);
+  SwfdecAsContext *cx = swfdec_gc_object_get_context (mov);
 
   switch (prop_id) {
     case SWFDEC_MOVIE_PROPERTY_CURRENTFRAME:
-      SWFDEC_AS_VALUE_SET_INT (val, movie->frame);
+      swfdec_as_value_set_integer (cx, val, movie->frame);
       break;
     case SWFDEC_MOVIE_PROPERTY_FRAMESLOADED:
-      SWFDEC_AS_VALUE_SET_INT (val, swfdec_sprite_movie_get_frames_loaded (movie));
+      swfdec_as_value_set_integer (cx, val, swfdec_sprite_movie_get_frames_loaded (movie));
       break;
     case SWFDEC_MOVIE_PROPERTY_TOTALFRAMES:
-      SWFDEC_AS_VALUE_SET_INT (val, swfdec_sprite_movie_get_frames_total (movie));
+      swfdec_as_value_set_integer (cx, val, swfdec_sprite_movie_get_frames_total (movie));
       break;
     default:
       SWFDEC_MOVIE_CLASS (swfdec_sprite_movie_parent_class)->property_get (mov, prop_id, val);
diff --git a/swfdec/swfdec_sprite_movie_as.c b/swfdec/swfdec_sprite_movie_as.c
index ab22c74..2d6f76b 100644
--- a/swfdec/swfdec_sprite_movie_as.c
+++ b/swfdec/swfdec_sprite_movie_as.c
@@ -286,8 +286,8 @@ swfdec_sprite_movie_localToGlobal (SwfdecAsContext *cx, SwfdecAsObject *object,
   x = swfdec_as_double_to_integer (x * SWFDEC_TWIPS_SCALE_FACTOR);
   y = swfdec_as_double_to_integer (y * SWFDEC_TWIPS_SCALE_FACTOR);
   swfdec_movie_local_to_global (movie, &x, &y);
-  SWFDEC_AS_VALUE_SET_NUMBER (xv, SWFDEC_TWIPS_TO_DOUBLE ((SwfdecTwips) x));
-  SWFDEC_AS_VALUE_SET_NUMBER (yv, SWFDEC_TWIPS_TO_DOUBLE ((SwfdecTwips) y));
+  swfdec_as_value_set_number (cx, xv, SWFDEC_TWIPS_TO_DOUBLE ((SwfdecTwips) x));
+  swfdec_as_value_set_number (cx, yv, SWFDEC_TWIPS_TO_DOUBLE ((SwfdecTwips) y));
 }
 
 SWFDEC_AS_NATIVE (900, 3, swfdec_sprite_movie_globalToLocal)
@@ -314,8 +314,8 @@ swfdec_sprite_movie_globalToLocal (SwfdecAsContext *cx, SwfdecAsObject *object,
   x = swfdec_as_double_to_integer (x * SWFDEC_TWIPS_SCALE_FACTOR);
   y = swfdec_as_double_to_integer (y * SWFDEC_TWIPS_SCALE_FACTOR);
   swfdec_movie_global_to_local (movie, &x, &y);
-  SWFDEC_AS_VALUE_SET_NUMBER (xv, SWFDEC_TWIPS_TO_DOUBLE ((SwfdecTwips) x));
-  SWFDEC_AS_VALUE_SET_NUMBER (yv, SWFDEC_TWIPS_TO_DOUBLE ((SwfdecTwips) y));
+  swfdec_as_value_set_number (cx, xv, SWFDEC_TWIPS_TO_DOUBLE ((SwfdecTwips) x));
+  swfdec_as_value_set_number (cx, yv, SWFDEC_TWIPS_TO_DOUBLE ((SwfdecTwips) y));
 }
 
 SWFDEC_AS_NATIVE (900, 8, swfdec_sprite_movie_attachAudio)
@@ -363,10 +363,10 @@ swfdec_sprite_movie_getSWFVersion (SwfdecAsContext *cx, SwfdecAsObject *object,
     guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
 {
   if (object != NULL && SWFDEC_IS_MOVIE (object)) {
-    SWFDEC_AS_VALUE_SET_INT (rval,
+    swfdec_as_value_set_integer (cx, rval,
 	swfdec_movie_get_version (SWFDEC_MOVIE (object)));
   } else {
-    SWFDEC_AS_VALUE_SET_INT (rval, -1);
+    swfdec_as_value_set_integer (cx, rval, -1);
   }
 }
 
@@ -443,9 +443,9 @@ swfdec_sprite_movie_getBytesLoaded (SwfdecAsContext *cx, SwfdecAsObject *object,
 
   resource = swfdec_movie_get_own_resource (movie);
   if (resource && resource->decoder) {
-    SWFDEC_AS_VALUE_SET_INT (rval, resource->decoder->bytes_loaded);
+    swfdec_as_value_set_integer (cx, rval, resource->decoder->bytes_loaded);
   } else {
-    SWFDEC_AS_VALUE_SET_INT (rval, 0);
+    swfdec_as_value_set_integer (cx, rval, 0);
   }
 }
 
@@ -462,12 +462,12 @@ swfdec_sprite_movie_getBytesTotal (SwfdecAsContext *cx, SwfdecAsObject *object,
   resource = swfdec_movie_get_own_resource (movie);
   if (resource) {
     if (resource->decoder) {
-      SWFDEC_AS_VALUE_SET_INT (rval, resource->decoder->bytes_total);
+      swfdec_as_value_set_integer (cx, rval, resource->decoder->bytes_total);
     } else {
-      SWFDEC_AS_VALUE_SET_INT (rval, -1);
+      swfdec_as_value_set_integer (cx, rval, -1);
     }
   } else {
-    SWFDEC_AS_VALUE_SET_INT (rval, 0);
+    swfdec_as_value_set_integer (cx, rval, 0);
   }
 }
 
@@ -488,7 +488,7 @@ swfdec_sprite_movie_getNextHighestDepth (SwfdecAsContext *cx, SwfdecAsObject *ob
   } else {
     depth = 0;
   }
-  SWFDEC_AS_VALUE_SET_INT (rval, depth);
+  swfdec_as_value_set_integer (cx, rval, depth);
 }
 
 static void
@@ -883,7 +883,7 @@ swfdec_sprite_movie_getDepth (SwfdecAsContext *cx, SwfdecAsObject *object,
 
   SWFDEC_AS_CHECK (SWFDEC_TYPE_MOVIE, (gpointer)&movie, "");
 
-  SWFDEC_AS_VALUE_SET_INT (rval, movie->depth);
+  swfdec_as_value_set_integer (cx, rval, movie->depth);
 }
 
 SWFDEC_AS_NATIVE (900, 5, swfdec_sprite_movie_getBounds)
@@ -925,13 +925,13 @@ swfdec_sprite_movie_getBounds (SwfdecAsContext *cx, SwfdecAsObject *object,
     x1 = rect.x1;
     y1 = rect.y1;
   }
-  SWFDEC_AS_VALUE_SET_NUMBER (&val, SWFDEC_TWIPS_TO_DOUBLE (x0));
+  swfdec_as_value_set_number (cx, &val, SWFDEC_TWIPS_TO_DOUBLE (x0));
   swfdec_as_object_set_variable (obj, SWFDEC_AS_STR_xMin, &val);
-  SWFDEC_AS_VALUE_SET_NUMBER (&val, SWFDEC_TWIPS_TO_DOUBLE (y0));
+  swfdec_as_value_set_number (cx, &val, SWFDEC_TWIPS_TO_DOUBLE (y0));
   swfdec_as_object_set_variable (obj, SWFDEC_AS_STR_yMin, &val);
-  SWFDEC_AS_VALUE_SET_NUMBER (&val, SWFDEC_TWIPS_TO_DOUBLE (x1));
+  swfdec_as_value_set_number (cx, &val, SWFDEC_TWIPS_TO_DOUBLE (x1));
   swfdec_as_object_set_variable (obj, SWFDEC_AS_STR_xMax, &val);
-  SWFDEC_AS_VALUE_SET_NUMBER (&val, SWFDEC_TWIPS_TO_DOUBLE (y1));
+  swfdec_as_value_set_number (cx, &val, SWFDEC_TWIPS_TO_DOUBLE (y1));
   swfdec_as_object_set_variable (obj, SWFDEC_AS_STR_yMax, &val);
 
   SWFDEC_AS_VALUE_SET_OBJECT (rval, obj);
diff --git a/swfdec/swfdec_stage_as.c b/swfdec/swfdec_stage_as.c
index 88f82d2..444c0a3 100644
--- a/swfdec/swfdec_stage_as.c
+++ b/swfdec/swfdec_stage_as.c
@@ -139,9 +139,9 @@ get_width (SwfdecAsContext *cx, SwfdecAsObject *object,
   SwfdecPlayerPrivate *priv = SWFDEC_PLAYER (cx)->priv;
 
   if (priv->scale_mode == SWFDEC_SCALE_NONE)
-    SWFDEC_AS_VALUE_SET_INT (ret, priv->internal_width);
+    swfdec_as_value_set_integer (cx, ret, priv->internal_width);
   else
-    SWFDEC_AS_VALUE_SET_INT (ret, priv->width);
+    swfdec_as_value_set_integer (cx, ret, priv->width);
 }
 
 SWFDEC_AS_NATIVE (666, 7, get_height)
@@ -152,9 +152,9 @@ get_height (SwfdecAsContext *cx, SwfdecAsObject *object,
   SwfdecPlayerPrivate *priv = SWFDEC_PLAYER (cx)->priv;
 
   if (priv->scale_mode == SWFDEC_SCALE_NONE)
-    SWFDEC_AS_VALUE_SET_INT (ret, priv->internal_height);
+    swfdec_as_value_set_integer (cx, ret, priv->internal_height);
   else
-    SWFDEC_AS_VALUE_SET_INT (ret, priv->height);
+    swfdec_as_value_set_integer (cx, ret, priv->height);
 }
 
 /* FIXME: do this smarter */
diff --git a/swfdec/swfdec_style_sheet.c b/swfdec/swfdec_style_sheet.c
index 2d3a249..94e0e29 100644
--- a/swfdec/swfdec_style_sheet.c
+++ b/swfdec/swfdec_style_sheet.c
@@ -304,7 +304,7 @@ swfdec_style_sheet_parseColor (SwfdecAsContext *cx, SwfdecAsObject *object,
   if (*tail != '\0')
     return;
 
-  SWFDEC_AS_VALUE_SET_INT (rval, result);
+  swfdec_as_value_set_integer (cx, rval, result);
 }
 
 SWFDEC_AS_CONSTRUCTOR (113, 0, swfdec_style_sheet_construct, swfdec_style_sheet_get_type)
diff --git a/swfdec/swfdec_system_as.c b/swfdec/swfdec_system_as.c
index a385060..81b6e4f 100644
--- a/swfdec/swfdec_system_as.c
+++ b/swfdec/swfdec_system_as.c
@@ -172,19 +172,19 @@ swfdec_system_manufacturer (SwfdecPlayer *player, SwfdecAsValue *ret)
 static void
 swfdec_system_screen_width (SwfdecPlayer *player, SwfdecAsValue *ret)
 {
-  SWFDEC_AS_VALUE_SET_INT (ret, player->priv->system->screen_width);
+  swfdec_as_value_set_integer (SWFDEC_AS_CONTEXT (player), ret, player->priv->system->screen_width);
 }
 
 static void
 swfdec_system_screen_height (SwfdecPlayer *player, SwfdecAsValue *ret)
 {
-  SWFDEC_AS_VALUE_SET_INT (ret, player->priv->system->screen_height);
+  swfdec_as_value_set_integer (SWFDEC_AS_CONTEXT (player), ret, player->priv->system->screen_height);
 }
 
 static void
 swfdec_system_screen_dpi (SwfdecPlayer *player, SwfdecAsValue *ret)
 {
-  SWFDEC_AS_VALUE_SET_INT (ret, player->priv->system->dpi);
+  swfdec_as_value_set_integer (SWFDEC_AS_CONTEXT (player), ret, player->priv->system->dpi);
 }
 
 static void
@@ -197,7 +197,7 @@ swfdec_system_screen_color (SwfdecPlayer *player, SwfdecAsValue *ret)
 static void
 swfdec_system_screen_par (SwfdecPlayer *player, SwfdecAsValue *ret)
 {
-  SWFDEC_AS_VALUE_SET_NUMBER (ret, player->priv->system->par);
+  swfdec_as_value_set_number (SWFDEC_AS_CONTEXT (player), ret, player->priv->system->par);
 }
 
 static void
diff --git a/swfdec/swfdec_text_field_movie.c b/swfdec/swfdec_text_field_movie.c
index 4c9505a..feaf4f0 100644
--- a/swfdec/swfdec_text_field_movie.c
+++ b/swfdec/swfdec_text_field_movie.c
@@ -858,6 +858,7 @@ swfdec_text_field_movie_property_get (SwfdecMovie *movie, guint prop_id,
     SwfdecAsValue *val)
 {
   SwfdecTextFieldMovie *text = SWFDEC_TEXT_FIELD_MOVIE (movie);
+  SwfdecAsContext *cx = swfdec_gc_object_get_context (text);
   double d;
 
   switch (prop_id) {
@@ -865,13 +866,13 @@ swfdec_text_field_movie_property_get (SwfdecMovie *movie, guint prop_id,
       swfdec_text_field_movie_autosize (text);
       swfdec_movie_update (movie);
       d = SWFDEC_TWIPS_TO_DOUBLE (movie->matrix.x0 + text->extents.x0);
-      SWFDEC_AS_VALUE_SET_NUMBER (val, d);
+      swfdec_as_value_set_number (cx, val, d);
       return;
     case SWFDEC_MOVIE_PROPERTY_Y:
       swfdec_text_field_movie_autosize (text);
       swfdec_movie_update (movie);
       d = SWFDEC_TWIPS_TO_DOUBLE (movie->matrix.y0 + text->extents.y0);
-      SWFDEC_AS_VALUE_SET_NUMBER (val, d);
+      swfdec_as_value_set_number (cx, val, d);
       return;
     case SWFDEC_MOVIE_PROPERTY_WIDTH:
     case SWFDEC_MOVIE_PROPERTY_HEIGHT:
diff --git a/swfdec/swfdec_text_field_movie_as.c b/swfdec/swfdec_text_field_movie_as.c
index 8118023..9d04b72 100644
--- a/swfdec/swfdec_text_field_movie_as.c
+++ b/swfdec/swfdec_text_field_movie_as.c
@@ -182,7 +182,7 @@ swfdec_text_field_movie_get_length (SwfdecAsContext *cx, SwfdecAsObject *object,
 
   SWFDEC_AS_CHECK (SWFDEC_TYPE_TEXT_FIELD_MOVIE, &text, "");
 
-  SWFDEC_AS_VALUE_SET_INT (ret, g_utf8_strlen (swfdec_text_buffer_get_text (text->text), -1));
+  swfdec_as_value_set_integer (cx, ret, g_utf8_strlen (swfdec_text_buffer_get_text (text->text), -1));
 }
 
 /*
@@ -225,7 +225,7 @@ swfdec_text_field_movie_get_maxChars (SwfdecAsContext *cx,
   SWFDEC_AS_CHECK (SWFDEC_TYPE_TEXT_FIELD_MOVIE, &text, "");
 
   if (text->max_chars != 0) {
-    SWFDEC_AS_VALUE_SET_INT (ret, text->max_chars);
+    swfdec_as_value_set_integer (cx, ret, text->max_chars);
   } else {
     SWFDEC_AS_VALUE_SET_NULL (ret);
   }
@@ -433,7 +433,7 @@ swfdec_text_field_movie_get_textHeight (SwfdecAsContext *cx,
 
   swfdec_movie_update (SWFDEC_MOVIE (text));
   swfdec_text_field_movie_update_layout (text);
-  SWFDEC_AS_VALUE_SET_INT (ret, floor (text->layout_height * 
+  swfdec_as_value_set_integer (cx, ret, floor (text->layout_height * 
 	text->from_layout.yy / SWFDEC_TWIPS_SCALE_FACTOR));
 }
 
@@ -448,7 +448,7 @@ swfdec_text_field_movie_get_textWidth (SwfdecAsContext *cx,
 
   swfdec_movie_update (SWFDEC_MOVIE (text));
   swfdec_text_field_movie_update_layout (text);
-  SWFDEC_AS_VALUE_SET_INT (ret, floor (text->layout_width *
+  swfdec_as_value_set_integer (cx, ret, floor (text->layout_width *
 	text->from_layout.xx / SWFDEC_TWIPS_SCALE_FACTOR));
 }
 
@@ -494,7 +494,7 @@ swfdec_text_field_movie_get_backgroundColor (SwfdecAsContext *cx,
 
   SWFDEC_AS_CHECK (SWFDEC_TYPE_TEXT_FIELD_MOVIE, &text, "");
 
-  SWFDEC_AS_VALUE_SET_NUMBER (ret,
+  swfdec_as_value_set_number (cx, ret,
       SWFDEC_COLOR_RED (text->background_color) << 16 |
       SWFDEC_COLOR_GREEN (text->background_color) << 8 |
       SWFDEC_COLOR_BLUE (text->background_color));
@@ -558,7 +558,7 @@ swfdec_text_field_movie_get_borderColor (SwfdecAsContext *cx,
   SWFDEC_AS_CHECK (SWFDEC_TYPE_TEXT_FIELD_MOVIE, &text, "");
 
 
-  SWFDEC_AS_VALUE_SET_NUMBER (ret,
+  swfdec_as_value_set_number (cx, ret,
       SWFDEC_COLOR_RED (text->border_color) << 16 |
       SWFDEC_COLOR_GREEN (text->border_color) << 8 |
       SWFDEC_COLOR_BLUE (text->border_color));
@@ -594,7 +594,7 @@ swfdec_text_field_movie_get_bottomScroll (SwfdecAsContext *cx,
 
   SWFDEC_AS_CHECK (SWFDEC_TYPE_TEXT_FIELD_MOVIE, &text, "");
 
-  SWFDEC_AS_VALUE_SET_NUMBER (ret, text->scroll + text->lines_visible);
+  swfdec_as_value_set_number (cx, ret, text->scroll + text->lines_visible);
 }
 
 static void
@@ -606,7 +606,7 @@ swfdec_text_field_movie_do_get_hscroll (SwfdecAsContext *cx,
 
   SWFDEC_AS_CHECK (SWFDEC_TYPE_TEXT_FIELD_MOVIE, &text, "");
 
-  SWFDEC_AS_VALUE_SET_NUMBER (ret, text->hscroll);
+  swfdec_as_value_set_number (cx, ret, text->hscroll);
 }
 
 static void
@@ -636,7 +636,7 @@ swfdec_text_field_movie_get_maxhscroll (SwfdecAsContext *cx,
 
   SWFDEC_AS_CHECK (SWFDEC_TYPE_TEXT_FIELD_MOVIE, &text, "");
 
-  SWFDEC_AS_VALUE_SET_INT (ret, swfdec_text_field_movie_get_hscroll_max (text));
+  swfdec_as_value_set_integer (cx, ret, swfdec_text_field_movie_get_hscroll_max (text));
 }
 
 static void
@@ -648,7 +648,7 @@ swfdec_text_field_movie_get_maxscroll (SwfdecAsContext *cx,
 
   SWFDEC_AS_CHECK (SWFDEC_TYPE_TEXT_FIELD_MOVIE, &text, "");
 
-  SWFDEC_AS_VALUE_SET_NUMBER (ret, text->scroll_max + 1);
+  swfdec_as_value_set_number (cx, ret, text->scroll_max + 1);
 }
 
 static void
@@ -687,7 +687,7 @@ swfdec_text_field_movie_do_get_scroll (SwfdecAsContext *cx,
 
   SWFDEC_AS_CHECK (SWFDEC_TYPE_TEXT_FIELD_MOVIE, &text, "");
 
-  SWFDEC_AS_VALUE_SET_NUMBER (ret, text->scroll + 1);
+  swfdec_as_value_set_number (cx, ret, text->scroll + 1);
 }
 
 static void
@@ -942,7 +942,7 @@ swfdec_text_field_movie_get_textColor (SwfdecAsContext *cx,
 
   SWFDEC_AS_CHECK (SWFDEC_TYPE_TEXT_FIELD_MOVIE, &text, "");
 
-  SWFDEC_AS_VALUE_SET_NUMBER (ret, 
+  swfdec_as_value_set_number (cx, ret, 
       swfdec_text_buffer_get_default_attributes (text->text)->color);
 }
 
@@ -1308,7 +1308,7 @@ swfdec_text_field_movie_getDepth (SwfdecAsContext *cx, SwfdecAsObject *object,
 
   SWFDEC_AS_CHECK (SWFDEC_TYPE_TEXT_FIELD_MOVIE, &text, "");
 
-  SWFDEC_AS_VALUE_SET_INT (rval, SWFDEC_MOVIE (text)->depth);
+  swfdec_as_value_set_integer (cx, rval, SWFDEC_MOVIE (text)->depth);
 }
 
 SWFDEC_AS_NATIVE (104, 103, swfdec_text_field_movie_removeTextField)
diff --git a/swfdec/swfdec_text_field_movie_html.c b/swfdec/swfdec_text_field_movie_html.c
index bcc606d..a68bb1c 100644
--- a/swfdec/swfdec_text_field_movie_html.c
+++ b/swfdec/swfdec_text_field_movie_html.c
@@ -116,6 +116,7 @@ swfdec_text_field_movie_html_tag_set_attribute (ParserData *data,
 {
   SwfdecAsValue val;
   SwfdecAsObject *object;
+  SwfdecAsContext *cx;
 
   g_return_if_fail (data != NULL);
   g_return_if_fail (tag != NULL);
@@ -128,8 +129,9 @@ swfdec_text_field_movie_html_tag_set_attribute (ParserData *data,
     return;
 
   object = SWFDEC_AS_OBJECT (tag->format);
+  cx = swfdec_gc_object_get_context (object);
   SWFDEC_AS_VALUE_SET_STRING (&val, swfdec_as_context_give_string (
-	swfdec_gc_object_get_context (object), g_strndup (value, value_length)));
+	cx, g_strndup (value, value_length)));
 
   if (tag->name_length == 10 && !g_strncasecmp (tag->name, "textformat", 10))
   {
@@ -177,7 +179,7 @@ swfdec_text_field_movie_html_tag_set_attribute (ParserData *data,
       SwfdecAsValue val_number;
 
       if (value_length != 7 || *value != '#') {
-	SWFDEC_AS_VALUE_SET_NUMBER (&val_number, 0);
+	swfdec_as_value_set_number (cx, &val_number, 0);
       } else {
 	int number;
 	char *tail;
@@ -185,7 +187,7 @@ swfdec_text_field_movie_html_tag_set_attribute (ParserData *data,
 	number = g_ascii_strtoll (value + 1, &tail, 16);
 	if (tail != value + 7)
 	  number = 0;
-	SWFDEC_AS_VALUE_SET_NUMBER (&val_number, number);
+	swfdec_as_value_set_number (cx, &val_number, number);
       }
 
       swfdec_as_object_set_variable (object, SWFDEC_AS_STR_color, &val_number);
diff --git a/swfdec/swfdec_text_format.c b/swfdec/swfdec_text_format.c
index 7442a0d..401201c 100644
--- a/swfdec/swfdec_text_format.c
+++ b/swfdec/swfdec_text_format.c
@@ -203,7 +203,7 @@ swfdec_text_format_get_integer (SwfdecAsObject *object,
     return;
   }
 
-  SWFDEC_AS_VALUE_SET_NUMBER (ret,
+  swfdec_as_value_set_number (swfdec_gc_object_get_context (object), ret,
       (double)G_STRUCT_MEMBER (int, format, property_offsets[property]));
 }
 
@@ -398,7 +398,7 @@ swfdec_text_format_do_get_color (SwfdecAsContext *cx, SwfdecAsObject *object,
     return;
   }
 
-  SWFDEC_AS_VALUE_SET_NUMBER (ret, format->attr.color);
+  swfdec_as_value_set_number (cx, ret, format->attr.color);
 }
 
 static void
@@ -588,7 +588,7 @@ swfdec_text_format_do_get_letter_spacing (SwfdecAsContext *cx,
     return;
   }
 
-  SWFDEC_AS_VALUE_SET_NUMBER (ret, format->attr.letter_spacing);
+  swfdec_as_value_set_number (cx, ret, format->attr.letter_spacing);
 }
 
 static void
@@ -676,7 +676,7 @@ swfdec_text_format_do_get_tab_stops (SwfdecAsContext *cx,
 
   array = swfdec_as_array_new (cx);
   for (i = 0; i < format->attr.n_tab_stops; i++) {
-    SWFDEC_AS_VALUE_SET_INT (&val, format->attr.tab_stops[i]);
+    swfdec_as_value_set_integer (cx, &val, format->attr.tab_stops[i]);
     swfdec_as_array_push (SWFDEC_AS_ARRAY (array), &val);
   }
   SWFDEC_AS_VALUE_SET_OBJECT (ret, array);
@@ -829,25 +829,25 @@ swfdec_text_format_getTextExtent (SwfdecAsContext *cx, SwfdecAsObject *object,
   layout = swfdec_text_layout_new (buffer);
   
   i = swfdec_text_layout_get_width (layout);
-  SWFDEC_AS_VALUE_SET_INT (&val, i);
+  swfdec_as_value_set_integer (cx, &val, i);
   swfdec_as_object_set_variable (obj, SWFDEC_AS_STR_width, &val);
   if (i)
     i += 4;
-  SWFDEC_AS_VALUE_SET_INT (&val, i);
+  swfdec_as_value_set_integer (cx, &val, i);
   swfdec_as_object_set_variable (obj, SWFDEC_AS_STR_textFieldWidth, &val);
 
   i = swfdec_text_layout_get_height (layout);
-  SWFDEC_AS_VALUE_SET_INT (&val, i);
+  swfdec_as_value_set_integer (cx, &val, i);
   swfdec_as_object_set_variable (obj, SWFDEC_AS_STR_height, &val);
   if (i)
     i += 4;
-  SWFDEC_AS_VALUE_SET_INT (&val, i);
+  swfdec_as_value_set_integer (cx, &val, i);
   swfdec_as_object_set_variable (obj, SWFDEC_AS_STR_textFieldHeight, &val);
 
   swfdec_text_layout_get_ascent_descent (layout, &i, &j);
-  SWFDEC_AS_VALUE_SET_INT (&val, i);
+  swfdec_as_value_set_integer (cx, &val, i);
   swfdec_as_object_set_variable (obj, SWFDEC_AS_STR_ascent, &val);
-  SWFDEC_AS_VALUE_SET_INT (&val, j);
+  swfdec_as_value_set_integer (cx, &val, j);
   swfdec_as_object_set_variable (obj, SWFDEC_AS_STR_descent, &val);
 
   SWFDEC_AS_VALUE_SET_OBJECT (ret, obj);
diff --git a/swfdec/swfdec_transform_as.c b/swfdec/swfdec_transform_as.c
index dc4dbc5..c27b465 100644
--- a/swfdec/swfdec_transform_as.c
+++ b/swfdec/swfdec_transform_as.c
@@ -63,19 +63,19 @@ swfdec_transform_as_get_matrix (SwfdecAsContext *cx, SwfdecAsObject *object,
   swfdec_as_object_set_constructor_by_name (o, SWFDEC_AS_STR_flash,
 	SWFDEC_AS_STR_geom, SWFDEC_AS_STR_Matrix, NULL);
 
-  SWFDEC_AS_VALUE_SET_NUMBER (&val, matrix->xx);
+  swfdec_as_value_set_number (cx, &val, matrix->xx);
   swfdec_as_object_set_variable (o, SWFDEC_AS_STR_a, &val);
-  SWFDEC_AS_VALUE_SET_NUMBER (&val, matrix->yx);
+  swfdec_as_value_set_number (cx, &val, matrix->yx);
   swfdec_as_object_set_variable (o, SWFDEC_AS_STR_b, &val);
-  SWFDEC_AS_VALUE_SET_NUMBER (&val, matrix->xy);
+  swfdec_as_value_set_number (cx, &val, matrix->xy);
   swfdec_as_object_set_variable (o, SWFDEC_AS_STR_c, &val);
-  SWFDEC_AS_VALUE_SET_NUMBER (&val, matrix->yy);
+  swfdec_as_value_set_number (cx, &val, matrix->yy);
   swfdec_as_object_set_variable (o, SWFDEC_AS_STR_d, &val);
-  SWFDEC_AS_VALUE_SET_NUMBER (&val, matrix->yy);
+  swfdec_as_value_set_number (cx, &val, matrix->yy);
   swfdec_as_object_set_variable (o, SWFDEC_AS_STR_d, &val);
-  SWFDEC_AS_VALUE_SET_NUMBER (&val, SWFDEC_TWIPS_TO_DOUBLE (matrix->x0));
+  swfdec_as_value_set_number (cx, &val, SWFDEC_TWIPS_TO_DOUBLE (matrix->x0));
   swfdec_as_object_set_variable (o, SWFDEC_AS_STR_tx, &val);
-  SWFDEC_AS_VALUE_SET_NUMBER (&val, SWFDEC_TWIPS_TO_DOUBLE (matrix->y0));
+  swfdec_as_value_set_number (cx, &val, SWFDEC_TWIPS_TO_DOUBLE (matrix->y0));
   swfdec_as_object_set_variable (o, SWFDEC_AS_STR_ty, &val);
 
   SWFDEC_AS_VALUE_SET_OBJECT (ret, o);
diff --git a/swfdec/swfdec_video_movie.c b/swfdec/swfdec_video_movie.c
index 6369b7f..01d2688 100644
--- a/swfdec/swfdec_video_movie.c
+++ b/swfdec/swfdec_video_movie.c
@@ -107,8 +107,10 @@ swfdec_video_movie_get_variable (SwfdecAsObject *object, SwfdecAsObject *orig,
 {
   guint version = swfdec_gc_object_get_context (object)->version;
   SwfdecVideoMovie *video;
+  SwfdecAsContext *cx;
 
   video = SWFDEC_VIDEO_MOVIE (object);
+  cx = swfdec_gc_object_get_context (video);
 
   if (swfdec_strcmp (version, variable, SWFDEC_AS_STR_width) == 0) {
     guint w;
@@ -117,7 +119,7 @@ swfdec_video_movie_get_variable (SwfdecAsObject *object, SwfdecAsObject *orig,
     } else {
       w = 0;
     }
-    SWFDEC_AS_VALUE_SET_INT (val, w);
+    swfdec_as_value_set_integer (cx, val, w);
     return TRUE;
   } else if (swfdec_strcmp (version, variable, SWFDEC_AS_STR_height) == 0) {
     guint h;
@@ -126,11 +128,11 @@ swfdec_video_movie_get_variable (SwfdecAsObject *object, SwfdecAsObject *orig,
     } else {
       h = 0;
     }
-    SWFDEC_AS_VALUE_SET_INT (val, h);
+    swfdec_as_value_set_integer (cx, val, h);
     return TRUE;
   } else if (swfdec_strcmp (version, variable, SWFDEC_AS_STR_deblocking) == 0) {
     SWFDEC_STUB ("Video.deblocking (get)");
-    SWFDEC_AS_VALUE_SET_NUMBER (val, 0);
+    swfdec_as_value_set_number (cx, val, 0);
     return TRUE;
   } else if (swfdec_strcmp (version, variable, SWFDEC_AS_STR_smoothing) == 0) {
     SWFDEC_STUB ("Video.smoothing (get)");
diff --git a/swfdec/swfdec_xml.c b/swfdec/swfdec_xml.c
index 988d7be..4ca7be5 100644
--- a/swfdec/swfdec_xml.c
+++ b/swfdec/swfdec_xml.c
@@ -340,7 +340,7 @@ swfdec_xml_get_status (SwfdecAsContext *cx, SwfdecAsObject *object,
   if (!SWFDEC_IS_XML (object))
     return;
 
-  SWFDEC_AS_VALUE_SET_INT (ret, SWFDEC_XML (object)->status);
+  swfdec_as_value_set_integer (cx, ret, SWFDEC_XML (object)->status);
 }
 
 static void
diff --git a/swfdec/swfdec_xml_node.c b/swfdec/swfdec_xml_node.c
index 27bd006..2beccf8 100644
--- a/swfdec/swfdec_xml_node.c
+++ b/swfdec/swfdec_xml_node.c
@@ -129,7 +129,7 @@ swfdec_xml_node_update_child_nodes (SwfdecXmlNode *node)
   g_return_if_fail (SWFDEC_IS_VALID_XML_NODE (node));
 
   // remove old
-  SWFDEC_AS_VALUE_SET_INT (&val, 0);
+  swfdec_as_value_set_integer (swfdec_gc_object_get_context (node), &val, 0);
   swfdec_as_object_set_variable (SWFDEC_AS_OBJECT (node->child_nodes),
       SWFDEC_AS_STR_length, &val);
 
@@ -258,7 +258,7 @@ swfdec_xml_node_get_nodeType (SwfdecAsContext *cx, SwfdecAsObject *object,
   if (!SWFDEC_IS_VALID_XML_NODE (object))
     return;
 
-  SWFDEC_AS_VALUE_SET_INT (ret, SWFDEC_XML_NODE (object)->type);
+  swfdec_as_value_set_integer (cx, ret, SWFDEC_XML_NODE (object)->type);
 }
 
 static void
diff --git a/test/swfdec_test_buffer.c b/test/swfdec_test_buffer.c
index f9064d3..b9ddda4 100644
--- a/test/swfdec_test_buffer.c
+++ b/test/swfdec_test_buffer.c
@@ -177,11 +177,11 @@ swfdec_test_buffer_find (SwfdecAsContext *cx, SwfdecAsObject *object, guint argc
   
   SWFDEC_AS_CHECK (SWFDEC_TYPE_TEST_BUFFER, &buffer, "i", &c);
 
-  SWFDEC_AS_VALUE_SET_INT (retval, -1);
+  swfdec_as_value_set_integer (cx, retval, -1);
 
   found = memchr (buffer->buffer->data, c, buffer->buffer->length);
   if (found)
-    SWFDEC_AS_VALUE_SET_INT (retval, found - buffer->buffer->data);
+    swfdec_as_value_set_integer (cx, retval, found - buffer->buffer->data);
 }
 
 SWFDEC_TEST_FUNCTION ("Buffer_load", swfdec_test_buffer_load, 0)
diff --git a/test/swfdec_test_http_request.c b/test/swfdec_test_http_request.c
index 5541e02..9f00671 100644
--- a/test/swfdec_test_http_request.c
+++ b/test/swfdec_test_http_request.c
@@ -265,7 +265,7 @@ swfdec_test_http_request_get_statusCode (SwfdecAsContext *cx,
 
   SWFDEC_AS_CHECK (SWFDEC_TYPE_TEST_HTTP_REQUEST, &request, "");
 
-  SWFDEC_AS_VALUE_SET_INT (retval, request->message->status_code);
+  swfdec_as_value_set_integer (cx, retval, request->message->status_code);
 }
 
 SWFDEC_TEST_FUNCTION ("HTTPRequest_set_statusCode", swfdec_test_http_request_set_statusCode, 0)
diff --git a/test/swfdec_test_http_server.c b/test/swfdec_test_http_server.c
index 27960bd..94593b0 100644
--- a/test/swfdec_test_http_server.c
+++ b/test/swfdec_test_http_server.c
@@ -162,7 +162,7 @@ swfdec_test_http_server_get_port (SwfdecAsContext *cx, SwfdecAsObject *object,
 
   SWFDEC_AS_CHECK (SWFDEC_TYPE_TEST_HTTP_REQUEST, &server, "");
 
-  SWFDEC_AS_VALUE_SET_INT (retval, server->port);
+  swfdec_as_value_set_integer (cx, retval, server->port);
 }
 
 SWFDEC_TEST_FUNCTION ("HTTPServer_getRequest", swfdec_test_http_server_get_request, 0)
diff --git a/test/swfdec_test_socket.c b/test/swfdec_test_socket.c
index 2b65f14..d6dcba7 100644
--- a/test/swfdec_test_socket.c
+++ b/test/swfdec_test_socket.c
@@ -224,7 +224,7 @@ swfdec_test_socket_new (SwfdecTestTest *test, SwfdecTestPluginSocket *plugin)
       swfdec_as_context_get_string (cx, plugin->host));
   swfdec_as_object_set_variable (new, 
       swfdec_as_context_get_string (cx, "host"), &val);
-  SWFDEC_AS_VALUE_SET_INT (&val, plugin->port);
+  swfdec_as_value_set_integer (cx, &val, plugin->port);
   swfdec_as_object_set_variable (new, 
       swfdec_as_context_get_string (cx, "port"), &val);
 
diff --git a/test/swfdec_test_test.c b/test/swfdec_test_test.c
index b567d32..ee16a2a 100644
--- a/test/swfdec_test_test.c
+++ b/test/swfdec_test_test.c
@@ -437,6 +437,6 @@ swfdec_test_test_get_rate (SwfdecAsContext *cx, SwfdecAsObject *object, guint ar
   if (!test->plugin_loaded)
     return;
   
-  SWFDEC_AS_VALUE_SET_NUMBER (retval, test->plugin.rate / 256.0);
+  swfdec_as_value_set_number (cx, retval, test->plugin.rate / 256.0);
 }
 


More information about the Swfdec-commits mailing list