[Swfdec] Branch 'as' - 6 commits - libswfdec/swfdec_as_array.c libswfdec/swfdec_button_movie.c libswfdec/swfdec_morph_movie.c libswfdec/swfdec_movie_asprops.c libswfdec/swfdec_movie.c libswfdec/swfdec_movie.h libswfdec/swfdec_player.c libswfdec/swfdec_sprite.c libswfdec/swfdec_sprite.h libswfdec/swfdec_sprite_movie_as.c libswfdec/swfdec_sprite_movie.c libswfdec/swfdec_swf_instance.c test/dump.c test/trace

Benjamin Otte company at kemper.freedesktop.org
Wed Jun 13 07:21:44 PDT 2007


 libswfdec/swfdec_as_array.c               |   34 +++
 libswfdec/swfdec_button_movie.c           |    2 
 libswfdec/swfdec_morph_movie.c            |    6 
 libswfdec/swfdec_movie.c                  |  314 ++++++++++++++----------------
 libswfdec/swfdec_movie.h                  |   41 ++-
 libswfdec/swfdec_movie_asprops.c          |   16 -
 libswfdec/swfdec_player.c                 |   13 -
 libswfdec/swfdec_sprite.c                 |  118 -----------
 libswfdec/swfdec_sprite.h                 |    5 
 libswfdec/swfdec_sprite_movie.c           |  193 ++++++++----------
 libswfdec/swfdec_sprite_movie_as.c        |   43 +---
 libswfdec/swfdec_swf_instance.c           |    4 
 test/dump.c                               |    9 
 test/trace/Makefile.am                    |   14 +
 test/trace/array-new-5.swf                |binary
 test/trace/array-new-5.swf.trace          |  271 +++++++++++++++++++++++++
 test/trace/array-new-6.swf                |binary
 test/trace/array-new-6.swf.trace          |  272 +++++++++++++++++++++++++
 test/trace/array-new-7.swf                |binary
 test/trace/array-new-7.swf.trace          |  272 +++++++++++++++++++++++++
 test/trace/array-new-override-5.swf       |binary
 test/trace/array-new-override-5.swf.trace |    4 
 test/trace/array-new-override-6.swf       |binary
 test/trace/array-new-override-6.swf.trace |    4 
 test/trace/array-new-override-7.swf       |binary
 test/trace/array-new-override-7.swf.trace |    4 
 test/trace/array-new-override.as          |   13 +
 test/trace/array-new.as                   |   25 ++
 28 files changed, 1223 insertions(+), 454 deletions(-)

New commits:
diff-tree a6c380467a9cb20fd2d151d74603f1de5637cabf (from c1678f97c65c068803abb01d9969f38fc4da9171)
Author: Benjamin Otte <otte at gnome.org>
Date:   Wed Jun 13 15:58:31 2007 +0200

    make Array constructor prototype correspond to new native constructor

diff --git a/libswfdec/swfdec_as_array.c b/libswfdec/swfdec_as_array.c
index ed0ee0d..7415667 100644
--- a/libswfdec/swfdec_as_array.c
+++ b/libswfdec/swfdec_as_array.c
@@ -197,9 +197,8 @@ swfdec_as_array_do_push (SwfdecAsContext
 }
 
 static void
-swfdec_as_array_construct (SwfdecAsObject *object, guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
+swfdec_as_array_construct (SwfdecAsContext *cx, SwfdecAsObject *object, guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
 {
-  SwfdecAsContext *cx = object->context;
   SwfdecAsArray *array;
 
   if (!cx->frame->construct) {
diff-tree c1678f97c65c068803abb01d9969f38fc4da9171 (from parents)
Merge: 8680a64a0a4398d1095f1ff0de40d19eced9934d e7db3c7145922223dbd67702992e5d47df703fa4
Author: Benjamin Otte <otte at gnome.org>
Date:   Wed Jun 13 15:38:50 2007 +0200

    Merge branch 'as' of ssh://company@git.freedesktop.org/git/swfdec into as

diff --cc libswfdec/swfdec_sprite_movie_as.c
index cf35c13,c5a3c4c..c2e9a42
@@@ -281,12 -298,13 +295,12 @@@
    SwfdecMovie *ret;
    const char *name, *export;
    int depth;
 -  SwfdecContent *content;
    SwfdecGraphic *sprite;
  
-   export = swfdec_as_value_to_string (obj->context, &argv[0]);
-   name = swfdec_as_value_to_string (obj->context, &argv[1]);
+   export = swfdec_as_value_to_string (cx, &argv[0]);
+   name = swfdec_as_value_to_string (cx, &argv[1]);
    if (argc > 3) {
-     SWFDEC_WARNING ("attachMovie's initObject isn't implemented");
+     SWFDEC_FIXME ("attachMovie's initObject isn't implemented");
    }
    sprite = swfdec_swf_instance_get_export (movie->swf, export);
    if (!SWFDEC_IS_SPRITE (sprite)) {
@@@ -318,10 -347,10 +333,10 @@@
    SwfdecMovie *ret;
    const char *name;
    int depth;
 -  SwfdecContent *content;
 +  SwfdecGraphic *graphic = NULL;
  
-   name = swfdec_as_value_to_string (obj->context, &argv[0]);
-   depth = swfdec_as_value_to_integer (obj->context, &argv[1]);
+   name = swfdec_as_value_to_string (cx, &argv[0]);
+   depth = swfdec_as_value_to_integer (cx, &argv[1]);
    if (swfdec_depth_classify (depth) == SWFDEC_DEPTH_CLASS_EMPTY)
      return;
    if (!movie->parent) {
diff-tree 8680a64a0a4398d1095f1ff0de40d19eced9934d (from 82959bab78752fb764d70c2d60d005a0e9f5ba95)
Author: Benjamin Otte <otte at gnome.org>
Date:   Wed Jun 13 15:38:36 2007 +0200

    huge patch that reorganizes PlaceObject handling
    
    Previously, the code was building up a range of frames for every piece of
    content that showed when it was active. On backward gotos only those items were
    kept where the frame was included in their range.
    The new code just performs all actions again and copies old objects over where
    appropriate. This produces resultss that are a lot closer to the official
    player.

diff --git a/libswfdec/swfdec_button_movie.c b/libswfdec/swfdec_button_movie.c
index 19e50f0..4940b74 100644
--- a/libswfdec/swfdec_button_movie.c
+++ b/libswfdec/swfdec_button_movie.c
@@ -144,7 +144,7 @@ swfdec_button_movie_change_state (Swfdec
       if (child) {
 	g_assert_not_reached ();
       }
-      swfdec_movie_new (mov, content);
+      swfdec_movie_new_for_content (mov, content);
     }
   }
   movie->state = state;
diff --git a/libswfdec/swfdec_morph_movie.c b/libswfdec/swfdec_morph_movie.c
index 8bcd4e5..b3cffb0 100644
--- a/libswfdec/swfdec_morph_movie.c
+++ b/libswfdec/swfdec_morph_movie.c
@@ -67,7 +67,7 @@ static void
 swfdec_morph_movie_update_extents (SwfdecMovie *movie,
     SwfdecRect *extents)
 {
-  guint ratio = movie->content->ratio;
+  guint ratio = movie->original_ratio;
   SwfdecMorphMovie *mmovie = SWFDEC_MORPH_MOVIE (movie);
   SwfdecMorphShape *morph = mmovie->morph;
   SwfdecGraphic *graphic = SWFDEC_GRAPHIC (morph);
@@ -117,9 +117,9 @@ swfdec_morph_movie_render (SwfdecMovie *
 
     if (fill) {
       if (SWFDEC_IS_PATTERN (vec->pattern)) {
-	swfdec_pattern_paint (vec->pattern, cr, path, trans, movie->content->ratio);
+	swfdec_pattern_paint (vec->pattern, cr, path, trans, morph->ratio);
       } else {
-	swfdec_stroke_paint (vec->pattern, cr, path, trans, movie->content->ratio);
+	swfdec_stroke_paint (vec->pattern, cr, path, trans, morph->ratio);
       }
     } else {
       cairo_append_path (cr, path);
diff --git a/libswfdec/swfdec_movie.c b/libswfdec/swfdec_movie.c
index 908e0ef..cee0ba6 100644
--- a/libswfdec/swfdec_movie.c
+++ b/libswfdec/swfdec_movie.c
@@ -41,20 +41,19 @@
 
 /*** MOVIE ***/
 
-static const SwfdecContent default_content = SWFDEC_CONTENT_DEFAULT;
-
 G_DEFINE_ABSTRACT_TYPE (SwfdecMovie, swfdec_movie, SWFDEC_TYPE_AS_OBJECT)
 
 static void
 swfdec_movie_init (SwfdecMovie * movie)
 {
-  movie->content = &default_content;
-
   movie->xscale = 100;
   movie->yscale = 100;
+  cairo_matrix_init_identity (&movie->original_transform);
   cairo_matrix_init_identity (&movie->matrix);
   cairo_matrix_init_identity (&movie->inverse_matrix);
+
   swfdec_color_transform_init_identity (&movie->color_transform);
+  swfdec_color_transform_init_identity (&movie->original_ctrans);
 
   movie->visible = TRUE;
   movie->n_frames = 1;
@@ -139,15 +138,15 @@ swfdec_movie_update_matrix (SwfdecMovie 
 {
   double d, e;
 
-  movie->matrix.xx = movie->content->transform.xx;
-  movie->matrix.xy = movie->content->transform.xy;
-  movie->matrix.yx = movie->content->transform.yx;
-  movie->matrix.yy = movie->content->transform.yy;
+  movie->matrix.xx = movie->original_transform.xx;
+  movie->matrix.xy = movie->original_transform.xy;
+  movie->matrix.yx = movie->original_transform.yx;
+  movie->matrix.yy = movie->original_transform.yy;
 
-  d = movie->xscale / swfdec_matrix_get_xscale (&movie->content->transform);
-  e = movie->yscale / swfdec_matrix_get_yscale (&movie->content->transform);
+  d = movie->xscale / swfdec_matrix_get_xscale (&movie->original_transform);
+  e = movie->yscale / swfdec_matrix_get_yscale (&movie->original_transform);
   cairo_matrix_scale (&movie->matrix, d, e);
-  d = movie->rotation - swfdec_matrix_get_rotation (&movie->content->transform);
+  d = movie->rotation - swfdec_matrix_get_rotation (&movie->original_transform);
   cairo_matrix_rotate (&movie->matrix, d * G_PI / 180);
   swfdec_matrix_ensure_invertible (&movie->matrix, &movie->inverse_matrix);
 
@@ -207,51 +206,6 @@ swfdec_movie_update (SwfdecMovie *movie)
   }
 }
 
-/**
- * swfdec_movie_set_content:
- * @movie: a #SwfdecMovie
- * @content: #SwfdecContent to set for this movie or NULL to unset
- *
- * Sets new contents for @movie. Note that name and graphic of @content must 
- * be identical to the current content of @movie.
- **/
-void
-swfdec_movie_set_content (SwfdecMovie *movie, const SwfdecContent *content)
-{
-  g_return_if_fail (SWFDEC_IS_MOVIE (movie));
-
-  if (content == NULL)
-    content = &default_content;
-
-  if (movie->content == content)
-    return;
-
-  if (movie->content != &default_content && content != &default_content) {
-    g_return_if_fail (movie->depth == content->depth);
-    g_return_if_fail (movie->content->graphic == content->graphic);
-    if (content->name) {
-      g_return_if_fail (movie->content->name != NULL);
-      g_return_if_fail (g_str_equal (content->name, movie->content->name));
-    } else {
-      g_return_if_fail (movie->content->name == NULL);
-    }
-  } else {
-    movie->depth = content->depth;
-  }
-  SWFDEC_LOG ("setting content of movie %s from %p to %p", 
-      movie->name, movie->content, content);
-  if (movie->content->free)
-    swfdec_content_free ((SwfdecContent *) movie->content);
-  movie->content = content;
-  if (!movie->modified) {
-    movie->matrix = content->transform;
-    movie->xscale = swfdec_matrix_get_xscale (&movie->matrix);
-    movie->yscale = swfdec_matrix_get_yscale (&movie->matrix);
-    movie->rotation = swfdec_matrix_get_rotation (&movie->matrix);
-    swfdec_movie_queue_update (movie, SWFDEC_MOVIE_INVALID_MATRIX);
-  }
-}
-
 SwfdecMovie *
 swfdec_movie_find (SwfdecMovie *movie, int depth)
 {
@@ -359,7 +313,6 @@ swfdec_movie_destroy (SwfdecMovie *movie
     }
     player->roots = g_list_remove (player->roots, movie);
   }
-  swfdec_movie_set_content (movie, NULL);
   /* FIXME: figure out how to handle destruction pre-init/construct.
    * This is just a stop-gap measure to avoid dead movies in those queues */
   g_queue_remove (player->init_queue, movie);
@@ -418,8 +371,8 @@ swfdec_movie_execute_script (SwfdecMovie
   g_return_if_fail (SWFDEC_IS_MOVIE (movie));
   g_return_if_fail (condition != 0);
 
-  if (movie->content->events) {
-    swfdec_event_list_execute (movie->content->events, 
+  if (movie->events) {
+    swfdec_event_list_execute (movie->events, 
 	SWFDEC_AS_OBJECT (movie), condition, 0);
   }
   name = swfdec_event_type_get_name (condition);
@@ -450,8 +403,8 @@ swfdec_movie_queue_script (SwfdecMovie *
   g_return_val_if_fail (SWFDEC_IS_MOVIE (movie), FALSE);
   g_return_val_if_fail (condition != 0, FALSE);
 
-  if (movie->content->events) {
-    if (!swfdec_event_list_has_conditions (movie->content->events, 
+  if (movie->events) {
+    if (!swfdec_event_list_has_conditions (movie->events, 
 	  SWFDEC_AS_OBJECT (movie), condition, 0))
       return FALSE;
   } else {
@@ -618,18 +571,18 @@ swfdec_movie_get_movie_at (SwfdecMovie *
       clip_depth = 0;
       for (clip_walk = clip_walk->prev; clip_walk; clip_walk = clip_walk->prev) {
 	SwfdecMovie *clip = walk->data;
-	if (clip->content->clip_depth) {
+	if (clip->clip_depth) {
 	  double tmpx = x, tmpy = y;
 	  cairo_matrix_transform_point (&clip->inverse_matrix, &tmpx, &tmpy);
 	  if (!swfdec_movie_mouse_in (clip, tmpx, tmpy)) {
-	    SWFDEC_LOG ("skipping depth %d to %d due to clipping", clip->content->depth, clip->content->clip_depth);
-	    clip_depth = child->content->clip_depth;
+	    SWFDEC_LOG ("skipping depth %d to %d due to clipping", clip->depth, clip->clip_depth);
+	    clip_depth = child->clip_depth;
 	  }
 	  break;
 	}
       }
     }
-    if (child->content->clip_depth) {
+    if (child->clip_depth) {
       SWFDEC_LOG ("resetting clip depth");
       clip_depth = 0;
       continue;
@@ -691,13 +644,13 @@ swfdec_movie_render (SwfdecMovie *movie,
   swfdec_rect_transform (&rect, inval, &movie->inverse_matrix);
   SWFDEC_LOG ("%sinvalid area is now: %g %g  %g %g",  movie->parent ? "  " : "",
       rect.x0, rect.y0, rect.x1, rect.y1);
-  swfdec_color_transform_chain (&trans, &movie->content->color_transform, color_transform);
+  swfdec_color_transform_chain (&trans, &movie->original_ctrans, color_transform);
   swfdec_color_transform_chain (&trans, &movie->color_transform, &trans);
 
   for (g = movie->list; g; g = g_list_next (g)) {
     SwfdecMovie *child = g->data;
 
-    if (child->content->clip_depth) {
+    if (child->clip_depth) {
       if (clip_depth) {
 	/* FIXME: is clipping additive? */
 	SWFDEC_INFO ("unsetting clip depth %d for new clip depth", clip_depth);
@@ -710,9 +663,9 @@ swfdec_movie_render (SwfdecMovie *movie,
 	/* FIXME FIXME FIXME: overlapping objects in the clip movie cause problems
 	 * due to them being accumulated with CAIRO_FILL_RULE_EVEN_ODD
 	 */
-	SWFDEC_INFO ("clipping up to depth %d by using %p with depth %d", child->content->clip_depth,
+	SWFDEC_INFO ("clipping up to depth %d by using %p with depth %d", child->clip_depth,
 	    child, child->depth);
-	clip_depth = child->content->clip_depth;
+	clip_depth = child->clip_depth;
 	cairo_save (cr);
 	swfdec_movie_render (child, cr, &trans, &rect, FALSE);
 	cairo_clip (cr);
@@ -763,13 +716,16 @@ swfdec_movie_dispose (GObject *object)
   SwfdecMovie * movie = SWFDEC_MOVIE (object);
 
   g_assert (movie->list == NULL);
-  g_assert (movie->content == &default_content);
 
   SWFDEC_LOG ("disposing movie %s", movie->name);
   if (movie->swf) {
     g_object_unref (movie->swf);
     movie->swf = NULL;
   }
+  if (movie->events) {
+    swfdec_event_list_free (movie->events);
+    movie->events = NULL;
+  }
 
   G_OBJECT_CLASS (swfdec_movie_parent_class)->dispose (G_OBJECT (movie));
 }
@@ -878,138 +834,168 @@ swfdec_movie_class_init (SwfdecMovieClas
   movie_class->iterate_end = swfdec_movie_iterate_end;
 }
 
-static void
-swfdec_movie_set_name (SwfdecMovie *movie)
+void
+swfdec_movie_initialize (SwfdecMovie *movie)
 {
-  SwfdecAsContext *context = SWFDEC_AS_OBJECT (movie)->context;
+  SwfdecMovieClass *klass;
 
-  /* FIXME: implement this function in a smarter way, not if (IS_FOO_MOVIE (x)) */
-  g_assert (movie->name == NULL);
-  if (movie->content->name) {
-    movie->name = swfdec_as_context_get_string (context, movie->content->name);
-    movie->has_name = TRUE;
-  } else if (SWFDEC_IS_SPRITE_MOVIE (movie)) {
-    SwfdecPlayer *player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context);
-    movie->name = swfdec_as_context_give_string (context, 
-	g_strdup_printf ("instance%u", ++player->unnamed_count));
-    movie->has_name = FALSE;
-  } else {
-    movie->name = swfdec_as_context_get_string (context, G_OBJECT_TYPE_NAME (movie));
-    movie->has_name = FALSE;
-  }
-  SWFDEC_LOG ("created movie %s", movie->name);
+  g_return_if_fail (SWFDEC_IS_MOVIE (movie));
+
+  klass = SWFDEC_MOVIE_GET_CLASS (movie);
+  if (klass->init_movie)
+    klass->init_movie (movie);
 }
 
-static void
-swfdec_movie_set_parent (SwfdecMovie *movie)
+/**
+ * swfdec_movie_new:
+ * @player: a #SwfdecPlayer
+ * @depth: depth of movie
+ * @parent: the parent movie or %NULL to make this a root movie
+ * @graphic: the graphic that is displayed by this movie or %NULL to create an 
+ *           empty movieclip
+ * @name: a garbage-collected string to be used as the name for this movie or 
+ *        %NULL for a default one.
+ *
+ * Creates a new movie #SwfdecMovie for the given properties. No movie may exist
+ * at the given @depth. The actual type of
+ * this movie depends on the @graphic parameter. The movie will be initialized 
+ * with default properties. No script execution will be scheduled. After all 
+ * properties are set, the new-movie signal will be emitted if @player is a 
+ * debugger.
+ *
+ * Returns: a new #SwfdecMovie
+ **/
+SwfdecMovie *
+swfdec_movie_new (SwfdecPlayer *player, int depth, SwfdecMovie *parent, SwfdecGraphic *graphic, const char *name)
 {
-  SwfdecMovie *parent = movie->parent;
-  SwfdecPlayer *player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context);
+  SwfdecMovie *movie;
+  gsize size;
 
-  g_return_if_fail (SWFDEC_IS_MOVIE (movie));
+  g_return_val_if_fail (SWFDEC_IS_PLAYER (player), NULL);
+  g_return_val_if_fail (depth > -16385, NULL); /* the lower depths are for deleted movies */
+  g_return_val_if_fail (parent == NULL || SWFDEC_IS_MOVIE (parent), NULL);
+  if (parent) {
+    g_return_val_if_fail (swfdec_movie_find (parent, depth) == NULL, NULL);
+  } else {
+    /* FIXME: do a find on player here */
+  }
+  g_return_val_if_fail (graphic == NULL || SWFDEC_IS_GRAPHIC (graphic), NULL);
 
-  swfdec_movie_set_name (movie);
+  /* create the right movie */
+  if (graphic == NULL) {
+    movie = g_object_new (SWFDEC_TYPE_SPRITE_MOVIE, NULL);
+    size = sizeof (SwfdecSpriteMovie);
+  } else {
+    SwfdecGraphicClass *klass = SWFDEC_GRAPHIC_GET_CLASS (graphic);
+    g_return_val_if_fail (klass->create_movie != NULL, NULL);
+    movie = klass->create_movie (graphic, &size);
+  }
+  /* register it to the VM */
+  /* FIXME: It'd be nice if we'd not overuse memory here when calling this function from a script */
+  if (swfdec_as_context_use_mem (SWFDEC_AS_CONTEXT (player), size)) {
+    g_object_ref (movie);
+    swfdec_as_object_add (SWFDEC_AS_OBJECT (movie), SWFDEC_AS_CONTEXT (player), size);
+  } else {
+    SWFDEC_AS_OBJECT (movie)->context = SWFDEC_AS_CONTEXT (player);
+  }
+  /* set essential properties */
+  movie->parent = parent;
   if (parent) {
+    movie->swf = g_object_ref (parent->swf);
     parent->list = g_list_insert_sorted (parent->list, movie, swfdec_movie_compare_depths);
     SWFDEC_DEBUG ("inserting %s %s (depth %d) into %s %p", G_OBJECT_TYPE_NAME (movie), movie->name,
 	movie->depth,  G_OBJECT_TYPE_NAME (parent), parent);
   } else {
     player->roots = g_list_insert_sorted (player->roots, movie, swfdec_movie_compare_depths);
   }
+  movie->depth = depth;
+  /* set its name */
+  if (name) {
+    movie->original_name = name;
+    movie->name = name;
+  } else {
+    movie->original_name = SWFDEC_AS_STR_EMPTY;
+    if (SWFDEC_IS_SPRITE_MOVIE (movie)) {
+      movie->name = swfdec_as_context_give_string (SWFDEC_AS_CONTEXT (player), 
+	  g_strdup_printf ("instance%u", ++player->unnamed_count));
+    } else {
+      movie->name = SWFDEC_AS_STR_EMPTY;
+    }
+  }
+  /* add the movie to the global movies list */
   /* NB: adding to the movies list happens before setting the parent.
    * Setting the parent does a gotoAndPlay(0) for Sprites which can cause
    * new movies to be created (and added to this list)
    */
   player->movies = g_list_prepend (player->movies, movie);
-  //swfdec_js_movie_create_jsobject (movie);
-  /* queue init and construct events for non-root movies */
-  if (movie->parent) {
-    g_queue_push_tail (player->init_queue, movie);
-    g_queue_push_tail (player->construct_queue, movie);
-  }
+  /* emit the new-movie signal */
   if (SWFDEC_IS_DEBUGGER (player))
     g_signal_emit_by_name (player, "movie-added", movie);
-  swfdec_movie_queue_script (movie, SWFDEC_EVENT_LOAD);
+  return movie;
 }
 
+/* FIXME: since this is only used in PlaceObject, wouldn't it be easier to just have
+ * swfdec_movie_update_static_properties (movie); that's notified when any of these change
+ * and let PlaceObject modify the movie directly?
+ */
 void
-swfdec_movie_initialize (SwfdecMovie *movie)
+swfdec_movie_set_static_properties (SwfdecMovie *movie, const cairo_matrix_t *transform,
+    const SwfdecColorTransform *ctrans, guint ratio, int clip_depth, SwfdecEventList *events)
 {
-  SwfdecMovieClass *klass;
-
   g_return_if_fail (SWFDEC_IS_MOVIE (movie));
+  g_return_if_fail (clip_depth >= -16384 || clip_depth <= 0);
 
-  klass = SWFDEC_MOVIE_GET_CLASS (movie);
-  if (klass->init_movie)
-    klass->init_movie (movie);
+  if (movie->modified) {
+    SWFDEC_LOG ("%s has already been modified by scripts, ignoring updates", movie->name);
+    return;
+  }
+  if (transform) {
+    movie->original_transform = *transform;
+    swfdec_movie_queue_update (movie, SWFDEC_MOVIE_INVALID_MATRIX);
+  }
+  if (ctrans) {
+    movie->original_ctrans = *ctrans;
+    swfdec_movie_invalidate (movie);
+  }
+  if (ratio != movie->original_ratio) {
+    movie->original_ratio = ratio;
+    swfdec_movie_queue_update (movie, SWFDEC_MOVIE_INVALID_EXTENTS);
+  }
+  if (clip_depth != movie->clip_depth) {
+    movie->clip_depth = clip_depth;
+    /* FIXME: is this correct? */
+    swfdec_movie_invalidate (movie->parent ? movie->parent : movie);
+  }
+  if (events) {
+    if (movie->events)
+      swfdec_event_list_free (movie->events);
+    movie->events = swfdec_event_list_copy (events);
+  }
 }
 
-/**
- * swfdec_movie_new:
- * @parent: the parent movie that will contain this movie
- * @content: the content to display
- *
- * Creates a new #SwfdecMovie as a child of @parent with the given content.
- * @parent must not contain a movie clip at the depth specified by @content.
- *
- * Returns: a new #SwfdecMovie
- **/
 SwfdecMovie *
-swfdec_movie_new (SwfdecMovie *parent, const SwfdecContent *content)
+swfdec_movie_new_for_content (SwfdecMovie *parent, const SwfdecContent *content)
 {
-  SwfdecGraphicClass *klass;
-  SwfdecMovie *ret;
-  SwfdecAsObject *object;
-  gsize size;
+  SwfdecPlayer *player;
+  SwfdecMovie *movie;
 
   g_return_val_if_fail (SWFDEC_IS_MOVIE (parent), NULL);
   g_return_val_if_fail (SWFDEC_IS_GRAPHIC (content->graphic), NULL);
   g_return_val_if_fail (swfdec_movie_find (parent, content->depth) == NULL, NULL);
 
   SWFDEC_DEBUG ("new movie for parent %p", parent);
-  klass = SWFDEC_GRAPHIC_GET_CLASS (content->graphic);
-  g_return_val_if_fail (klass->create_movie != NULL, NULL);
-  ret = klass->create_movie (content->graphic, &size);
-  object = SWFDEC_AS_OBJECT (parent);
-  ret->parent = parent;
-  ret->swf = g_object_ref (parent->swf);
-  if (swfdec_as_context_use_mem (object->context, size)) {
-    g_object_ref (ret);
-    swfdec_as_object_add (SWFDEC_AS_OBJECT (ret), object->context, size);
-  } else {
-    SWFDEC_AS_OBJECT (ret)->context = object->context;
-  }
-  swfdec_movie_set_content (ret, content);
-  swfdec_movie_set_parent (ret);
-  swfdec_movie_initialize (ret);
-
-  return ret;
-}
-
-SwfdecMovie *
-swfdec_movie_new_for_player (SwfdecPlayer *player, guint depth)
-{
-  SwfdecMovie *ret;
-  SwfdecContent *content;
-
-  g_return_val_if_fail (SWFDEC_IS_PLAYER (player), NULL);
-
-  content = swfdec_content_new ((int) depth - 16384);
-  content->name = g_strdup_printf ("_level%u", depth);
-  ret = g_object_new (SWFDEC_TYPE_SPRITE_MOVIE, NULL);
-  content->free = TRUE;
-  if (swfdec_as_context_use_mem (SWFDEC_AS_CONTEXT (player), sizeof (SwfdecSpriteMovie))) {
-    g_object_ref (ret);
-    swfdec_as_object_add (SWFDEC_AS_OBJECT (ret),
-	SWFDEC_AS_CONTEXT (player), sizeof (SwfdecSpriteMovie));
-  } else {
-    SWFDEC_AS_OBJECT (ret)->context = SWFDEC_AS_CONTEXT (player);
-  }
-  swfdec_movie_set_content (ret, content);
-  swfdec_movie_set_parent (ret);
-  ret->has_name = FALSE;
+  player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (parent)->context);
+  movie = swfdec_movie_new (player, content->depth, parent, content->graphic, 
+      content->name ? swfdec_as_context_get_string (SWFDEC_AS_CONTEXT (player), content->name) : NULL);
+
+  swfdec_movie_set_static_properties (movie, &content->transform,
+      &content->color_transform, content->ratio, content->clip_depth, content->events);
+  g_queue_push_tail (player->init_queue, movie);
+  g_queue_push_tail (player->construct_queue, movie);
+  swfdec_movie_queue_script (movie, SWFDEC_EVENT_LOAD);
+  swfdec_movie_initialize (movie);
 
-  return ret;
+  return movie;
 }
 
 void
diff --git a/libswfdec/swfdec_movie.h b/libswfdec/swfdec_movie.h
index 9c3aa62..0b89f52 100644
--- a/libswfdec/swfdec_movie.h
+++ b/libswfdec/swfdec_movie.h
@@ -58,12 +58,10 @@ struct _SwfdecContent {
   SwfdecEventList *	events;
   cairo_operator_t	operator;	/* operator to use when painting (aka blend mode) */   
 
-  SwfdecContent *	sequence;	/* first element in sequence this content belongs to */
-  /* NB: the next two elements are only filled for the sequence leader */
-  guint			start;		/* first frame that contains this sequence */
-  guint			end;		/* first frame that does not contain this sequence anymore */
-
-  gboolean		free;		/* free when unsetting */
+  /* only used by buttons */
+  SwfdecContent *	sequence;
+  guint			start;
+  guint			end;
 };
 #define SWFDEC_CONTENT_DEFAULT { NULL, -1, 0, 0, { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 }, \
   { 256, 0, 256, 0, 256, 0, 256, 0 }, NULL, NULL, CAIRO_OPERATOR_OVER, NULL, 0, G_MAXUINT, FALSE }
@@ -79,21 +77,26 @@ typedef enum {
   SWFDEC_MOVIE_UP_TO_DATE = 0,
   SWFDEC_MOVIE_INVALID_CHILDREN,
   SWFDEC_MOVIE_INVALID_EXTENTS,
-  SWFDEC_MOVIE_INVALID_AREA,
-  SWFDEC_MOVIE_INVALID_MATRIX,
+  SWFDEC_MOVIE_INVALID_MATRIX
 } SwfdecMovieCacheState;
 
 struct _SwfdecMovie {
   SwfdecAsObject	object;
 
   const char *		name;			/* name of movie - GC'd */
-  gboolean		has_name;		/* TRUE if name wasn't given automagically */
   GList *		list;			/* our contained movie clips (ordered by depth) */
   int			depth;			/* depth of movie (equals content->depth unless explicitly set) */
-  const SwfdecContent *	content;           	/* the content we are displaying */
   SwfdecMovieCacheState	cache_state;		/* whether we are up to date */
   SwfdecMovieState	state;			/* state the movie is in */
 
+  /* static properties (set by PlaceObject tags) */
+  const char *		original_name;		/* the original name - GC'd and static */
+  SwfdecColorTransform	original_ctrans;	/* color transform set on this movie */
+  cairo_matrix_t	original_transform;	/* initial transform used */
+  guint			original_ratio;		/* ratio used in this movie */
+  int			clip_depth;		/* up to which movie this movie clips */
+  SwfdecEventList *	events;			/* events queued on this movie */
+
   /* parenting information */
   SwfdecMovie *		parent;			/* movie that contains us or NULL for root movies */
   SwfdecSwfInstance *	swf;			/* the instance that created us */
@@ -157,17 +160,25 @@ struct _SwfdecMovieClass {
 
 GType		swfdec_movie_get_type		(void);
 
-SwfdecMovie *	swfdec_movie_new		(SwfdecMovie *		parent,
+SwfdecMovie *	swfdec_movie_new		(SwfdecPlayer *		player,
+						 int			depth,
+						 SwfdecMovie *		parent,
+						 SwfdecGraphic *	graphic,
+						 const char *		name);
+SwfdecMovie *	swfdec_movie_new_for_content  	(SwfdecMovie *		parent,
 						 const SwfdecContent *	content);
-SwfdecMovie *	swfdec_movie_new_for_player	(SwfdecPlayer *		player,
-						 guint			depth);
 void		swfdec_movie_initialize		(SwfdecMovie *		movie);
 SwfdecMovie *	swfdec_movie_find		(SwfdecMovie *		movie,
 						 int			depth);
 void		swfdec_movie_remove		(SwfdecMovie *		movie);
 void		swfdec_movie_destroy		(SwfdecMovie *		movie);
-void		swfdec_movie_set_content	(SwfdecMovie *		movie,
-						 const SwfdecContent *	content);
+void		swfdec_movie_set_static_properties 
+						(SwfdecMovie *		movie,
+						 const cairo_matrix_t *	transform,
+						 const SwfdecColorTransform *ctrans,
+						 guint			ratio,
+						 int			clip_depth,
+						 SwfdecEventList *	events);
 void		swfdec_movie_invalidate		(SwfdecMovie *		movie);
 void		swfdec_movie_queue_update	(SwfdecMovie *		movie,
 						 SwfdecMovieCacheState	state);
diff --git a/libswfdec/swfdec_movie_asprops.c b/libswfdec/swfdec_movie_asprops.c
index c037a2c..2288b0a 100644
--- a/libswfdec/swfdec_movie_asprops.c
+++ b/libswfdec/swfdec_movie_asprops.c
@@ -153,25 +153,13 @@ mc_framesloaded (SwfdecMovie *mov, Swfde
 static void
 mc_name_get (SwfdecMovie *movie, SwfdecAsValue *rval)
 {
-  const char *string;
-
-  if (movie->has_name) {
-    string = movie->name;
-  } else {
-    string = SWFDEC_AS_STR_EMPTY;
-  }
-  SWFDEC_AS_VALUE_SET_STRING (rval, string);
+  SWFDEC_AS_VALUE_SET_STRING (rval, movie->name);
 }
 
 static void
 mc_name_set (SwfdecMovie *movie, const SwfdecAsValue *val)
 {
-  const char *str;
-
-  /* FIXME: check how names really work */
-  str = swfdec_as_value_to_string (SWFDEC_AS_OBJECT (movie)->context, val);
-  movie->name = str;
-  movie->has_name = TRUE;
+  movie->name = swfdec_as_value_to_string (SWFDEC_AS_OBJECT (movie)->context, val);
 }
 
 static void
diff --git a/libswfdec/swfdec_player.c b/libswfdec/swfdec_player.c
index ce337ea..038b5d4 100644
--- a/libswfdec/swfdec_player.c
+++ b/libswfdec/swfdec_player.c
@@ -630,13 +630,7 @@ swfdec_player_iterate (SwfdecTimeout *ti
   GList *walk;
 
   SWFDEC_INFO ("=== START ITERATION ===");
-  /* First, we prepare the iteration. We flag all movies for removal that will 
-   * be removed */
-  for (walk = player->movies; walk; walk = walk->next) {
-    if (SWFDEC_IS_SPRITE_MOVIE (walk->data))
-      swfdec_sprite_movie_prepare (walk->data);
-  }
-  /* Step 2: start the iteration. This performs a goto next frame on all 
+  /* start the iteration. This performs a goto next frame on all 
    * movies that are not stopped. It also queues onEnterFrame.
    */
   for (walk = player->movies; walk; walk = walk->next) {
@@ -963,9 +957,12 @@ swfdec_player_add_level_from_loader (Swf
     SwfdecLoader *loader, const char *variables)
 {
   SwfdecMovie *movie;
+  const char *name;
 
   swfdec_player_remove_level (player, depth);
-  movie = swfdec_movie_new_for_player (player, depth);
+  name = swfdec_as_context_give_string (SWFDEC_AS_CONTEXT (player), g_strdup_printf ("_level%u", depth));
+  movie = swfdec_movie_new (player, depth - 16384, NULL, NULL, name);
+  movie->name = SWFDEC_AS_STR_EMPTY;
   swfdec_swf_instance_new (SWFDEC_SPRITE_MOVIE (movie), loader);
   g_object_unref (loader);
   if (variables)
diff --git a/libswfdec/swfdec_sprite.c b/libswfdec/swfdec_sprite.c
index fe39705..eaee0db 100644
--- a/libswfdec/swfdec_sprite.c
+++ b/libswfdec/swfdec_sprite.c
@@ -50,10 +50,6 @@ swfdec_sprite_dispose (GObject *object)
   SwfdecSprite * sprite = SWFDEC_SPRITE (object);
   guint i;
 
-  if (sprite->live_content) {
-    g_hash_table_destroy (sprite->live_content);
-    sprite->live_content = NULL;
-  }
   if (sprite->frames) {
     for (i = 0; i < sprite->n_frames; i++) {
       g_free (sprite->frames[i].label);
@@ -121,66 +117,6 @@ swfdec_sprite_add_sound_chunk (SwfdecSpr
     SWFDEC_AUDIO_OUT_GRANULARITY (sprite->frames[frame].sound_head->original_format);
 }
 
-/* find the last action in this depth if it exists */
-/* NB: we look in the current frame, too - so call this before adding actions
- * that might modify the frame you're looking for */
-static SwfdecContent *
-swfdec_content_find (SwfdecSprite *sprite, int depth)
-{
-  return g_hash_table_lookup (sprite->live_content, GINT_TO_POINTER (depth));
-}
-
-static void
-swfdec_content_update_lifetime (SwfdecSprite *sprite,
-    SwfdecSpriteActionType type, gpointer data)
-{
-  SwfdecContent *content;
-  int depth;
-  switch (type) {
-    case SWFDEC_SPRITE_ACTION_SCRIPT:
-    case SWFDEC_SPRITE_ACTION_UPDATE:
-      return;
-    case SWFDEC_SPRITE_ACTION_ADD:
-      depth = ((SwfdecContent *) data)->depth;
-      break;
-    case SWFDEC_SPRITE_ACTION_REMOVE:
-      depth = GPOINTER_TO_INT (data);
-      break;
-    default:
-      g_assert_not_reached ();
-      return;
-  }
-  content = swfdec_content_find (sprite, depth);
-  if (content == NULL)
-    return;
-  content->sequence->end = sprite->parse_frame;
-}
-
-static void
-swfdec_content_update_live (SwfdecSprite *sprite,
-    SwfdecSpriteActionType type, gpointer data)
-{
-  SwfdecContent *content;
-  switch (type) {
-    case SWFDEC_SPRITE_ACTION_SCRIPT:
-      return;
-    case SWFDEC_SPRITE_ACTION_UPDATE:
-    case SWFDEC_SPRITE_ACTION_ADD:
-      content = data;
-      g_hash_table_insert (sprite->live_content, 
-	  GINT_TO_POINTER (content->depth), content);
-      break;
-    case SWFDEC_SPRITE_ACTION_REMOVE:
-      /* data is GINT_TO_POINTER (depth) */
-      g_hash_table_remove (sprite->live_content, data);
-      break;
-    default:
-      g_assert_not_reached ();
-      return;
-  }
-}
-
-/* NB: does not free the action data */
 static void
 swfdec_sprite_remove_last_action (SwfdecSprite * sprite, guint frame_id)
 {
@@ -207,8 +143,6 @@ swfdec_sprite_add_action (SwfdecSprite *
   if (frame->actions == NULL)
     frame->actions = g_array_new (FALSE, FALSE, sizeof (SwfdecSpriteAction));
 
-  swfdec_content_update_lifetime (sprite, type, data);
-  swfdec_content_update_live (sprite, type, data);
   action.type = type;
   action.data = data;
   g_array_append_val (frame->actions, action);
@@ -275,42 +209,16 @@ swfdec_content_new (int depth)
   swfdec_color_transform_init_identity (&content->color_transform);
   content->depth = depth;
   content->operator = CAIRO_OPERATOR_OVER;
-  content->sequence = content;
-  content->end = G_MAXUINT;
   return content;
 }
 
 static SwfdecContent *
 swfdec_contents_create (SwfdecSprite *sprite, 
-    int depth, gboolean copy, gboolean new)
+    int depth, gboolean move)
 {
   SwfdecContent *content = swfdec_content_new (depth);
 
-  content->start = sprite->parse_frame;
-  content->end = sprite->n_frames;
-  if (copy) {
-    SwfdecContent *copy;
-
-    copy = swfdec_content_find (sprite, depth);
-    if (copy == NULL) {
-      SWFDEC_WARNING ("Couldn't copy depth %d in frame %u", (depth + 16384), sprite->parse_frame);
-    } else {
-      *content = *copy;
-      SWFDEC_LOG ("Copying from content %p", copy);
-      if (content->name)
-	content->name = g_strdup (copy->name);
-      if (content->events)
-	content->events = swfdec_event_list_copy (copy->events);
-      if (new) {
-	content->start = sprite->parse_frame;
-	content->end = sprite->n_frames;
-      }
-      swfdec_sprite_add_action (sprite, 
-	  new ? SWFDEC_SPRITE_ACTION_ADD : SWFDEC_SPRITE_ACTION_UPDATE, content);
-      return content;
-    }
-  }
-  swfdec_sprite_add_action (sprite, SWFDEC_SPRITE_ACTION_ADD, content);
+  swfdec_sprite_add_action (sprite, move ? SWFDEC_SPRITE_ACTION_UPDATE : SWFDEC_SPRITE_ACTION_ADD, content);
   return content;
 }
 
@@ -374,29 +282,27 @@ swfdec_spriteseg_do_place_object (Swfdec
   depth -= 16384;
 
   /* new name always means new object */
-  content = swfdec_contents_create (s->parse_sprite, depth, move, has_character || has_name);
+  content = swfdec_contents_create (s->parse_sprite, depth, move);
   if (has_character) {
     int id = swfdec_bits_get_u16 (bits);
     content->graphic = swfdec_swf_decoder_get_character (s, id);
     if (!SWFDEC_IS_GRAPHIC (content->graphic)) {
-      g_hash_table_remove (s->parse_sprite->live_content, GUINT_TO_POINTER (content->depth));
       swfdec_content_free (content);
       swfdec_sprite_remove_last_action (s->parse_sprite,
 	        s->parse_sprite->parse_frame);
       SWFDEC_ERROR ("id %u does not specify a graphic", id);
       return SWFDEC_STATUS_OK;
     }
-    content->sequence = content;
     SWFDEC_LOG ("  id = %d", id);
-  } else if (content->graphic == NULL) {
-    SWFDEC_ERROR ("no character specified and copying didn't give one");
-    g_hash_table_remove (s->parse_sprite->live_content, GUINT_TO_POINTER (content->depth));
+  } else if (!move) {
+    SWFDEC_ERROR ("no character specified and not a move command");
     swfdec_content_free (content);
     swfdec_sprite_remove_last_action (s->parse_sprite,
-	      s->parse_sprite->parse_frame);
+      s->parse_sprite->parse_frame);
     return SWFDEC_STATUS_OK;
   }
 
+
   if (has_matrix) {
     swfdec_bits_get_matrix (bits, &content->transform, NULL);
     SWFDEC_LOG ("  matrix = { %g %g, %g %g } + { %g %g }", 
@@ -428,7 +334,6 @@ swfdec_spriteseg_do_place_object (Swfdec
   }
   if (has_filter) {
     SWFDEC_ERROR ("filters aren't implemented, skipping PlaceObject tag!");
-    g_hash_table_remove (s->parse_sprite->live_content, GUINT_TO_POINTER (content->depth));
     swfdec_content_free (content);
     swfdec_sprite_remove_last_action (s->parse_sprite,
 	      s->parse_sprite->parse_frame);
@@ -443,10 +348,8 @@ swfdec_spriteseg_do_place_object (Swfdec
     int reserved, clip_event_flags, event_flags, key_code;
     char *script_name;
 
-    if (content->events) {
-      swfdec_event_list_free (content->events);
-      content->events = NULL;
-    }
+    g_assert (content->events == NULL);
+    content->events = swfdec_event_list_new (SWFDEC_DECODER (s)->player);
     reserved = swfdec_bits_get_u16 (bits);
     clip_event_flags = swfdec_get_clipeventflags (s, bits);
 
@@ -471,8 +374,6 @@ swfdec_spriteseg_do_place_object (Swfdec
       if (event_flags & ~SWFDEC_IMPLEMENTED_EVENTS) {
 	SWFDEC_ERROR ("using non-implemented clip events %u", event_flags & ~SWFDEC_IMPLEMENTED_EVENTS);
       }
-      if (content->events == NULL)
-	content->events = swfdec_event_list_new (SWFDEC_DECODER (s)->player);
       swfdec_event_list_parse (content->events, &action_bits, s->version, 
 	  event_flags, key_code, script_name);
       if (swfdec_bits_left (&action_bits)) {
@@ -550,7 +451,6 @@ swfdec_sprite_class_init (SwfdecSpriteCl
 static void
 swfdec_sprite_init (SwfdecSprite * sprite)
 {
-  sprite->live_content = g_hash_table_new (g_direct_hash, g_direct_equal);
 }
 
 void
diff --git a/libswfdec/swfdec_sprite.h b/libswfdec/swfdec_sprite.h
index 43aa4d1..b9d62db 100644
--- a/libswfdec/swfdec_sprite.h
+++ b/libswfdec/swfdec_sprite.h
@@ -71,12 +71,11 @@ struct _SwfdecSprite
   SwfdecGraphic		graphic;
 
   SwfdecSpriteFrame *	frames;		/* the n_frames different frames */
-  guint		n_frames;	/* number of frames in this sprite */
+  guint			n_frames;	/* number of frames in this sprite */
   SwfdecScript *	init_action;	/* action to run when initializing this sprite */
 
   /* parse state */
-  guint		parse_frame;	/* frame we're currently parsing. == n_frames if done parsing */
-  GHashTable *		live_content;	/* depth->SwfdecSpriteContent for every content in parse_frame */
+  guint			parse_frame;	/* frame we're currently parsing. == n_frames if done parsing */
 };
 
 struct _SwfdecSpriteClass
diff --git a/libswfdec/swfdec_sprite_movie.c b/libswfdec/swfdec_sprite_movie.c
index a10e270..3996095 100644
--- a/libswfdec/swfdec_sprite_movie.c
+++ b/libswfdec/swfdec_sprite_movie.c
@@ -33,26 +33,10 @@
 #include "swfdec_script.h"
 #include "swfdec_sprite.h"
 #include "swfdec_swf_instance.h"
+#include "swfdec_utils.h"
 
 /*** SWFDEC_SPRITE_MOVIE ***/
 
-static SwfdecMovie *
-swfdec_sprite_movie_find (GList *movie_list, int depth)
-{
-  GList *walk;
-
-  for (walk = movie_list; walk; walk = walk->next) {
-    SwfdecMovie *movie = walk->data;
-
-    if (movie->depth < depth)
-      continue;
-    if (movie->depth == depth)
-      return movie;
-    break;
-  }
-  return NULL;
-}
-
 static gboolean
 swfdec_sprite_movie_remove_child (SwfdecMovie *movie, int depth)
 {
@@ -73,7 +57,7 @@ swfdec_sprite_movie_run_script (gpointer
 
 static void
 swfdec_sprite_movie_perform_one_action (SwfdecSpriteMovie *movie, SwfdecSpriteAction *action,
-    gboolean skip_scripts, GList **movie_list)
+    gboolean skip_scripts)
 {
   SwfdecMovie *mov = SWFDEC_MOVIE (movie);
   SwfdecPlayer *player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (mov)->context);
@@ -90,28 +74,26 @@ swfdec_sprite_movie_perform_one_action (
     case SWFDEC_SPRITE_ACTION_ADD:
       content = action->data;
       SWFDEC_LOG ("ADD action: depth %d", content->depth);
-      if (swfdec_sprite_movie_remove_child (mov, content->depth))
-	SWFDEC_DEBUG ("removed a child before adding new one");
-      child = swfdec_sprite_movie_find (*movie_list, content->depth);
-      if (child == NULL || child->content->sequence != content->sequence) {
-	child = swfdec_movie_new (mov, content);
+      if (swfdec_movie_find (mov, content->depth)) {
+	SWFDEC_WARNING ("Could not add movie, depth %d is already occupied", content->depth);
       } else {
-	swfdec_movie_set_content (child, content);
-	*movie_list = g_list_remove (*movie_list, child);
-	mov->list = g_list_insert_sorted (mov->list, child, swfdec_movie_compare_depths);
+	child = swfdec_movie_new_for_content (mov, content);
       }
       break;
     case SWFDEC_SPRITE_ACTION_UPDATE:
       content = action->data;
-      SWFDEC_LOG ("UPDATE action: depth %d", content->depth);
+      SWFDEC_LOG ("ADD action: depth %d", content->depth);
       child = swfdec_movie_find (mov, content->depth);
-      if (child != NULL && child->content->sequence == content->sequence) {
-	swfdec_movie_set_content (child, content);
-      } else if (child) {
-	SWFDEC_INFO ("supposed to update depth %d, but child is in different sequence", 
-	    content->depth);
+      if (child != NULL) {
+	/* FIXME: add ability to change characters - This needs lots of refactoring */
+	swfdec_movie_set_static_properties (child, &content->transform,
+	    &content->color_transform, content->ratio, content->clip_depth, content->events);
+	if (content->name && !g_str_equal (content->name, child->name)) {
+	  /* test this more */
+	  child->name = swfdec_as_context_get_string (SWFDEC_AS_CONTEXT (player), content->name);
+	}
       } else {
-	SWFDEC_INFO ("supposed to update depth %d, but no child", content->depth);
+	SWFDEC_WARNING ("supposed to move a character, but can't");
       }
       break;
     case SWFDEC_SPRITE_ACTION_REMOVE:
@@ -124,38 +106,20 @@ swfdec_sprite_movie_perform_one_action (
   }
 }
 
-static void
-swfdec_movie_tell_about_removal (SwfdecMovie *movie)
-{
-  GList *walk;
-  if (movie->will_be_removed)
-    return;
-  movie->will_be_removed = TRUE;
-  for (walk = movie->list; walk; walk = walk->next) {
-    swfdec_movie_tell_about_removal (walk->data);
-  }
-}
-
-void
-swfdec_sprite_movie_prepare (SwfdecSpriteMovie *movie)
+static gboolean
+swfdec_movie_is_compatible (SwfdecMovie *movie, SwfdecMovie *with)
 {
-  GList *walk;
-  guint frame;
+  g_assert (movie->depth == with->depth);
 
-  g_return_if_fail (SWFDEC_IS_SPRITE_MOVIE (movie));
-
-  if (SWFDEC_MOVIE (movie)->stopped ||
-      movie->sprite == NULL)
-    return;
+  if (movie->original_ratio != with->original_ratio)
+    return FALSE;
 
-  frame = swfdec_sprite_get_next_frame (movie->sprite, SWFDEC_MOVIE (movie)->frame);
-  /* tell all relevant movies that they won't survive this */
-  for (walk = SWFDEC_MOVIE (movie)->list; walk; walk = walk->next) {
-    SwfdecMovie *cur = walk->data;
-    if (frame < cur->content->sequence->start || 
-	frame >= cur->content->sequence->end)
-      swfdec_movie_tell_about_removal (cur);
+  if (G_OBJECT_TYPE (movie) != G_OBJECT_TYPE (with)) {
+    SWFDEC_FIXME ("this should work, shouldn't it?");
+    return FALSE;
   }
+
+  return TRUE;
 }
 
 static void
@@ -163,12 +127,10 @@ swfdec_sprite_movie_goto (SwfdecMovie *m
 {
   SwfdecSpriteMovie *movie = SWFDEC_SPRITE_MOVIE (mov);
   SwfdecPlayer *player;
-  GList *old, *walk;
+  GList *old;
   guint i, j, start;
 
   g_assert (goto_frame < mov->n_frames);
-  if (movie->sprite == NULL)
-    return;
   if (goto_frame >= movie->sprite->parse_frame) {
     SWFDEC_WARNING ("jumping to not-yet-loaded frame %u (loaded: %u/%u)",
 	goto_frame, movie->sprite->parse_frame, movie->sprite->n_frames);
@@ -196,6 +158,8 @@ swfdec_sprite_movie_goto (SwfdecMovie *m
   movie->current_frame = goto_frame;
   SWFDEC_DEBUG ("performing goto %u -> %u for character %u", 
       start, goto_frame, SWFDEC_CHARACTER (movie->sprite)->id);
+  if (movie->sprite == NULL)
+    return;
   for (i = start; i <= movie->current_frame; i++) {
     SwfdecSpriteFrame *frame = &movie->sprite->frames[i];
     if (movie == mov->swf->movie &&
@@ -207,14 +171,43 @@ swfdec_sprite_movie_goto (SwfdecMovie *m
     for (j = 0; j < frame->actions->len; j++) {
       swfdec_sprite_movie_perform_one_action (movie,
 	  &g_array_index (frame->actions, SwfdecSpriteAction, j),
-	  i != movie->current_frame, &old);
+	  i != movie->current_frame);
     }
   }
-  /* FIXME: not sure about the order here, might be relevant for unload events */
-  for (walk = old; walk; walk = walk->next) {
-    swfdec_movie_remove (walk->data);
+  /* now try to copy eventual movies */
+  if (old) {
+    SwfdecMovie *prev, *cur;
+    GList *old_walk, *walk;
+    walk = mov->list;
+    old_walk = old;
+    if (!walk)
+      goto out;
+    cur = walk->data;
+    for (; old_walk; old_walk = old_walk->next) {
+      prev = old_walk->data;
+      while (cur->depth < prev->depth) {
+	walk = walk->next;
+	if (!walk)
+	  goto out;
+	cur = walk->data;
+      }
+      if (cur->depth == prev->depth &&
+	  swfdec_movie_is_compatible (prev, cur)) {
+	walk->data = prev;
+	swfdec_movie_set_static_properties (prev, &cur->original_transform,
+	    &cur->original_ctrans, cur->original_ratio, cur->clip_depth, cur->events);
+	swfdec_movie_destroy (cur);
+	cur = prev;
+	continue;
+      }
+      swfdec_movie_remove (prev);
+    }
+out:
+    for (; old_walk; old_walk = old_walk->next) {
+      swfdec_movie_remove (old_walk->data);
+    }
+    g_list_free (old);
   }
-  g_list_free (old);
 }
 
 /*** MOVIE ***/
@@ -232,15 +225,24 @@ swfdec_sprite_movie_dispose (GObject *ob
 }
 
 static void
+swfdec_sprite_movie_do_enter_frame (gpointer movie, gpointer unused)
+{
+  if (SWFDEC_MOVIE (movie)->will_be_removed)
+    return;
+  swfdec_movie_execute_script (movie, SWFDEC_EVENT_ENTER);
+}
+
+static void
 swfdec_sprite_movie_iterate (SwfdecMovie *mov)
 {
   SwfdecSpriteMovie *movie = SWFDEC_SPRITE_MOVIE (mov);
+  SwfdecPlayer *player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (mov)->context);
   guint goto_frame;
 
   if (mov->will_be_removed)
     return;
 
-  swfdec_movie_queue_script (mov, SWFDEC_EVENT_ENTER);
+  swfdec_player_add_action (player, movie, swfdec_sprite_movie_do_enter_frame, NULL);
   if (!mov->stopped && movie->sprite != NULL) {
     goto_frame = swfdec_sprite_get_next_frame (movie->sprite, mov->frame);
     swfdec_sprite_movie_goto (mov, goto_frame);
@@ -256,6 +258,7 @@ swfdec_sprite_movie_iterate_end (SwfdecM
   GSList *walk;
   SwfdecPlayer *player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (mov)->context);
 
+  g_assert (movie->current_frame < mov->n_frames);
   if (!SWFDEC_MOVIE_CLASS (swfdec_sprite_movie_parent_class)->iterate_end (mov)) {
     g_assert (movie->sound_stream == NULL);
     return FALSE;
@@ -318,9 +321,25 @@ static void
 swfdec_sprite_movie_init_movie (SwfdecMovie *mov)
 {
   SwfdecSpriteMovie *movie = SWFDEC_SPRITE_MOVIE (mov);
+  SwfdecAsContext *context;
+  SwfdecAsObject *constructor;
+  const char *name;
 
-  mov->n_frames = movie->sprite->n_frames;
   g_assert (movie->sprite->parse_frame > 0);
+  g_assert (mov->swf != NULL);
+
+  mov->n_frames = movie->sprite->n_frames;
+  name = swfdec_swf_instance_get_export_name (mov->swf,
+      SWFDEC_CHARACTER (movie->sprite));
+  context = SWFDEC_AS_OBJECT (movie)->context;
+  if (name != NULL) {
+    name = swfdec_as_context_get_string (context, name);
+    constructor = swfdec_player_get_export_class (SWFDEC_PLAYER (context),
+      name);
+  } else {
+    constructor = SWFDEC_PLAYER (context)->MovieClip;
+  }
+  swfdec_as_object_set_constructor (SWFDEC_AS_OBJECT (movie), constructor, FALSE);
   swfdec_sprite_movie_goto (mov, 0);
   if (!swfdec_sprite_movie_iterate_end (mov)) {
     g_assert_not_reached ();
@@ -341,30 +360,6 @@ swfdec_sprite_movie_finish_movie (Swfdec
   }
 }
 
-static void
-swfdec_sprite_movie_add (SwfdecAsObject *object)
-{
-  const char *name;
-  SwfdecAsObject *constructor;
-  SwfdecSpriteMovie *movie;
-
-  movie = SWFDEC_SPRITE_MOVIE (object);
-  if (!movie->sprite)
-    return;
-
-  name = swfdec_swf_instance_get_export_name (SWFDEC_MOVIE (movie)->swf,
-      SWFDEC_CHARACTER (movie->sprite));
-  if (name != NULL) {
-    name = swfdec_as_context_get_string (object->context, name);
-    constructor = swfdec_player_get_export_class (SWFDEC_PLAYER (object->context),
-      name);
-  } else {
-    constructor = SWFDEC_PLAYER (object->context)->MovieClip;
-  }
-  swfdec_as_object_set_constructor (object, constructor, FALSE);
-  SWFDEC_AS_OBJECT_CLASS (swfdec_sprite_movie_parent_class)->add (object);
-}
-
 static SwfdecMovie *
 swfdec_sprite_movie_get_by_name (SwfdecMovie *movie, const char *name)
 {
@@ -373,11 +368,10 @@ swfdec_sprite_movie_get_by_name (SwfdecM
 
   for (walk = movie->list; walk; walk = walk->next) {
     SwfdecMovie *cur = walk->data;
-    if (!cur->has_name)
+    if (movie->original_name == SWFDEC_AS_STR_EMPTY)
       continue;
-    /* FIXME: make the name string GC'd */
-    if ((version >= 7 && g_str_equal (cur->name, name)) ||
-	strcasecmp (cur->name, name) == 0)
+    if ((version >= 7 && cur->name == name) ||
+	swfdec_str_case_equal (cur->name, name))
       return cur;
   }
   return NULL;
@@ -424,7 +418,6 @@ swfdec_sprite_movie_class_init (SwfdecSp
 
   object_class->dispose = swfdec_sprite_movie_dispose;
 
-  asobject_class->add = swfdec_sprite_movie_add;
   asobject_class->get = swfdec_sprite_movie_get_variable;
   asobject_class->mark = swfdec_sprite_movie_mark;
 
diff --git a/libswfdec/swfdec_sprite_movie_as.c b/libswfdec/swfdec_sprite_movie_as.c
index 6141dcc..cf35c13 100644
--- a/libswfdec/swfdec_sprite_movie_as.c
+++ b/libswfdec/swfdec_sprite_movie_as.c
@@ -271,10 +271,7 @@ swfdec_sprite_movie_copy_props (SwfdecMo
 static void
 swfdec_sprite_movie_init_from_object (SwfdecMovie *movie, SwfdecAsObject *obj)
 {
-  SwfdecPlayer *player;
-
-  player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context);
-  g_queue_remove (player->init_queue, movie);
+  swfdec_movie_initialize (movie);
 }
 
 static void
@@ -284,7 +281,6 @@ swfdec_sprite_movie_attachMovie (SwfdecA
   SwfdecMovie *ret;
   const char *name, *export;
   int depth;
-  SwfdecContent *content;
   SwfdecGraphic *sprite;
 
   export = swfdec_as_value_to_string (obj->context, &argv[0]);
@@ -307,21 +303,11 @@ swfdec_sprite_movie_attachMovie (SwfdecA
   ret = swfdec_movie_find (movie, depth);
   if (ret)
     swfdec_movie_remove (ret);
-  content = swfdec_content_new (depth);
-  content->graphic = sprite;
-  content->depth = depth;
-  content->clip_depth = 0; /* FIXME: check this */
-  content->name = g_strdup (name);
-  content->sequence = content;
-  content->start = 0;
-  content->end = G_MAXUINT;
-  content->free = TRUE;
-  ret = swfdec_movie_new (movie, content);
+  ret = swfdec_movie_new (SWFDEC_PLAYER (obj->context), depth, movie, sprite, name);
   SWFDEC_LOG ("attached %s (%u) as %s to depth %u", export, SWFDEC_CHARACTER (sprite)->id,
       ret->name, ret->depth);
   /* run init and construct */
   swfdec_sprite_movie_init_from_object (ret, NULL);
-  swfdec_movie_run_construct (ret);
   SWFDEC_AS_VALUE_SET_OBJECT (rval, SWFDEC_AS_OBJECT (ret));
 }
 
@@ -332,7 +318,7 @@ swfdec_sprite_movie_duplicateMovieClip (
   SwfdecMovie *ret;
   const char *name;
   int depth;
-  SwfdecContent *content;
+  SwfdecGraphic *graphic = NULL;
 
   name = swfdec_as_value_to_string (obj->context, &argv[0]);
   depth = swfdec_as_value_to_integer (obj->context, &argv[1]);
@@ -345,20 +331,17 @@ swfdec_sprite_movie_duplicateMovieClip (
   ret = swfdec_movie_find (movie->parent, depth);
   if (ret)
     swfdec_movie_remove (ret);
-  content = swfdec_content_new (depth);
-  *content = *movie->content;
-  if (content->events)
-    content->events = swfdec_event_list_copy (content->events);
-  content->depth = depth;
-  content->clip_depth = 0; /* FIXME: check this */
-  content->name = g_strdup (name);
-  content->sequence = content;
-  content->start = 0;
-  content->end = G_MAXUINT;
-  content->free = TRUE;
-  ret = swfdec_movie_new (movie->parent, content);
-  /* must be set by now, the movie has a name */
+  /* FIXME: make this a vfunc */
+  if (SWFDEC_IS_SPRITE_MOVIE (movie)) {
+    graphic = SWFDEC_GRAPHIC (SWFDEC_SPRITE_MOVIE (movie)->sprite);
+  } else {
+    SWFDEC_FIXME ("need a way to get the graphic from a movie");
+  }
+  ret = swfdec_movie_new (SWFDEC_PLAYER (obj->context), depth, movie->parent, graphic, name);
+  swfdec_movie_set_static_properties (ret, &movie->original_transform,
+      &movie->original_ctrans, movie->original_ratio, movie->clip_depth, movie->events);
   swfdec_sprite_movie_copy_props (ret, movie);
+  swfdec_movie_initialize (ret);
   SWFDEC_LOG ("duplicated %s as %s to depth %u", movie->name, ret->name, ret->depth);
   SWFDEC_AS_VALUE_SET_OBJECT (rval, SWFDEC_AS_OBJECT (ret));
 }
diff --git a/test/dump.c b/test/dump.c
index 6a85b4b..b073320 100644
--- a/test/dump.c
+++ b/test/dump.c
@@ -111,15 +111,16 @@ dump_sprite (SwfdecSprite *s)
 	switch (action->type) {
 	  case SWFDEC_SPRITE_ACTION_SCRIPT:
 	    g_print ("   %4u script\n", i);
-	  case SWFDEC_SPRITE_ACTION_UPDATE:
+	    break;
 	  case SWFDEC_SPRITE_ACTION_REMOVE:
+	    g_print ("   %4u %4d remove\n", i, GPOINTER_TO_INT (action->data) + 16384);
 	    break;
 	  case SWFDEC_SPRITE_ACTION_ADD:
+	  case SWFDEC_SPRITE_ACTION_UPDATE:
 	    {
 	      SwfdecContent *content = action->data;
-	      g_assert (content == content->sequence);
-	      g_assert (content->start == i);
-	      g_print ("   %4u -%4u %3d", i, content->end, content->depth + 16384);
+	      g_print ("   %4u %4u %s", i, content->depth + 16384, 
+		  action->type == SWFDEC_SPRITE_ACTION_ADD ? "add   " : "update");
 	      if (content->clip_depth)
 		g_print ("%4d", content->clip_depth + 16384);
 	      else
diff-tree 82959bab78752fb764d70c2d60d005a0e9f5ba95 (from 1cdcfc8200ba59d722fd932267336fd263d7fa3f)
Author: Andreas Henriksson <andreas at fatal.se>
Date:   Wed Jun 13 15:21:25 2007 +0200

    fix segfault when parser is called the second time

diff --git a/libswfdec/swfdec_swf_instance.c b/libswfdec/swfdec_swf_instance.c
index e42afe3..5ff43b5 100644
--- a/libswfdec/swfdec_swf_instance.c
+++ b/libswfdec/swfdec_swf_instance.c
@@ -76,12 +76,12 @@ swfdec_swf_instance_loader_target_parse 
 {
   SwfdecSwfInstance *instance = SWFDEC_SWF_INSTANCE (target);
   SwfdecPlayer *player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (instance->movie)->context);
-  SwfdecDecoder *dec;
+  SwfdecDecoder *dec = instance->decoder;
   SwfdecDecoderClass *klass;
 
   if (loader->error)
     return;
-  if (instance->decoder == NULL) {
+  if (dec == NULL) {
     if (!swfdec_decoder_can_detect (loader->queue))
       return;
     dec = swfdec_decoder_new (player, loader->queue);
diff-tree 1cdcfc8200ba59d722fd932267336fd263d7fa3f (from 8d08ca0fa54212527bd7b1ed59f60b4ec0faddc1)
Author: Benjamin Otte <otte at gnome.org>
Date:   Wed Jun 13 09:22:58 2007 +0200

    add tests for Array()

diff --git a/test/trace/Makefile.am b/test/trace/Makefile.am
index a39696a..5adb037 100644
--- a/test/trace/Makefile.am
+++ b/test/trace/Makefile.am
@@ -24,6 +24,20 @@ EXTRA_DIST = \
 	and-or-7.swf.trace \
 	array.swf \
 	array.swf.trace \
+	array-new.as \
+	array-new-5.swf \
+	array-new-5.swf.trace \
+	array-new-6.swf \
+	array-new-6.swf.trace \
+	array-new-7.swf \
+	array-new-7.swf.trace \
+	array-new-override.as \
+	array-new-override-5.swf \
+	array-new-override-5.swf.trace \
+	array-new-override-6.swf \
+	array-new-override-6.swf.trace \
+	array-new-override-7.swf \
+	array-new-override-7.swf.trace \
 	bitwise.as \
 	bitwise-5.swf \
 	bitwise-5.swf.trace \
diff --git a/test/trace/array-new-5.swf b/test/trace/array-new-5.swf
new file mode 100644
index 0000000..3a0d577
Binary files /dev/null and b/test/trace/array-new-5.swf differ
diff --git a/test/trace/array-new-5.swf.trace b/test/trace/array-new-5.swf.trace
new file mode 100644
index 0000000..ed6d1e2
--- /dev/null
+++ b/test/trace/array-new-5.swf.trace
@@ -0,0 +1,271 @@
+Check how "Array" and "new Array" react to parameters
+valueOf called
+toString called
+toString called with 
+valueOf called with 
+0: valueOf!
+1: valueOf!
+2: valueOf!
+3: valueOf!
+4: valueOf!
+5: valueOf!
+6: valueOf!
+7: valueOf!
+8: valueOf!
+9: valueOf!
+10: valueOf!
+11: valueOf!
+12: valueOf!
+13: valueOf!
+14: valueOf!
+15: valueOf!
+16: valueOf!
+17: valueOf!
+18: valueOf!
+19: valueOf!
+20: valueOf!
+21: valueOf!
+21: toString!
+22: valueOf!
+23: valueOf!
+23: toString!
+24: valueOf!
+24: toString!
+25: valueOf!
+25: toString!
+26: valueOf!
+26: toString!
+
+
+null
+null
+true
+true
+false
+false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+0
+0
+-0
+-0
+0.0
+0.0
+1
+1
+Hello World!
+Hello World!
+true
+true
+_level0
+_level0
+_level0
+_level0
+[object Object]
+[object Object]
+
+
+toString called
+[type Object]
+toString called
+[type Object]
+toString called with 
+[type Object]
+toString called with 
+[type Object]
+[object Object]
+[object Object]
+[type Object]
+[type Object]
+0: toString!
+[type Object]
+0: toString!
+[type Object]
+1: toString!
+[type Object]
+1: toString!
+[type Object]
+2: toString!
+[type Object]
+2: toString!
+[type Object]
+3: toString!
+[type Object]
+3: toString!
+[type Object]
+4: toString!
+[type Object]
+4: toString!
+[type Object]
+5: toString!
+[type Object]
+5: toString!
+[type Object]
+6: toString!
+[type Object]
+6: toString!
+[type Object]
+7: toString!
+[type Object]
+7: toString!
+[type Object]
+8: toString!
+[type Object]
+8: toString!
+[type Object]
+9: toString!
+[type Object]
+9: toString!
+[type Object]
+10: toString!
+[type Object]
+10: toString!
+[type Object]
+11: toString!
+[type Object]
+11: toString!
+[type Object]
+12: toString!
+
+12: toString!
+
+13: toString!
+0
+13: toString!
+0
+14: toString!
+-0
+14: toString!
+-0
+15: toString!
+0.0
+15: toString!
+0.0
+16: toString!
+1
+16: toString!
+1
+17: toString!
+Hello World!
+17: toString!
+Hello World!
+18: toString!
+true
+18: toString!
+true
+19: toString!
+_level0
+19: toString!
+_level0
+20: toString!
+[type Object]
+20: toString!
+[type Object]
+21: toString!
+[type Object]
+21: toString!
+[type Object]
+22: toString!
+[type Object]
+22: toString!
+[type Object]
+23: toString!
+[type Object]
+23: toString!
+[type Object]
+24: toString!
+[type Object]
+24: toString!
+[type Object]
+25: toString!
+[type Object]
+25: toString!
+[type Object]
+26: toString!
+[type Object]
+26: toString!
+[type Object]
+toString called
+toString called with 
+0: toString!
+1: toString!
+2: toString!
+3: toString!
+4: toString!
+5: toString!
+6: toString!
+7: toString!
+8: toString!
+9: toString!
+10: toString!
+11: toString!
+12: toString!
+13: toString!
+14: toString!
+15: toString!
+16: toString!
+17: toString!
+18: toString!
+19: toString!
+20: toString!
+21: toString!
+22: toString!
+23: toString!
+24: toString!
+25: toString!
+26: toString!
+,null,true,false,0,1,0.5,-1,-0.5,Infinity,-Infinity,NaN,,0,-0,0.0,1,Hello World!,true,_level0,_level0,[object Object],,[type Object],[type Object],[object Object],[type Object],[type Object],[type Object],[type Object],[type Object],[type Object],[type Object],[type Object],[type Object],[type Object],[type Object],[type Object],[type Object],,0,-0,0.0,1,Hello World!,true,_level0,[type Object],[type Object],[type Object],[type Object],[type Object],[type Object],[type Object]
+toString called
+toString called with 
+0: toString!
+1: toString!
+2: toString!
+3: toString!
+4: toString!
+5: toString!
+6: toString!
+7: toString!
+8: toString!
+9: toString!
+10: toString!
+11: toString!
+12: toString!
+13: toString!
+14: toString!
+15: toString!
+16: toString!
+17: toString!
+18: toString!
+19: toString!
+20: toString!
+21: toString!
+22: toString!
+23: toString!
+24: toString!
+25: toString!
+26: toString!
+,null,true,false,0,1,0.5,-1,-0.5,Infinity,-Infinity,NaN,,0,-0,0.0,1,Hello World!,true,_level0,_level0,[object Object],,[type Object],[type Object],[object Object],[type Object],[type Object],[type Object],[type Object],[type Object],[type Object],[type Object],[type Object],[type Object],[type Object],[type Object],[type Object],[type Object],,0,-0,0.0,1,Hello World!,true,_level0,[type Object],[type Object],[type Object],[type Object],[type Object],[type Object],[type Object]
+(0)  (undefined),(1) null (null),(2) true (boolean),(3) false (boolean),(4) 0 (number),(5) 1 (number),(6) 0.5 (number),(7) -1 (number),(8) -0.5 (number),(9) Infinity (number),(10) -Infinity (number),(11) NaN (number),(12)  (string),(13) 0 (string),(14) -0 (string),(15) 0.0 (string),(16) 1 (string),(17) Hello World! (string),(18) true (string),(19) _level0 (string),(20) _level0 (movieclip),(21) [object Object] (object),(22)  (undefined),(23) [type Object] (object),(24) [type Object] (object),(25) [object Object] (object),(26)  (object),(27)  (object),(28) null (object),(29) true (object),(30) false (object),(31) 0 (object),(32) 1 (object),(33) 0.5 (object),(34) -1 (object),(35) -0.5 (object),(36) Infinity (object),(37) -Infinity (object),(38) NaN (object),(39)  (object),(40) 0 (object),(41) -0 (object),(42) 0.0 (object),(43) 1 (object),(44) Hello World! (object),(45) true (object),(46) _level0 (object),(47) _level0 (object),(48) [type Object] (object),(49)  (object),(50) [type Object] (object),(51) [type Object] (object),(52) [type Object] (object),(53) [type Object] (object)
+(0)  (undefined),(1) null (null),(2) true (boolean),(3) false (boolean),(4) 0 (number),(5) 1 (number),(6) 0.5 (number),(7) -1 (number),(8) -0.5 (number),(9) Infinity (number),(10) -Infinity (number),(11) NaN (number),(12)  (string),(13) 0 (string),(14) -0 (string),(15) 0.0 (string),(16) 1 (string),(17) Hello World! (string),(18) true (string),(19) _level0 (string),(20) _level0 (movieclip),(21) [object Object] (object),(22)  (undefined),(23) [type Object] (object),(24) [type Object] (object),(25) [object Object] (object),(26)  (object),(27)  (object),(28) null (object),(29) true (object),(30) false (object),(31) 0 (object),(32) 1 (object),(33) 0.5 (object),(34) -1 (object),(35) -0.5 (object),(36) Infinity (object),(37) -Infinity (object),(38) NaN (object),(39)  (object),(40) 0 (object),(41) -0 (object),(42) 0.0 (object),(43) 1 (object),(44) Hello World! (object),(45) true (object),(46) _level0 (object),(47) _level0 (object),(48) [type Object] (object),(49)  (object),(50) [type Object] (object),(51) [type Object] (object),(52) [type Object] (object),(53) [type Object] (object)
+,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
+,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
+,,,,
+,,,,
+
+
diff --git a/test/trace/array-new-6.swf b/test/trace/array-new-6.swf
new file mode 100644
index 0000000..1f91069
Binary files /dev/null and b/test/trace/array-new-6.swf differ
diff --git a/test/trace/array-new-6.swf.trace b/test/trace/array-new-6.swf.trace
new file mode 100644
index 0000000..b02b658
--- /dev/null
+++ b/test/trace/array-new-6.swf.trace
@@ -0,0 +1,272 @@
+Check how "Array" and "new Array" react to parameters
+valueOf called
+toString called
+toString called with 
+valueOf called with 
+0: valueOf!
+1: valueOf!
+2: valueOf!
+3: valueOf!
+4: valueOf!
+5: valueOf!
+6: valueOf!
+7: valueOf!
+8: valueOf!
+9: valueOf!
+10: valueOf!
+11: valueOf!
+12: valueOf!
+13: valueOf!
+14: valueOf!
+15: valueOf!
+16: valueOf!
+17: valueOf!
+18: valueOf!
+19: valueOf!
+20: valueOf!
+21: valueOf!
+21: toString!
+22: valueOf!
+22: toString!
+23: valueOf!
+23: toString!
+24: valueOf!
+24: toString!
+25: valueOf!
+25: toString!
+26: valueOf!
+26: toString!
+
+
+null
+null
+true
+true
+false
+false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+0
+0
+-0
+-0
+0.0
+0.0
+1
+1
+Hello World!
+Hello World!
+true
+true
+_level0
+_level0
+_level0
+_level0
+[object Object]
+[object Object]
+[type Function]
+[type Function]
+toString called
+[type Object]
+toString called
+[type Object]
+toString called with 
+[type Object]
+toString called with 
+[type Object]
+[object Object]
+[object Object]
+[type Object]
+[type Object]
+0: toString!
+[type Object]
+0: toString!
+[type Object]
+1: toString!
+[type Object]
+1: toString!
+[type Object]
+2: toString!
+[type Object]
+2: toString!
+[type Object]
+3: toString!
+[type Object]
+3: toString!
+[type Object]
+4: toString!
+[type Object]
+4: toString!
+[type Object]
+5: toString!
+[type Object]
+5: toString!
+[type Object]
+6: toString!
+[type Object]
+6: toString!
+[type Object]
+7: toString!
+[type Object]
+7: toString!
+[type Object]
+8: toString!
+[type Object]
+8: toString!
+[type Object]
+9: toString!
+[type Object]
+9: toString!
+[type Object]
+10: toString!
+[type Object]
+10: toString!
+[type Object]
+11: toString!
+[type Object]
+11: toString!
+[type Object]
+12: toString!
+
+12: toString!
+
+13: toString!
+0
+13: toString!
+0
+14: toString!
+-0
+14: toString!
+-0
+15: toString!
+0.0
+15: toString!
+0.0
+16: toString!
+1
+16: toString!
+1
+17: toString!
+Hello World!
+17: toString!
+Hello World!
+18: toString!
+true
+18: toString!
+true
+19: toString!
+_level0
+19: toString!
+_level0
+20: toString!
+[type Object]
+20: toString!
+[type Object]
+21: toString!
+[type Object]
+21: toString!
+[type Object]
+22: toString!
+[type Object]
+22: toString!
+[type Object]
+23: toString!
+[type Object]
+23: toString!
+[type Object]
+24: toString!
+[type Object]
+24: toString!
+[type Object]
+25: toString!
+[type Object]
+25: toString!
+[type Object]
+26: toString!
+[type Object]
+26: toString!
+[type Object]
+toString called
+toString called with 
+0: toString!
+1: toString!
+2: toString!
+3: toString!
+4: toString!
+5: toString!
+6: toString!
+7: toString!
+8: toString!
+9: toString!
+10: toString!
+11: toString!
+12: toString!
+13: toString!
+14: toString!
+15: toString!
+16: toString!
+17: toString!
+18: toString!
+19: toString!
+20: toString!
+21: toString!
+22: toString!
+23: toString!
+24: toString!
+25: toString!
+26: toString!
+,null,true,false,0,1,0.5,-1,-0.5,Infinity,-Infinity,NaN,,0,-0,0.0,1,Hello World!,true,_level0,_level0,[object Object],[type Function],[type Object],[type Object],[object Object],[type Object],[type Object],[type Object],[type Object],[type Object],[type Object],[type Object],[type Object],[type Object],[type Object],[type Object],[type Object],[type Object],,0,-0,0.0,1,Hello World!,true,_level0,[type Object],[type Object],[type Object],[type Object],[type Object],[type Object],[type Object]
+toString called
+toString called with 
+0: toString!
+1: toString!
+2: toString!
+3: toString!
+4: toString!
+5: toString!
+6: toString!
+7: toString!
+8: toString!
+9: toString!
+10: toString!
+11: toString!
+12: toString!
+13: toString!
+14: toString!
+15: toString!
+16: toString!
+17: toString!
+18: toString!
+19: toString!
+20: toString!
+21: toString!
+22: toString!
+23: toString!
+24: toString!
+25: toString!
+26: toString!
+,null,true,false,0,1,0.5,-1,-0.5,Infinity,-Infinity,NaN,,0,-0,0.0,1,Hello World!,true,_level0,_level0,[object Object],[type Function],[type Object],[type Object],[object Object],[type Object],[type Object],[type Object],[type Object],[type Object],[type Object],[type Object],[type Object],[type Object],[type Object],[type Object],[type Object],[type Object],,0,-0,0.0,1,Hello World!,true,_level0,[type Object],[type Object],[type Object],[type Object],[type Object],[type Object],[type Object]
+(0)  (undefined),(1) null (null),(2) true (boolean),(3) false (boolean),(4) 0 (number),(5) 1 (number),(6) 0.5 (number),(7) -1 (number),(8) -0.5 (number),(9) Infinity (number),(10) -Infinity (number),(11) NaN (number),(12)  (string),(13) 0 (string),(14) -0 (string),(15) 0.0 (string),(16) 1 (string),(17) Hello World! (string),(18) true (string),(19) _level0 (string),(20) _level0 (movieclip),(21) [object Object] (object),(22) [type Function] (function),(23) [type Object] (object),(24) [type Object] (object),(25) [object Object] (object),(26)  (object),(27)  (object),(28) null (object),(29) true (object),(30) false (object),(31) 0 (object),(32) 1 (object),(33) 0.5 (object),(34) -1 (object),(35) -0.5 (object),(36) Infinity (object),(37) -Infinity (object),(38) NaN (object),(39)  (object),(40) 0 (object),(41) -0 (object),(42) 0.0 (object),(43) 1 (object),(44) Hello World! (object),(45) true (object),(46) _level0 (object),(47) _level0 (object),(48) [type Object] (object),(49) [type Object] (object),(50) [type Object] (object),(51) [type Object] (object),(52) [type Object] (object),(53) [type Object] (object)
+(0)  (undefined),(1) null (null),(2) true (boolean),(3) false (boolean),(4) 0 (number),(5) 1 (number),(6) 0.5 (number),(7) -1 (number),(8) -0.5 (number),(9) Infinity (number),(10) -Infinity (number),(11) NaN (number),(12)  (string),(13) 0 (string),(14) -0 (string),(15) 0.0 (string),(16) 1 (string),(17) Hello World! (string),(18) true (string),(19) _level0 (string),(20) _level0 (movieclip),(21) [object Object] (object),(22) [type Function] (function),(23) [type Object] (object),(24) [type Object] (object),(25) [object Object] (object),(26)  (object),(27)  (object),(28) null (object),(29) true (object),(30) false (object),(31) 0 (object),(32) 1 (object),(33) 0.5 (object),(34) -1 (object),(35) -0.5 (object),(36) Infinity (object),(37) -Infinity (object),(38) NaN (object),(39)  (object),(40) 0 (object),(41) -0 (object),(42) 0.0 (object),(43) 1 (object),(44) Hello World! (object),(45) true (object),(46) _level0 (object),(47) _level0 (object),(48) [type Object] (object),(49) [type Object] (object),(50) [type Object] (object),(51) [type Object] (object),(52) [type Object] (object),(53) [type Object] (object)
+,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
+,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
+,,,,
+,,,,
+
+
diff --git a/test/trace/array-new-7.swf b/test/trace/array-new-7.swf
new file mode 100644
index 0000000..4d2de99
Binary files /dev/null and b/test/trace/array-new-7.swf differ
diff --git a/test/trace/array-new-7.swf.trace b/test/trace/array-new-7.swf.trace
new file mode 100644
index 0000000..ac5340b
--- /dev/null
+++ b/test/trace/array-new-7.swf.trace
@@ -0,0 +1,272 @@
+Check how "Array" and "new Array" react to parameters
+valueOf called
+toString called
+toString called with 
+valueOf called with 
+0: valueOf!
+1: valueOf!
+2: valueOf!
+3: valueOf!
+4: valueOf!
+5: valueOf!
+6: valueOf!
+7: valueOf!
+8: valueOf!
+9: valueOf!
+10: valueOf!
+11: valueOf!
+12: valueOf!
+13: valueOf!
+14: valueOf!
+15: valueOf!
+16: valueOf!
+17: valueOf!
+18: valueOf!
+19: valueOf!
+20: valueOf!
+21: valueOf!
+21: toString!
+22: valueOf!
+22: toString!
+23: valueOf!
+23: toString!
+24: valueOf!
+24: toString!
+25: valueOf!
+25: toString!
+26: valueOf!
+26: toString!
+undefined
+undefined
+null
+null
+true
+true
+false
+false
+
+
+undefined
+undefined
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+0
+0
+-0
+-0
+0.0
+0.0
+1
+1
+Hello World!
+Hello World!
+true
+true
+_level0
+_level0
+_level0
+_level0
+[object Object]
+[object Object]
+[type Function]
+[type Function]
+toString called
+[type Object]
+toString called
+[type Object]
+toString called with 
+[type Object]
+toString called with 
+[type Object]
+[object Object]
+[object Object]
+[type Object]
+[type Object]
+0: toString!
+[type Object]
+0: toString!
+[type Object]
+1: toString!
+[type Object]
+1: toString!
+[type Object]
+2: toString!
+[type Object]
+2: toString!
+[type Object]
+3: toString!
+[type Object]
+3: toString!
+[type Object]
+4: toString!
+[type Object]
+4: toString!
+[type Object]
+5: toString!
+[type Object]
+5: toString!
+[type Object]
+6: toString!
+[type Object]
+6: toString!
+[type Object]
+7: toString!
+[type Object]
+7: toString!
+[type Object]
+8: toString!
+[type Object]
+8: toString!
+[type Object]
+9: toString!
+[type Object]
+9: toString!
+[type Object]
+10: toString!
+[type Object]
+10: toString!
+[type Object]
+11: toString!
+[type Object]
+11: toString!
+[type Object]
+12: toString!
+
+12: toString!
+
+13: toString!
+0
+13: toString!
+0
+14: toString!
+-0
+14: toString!
+-0
+15: toString!
+0.0
+15: toString!
+0.0
+16: toString!
+1
+16: toString!
+1
+17: toString!
+Hello World!
+17: toString!
+Hello World!
+18: toString!
+true
+18: toString!
+true
+19: toString!
+_level0
+19: toString!
+_level0
+20: toString!
+[type Object]
+20: toString!
+[type Object]
+21: toString!
+[type Object]
+21: toString!
+[type Object]
+22: toString!
+[type Object]
+22: toString!
+[type Object]
+23: toString!
+[type Object]
+23: toString!
+[type Object]
+24: toString!
+[type Object]
+24: toString!
+[type Object]
+25: toString!
+[type Object]
+25: toString!
+[type Object]
+26: toString!
+[type Object]
+26: toString!
+[type Object]
+toString called
+toString called with 
+0: toString!
+1: toString!
+2: toString!
+3: toString!
+4: toString!
+5: toString!
+6: toString!
+7: toString!
+8: toString!
+9: toString!
+10: toString!
+11: toString!
+12: toString!
+13: toString!
+14: toString!
+15: toString!
+16: toString!
+17: toString!
+18: toString!
+19: toString!
+20: toString!
+21: toString!
+22: toString!
+23: toString!
+24: toString!
+25: toString!
+26: toString!
+undefined,null,true,false,0,1,0.5,-1,-0.5,Infinity,-Infinity,NaN,,0,-0,0.0,1,Hello World!,true,_level0,_level0,[object Object],[type Function],[type Object],[type Object],[object Object],[type Object],[type Object],[type Object],[type Object],[type Object],[type Object],[type Object],[type Object],[type Object],[type Object],[type Object],[type Object],[type Object],,0,-0,0.0,1,Hello World!,true,_level0,[type Object],[type Object],[type Object],[type Object],[type Object],[type Object],[type Object]
+toString called
+toString called with 
+0: toString!
+1: toString!
+2: toString!
+3: toString!
+4: toString!
+5: toString!
+6: toString!
+7: toString!
+8: toString!
+9: toString!
+10: toString!
+11: toString!
+12: toString!
+13: toString!
+14: toString!
+15: toString!
+16: toString!
+17: toString!
+18: toString!
+19: toString!
+20: toString!
+21: toString!
+22: toString!
+23: toString!
+24: toString!
+25: toString!
+26: toString!
+undefined,null,true,false,0,1,0.5,-1,-0.5,Infinity,-Infinity,NaN,,0,-0,0.0,1,Hello World!,true,_level0,_level0,[object Object],[type Function],[type Object],[type Object],[object Object],[type Object],[type Object],[type Object],[type Object],[type Object],[type Object],[type Object],[type Object],[type Object],[type Object],[type Object],[type Object],[type Object],,0,-0,0.0,1,Hello World!,true,_level0,[type Object],[type Object],[type Object],[type Object],[type Object],[type Object],[type Object]
+(0) undefined (undefined),(1) null (null),(2) true (boolean),(3) false (boolean),(4) 0 (number),(5) 1 (number),(6) 0.5 (number),(7) -1 (number),(8) -0.5 (number),(9) Infinity (number),(10) -Infinity (number),(11) NaN (number),(12)  (string),(13) 0 (string),(14) -0 (string),(15) 0.0 (string),(16) 1 (string),(17) Hello World! (string),(18) true (string),(19) _level0 (string),(20) _level0 (movieclip),(21) [object Object] (object),(22) [type Function] (function),(23) [type Object] (object),(24) [type Object] (object),(25) [object Object] (object),(26) undefined (object),(27) undefined (object),(28) null (object),(29) true (object),(30) false (object),(31) 0 (object),(32) 1 (object),(33) 0.5 (object),(34) -1 (object),(35) -0.5 (object),(36) Infinity (object),(37) -Infinity (object),(38) NaN (object),(39)  (object),(40) 0 (object),(41) -0 (object),(42) 0.0 (object),(43) 1 (object),(44) Hello World! (object),(45) true (object),(46) _level0 (object),(47) _level0 (object),(48) [type Object] (object),(49) [type Object] (object),(50) [type Object] (object),(51) [type Object] (object),(52) [type Object] (object),(53) [type Object] (object)
+(0) undefined (undefined),(1) null (null),(2) true (boolean),(3) false (boolean),(4) 0 (number),(5) 1 (number),(6) 0.5 (number),(7) -1 (number),(8) -0.5 (number),(9) Infinity (number),(10) -Infinity (number),(11) NaN (number),(12)  (string),(13) 0 (string),(14) -0 (string),(15) 0.0 (string),(16) 1 (string),(17) Hello World! (string),(18) true (string),(19) _level0 (string),(20) _level0 (movieclip),(21) [object Object] (object),(22) [type Function] (function),(23) [type Object] (object),(24) [type Object] (object),(25) [object Object] (object),(26) undefined (object),(27) undefined (object),(28) null (object),(29) true (object),(30) false (object),(31) 0 (object),(32) 1 (object),(33) 0.5 (object),(34) -1 (object),(35) -0.5 (object),(36) Infinity (object),(37) -Infinity (object),(38) NaN (object),(39)  (object),(40) 0 (object),(41) -0 (object),(42) 0.0 (object),(43) 1 (object),(44) Hello World! (object),(45) true (object),(46) _level0 (object),(47) _level0 (object),(48) [type Object] (object),(49) [type Object] (object),(50) [type Object] (object),(51) [type Object] (object),(52) [type Object] (object),(53) [type Object] (object)
+undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined
+undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined
+undefined,undefined,undefined,undefined,undefined
+undefined,undefined,undefined,undefined,undefined
+
+
diff --git a/test/trace/array-new-override-5.swf b/test/trace/array-new-override-5.swf
new file mode 100644
index 0000000..88033ba
Binary files /dev/null and b/test/trace/array-new-override-5.swf differ
diff --git a/test/trace/array-new-override-5.swf.trace b/test/trace/array-new-override-5.swf.trace
new file mode 100644
index 0000000..fd746c7
--- /dev/null
+++ b/test/trace/array-new-override-5.swf.trace
@@ -0,0 +1,4 @@
+1,2,3
+1,2,3
+2
+3
diff --git a/test/trace/array-new-override-6.swf b/test/trace/array-new-override-6.swf
new file mode 100644
index 0000000..636b28e
Binary files /dev/null and b/test/trace/array-new-override-6.swf differ
diff --git a/test/trace/array-new-override-6.swf.trace b/test/trace/array-new-override-6.swf.trace
new file mode 100644
index 0000000..9ade318
--- /dev/null
+++ b/test/trace/array-new-override-6.swf.trace
@@ -0,0 +1,4 @@
+[object Object]
+1,2,3
+2
+3
diff --git a/test/trace/array-new-override-7.swf b/test/trace/array-new-override-7.swf
new file mode 100644
index 0000000..f0de5ce
Binary files /dev/null and b/test/trace/array-new-override-7.swf differ
diff --git a/test/trace/array-new-override-7.swf.trace b/test/trace/array-new-override-7.swf.trace
new file mode 100644
index 0000000..9ade318
--- /dev/null
+++ b/test/trace/array-new-override-7.swf.trace
@@ -0,0 +1,4 @@
+[object Object]
+1,2,3
+2
+3
diff --git a/test/trace/array-new-override.as b/test/trace/array-new-override.as
new file mode 100644
index 0000000..03ca962
--- /dev/null
+++ b/test/trace/array-new-override.as
@@ -0,0 +1,13 @@
+// makeswf -v 7 -s 200x150 -r 1 -o array-new-override.swf array-new-override.as
+
+MyArray = Array;
+_global.Array = function () {
+  trace ("hi");
+};
+trace (MyArray (1, 2, 3));
+trace (new MyArray (1, 2, 3));
+foo = MyArray (1, 2, 3);
+trace (foo[1]);
+trace (foo.length);
+
+loadMovie ("FSCommand:quit", "");
diff --git a/test/trace/array-new.as b/test/trace/array-new.as
new file mode 100644
index 0000000..f42aa29
--- /dev/null
+++ b/test/trace/array-new.as
@@ -0,0 +1,25 @@
+// makeswf -v 7 -s 200x150 -r 1 -o array-new.swf array-new.as
+
+trace ("Check how \"Array\" and \"new Array\" react to parameters");
+
+#include "values.as"
+
+// check default values first
+for (i = 0; i < values.length; i++) {
+  trace (Array (values[i]));
+  trace (new Array (values[i]));
+};
+trace (Array (values));
+trace (new Array (values));
+trace (Array (names));
+trace (new Array (names));
+
+// check numbers
+trace (Array (42));
+trace (new Array (42));
+trace (Array (5.5));
+trace (new Array (5.5));
+trace (Array (-3));
+trace (new Array (-3));
+
+loadMovie ("FSCommand:quit", "");
diff-tree 8d08ca0fa54212527bd7b1ed59f60b4ec0faddc1 (from 7bd2ff52ba93f0405bd99cb4162649e92ba4c1fd)
Author: Benjamin Otte <otte at gnome.org>
Date:   Wed Jun 13 09:20:54 2007 +0200

    fix "Array ()" and "new Array ()"
    
    The first used to just return undefined and the second didn't handle arguments

diff --git a/libswfdec/swfdec_as_array.c b/libswfdec/swfdec_as_array.c
index e2071b6..f65dd06 100644
--- a/libswfdec/swfdec_as_array.c
+++ b/libswfdec/swfdec_as_array.c
@@ -26,6 +26,7 @@
 
 #include "swfdec_as_array.h"
 #include "swfdec_as_context.h"
+#include "swfdec_as_frame.h"
 #include "swfdec_as_function.h"
 #include "swfdec_as_native_function.h"
 #include "swfdec_debug.h"
@@ -194,6 +195,38 @@ swfdec_as_array_do_push (SwfdecAsObject 
   SWFDEC_AS_VALUE_SET_INT (ret, swfdec_as_array_get_length (object));
 }
 
+static void
+swfdec_as_array_construct (SwfdecAsObject *object, guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
+{
+  SwfdecAsContext *cx = object->context;
+  SwfdecAsArray *array;
+
+  if (!cx->frame->construct) {
+    SwfdecAsValue val;
+    if (!swfdec_as_context_use_mem (cx, sizeof (SwfdecAsArray)))
+      return;
+    object = g_object_new (SWFDEC_TYPE_AS_ARRAY, NULL);
+    swfdec_as_object_add (object, cx, sizeof (SwfdecAsArray));
+    swfdec_as_object_get_variable (cx->global, SWFDEC_AS_STR_Array, &val);
+    if (SWFDEC_AS_VALUE_IS_OBJECT (&val)) {
+      swfdec_as_object_set_constructor (object, SWFDEC_AS_VALUE_GET_OBJECT (&val), FALSE);
+    } else {
+      SWFDEC_INFO ("\"Array\" is not an object");
+    }
+  }
+  array = SWFDEC_AS_ARRAY (object);
+  if (argc == 1 && SWFDEC_AS_VALUE_IS_NUMBER (&argv[0])) {
+    SwfdecAsValue val;
+    int l = swfdec_as_value_to_integer (cx, &argv[0]);
+    SWFDEC_AS_VALUE_SET_INT (&val, l < 0 ? 0 : l);
+    swfdec_as_object_set_variable (object, SWFDEC_AS_STR_length, &val);
+  } else if (argc > 0) {
+    swfdec_as_array_append (array, argc, argv);
+  }
+
+  SWFDEC_AS_VALUE_SET_OBJECT (ret, object);
+}
+
 void
 swfdec_as_array_init_context (SwfdecAsContext *context, guint version)
 {
@@ -203,7 +236,7 @@ swfdec_as_array_init_context (SwfdecAsCo
   g_return_if_fail (SWFDEC_IS_AS_CONTEXT (context));
 
   array = SWFDEC_AS_OBJECT (swfdec_as_object_add_function (context->global, 
-      SWFDEC_AS_STR_Array, SWFDEC_TYPE_AS_ARRAY, NULL, 0));
+      SWFDEC_AS_STR_Array, 0, swfdec_as_array_construct, 0));
   swfdec_as_native_function_set_construct_type (SWFDEC_AS_NATIVE_FUNCTION (array), SWFDEC_TYPE_AS_ARRAY);
   if (!array)
     return;


More information about the Swfdec mailing list