[Swfdec] Branch 'vivi' - 9 commits - libswfdec/swfdec_as_array.c libswfdec/swfdec_as_function.c libswfdec/swfdec_as_function.h libswfdec/swfdec_as_internal.h libswfdec/swfdec_as_interpret.c libswfdec/swfdec_as_native_function.c libswfdec/swfdec_as_script_function.c libswfdec/swfdec_as_script_function.h test/trace vivified/core

Benjamin Otte company at kemper.freedesktop.org
Fri Aug 17 10:51:45 PDT 2007


 libswfdec/swfdec_as_array.c           |  407 ++++++++++++++++++++--------------
 libswfdec/swfdec_as_function.c        |   37 +--
 libswfdec/swfdec_as_function.h        |    4 
 libswfdec/swfdec_as_internal.h        |    4 
 libswfdec/swfdec_as_interpret.c       |   25 +-
 libswfdec/swfdec_as_native_function.c |   20 -
 libswfdec/swfdec_as_script_function.c |   23 +
 libswfdec/swfdec_as_script_function.h |    3 
 test/trace/array2-5.swf               |binary
 test/trace/array2-5.swf.trace         |   38 +++
 test/trace/array2-6.swf               |binary
 test/trace/array2-6.swf.trace         |   38 +++
 test/trace/array2-7.swf               |binary
 test/trace/array2-7.swf.trace         |   38 +++
 test/trace/array2.as                  |   77 ++++++
 vivified/core/vivi_breakpoint.h       |    2 
 vivified/core/vivi_initialize.as      |   35 ++
 17 files changed, 531 insertions(+), 220 deletions(-)

New commits:
diff-tree 85702bb6de0af42a70cd4dccda70c5f4d6cd33fc (from 91daf3604631f9c33d289a176e9e3ec5adf4732a)
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Aug 17 19:51:23 2007 +0200

    implement watch command

diff --git a/vivified/core/vivi_initialize.as b/vivified/core/vivi_initialize.as
index 65f51d1..93c1ecf 100644
--- a/vivified/core/vivi_initialize.as
+++ b/vivified/core/vivi_initialize.as
@@ -115,3 +115,38 @@ Commands.where = function () {
 };
 Commands.backtrace = Commands.where;
 Commands.bt = Commands.where;
+Commands.watch = function () {
+  var object;
+  var name;
+  if (arguments.length == 1) {
+    name = arguments[0];
+  } else if (arguments.length == 2) {
+    object = arguments[0];
+    name = arguments[1];
+  } else {
+    Commands.error ("usage: watch [object] name");
+    return;
+  }
+  var ret = new Breakpoint ();
+  ret.onSetVariable = function (o, variable, value) {
+    if (object && o != object)
+      return false;
+    if (variable != name)
+      return;
+
+    if (object) {
+      Commands.print ("Breakpoint: variable " + name + " on " + object);
+    } else {
+      Commands.print ("Breakpoint: variable " + name);
+    }
+    Commands.print ("  " + Player.frame);
+    return true;
+  };
+  ret.toString = function () {
+    var s = "watch " + name;
+    if (object)
+      s += " on " + object;
+    return s;
+  };
+  return ret;
+};
diff-tree 91daf3604631f9c33d289a176e9e3ec5adf4732a (from 571b80372d3a7c4e2970a408f482c926f48f588a)
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Aug 17 19:41:41 2007 +0200

    we have a handler more now...

diff --git a/vivified/core/vivi_breakpoint.h b/vivified/core/vivi_breakpoint.h
index 87b2220..35a8d28 100644
--- a/vivified/core/vivi_breakpoint.h
+++ b/vivified/core/vivi_breakpoint.h
@@ -41,7 +41,7 @@ struct _ViviBreakpoint
   SwfdecAsObject	object;
 
   gboolean		active;		/* only active breakpoints receive events */
-  gulong		handlers[4];	/* handlers for every signal of the debugger or 0 */
+  gulong		handlers[5];	/* handlers for every signal of the debugger or 0 */
 };
 
 struct _ViviBreakpointClass
diff-tree 571b80372d3a7c4e2970a408f482c926f48f588a (from 3589dfbffcdca650ce957c86ccbe0ce96078a24c)
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Aug 17 19:22:52 2007 +0200

    change function creation procedure
    
    This is supposed to make every function a proper object when it can be passed
    to a breakpoint the first time. Especially all members are supposed to be
    set already.

diff --git a/libswfdec/swfdec_as_function.c b/libswfdec/swfdec_as_function.c
index 3e9b6dd..879ed9d 100644
--- a/libswfdec/swfdec_as_function.c
+++ b/libswfdec/swfdec_as_function.c
@@ -67,40 +67,31 @@ swfdec_as_function_init (SwfdecAsFunctio
 }
 
 /**
- * swfdec_as_function_create:
- * @context: a #SwfdecAsFunction
- * @type: the type of function to create
- * @size: size of @type
+ * swfdec_as_function_set_constructor:
+ * @fun: a #SwfdecAsFunction
  *
- * Creates a new function. The function will be of @type. It will be added to
- * @context and its prototype and constructor object will be set correctly.
- *
- * Returns: a new object of @type or %NULL on OOM
+ * Sets the constructor and prototype of @fun. This is a shortcut for calling
+ * swfdec_as_object_set_constructor() with the right arguments.
  **/
-SwfdecAsFunction *
-swfdec_as_function_create (SwfdecAsContext *context, GType type, guint size)
+void
+swfdec_as_function_set_constructor (SwfdecAsFunction *fun)
 {
+  SwfdecAsContext *context;
+  SwfdecAsObject *object;
   SwfdecAsValue val;
-  SwfdecAsObject *fun;
 
-  g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), NULL);
-  g_return_val_if_fail (g_type_is_a (type, SWFDEC_TYPE_AS_FUNCTION), NULL);
-  g_return_val_if_fail (size >= sizeof (SwfdecAsFunction), NULL);
-
-  if (!swfdec_as_context_use_mem (context, size))
-    return NULL;
-  fun = g_object_new (type, NULL);
-  swfdec_as_object_add (SWFDEC_AS_OBJECT (fun), context, size);
+  g_return_if_fail (SWFDEC_IS_AS_FUNCTION (fun));
+
+  object = SWFDEC_AS_OBJECT (fun);
+  context = object->context;
   if (context->Function) {
     SWFDEC_AS_VALUE_SET_OBJECT (&val, context->Function);
-    swfdec_as_object_set_variable (fun, SWFDEC_AS_STR_constructor, &val);
+    swfdec_as_object_set_variable (object, SWFDEC_AS_STR_constructor, &val);
   }
   if (context->Function_prototype) {
     SWFDEC_AS_VALUE_SET_OBJECT (&val, context->Function_prototype);
-    swfdec_as_object_set_variable (fun, SWFDEC_AS_STR___proto__, &val);
+    swfdec_as_object_set_variable (object, SWFDEC_AS_STR___proto__, &val);
   }
-
-  return SWFDEC_AS_FUNCTION (fun);
 }
 
 /**
diff --git a/libswfdec/swfdec_as_function.h b/libswfdec/swfdec_as_function.h
index ae3103a..534aad5 100644
--- a/libswfdec/swfdec_as_function.h
+++ b/libswfdec/swfdec_as_function.h
@@ -50,10 +50,6 @@ struct _SwfdecAsFunctionClass {
 
 GType			swfdec_as_function_get_type	(void);
 
-SwfdecAsFunction *	swfdec_as_function_create	(SwfdecAsContext *	context, 
-							 GType			type,
-							 guint			size);
-
 void			swfdec_as_function_call		(SwfdecAsFunction *	function,
 							 SwfdecAsObject *	thisp,
 							 guint			n_args,
diff --git a/libswfdec/swfdec_as_internal.h b/libswfdec/swfdec_as_internal.h
index 5906ef4..69db628 100644
--- a/libswfdec/swfdec_as_internal.h
+++ b/libswfdec/swfdec_as_internal.h
@@ -33,7 +33,8 @@ G_BEGIN_DECLS
 void	      	swfdec_as_array_init_context	(SwfdecAsContext *	context,
 					      	 guint			version);
 
-/* swfdec_as_function.c */
+
+void		swfdec_as_function_set_constructor (SwfdecAsFunction *	fun);
 void		swfdec_as_function_init_context (SwfdecAsContext *	context,
 						 guint			version);
 
@@ -53,5 +54,6 @@ void		swfdec_as_object_foreach_rename	(S
 void		swfdec_as_object_init_context	(SwfdecAsContext *	context,
 					      	 guint			version);
 
+
 G_END_DECLS
 #endif
diff --git a/libswfdec/swfdec_as_native_function.c b/libswfdec/swfdec_as_native_function.c
index 59cd182..9e92e1f 100644
--- a/libswfdec/swfdec_as_native_function.c
+++ b/libswfdec/swfdec_as_native_function.c
@@ -24,6 +24,7 @@
 #include "swfdec_as_native_function.h"
 #include "swfdec_as_context.h"
 #include "swfdec_as_frame_internal.h"
+#include "swfdec_as_internal.h"
 #include "swfdec_as_stack.h"
 #include "swfdec_debug.h"
 
@@ -122,22 +123,23 @@ SwfdecAsFunction *
 swfdec_as_native_function_new (SwfdecAsContext *context, const char *name,
     SwfdecAsNative native, guint min_args)
 {
-  SwfdecAsNativeFunction *nfun;
-  SwfdecAsFunction *fun;
+  SwfdecAsNativeFunction *fun;
 
   g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), NULL);
   g_return_val_if_fail (native != NULL, NULL);
 
-  fun = swfdec_as_function_create (context, SWFDEC_TYPE_AS_NATIVE_FUNCTION,
-      sizeof (SwfdecAsNativeFunction));
+  if (!swfdec_as_context_use_mem (context, sizeof (SwfdecAsNativeFunction)))
+    return NULL;
+  fun = g_object_new (SWFDEC_TYPE_AS_NATIVE_FUNCTION, NULL);
   if (fun == NULL)
     return NULL;
-  nfun = SWFDEC_AS_NATIVE_FUNCTION (fun);
-  nfun->native = native;
-  nfun->min_args = min_args;
-  nfun->name = g_strdup (name);
+  fun->native = native;
+  fun->min_args = min_args;
+  fun->name = g_strdup (name);
+  swfdec_as_object_add (SWFDEC_AS_OBJECT (fun), context, sizeof (SwfdecAsNativeFunction));
+  swfdec_as_function_set_constructor (SWFDEC_AS_FUNCTION (fun));
 
-  return fun;
+  return SWFDEC_AS_FUNCTION (fun);
 }
 
 /**
diff --git a/libswfdec/swfdec_as_script_function.c b/libswfdec/swfdec_as_script_function.c
index 10a553a..7623b7e 100644
--- a/libswfdec/swfdec_as_script_function.c
+++ b/libswfdec/swfdec_as_script_function.c
@@ -24,6 +24,7 @@
 #include "swfdec_as_script_function.h"
 #include "swfdec_as_context.h"
 #include "swfdec_as_frame_internal.h"
+#include "swfdec_as_internal.h"
 #include "swfdec_as_stack.h"
 #include "swfdec_as_strings.h"
 #include "swfdec_debug.h"
@@ -114,20 +115,26 @@ SwfdecAsFunction *
 swfdec_as_script_function_new (SwfdecAsScope *scope, SwfdecAsObject *target, SwfdecScript *script)
 {
   SwfdecAsValue val;
-  SwfdecAsFunction *fun;
+  SwfdecAsScriptFunction *fun;
   SwfdecAsObject *proto;
+  SwfdecAsContext *context;
 
   g_return_val_if_fail (SWFDEC_IS_AS_SCOPE (scope), NULL);
   g_return_val_if_fail (SWFDEC_IS_AS_OBJECT (target), NULL);
   g_return_val_if_fail (script != NULL, NULL);
 
-  fun = swfdec_as_function_create (SWFDEC_AS_OBJECT (scope)->context, 
-      SWFDEC_TYPE_AS_SCRIPT_FUNCTION, sizeof (SwfdecAsScriptFunction));
+  context = target->context;
+  if (!swfdec_as_context_use_mem (context, sizeof (SwfdecAsScriptFunction)))
+    return NULL;
+  fun = g_object_new (SWFDEC_TYPE_AS_SCRIPT_FUNCTION, NULL);
   if (fun == NULL)
     return NULL;
-  SWFDEC_AS_SCRIPT_FUNCTION (fun)->scope = scope;
-  SWFDEC_AS_SCRIPT_FUNCTION (fun)->script = script;
-  SWFDEC_AS_SCRIPT_FUNCTION (fun)->target = target;
+  fun->scope = scope;
+  fun->script = script;
+  fun->target = target;
+  swfdec_as_object_add (SWFDEC_AS_OBJECT (fun), context, sizeof (SwfdecAsScriptFunction));
+  swfdec_as_function_set_constructor (SWFDEC_AS_FUNCTION (fun));
+  /* set prototype */
   proto = swfdec_as_object_new (SWFDEC_AS_OBJECT (scope)->context);
   if (proto == NULL)
     return NULL;
@@ -136,6 +143,6 @@ swfdec_as_script_function_new (SwfdecAsS
   SWFDEC_AS_VALUE_SET_OBJECT (&val, proto);
   swfdec_as_object_set_variable (SWFDEC_AS_OBJECT (fun), SWFDEC_AS_STR_prototype, &val);
 
-  return fun;
+  return SWFDEC_AS_FUNCTION (fun);
 }
 
diff-tree 3589dfbffcdca650ce957c86ccbe0ce96078a24c (from 7f63d1408763835caedad52650757c8482ec0c46)
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Aug 17 19:03:23 2007 +0200

    require passing the script to swfdec_as_script_function_new()
    
    also refactor code to make use of this

diff --git a/libswfdec/swfdec_as_interpret.c b/libswfdec/swfdec_as_interpret.c
index 7b5d231..461c875 100644
--- a/libswfdec/swfdec_as_interpret.c
+++ b/libswfdec/swfdec_as_interpret.c
@@ -1484,18 +1484,6 @@ swfdec_action_define_function (SwfdecAsC
     SWFDEC_ERROR ("could not parse function name");
     return;
   }
-  /* see function-scope tests */
-  if (cx->version > 5) {
-    /* FIXME: or original target? */
-    fun = swfdec_as_script_function_new (frame->scope ? frame->scope : SWFDEC_AS_SCOPE (frame), frame->target);
-  } else {
-    SwfdecAsScope *scope = frame->scope ? frame->scope : SWFDEC_AS_SCOPE (frame);
-    while (scope->next)
-      scope = scope->next;
-    fun = swfdec_as_script_function_new (scope, frame->target);
-  }
-  if (fun == NULL)
-    return;
   n_args = swfdec_bits_get_u16 (&bits);
   if (v2) {
     n_registers = swfdec_bits_get_u8 (&bits);
@@ -1565,7 +1553,18 @@ swfdec_action_define_function (SwfdecAsC
   script->n_registers = n_registers;
   script->n_arguments = n_args;
   script->arguments = args;
-  SWFDEC_AS_SCRIPT_FUNCTION (fun)->script = script;
+  /* see function-scope tests */
+  if (cx->version > 5) {
+    /* FIXME: or original target? */
+    fun = swfdec_as_script_function_new (frame->scope ? frame->scope : SWFDEC_AS_SCOPE (frame), frame->target, script);
+  } else {
+    SwfdecAsScope *scope = frame->scope ? frame->scope : SWFDEC_AS_SCOPE (frame);
+    while (scope->next)
+      scope = scope->next;
+    fun = swfdec_as_script_function_new (scope, frame->target, script);
+  }
+  if (fun == NULL)
+    return;
   /* attach the function */
   if (*function_name == '\0') {
     swfdec_as_stack_ensure_free (cx, 1);
diff --git a/libswfdec/swfdec_as_script_function.c b/libswfdec/swfdec_as_script_function.c
index 3ab7064..10a553a 100644
--- a/libswfdec/swfdec_as_script_function.c
+++ b/libswfdec/swfdec_as_script_function.c
@@ -111,7 +111,7 @@ swfdec_as_script_function_init (SwfdecAs
 }
 
 SwfdecAsFunction *
-swfdec_as_script_function_new (SwfdecAsScope *scope, SwfdecAsObject *target)
+swfdec_as_script_function_new (SwfdecAsScope *scope, SwfdecAsObject *target, SwfdecScript *script)
 {
   SwfdecAsValue val;
   SwfdecAsFunction *fun;
@@ -119,12 +119,14 @@ swfdec_as_script_function_new (SwfdecAsS
 
   g_return_val_if_fail (SWFDEC_IS_AS_SCOPE (scope), NULL);
   g_return_val_if_fail (SWFDEC_IS_AS_OBJECT (target), NULL);
+  g_return_val_if_fail (script != NULL, NULL);
 
   fun = swfdec_as_function_create (SWFDEC_AS_OBJECT (scope)->context, 
       SWFDEC_TYPE_AS_SCRIPT_FUNCTION, sizeof (SwfdecAsScriptFunction));
   if (fun == NULL)
     return NULL;
   SWFDEC_AS_SCRIPT_FUNCTION (fun)->scope = scope;
+  SWFDEC_AS_SCRIPT_FUNCTION (fun)->script = script;
   SWFDEC_AS_SCRIPT_FUNCTION (fun)->target = target;
   proto = swfdec_as_object_new (SWFDEC_AS_OBJECT (scope)->context);
   if (proto == NULL)
diff --git a/libswfdec/swfdec_as_script_function.h b/libswfdec/swfdec_as_script_function.h
index 9f47919..69f3481 100644
--- a/libswfdec/swfdec_as_script_function.h
+++ b/libswfdec/swfdec_as_script_function.h
@@ -53,7 +53,8 @@ struct _SwfdecAsScriptFunctionClass {
 GType			swfdec_as_script_function_get_type	(void);
 
 SwfdecAsFunction *	swfdec_as_script_function_new		(SwfdecAsScope *	scope,
-								 SwfdecAsObject *	target);
+								 SwfdecAsObject *	target,
+								 SwfdecScript *		script);
 
 
 G_END_DECLS
diff-tree 7f63d1408763835caedad52650757c8482ec0c46 (from parents)
Merge: c168f4149f139c40bd7556f3baa4af67c969c32e afdf9987d560b315469d8747f56916dcd3235ecb
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Aug 17 17:43:45 2007 +0200

    Merge branch 'master' into vivi

diff-tree afdf9987d560b315469d8747f56916dcd3235ecb (from parents)
Merge: 2639fca86d427f3612d5ef1ed153e0090ccd9533 c44ef5cc232c3bad04a9c5e86d0f501b93e2390f
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Aug 17 17:43:21 2007 +0200

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

diff-tree 2639fca86d427f3612d5ef1ed153e0090ccd9533 (from bf81efebf34c71944530945a70c24532de6ea111)
Author: Benjamin Otte <otte at gnome.org>
Date:   Fri Aug 17 17:31:44 2007 +0200

    0 registers means 4 registers

diff --git a/libswfdec/swfdec_as_interpret.c b/libswfdec/swfdec_as_interpret.c
index ecc828a..47e62d5 100644
--- a/libswfdec/swfdec_as_interpret.c
+++ b/libswfdec/swfdec_as_interpret.c
@@ -1499,6 +1499,8 @@ swfdec_action_define_function (SwfdecAsC
   n_args = swfdec_bits_get_u16 (&bits);
   if (v2) {
     n_registers = swfdec_bits_get_u8 (&bits);
+    if (n_registers == 0)
+      n_registers = 4;
     flags = swfdec_bits_get_u16 (&bits);
   } else {
     n_registers = 5;
diff-tree c44ef5cc232c3bad04a9c5e86d0f501b93e2390f (from a41661fd62a2ed7ae083f3a9a583377991e20930)
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Fri Aug 17 12:21:16 2007 +0300

    Add test on whether the arrays length is increased if it's negative and a value
    is inserted in bigger, but still negative index.

diff --git a/test/trace/array2-5.swf b/test/trace/array2-5.swf
index 4057223..803ccac 100644
Binary files a/test/trace/array2-5.swf and b/test/trace/array2-5.swf differ
diff --git a/test/trace/array2-5.swf.trace b/test/trace/array2-5.swf.trace
index d3221d7..d3081e8 100644
--- a/test/trace/array2-5.swf.trace
+++ b/test/trace/array2-5.swf.trace
@@ -42,6 +42,8 @@ undefined
 [, , , , , , , , , ]
 []
 []
+[]
+[]
 [[], [], [], , ]
 []
 [[], [], [], , ]
diff --git a/test/trace/array2-6.swf b/test/trace/array2-6.swf
index 42059f3..1d5c236 100644
Binary files a/test/trace/array2-6.swf and b/test/trace/array2-6.swf differ
diff --git a/test/trace/array2-6.swf.trace b/test/trace/array2-6.swf.trace
index 51dc019..bd63dd6 100644
--- a/test/trace/array2-6.swf.trace
+++ b/test/trace/array2-6.swf.trace
@@ -42,6 +42,8 @@ undefined
 [, , , , , , , , , ]
 []
 -4
+[]
+-1
 [1, b, c, , ]
 3.4
 [1, b, c, , ]
diff --git a/test/trace/array2-7.swf b/test/trace/array2-7.swf
index 1ceb5d9..e93a801 100644
Binary files a/test/trace/array2-7.swf and b/test/trace/array2-7.swf differ
diff --git a/test/trace/array2-7.swf.trace b/test/trace/array2-7.swf.trace
index 04a5849..e51c513 100644
--- a/test/trace/array2-7.swf.trace
+++ b/test/trace/array2-7.swf.trace
@@ -42,6 +42,8 @@ undefined
 [undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined]
 []
 -4
+[]
+-1
 [1, b, c, undefined, ]
 3.4
 [1, b, c, undefined, ]
diff --git a/test/trace/array2.as b/test/trace/array2.as
index bea9179..237a156 100644
--- a/test/trace/array2.as
+++ b/test/trace/array2.as
@@ -100,6 +100,11 @@ a = new Array (1, "b", "c", 4);		// nega
 a.length = -4;
 mytrace (a);
 mytrace (a.length);
+a = new Array ();			// setting negative variable while negative length
+a.length = -4;
+a[-2] = "x";
+mytrace (a);
+mytrace (a.length);
 a = new Array (1, "b", "c", 4);		// floating point values
 a.length = 3.4;
 mytrace (a);
@@ -116,7 +121,7 @@ a = new Array (1, "b", "c", 4);		// non-
 a.length = new Object ();
 mytrace (a);
 mytrace (a.length);
-a = new Array (1, "b", "c", 4);		// disabled until crash bug fixed
+a = new Array (1, "b", "c", 4);
 a.length = "har";
 mytrace (a);
 mytrace (a.length);
diff-tree a41661fd62a2ed7ae083f3a9a583377991e20930 (from bf81efebf34c71944530945a70c24532de6ea111)
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Fri Aug 17 12:13:06 2007 +0300

    Make Array's method work with plain Objects.
    Fix push and pop methods to handle negative length values.
    Add test cases for both things.

diff --git a/libswfdec/swfdec_as_array.c b/libswfdec/swfdec_as_array.c
index f6314a7..9d245c3 100644
--- a/libswfdec/swfdec_as_array.c
+++ b/libswfdec/swfdec_as_array.c
@@ -33,6 +33,7 @@
 #include "swfdec_as_native_function.h"
 #include "swfdec_as_strings.h"
 #include "swfdec_debug.h"
+#include "swfdec_player_internal.h"
 
 G_DEFINE_TYPE (SwfdecAsArray, swfdec_as_array, SWFDEC_TYPE_AS_OBJECT)
 
@@ -73,7 +74,7 @@ swfdec_as_array_to_index (const char *st
 }
 
 static gint32
-swfdec_as_array_get_length (SwfdecAsObject *object)
+swfdec_as_array_get_length_as_integer (SwfdecAsObject *object)
 {
   SwfdecAsValue val;
   gint32 length;
@@ -83,6 +84,16 @@ swfdec_as_array_get_length (SwfdecAsObje
   swfdec_as_object_get_variable (object, SWFDEC_AS_STR_length, &val);
   length = swfdec_as_value_to_integer (object->context, &val);
 
+  return length;
+}
+
+static gint32
+swfdec_as_array_get_length (SwfdecAsObject *object)
+{
+  gint32 length;
+
+  length = swfdec_as_array_get_length_as_integer (object);
+
   if (length < 0)
     return 0;
 
@@ -105,7 +116,8 @@ typedef struct {
   gint32	num;
 } ForeachRemoveRangeData;
 
-static gboolean swfdec_as_array_foreach_remove_range (SwfdecAsObject *object,
+static gboolean
+swfdec_as_array_foreach_remove_range (SwfdecAsObject *object,
     const char *variable, SwfdecAsValue *value, guint flags, gpointer data)
 {
   ForeachRemoveRangeData *fdata = data;
@@ -122,7 +134,8 @@ static gboolean swfdec_as_array_foreach_
 }
 
 static void
-swfdec_as_array_remove_range (SwfdecAsArray *array, gint32 start_index, gint32 num)
+swfdec_as_array_remove_range (SwfdecAsArray *array, gint32 start_index,
+    gint32 num)
 {
   SwfdecAsObject *object = SWFDEC_AS_OBJECT (array);
 
@@ -140,7 +153,8 @@ swfdec_as_array_remove_range (SwfdecAsAr
     swfdec_as_object_delete_variable (object, var);
   } else {
     ForeachRemoveRangeData fdata = { start_index, num };
-    swfdec_as_object_foreach_remove (object, swfdec_as_array_foreach_remove_range, &fdata);
+    swfdec_as_object_foreach_remove (object,
+	swfdec_as_array_foreach_remove_range, &fdata);
   }
 }
 
@@ -151,8 +165,8 @@ typedef struct {
 } ForeachMoveRangeData;
 
 static const char *
-swfdec_as_array_foreach_move_range (SwfdecAsObject *object, const char *variable,
-    SwfdecAsValue *value, guint flags, gpointer data)
+swfdec_as_array_foreach_move_range (SwfdecAsObject *object,
+    const char *variable, SwfdecAsValue *value, guint flags, gpointer data)
 {
   ForeachMoveRangeData *fdata = data;
   gint32 idx;
@@ -172,12 +186,12 @@ swfdec_as_array_foreach_move_range (Swfd
 }
 
 static void
-swfdec_as_array_move_range (SwfdecAsArray *array, gint32 from_index, gint32 num, gint32 to_index)
+swfdec_as_array_move_range (SwfdecAsObject *object, gint32 from_index,
+    gint32 num, gint32 to_index)
 {
-  SwfdecAsObject *object = SWFDEC_AS_OBJECT (array);
   ForeachMoveRangeData fdata = { from_index, num, to_index };
 
-  g_return_if_fail (SWFDEC_IS_AS_ARRAY (array));
+  g_return_if_fail (SWFDEC_IS_AS_OBJECT (object));
   g_return_if_fail (from_index >= 0);
   g_return_if_fail (num >= 0);
   g_return_if_fail (from_index + num <= swfdec_as_array_get_length (object));
@@ -186,7 +200,8 @@ swfdec_as_array_move_range (SwfdecAsArra
   if (num == 0 || from_index == to_index)
     return;
 
-  swfdec_as_object_foreach_rename (object, swfdec_as_array_foreach_move_range, &fdata);
+  swfdec_as_object_foreach_rename (object, swfdec_as_array_foreach_move_range,
+      &fdata);
 
   // only changes length if it becomes bigger, not if it becomes smaller
   if (to_index + num > swfdec_as_array_get_length (object))
@@ -194,15 +209,14 @@ swfdec_as_array_move_range (SwfdecAsArra
 }
 
 static void
-swfdec_as_array_set_range (SwfdecAsArray *array, gint32 start_index, gint32 num,
-    const SwfdecAsValue *value)
+swfdec_as_array_set_range (SwfdecAsObject *object, gint32 start_index,
+    gint32 num, const SwfdecAsValue *value)
 {
-  SwfdecAsObject *object = SWFDEC_AS_OBJECT (array);
   gint32 i;
   const char *var;
 
-  g_return_if_fail (SWFDEC_IS_AS_ARRAY (array));
-  g_return_if_fail (start_index >= 0);
+  // allow negative indexes
+  g_return_if_fail (SWFDEC_IS_AS_OBJECT (object));
   g_return_if_fail (num >= 0);
   g_return_if_fail (value != NULL);
 
@@ -212,6 +226,15 @@ swfdec_as_array_set_range (SwfdecAsArray
   }
 }
 
+static void
+swfdec_as_array_append_internal (SwfdecAsObject *object, guint n,
+    const SwfdecAsValue *value)
+{
+  // allow negative length
+  swfdec_as_array_set_range (object,
+      swfdec_as_array_get_length_as_integer (object), n, value);
+}
+
 /**
  * swfdec_as_array_push:
  * @array: a #SwfdecAsArray
@@ -230,10 +253,12 @@ swfdec_as_array_set_range (SwfdecAsArray
  * Appends the given @values to the array.
  **/
 void
-swfdec_as_array_append (SwfdecAsArray *array, guint n, const SwfdecAsValue *value)
+swfdec_as_array_append (SwfdecAsArray *array, guint n,
+    const SwfdecAsValue *value)
 {
-  swfdec_as_array_set_range (array, swfdec_as_array_get_length (SWFDEC_AS_OBJECT (array)), n,
-    value);
+  // don't allow negative length
+  swfdec_as_array_set_range (SWFDEC_AS_OBJECT (array),
+      swfdec_as_array_get_length (SWFDEC_AS_OBJECT (array)), n, value);
 }
 
 typedef struct {
@@ -244,8 +269,8 @@ typedef struct {
 } ForeachAppendArrayRangeData;
 
 static gboolean
-swfdec_as_array_foreach_append_array_range (SwfdecAsObject *object, const char *variable,
-    SwfdecAsValue *value, guint flags, gpointer data)
+swfdec_as_array_foreach_append_array_range (SwfdecAsObject *object,
+    const char *variable, SwfdecAsValue *value, guint flags, gpointer data)
 {
   ForeachAppendArrayRangeData *fdata = data;
   gint32 idx;
@@ -262,16 +287,16 @@ swfdec_as_array_foreach_append_array_ran
 }
 
 static void
-swfdec_as_array_append_array_range (SwfdecAsArray *array_to, SwfdecAsArray *array_from,
-    gint32 start_index, gint32 num)
+swfdec_as_array_append_array_range (SwfdecAsArray *array_to,
+    SwfdecAsObject *object_from, gint32 start_index, gint32 num)
 {
-  SwfdecAsObject *object_from = SWFDEC_AS_OBJECT (array_from);
   ForeachAppendArrayRangeData fdata;
 
   g_return_if_fail (SWFDEC_IS_AS_ARRAY (array_to));
-  g_return_if_fail (SWFDEC_IS_AS_ARRAY (array_from));
+  g_return_if_fail (SWFDEC_IS_AS_OBJECT (object_from));
   g_return_if_fail (start_index >= 0);
-  g_return_if_fail (start_index + num <= swfdec_as_array_get_length (object_from));
+  g_return_if_fail (
+      start_index + num <= swfdec_as_array_get_length (object_from));
 
   if (num == 0)
     return;
@@ -282,14 +307,15 @@ swfdec_as_array_append_array_range (Swfd
   fdata.num = num;
 
   swfdec_as_array_set_length (fdata.object_to, fdata.offset + fdata.num);
-  swfdec_as_object_foreach (object_from, swfdec_as_array_foreach_append_array_range, &fdata);
+  swfdec_as_object_foreach (object_from,
+      swfdec_as_array_foreach_append_array_range, &fdata);
 }
 
 static void
-swfdec_as_array_append_array (SwfdecAsArray *array_to, SwfdecAsArray *array_from)
+swfdec_as_array_append_array (SwfdecAsArray *array_to, SwfdecAsObject *object_from)
 {
-  swfdec_as_array_append_array_range (array_to, array_from, 0,
-      swfdec_as_array_get_length (SWFDEC_AS_OBJECT (array_from)));
+  swfdec_as_array_append_array_range (array_to, object_from, 0,
+      swfdec_as_array_get_length (object_from));
 }
 
 /*
@@ -297,14 +323,6 @@ swfdec_as_array_append_array (SwfdecAsAr
  */
 
 static void
-swfdec_as_array_dispose (GObject *object)
-{
-  //SwfdecAsArray *array = SWFDEC_AS_ARRAY (object);
-
-  G_OBJECT_CLASS (swfdec_as_array_parent_class)->dispose (object);
-}
-
-static void
 swfdec_as_array_add (SwfdecAsObject *object)
 {
   swfdec_as_array_set_length (object, 0);
@@ -313,39 +331,42 @@ swfdec_as_array_add (SwfdecAsObject *obj
 }
 
 static void
-swfdec_as_array_set (SwfdecAsObject *object, const char *variable, const SwfdecAsValue *val)
+swfdec_as_array_set (SwfdecAsObject *object, const char *variable,
+    const SwfdecAsValue *val)
 {
-  gint32 l = swfdec_as_array_to_index (variable);
+  char *end;
+  gboolean indexvar = TRUE;
+  gint32 l = strtoul (variable, &end, 10);
+
+  if (*end != 0 || l > G_MAXINT32)
+    indexvar = FALSE;
 
   // if we changed to smaller length, destroy all values that are outside it
   if (!strcmp (variable, SWFDEC_AS_STR_length)) {
     gint32 length_old = swfdec_as_array_get_length (object);
-    gint32 length_new = MAX (0, swfdec_as_value_to_integer (object->context, val));
-    if (length_old > length_new)
-      swfdec_as_array_remove_range (SWFDEC_AS_ARRAY (object), length_new, length_old - length_new);
+    gint32 length_new = MAX (0,
+	swfdec_as_value_to_integer (object->context, val));
+    if (length_old > length_new) {
+      swfdec_as_array_remove_range (SWFDEC_AS_ARRAY (object), length_new,
+	  length_old - length_new);
+    }
   }
 
-  SWFDEC_AS_OBJECT_CLASS (swfdec_as_array_parent_class)->set (object, variable, val);
+  SWFDEC_AS_OBJECT_CLASS (swfdec_as_array_parent_class)->set (object, variable,
+      val);
 
   // if we added new value outside the current length, set a bigger length
-  if (l > -1) {
-    int cur;
-    l++;
-    cur = swfdec_as_array_get_length (object);
-    if (l > cur) {
+  if (indexvar) {
+    if (++l > swfdec_as_array_get_length_as_integer (object))
       swfdec_as_array_set_length (object, l);
-    }
   }
 }
 
 static void
 swfdec_as_array_class_init (SwfdecAsArrayClass *klass)
 {
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
   SwfdecAsObjectClass *asobject_class = SWFDEC_AS_OBJECT_CLASS (klass);
 
-  object_class->dispose = swfdec_as_array_dispose;
-
   asobject_class->add = swfdec_as_array_add;
   asobject_class->set = swfdec_as_array_set;
 }
@@ -374,7 +395,7 @@ swfdec_as_array_new (SwfdecAsContext *co
 
   g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), NULL);
   g_return_val_if_fail (context->Array != NULL, NULL);
-  
+
   if (!swfdec_as_context_use_mem (context, sizeof (SwfdecAsArray)))
     return FALSE;
   ret = g_object_new (SWFDEC_TYPE_AS_ARRAY, NULL);
@@ -385,9 +406,10 @@ swfdec_as_array_new (SwfdecAsContext *co
 
 /*** AS CODE ***/
 
-static void
-swfdec_as_array_join (SwfdecAsContext *cx, SwfdecAsObject *object, guint argc, SwfdecAsValue *argv,
-    SwfdecAsValue *ret)
+SWFDEC_AS_NATIVE (252, 7, swfdec_as_array_join)
+void
+swfdec_as_array_join (SwfdecAsContext *cx, SwfdecAsObject *object, guint argc,
+    SwfdecAsValue *argv, SwfdecAsValue *ret)
 {
   int i, length;
   const char *var, *str, *sep;
@@ -422,66 +444,84 @@ swfdec_as_array_join (SwfdecAsContext *c
   SWFDEC_AS_VALUE_SET_STRING (ret, str);
 }
 
-static void
-swfdec_as_array_toString (SwfdecAsContext *cx, SwfdecAsObject *object, guint argc,
-    SwfdecAsValue *argv, SwfdecAsValue *ret)
+SWFDEC_AS_NATIVE (252, 9, swfdec_as_array_toString)
+void
+swfdec_as_array_toString (SwfdecAsContext *cx, SwfdecAsObject *object,
+    guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
 {
   swfdec_as_array_join (cx, object, 0, NULL, ret);
 }
 
-static void
-swfdec_as_array_do_push (SwfdecAsContext *cx, SwfdecAsObject *object, guint argc,
-    SwfdecAsValue *argv, SwfdecAsValue *ret)
+SWFDEC_AS_NATIVE (252, 1, swfdec_as_array_do_push)
+void
+swfdec_as_array_do_push (SwfdecAsContext *cx, SwfdecAsObject *object,
+    guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
 {
-  SwfdecAsArray *array = SWFDEC_AS_ARRAY (object);
-
-  // we allow calling with 0 args, so that we'll return the length even in that case
-  if (argc > 0)
-    swfdec_as_array_append (array, argc, argv);
+  // if 0 args, just return the length
+  // manually set the length here to make the function work on non-Arrays
+  if (argc > 0) {
+    gint32 length = swfdec_as_array_get_length_as_integer (object);
+    swfdec_as_array_append_internal (object, argc, argv);
+    swfdec_as_array_set_length (object, length + argc);
+  }
 
-  SWFDEC_AS_VALUE_SET_INT (ret, swfdec_as_array_get_length (object));
+  SWFDEC_AS_VALUE_SET_INT (ret, swfdec_as_array_get_length_as_integer (object));
 }
 
-static void
+SWFDEC_AS_NATIVE (252, 2, swfdec_as_array_do_pop)
+void
 swfdec_as_array_do_pop (SwfdecAsContext *cx, SwfdecAsObject *object, guint argc,
     SwfdecAsValue *argv, SwfdecAsValue *ret)
 {
   gint32 length;
   const char *var;
 
-  length = swfdec_as_array_get_length (object);
-  if (length <= 0)
+  // we allow negative indexes here, but not 0
+  length = swfdec_as_array_get_length_as_integer (object);
+  if (length == 0)
     return;
 
   var = swfdec_as_double_to_string (object->context, length - 1);
   swfdec_as_object_get_variable (object, var, ret);
-  swfdec_as_array_set_length (object, length - 1);
+
+  // if Array, the length is reduced by one (which destroys the variable also)
+  // else the length is not reduced at all, but the variable is still deleted
+  if (SWFDEC_IS_AS_ARRAY (object)) {
+    swfdec_as_array_set_length (object, length - 1);
+  } else {
+    swfdec_as_object_delete_variable (object, var);
+  }
 }
 
-static void
-swfdec_as_array_do_unshift (SwfdecAsContext *cx, SwfdecAsObject *object, guint argc,
-    SwfdecAsValue *argv, SwfdecAsValue *ret)
+SWFDEC_AS_NATIVE (252, 5, swfdec_as_array_do_unshift)
+void
+swfdec_as_array_do_unshift (SwfdecAsContext *cx, SwfdecAsObject *object,
+    guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
 {
-  SwfdecAsArray *array = SWFDEC_AS_ARRAY (object);
   gint32 length;
 
   if (argc) {
+    // don't allow negative length
     length = swfdec_as_array_get_length (object);
-    swfdec_as_array_move_range (array, 0, length, argc);
-    swfdec_as_array_set_range (array, 0, argc, argv);
+    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))
+      swfdec_as_array_set_length (object, length);
   }
 
   SWFDEC_AS_VALUE_SET_INT (ret, swfdec_as_array_get_length (object));
 }
 
-static void
-swfdec_as_array_do_shift (SwfdecAsContext *cx, SwfdecAsObject *object, guint argc,
-    SwfdecAsValue *argv, SwfdecAsValue *ret)
+SWFDEC_AS_NATIVE (252, 4, swfdec_as_array_do_shift)
+void
+swfdec_as_array_do_shift (SwfdecAsContext *cx, SwfdecAsObject *object,
+    guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
 {
-  SwfdecAsArray *array = SWFDEC_AS_ARRAY (object);
   gint32 length;
   const char *var;
 
+  // don't allow negative length
   length = swfdec_as_array_get_length (object);
   if (length <= 0)
     return;
@@ -489,8 +529,23 @@ swfdec_as_array_do_shift (SwfdecAsContex
   var = swfdec_as_double_to_string (object->context, 0);
   swfdec_as_object_get_variable (object, var, ret);
 
-  swfdec_as_array_move_range (array, 1, length - 1, 0);
-  swfdec_as_array_set_length (object, length - 1);
+  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)) {
+    swfdec_as_array_set_length (object, length - 1);
+  } else {
+    // we have to put the last element back, because we used move, not copy
+    SwfdecAsValue val;
+    if (length > 1) {
+      var = swfdec_as_double_to_string (object->context, length - 2);
+      swfdec_as_object_get_variable (object, var, &val);
+    } else {
+      val = *ret;
+    }
+    var = swfdec_as_double_to_string (object->context, length - 1);
+    swfdec_as_object_set_variable (object, var, &val);
+  }
 }
 
 static const char *
@@ -507,19 +562,22 @@ swfdec_as_array_foreach_reverse (SwfdecA
   return swfdec_as_double_to_string (object->context, *length - 1 - idx);
 }
 
-static void
-swfdec_as_array_reverse (SwfdecAsContext *cx, SwfdecAsObject *object, guint argc,
-    SwfdecAsValue *argv, SwfdecAsValue *ret)
+SWFDEC_AS_NATIVE (252, 11, swfdec_as_array_reverse)
+void
+swfdec_as_array_reverse (SwfdecAsContext *cx, SwfdecAsObject *object,
+    guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
 {
   gint32 length;
 
   length = swfdec_as_array_get_length (object);
-  swfdec_as_object_foreach_rename (object, swfdec_as_array_foreach_reverse, &length);
+  swfdec_as_object_foreach_rename (object, swfdec_as_array_foreach_reverse,
+      &length);
 
   SWFDEC_AS_VALUE_SET_OBJECT (ret, object);
 }
 
-static void
+SWFDEC_AS_NATIVE (252, 3, swfdec_as_array_concat)
+void
 swfdec_as_array_concat (SwfdecAsContext *cx, SwfdecAsObject *object, guint argc,
     SwfdecAsValue *argv, SwfdecAsValue *ret)
 {
@@ -531,18 +589,19 @@ swfdec_as_array_concat (SwfdecAsContext 
   object_new = swfdec_as_array_new (cx);
   array_new = SWFDEC_AS_ARRAY (object_new);
 
-  swfdec_as_array_append_array (array_new, SWFDEC_AS_ARRAY (object));
+  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_array_append_array (array_new,
-	  SWFDEC_AS_ARRAY (SWFDEC_AS_VALUE_GET_OBJECT (&argv[j])));
+	  SWFDEC_AS_VALUE_GET_OBJECT (&argv[j]));
     }
     else
     {
-      var = swfdec_as_double_to_string (object->context, swfdec_as_array_get_length (object_new));
+      var = swfdec_as_double_to_string (object->context,
+	  swfdec_as_array_get_length (object_new));
       swfdec_as_object_set_variable (object_new, var, &argv[j]);
     }
   }
@@ -550,7 +609,8 @@ swfdec_as_array_concat (SwfdecAsContext 
   SWFDEC_AS_VALUE_SET_OBJECT (ret, object_new);
 }
 
-static void
+SWFDEC_AS_NATIVE (252, 6, swfdec_as_array_slice)
+void
 swfdec_as_array_slice (SwfdecAsContext *cx, SwfdecAsObject *object, guint argc,
     SwfdecAsValue *argv, SwfdecAsValue *ret)
 {
@@ -582,16 +642,16 @@ swfdec_as_array_slice (SwfdecAsContext *
   object_new = swfdec_as_array_new (cx);
   array_new = SWFDEC_AS_ARRAY (object_new);
 
-  swfdec_as_array_append_array_range (array_new, SWFDEC_AS_ARRAY (object), start_index, num);
+  swfdec_as_array_append_array_range (array_new, object, start_index, num);
 
   SWFDEC_AS_VALUE_SET_OBJECT (ret, object_new);
 }
 
-static void
+SWFDEC_AS_NATIVE (252, 8, swfdec_as_array_splice)
+void
 swfdec_as_array_splice (SwfdecAsContext *cx, SwfdecAsObject *object, guint argc,
     SwfdecAsValue *argv, SwfdecAsValue *ret)
 {
-  SwfdecAsArray *array = SWFDEC_AS_ARRAY (object);
   gint32 length, start_index, num_remove, num_add;
   SwfdecAsObject *object_new;
   SwfdecAsArray *array_new;
@@ -608,7 +668,8 @@ swfdec_as_array_splice (SwfdecAsContext 
   }
 
   if (argc > 1) {
-    num_remove = CLAMP (swfdec_as_value_to_integer (cx, &argv[1]), 0, length - start_index);
+    num_remove = CLAMP (swfdec_as_value_to_integer (cx, &argv[1]), 0,
+	length - start_index);
   } else {
     num_remove = length - start_index;
   }
@@ -618,13 +679,14 @@ swfdec_as_array_splice (SwfdecAsContext 
   object_new = swfdec_as_array_new (cx);
   array_new = SWFDEC_AS_ARRAY (object_new);
 
-  swfdec_as_array_append_array_range (array_new, array, start_index, num_remove);
-  swfdec_as_array_move_range (array, start_index + num_remove, length - (start_index + num_remove),
-      start_index + num_add);
+  swfdec_as_array_append_array_range (array_new, object, start_index,
+      num_remove);
+  swfdec_as_array_move_range (object, start_index + num_remove,
+      length - (start_index + num_remove), start_index + num_add);
   if (num_remove > num_add)
     swfdec_as_array_set_length (object, length - (num_remove - num_add));
   if (argc > 2)
-    swfdec_as_array_set_range (array, start_index, argc - 2, argv + 2);
+    swfdec_as_array_set_range (object, start_index, argc - 2, argv + 2);
 
   SWFDEC_AS_VALUE_SET_OBJECT (ret, object_new);
 }
@@ -651,8 +713,8 @@ typedef struct {
 } ForeachSortData;
 
 static gint
-swfdec_as_array_sort_compare (SwfdecAsContext *cx, SwfdecAsValue *a, SwfdecAsValue *b,
-    gint32 options, SwfdecAsFunction *fun)
+swfdec_as_array_sort_compare (SwfdecAsContext *cx, SwfdecAsValue *a,
+    SwfdecAsValue *b, gint32 options, SwfdecAsFunction *fun)
 {
   gint retval;
 
@@ -680,11 +742,13 @@ swfdec_as_array_sort_compare (SwfdecAsCo
   }
   else if (options & ARRAY_SORT_OPTION_CASEINSENSITIVE)
   {
-    retval = g_strcasecmp (swfdec_as_value_to_string (cx, a), swfdec_as_value_to_string (cx, b));
+    retval = g_strcasecmp (swfdec_as_value_to_string (cx, a),
+	swfdec_as_value_to_string (cx, b));
   }
   else
   {
-    retval = strcmp (swfdec_as_value_to_string (cx, a), swfdec_as_value_to_string (cx, b));
+    retval = strcmp (swfdec_as_value_to_string (cx, a),
+	swfdec_as_value_to_string (cx, b));
   }
 
   if (options & ARRAY_SORT_OPTION_DESCENDING) {
@@ -696,8 +760,8 @@ swfdec_as_array_sort_compare (SwfdecAsCo
 
 // renames values in the array based on fdata->order values
 static const char *
-swfdec_as_array_foreach_sort_rename (SwfdecAsObject *object, const char *variable,
-    SwfdecAsValue *value, guint flags, gpointer data)
+swfdec_as_array_foreach_sort_rename (SwfdecAsObject *object,
+    const char *variable, SwfdecAsValue *value, guint flags, gpointer data)
 {
   ForeachSortData *fdata = data;
   gint32 idx, i;
@@ -728,7 +792,8 @@ swfdec_as_array_foreach_sort_rename (Swf
 }
 
 // fills fdata->object_new array using indexes based on the fdata->order
-static gboolean swfdec_as_array_foreach_sort_indexedarray (SwfdecAsObject *object,
+static gboolean
+swfdec_as_array_foreach_sort_indexedarray (SwfdecAsObject *object,
     const char *variable, SwfdecAsValue *value, guint flags, gpointer data)
 {
   ForeachSortData *fdata = data;
@@ -767,7 +832,8 @@ static gboolean swfdec_as_array_foreach_
 // sets undefined values in the fdata->object_new array to indexes of undefined
 // values in the object array
 static void
-swfdec_as_array_sort_set_undefined_indexedarray (SwfdecAsObject *object, ForeachSortData *fdata)
+swfdec_as_array_sort_set_undefined_indexedarray (SwfdecAsObject *object,
+    ForeachSortData *fdata)
 {
   SwfdecAsValue val;
   const char *var;
@@ -795,8 +861,8 @@ swfdec_as_array_sort_set_undefined_index
 // (in the sense that sorting compare function returns 0)
 // used by uniquesort when there is exactly one undefined value in the array
 static gboolean
-swfdec_as_array_foreach_sort_compare_undefined (SwfdecAsObject *object, const char *variable,
-    SwfdecAsValue *value, guint flags, gpointer data)
+swfdec_as_array_foreach_sort_compare_undefined (SwfdecAsObject *object,
+    const char *variable, SwfdecAsValue *value, guint flags, gpointer data)
 {
   ForeachSortData *fdata = data;
   gint32 idx;
@@ -811,15 +877,16 @@ swfdec_as_array_foreach_sort_compare_und
   fdata->defined_values++;
 
   // when testing for uniquesort the custom compare function is NOT used
-  if (swfdec_as_array_sort_compare (object->context, value, &fdata->undefined, fdata->options, NULL) == 0)
+  if (swfdec_as_array_sort_compare (object->context, value, &fdata->undefined,
+	fdata->options, NULL) == 0)
     return FALSE;
 
   return TRUE;
 }
 
 static gboolean
-swfdec_as_array_foreach_sort_populate (SwfdecAsObject *object, const char *variable,
-    SwfdecAsValue *value, guint flags, gpointer data)
+swfdec_as_array_foreach_sort_populate (SwfdecAsObject *object,
+    const char *variable, SwfdecAsValue *value, guint flags, gpointer data)
 {
   ForeachSortData *fdata = data;
   gint32 idx, i;
@@ -837,15 +904,18 @@ swfdec_as_array_foreach_sort_populate (S
   // find the position for this value
   for (i = 0; i < fdata->order_size; i++)
   {
-    if (fdata->order[i] == NULL || (cval = swfdec_as_array_sort_compare (object->context, value, fdata->order[i], fdata->options, fdata->compare_custom_func)) <= 0)
+    if (fdata->order[i] == NULL ||
+	(cval = swfdec_as_array_sort_compare (object->context, value,
+	    fdata->order[i], fdata->options, fdata->compare_custom_func)) <= 0)
     {
       SwfdecAsValue *tmp2, *tmp;
 
-      // if we are doing uniquesort, see if this value is the same as some earlier value
+      // if we are doing uniquesort, see if this value is the same as some
+      // earlier value
       if (fdata->options & ARRAY_SORT_OPTION_UNIQUESORT && fdata->order[i] != NULL &&
 	  fdata->order[i] != &fdata->undefined) {
-	// when using custom function, uniquesort is still based on the equality given by
-	// the normal method, not the custom function
+	// when using custom function, uniquesort is still based on the
+	// equality given by the normal method, not the custom function
 	if (fdata->compare_custom_func != NULL) {
 	  if (swfdec_as_array_sort_compare (object->context, value, fdata->order[i], fdata->options, NULL) == 0)
 	    return FALSE;
@@ -872,7 +942,8 @@ swfdec_as_array_foreach_sort_populate (S
   return TRUE;
 }
 
-static void
+SWFDEC_AS_NATIVE (252, 10, swfdec_as_array_sort)
+void
 swfdec_as_array_sort (SwfdecAsContext *cx, SwfdecAsObject *object, guint argc,
     SwfdecAsValue *argv, SwfdecAsValue *ret)
 {
@@ -880,7 +951,8 @@ swfdec_as_array_sort (SwfdecAsContext *c
   guint pos;
 
   fdata.length = swfdec_as_array_get_length (object);
-  fdata.order_size = MIN ((gint32)g_hash_table_size (object->properties) + 1, fdata.length + 1);
+  fdata.order_size =
+    MIN ((gint32)g_hash_table_size (object->properties) + 1, fdata.length + 1);
   fdata.order = g_new0 (SwfdecAsValue *, fdata.order_size);
   SWFDEC_AS_VALUE_SET_UNDEFINED (&fdata.undefined);
   fdata.order[0] = &fdata.undefined;
@@ -890,7 +962,8 @@ swfdec_as_array_sort (SwfdecAsContext *c
   if (argc > 0 && !SWFDEC_AS_VALUE_IS_NUMBER (&argv[0])) {
     SwfdecAsFunction *fun;
     if (!SWFDEC_AS_VALUE_IS_OBJECT (&argv[0]) ||
-	!SWFDEC_IS_AS_FUNCTION (fun = (SwfdecAsFunction *) SWFDEC_AS_VALUE_GET_OBJECT (&argv[0])))
+	!SWFDEC_IS_AS_FUNCTION (
+	  fun = (SwfdecAsFunction *) SWFDEC_AS_VALUE_GET_OBJECT (&argv[0])))
 	return;
     fdata.compare_custom_func = fun;
     pos++;
@@ -905,24 +978,31 @@ swfdec_as_array_sort (SwfdecAsContext *c
   }
 
   // generate fdata.order which points to the values
-  if (!swfdec_as_object_foreach (object, swfdec_as_array_foreach_sort_populate, &fdata)) {
+  if (!swfdec_as_object_foreach (object, swfdec_as_array_foreach_sort_populate,
+	&fdata))
+  {
     // uniquesort failed
     SWFDEC_AS_VALUE_SET_INT (ret, 0);
     g_free (fdata.order);
     return;
   }
 
-  if (fdata.options & ARRAY_SORT_OPTION_UNIQUESORT && fdata.defined_values + 1 < fdata.length) {
+  if (fdata.options & ARRAY_SORT_OPTION_UNIQUESORT &&
+      fdata.defined_values + 1 < fdata.length)
+  {
     // uniquesort fails, because we have more than one undefined value
     SWFDEC_AS_VALUE_SET_INT (ret, 0);
     g_free (fdata.order);
     return;
   }
 
-  if (fdata.options & ARRAY_SORT_OPTION_UNIQUESORT && fdata.defined_values < fdata.length) {
-    // uniquesort used, and we have atleast one undefined value
-    // test if anything equeals to that
-    if (!swfdec_as_object_foreach (object, swfdec_as_array_foreach_sort_compare_undefined, &fdata))
+  if (fdata.options & ARRAY_SORT_OPTION_UNIQUESORT &&
+      fdata.defined_values < fdata.length)
+  {
+    // uniquesort used, and we have exactly one undefined value test if
+    // anything equeals to that
+    if (!swfdec_as_object_foreach (object,
+	  swfdec_as_array_foreach_sort_compare_undefined, &fdata))
     {
       SWFDEC_AS_VALUE_SET_INT (ret, 0);
       g_free (fdata.order);
@@ -933,20 +1013,23 @@ swfdec_as_array_sort (SwfdecAsContext *c
   if (fdata.options & ARRAY_SORT_OPTION_RETURNINDEXEDARRAY) {
     // make a new array and fill it with numbers based on the order
     fdata.object_new = swfdec_as_array_new (cx);
-    swfdec_as_object_foreach (object, swfdec_as_array_foreach_sort_indexedarray, &fdata);
-    // we only have the elements that have been set so far, so fill in the blanks
+    swfdec_as_object_foreach (object, swfdec_as_array_foreach_sort_indexedarray,
+       &fdata);
+    // we only have the elements that have been set so far, fill in the blanks
     swfdec_as_array_sort_set_undefined_indexedarray (object, &fdata);
     SWFDEC_AS_VALUE_SET_OBJECT (ret, fdata.object_new);
   } else {
     // rename properties based on the new order
-    swfdec_as_object_foreach_rename (object, swfdec_as_array_foreach_sort_rename, &fdata);
+    swfdec_as_object_foreach_rename (object,
+	swfdec_as_array_foreach_sort_rename, &fdata);
     SWFDEC_AS_VALUE_SET_OBJECT (ret, object);
   }
 
   g_free (fdata.order);
 }
 
-static void
+SWFDEC_AS_NATIVE (252, 12, swfdec_as_array_sortOn)
+void
 swfdec_as_array_sortOn (SwfdecAsContext *cx, SwfdecAsObject *object, guint argc,
     SwfdecAsValue *argv, SwfdecAsValue *ret)
 {
@@ -956,8 +1039,8 @@ swfdec_as_array_sortOn (SwfdecAsContext 
 // Constructor
 
 static void
-swfdec_as_array_construct (SwfdecAsContext *cx, SwfdecAsObject *object, guint argc,
-    SwfdecAsValue *argv, SwfdecAsValue *ret)
+swfdec_as_array_construct (SwfdecAsContext *cx, SwfdecAsObject *object,
+    guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
 {
   SwfdecAsArray *array;
 
@@ -969,7 +1052,8 @@ swfdec_as_array_construct (SwfdecAsConte
     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);
+      swfdec_as_object_set_constructor (object,
+	  SWFDEC_AS_VALUE_GET_OBJECT (&val), FALSE);
     } else {
       SWFDEC_INFO ("\"Array\" is not an object");
     }
@@ -994,10 +1078,10 @@ 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, 
+  array = SWFDEC_AS_OBJECT (swfdec_as_object_add_function (context->global,
       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);
+  swfdec_as_native_function_set_construct_type (
+      SWFDEC_AS_NATIVE_FUNCTION (array), SWFDEC_TYPE_AS_ARRAY);
   if (!array)
     return;
   context->Array = array;
@@ -1005,6 +1089,7 @@ swfdec_as_array_init_context (SwfdecAsCo
     return;
   proto = g_object_new (SWFDEC_TYPE_AS_ARRAY, NULL);
   swfdec_as_object_add (proto, context, sizeof (SwfdecAsArray));
+
   /* set the right properties on the Array object */
   SWFDEC_AS_VALUE_SET_OBJECT (&val, proto);
   swfdec_as_object_set_variable (array, SWFDEC_AS_STR_prototype, &val);
@@ -1020,32 +1105,34 @@ swfdec_as_array_init_context (SwfdecAsCo
   swfdec_as_object_set_variable (array, SWFDEC_AS_STR_RETURNINDEXEDARRAY, &val);
   SWFDEC_AS_VALUE_SET_NUMBER (&val, ARRAY_SORT_OPTION_NUMERIC);
   swfdec_as_object_set_variable (array, SWFDEC_AS_STR_NUMERIC, &val);
+
   /* set the right properties on the Array.prototype object */
   SWFDEC_AS_VALUE_SET_OBJECT (&val, context->Object_prototype);
   swfdec_as_object_set_variable (proto, SWFDEC_AS_STR___proto__, &val);
   SWFDEC_AS_VALUE_SET_OBJECT (&val, array);
   swfdec_as_object_set_variable (proto, SWFDEC_AS_STR_constructor, &val);
-  swfdec_as_object_add_function (proto, SWFDEC_AS_STR_toString, 0, swfdec_as_array_toString, 0);
-  swfdec_as_object_add_function (proto, SWFDEC_AS_STR_join, SWFDEC_TYPE_AS_ARRAY,
-      swfdec_as_array_join, 0);
-  swfdec_as_object_add_function (proto, SWFDEC_AS_STR_push, SWFDEC_TYPE_AS_ARRAY,
-      swfdec_as_array_do_push, 0);
-  swfdec_as_object_add_function (proto, SWFDEC_AS_STR_pop, SWFDEC_TYPE_AS_ARRAY,
-      swfdec_as_array_do_pop, 0);
-  swfdec_as_object_add_function (proto, SWFDEC_AS_STR_unshift, SWFDEC_TYPE_AS_ARRAY,
-      swfdec_as_array_do_unshift, 0);
-  swfdec_as_object_add_function (proto, SWFDEC_AS_STR_shift, SWFDEC_TYPE_AS_ARRAY,
-      swfdec_as_array_do_shift, 0);
-  swfdec_as_object_add_function (proto, SWFDEC_AS_STR_reverse, SWFDEC_TYPE_AS_ARRAY,
-      swfdec_as_array_reverse, 0);
-  swfdec_as_object_add_function (proto, SWFDEC_AS_STR_concat, SWFDEC_TYPE_AS_ARRAY,
-      swfdec_as_array_concat, 0);
-  swfdec_as_object_add_function (proto, SWFDEC_AS_STR_slice, SWFDEC_TYPE_AS_ARRAY,
-      swfdec_as_array_slice, 0);
-  swfdec_as_object_add_function (proto, SWFDEC_AS_STR_splice, SWFDEC_TYPE_AS_ARRAY,
-      swfdec_as_array_splice, 0);
-  swfdec_as_object_add_function (proto, SWFDEC_AS_STR_sort, SWFDEC_TYPE_AS_ARRAY,
-      swfdec_as_array_sort, 0);
-  swfdec_as_object_add_function (proto, SWFDEC_AS_STR_sortOn, SWFDEC_TYPE_AS_ARRAY,
-      swfdec_as_array_sortOn, 0);
+  swfdec_as_object_add_function (proto, SWFDEC_AS_STR_toString, 0,
+      swfdec_as_array_toString, 0);
+  swfdec_as_object_add_function (proto, SWFDEC_AS_STR_join,
+      SWFDEC_TYPE_AS_OBJECT, swfdec_as_array_join, 0);
+  swfdec_as_object_add_function (proto, SWFDEC_AS_STR_push,
+      SWFDEC_TYPE_AS_OBJECT, swfdec_as_array_do_push, 0);
+  swfdec_as_object_add_function (proto, SWFDEC_AS_STR_pop,
+      SWFDEC_TYPE_AS_OBJECT, swfdec_as_array_do_pop, 0);
+  swfdec_as_object_add_function (proto, SWFDEC_AS_STR_unshift,
+      SWFDEC_TYPE_AS_OBJECT, swfdec_as_array_do_unshift, 0);
+  swfdec_as_object_add_function (proto, SWFDEC_AS_STR_shift,
+      SWFDEC_TYPE_AS_OBJECT, swfdec_as_array_do_shift, 0);
+  swfdec_as_object_add_function (proto, SWFDEC_AS_STR_reverse,
+      SWFDEC_TYPE_AS_OBJECT, swfdec_as_array_reverse, 0);
+  swfdec_as_object_add_function (proto, SWFDEC_AS_STR_concat,
+      SWFDEC_TYPE_AS_OBJECT, swfdec_as_array_concat, 0);
+  swfdec_as_object_add_function (proto, SWFDEC_AS_STR_slice,
+      SWFDEC_TYPE_AS_OBJECT, swfdec_as_array_slice, 0);
+  swfdec_as_object_add_function (proto, SWFDEC_AS_STR_splice,
+      SWFDEC_TYPE_AS_OBJECT, swfdec_as_array_splice, 0);
+  swfdec_as_object_add_function (proto, SWFDEC_AS_STR_sort,
+      SWFDEC_TYPE_AS_OBJECT, swfdec_as_array_sort, 0);
+  swfdec_as_object_add_function (proto, SWFDEC_AS_STR_sortOn,
+      SWFDEC_TYPE_AS_OBJECT, swfdec_as_array_sortOn, 0);
 }
diff --git a/test/trace/array2-5.swf b/test/trace/array2-5.swf
index 4c11d71..4057223 100644
Binary files a/test/trace/array2-5.swf and b/test/trace/array2-5.swf differ
diff --git a/test/trace/array2-5.swf.trace b/test/trace/array2-5.swf.trace
index 38bc090..d3221d7 100644
--- a/test/trace/array2-5.swf.trace
+++ b/test/trace/array2-5.swf.trace
@@ -40,6 +40,8 @@
 [, , , , ]
 undefined
 [, , , , , , , , , ]
+[]
+[]
 [[], [], [], , ]
 []
 [[], [], [], , ]
@@ -91,9 +93,18 @@ undefined
 []
 [[], [], [], [], [], [[], [], []]]
 []
+undefined
+[[, , , , , , ]]
+[]
+undefined
+[]
+[]
 [[]]
 []
 [, , , , , []]
+[]
+[]
+[]
 [, , , , , ]
 [, , , , , , , , , , , , , ]
 []
@@ -103,6 +114,8 @@ undefined
 [, , , , , , , , , , , , , , ]
 undefined
 []
+undefined
+[]
 []
 [[], [], []]
 []
@@ -548,4 +561,27 @@ undefined
 [, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ]
 [[], [], [], [], []]
 [[[], [], []], [[], [], [], []], [], [[], []], [[]]]
+[, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ]
+[type Function]
+5
+5: a:b:c:x:z
+z
+5: a:b:c:x:
+5
+5: y:a:b:c:x
+5
+5: z:y:a:b:c
+6: z:y:a:b:c:x
+z
+6: y:a:b:c:x:x
+x,x,c,b,a,y
+6: x:x:c:b:a:y
+x:x:c:b:a:y:a:x,x,c,b,a,y
+6: x:x:c:b:a:y
+x,c
+6: x:x:c:b:a:y
+c,b,a
+5: x:x:i:j:y
+i,j,x,x,y
+5: i:j:x:x:y
 [, , , , , , ]
diff --git a/test/trace/array2-6.swf b/test/trace/array2-6.swf
index ff62b44..42059f3 100644
Binary files a/test/trace/array2-6.swf and b/test/trace/array2-6.swf differ
diff --git a/test/trace/array2-6.swf.trace b/test/trace/array2-6.swf.trace
index 84a7bd8..51dc019 100644
--- a/test/trace/array2-6.swf.trace
+++ b/test/trace/array2-6.swf.trace
@@ -40,6 +40,8 @@
 [, , , , ]
 undefined
 [, , , , , , , , , ]
+[]
+-4
 [1, b, c, , ]
 3.4
 [1, b, c, , ]
@@ -91,9 +93,18 @@ a:b:c
 6
 [1, 2, 3, 4, 5, [a, b, c]]
 1
+undefined
+[weirder]
+0
+undefined
+[]
+1
 [6]
 6
 [, , , , , 6]
+-2
+x
+-2
 ## Pop
 # Normal usage
 4
@@ -103,6 +114,8 @@ c
 # Special cases
 undefined
 []
+undefined
+[]
 4
 [1, b, c]
 c
@@ -548,4 +561,27 @@ sort customfunc 30 [[1, 2, 3], [1, 2, 3,
 sort customfunc 31 [[1, 2, 3], [1, 2, 3, 4], [], [1, 2], [1]]
 [1, 0, 3, 4, 2]
 [[1, 2, 3], [1, 2, 3, 4], [], [1, 2], [1]]
+## Fake Array (Object with Array's methods)
+[type Function]
+5
+5: a:b:c:x:z
+z
+5: a:b:c:x:
+5
+5: y:a:b:c:x
+5
+5: z:y:a:b:c
+6: z:y:a:b:c:x
+z
+6: y:a:b:c:x:x
+x,x,c,b,a,y
+6: x:x:c:b:a:y
+x:x:c:b:a:y:a:x,x,c,b,a,y
+6: x:x:c:b:a:y
+x,c
+6: x:x:c:b:a:y
+c,b,a
+5: x:x:i:j:y
+i,j,x,x,y
+5: i:j:x:x:y
 ## Done
diff --git a/test/trace/array2-7.swf b/test/trace/array2-7.swf
index db297a0..1ceb5d9 100644
Binary files a/test/trace/array2-7.swf and b/test/trace/array2-7.swf differ
diff --git a/test/trace/array2-7.swf.trace b/test/trace/array2-7.swf.trace
index 51ea2a3..04a5849 100644
--- a/test/trace/array2-7.swf.trace
+++ b/test/trace/array2-7.swf.trace
@@ -40,6 +40,8 @@
 [undefined, undefined, undefined, undefined, undefined]
 undefined
 [undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined]
+[]
+-4
 [1, b, c, undefined, ]
 3.4
 [1, b, c, undefined, ]
@@ -91,9 +93,18 @@ undefined:undefined:undefined:undefined:
 6
 [1, 2, 3, 4, 5, [a, b, c]]
 1
+undefined
+[weirder]
+0
+undefined
+[]
+1
 [6]
 6
 [undefined, undefined, undefined, undefined, undefined, 6]
+-2
+x
+-2
 ## Pop
 # Normal usage
 4
@@ -103,6 +114,8 @@ c
 # Special cases
 undefined
 []
+undefined
+[]
 4
 [1, b, c]
 c
@@ -548,4 +561,27 @@ sort customfunc 30 [[1, 2, 3], [1, 2, 3,
 sort customfunc 31 [[1, 2, 3], [1, 2, 3, 4], [], [1, 2], [1]]
 [1, 0, 3, 4, 2]
 [[1, 2, 3], [1, 2, 3, 4], [], [1, 2], [1]]
+## Fake Array (Object with Array's methods)
+[type Function]
+5
+5: a:b:c:x:z
+z
+5: a:b:c:x:undefined
+5
+5: y:a:b:c:x
+5
+5: z:y:a:b:c
+6: z:y:a:b:c:x
+z
+6: y:a:b:c:x:x
+x,x,c,b,a,y
+6: x:x:c:b:a:y
+x:x:c:b:a:y:a:x,x,c,b,a,y
+6: x:x:c:b:a:y
+x,c
+6: x:x:c:b:a:y
+c,b,a
+5: x:x:i:j:y
+i,j,x,x,y
+5: i:j:x:x:y
 ## Done
diff --git a/test/trace/array2.as b/test/trace/array2.as
index 7e8edb4..bea9179 100644
--- a/test/trace/array2.as
+++ b/test/trace/array2.as
@@ -96,6 +96,10 @@ mytrace (a);
 mytrace (a[9]);
 a.length = 10;
 mytrace (a);
+a = new Array (1, "b", "c", 4);		// negative value
+a.length = -4;
+mytrace (a);
+mytrace (a.length);
 a = new Array (1, "b", "c", 4);		// floating point values
 a.length = 3.4;
 mytrace (a);
@@ -187,12 +191,27 @@ mytrace (a.push ());			// pushing nothin
 mytrace (a);
 mytrace (a.push (["a", "b", "c"]));	// pushing another array
 mytrace (a);
+a = new Array ();			// pushing when weird length
+a.length = "weird";
+mytrace (a.push ("weirder"));
+mytrace (a["weird"]);
+mytrace (a);
+a = new Array ();			// pushing nothing, weird length
+a.length = "weird";
+mytrace (a.push ());
+mytrace (a["weird"]);
+mytrace (a);
 a = new Array ();			// pushing on empty array
 mytrace (a.push (6));
 mytrace (a);
 a = new Array (5);			// pushing on array with only undefined values
 mytrace (a.push (6));
 mytrace (a);
+a = new Array ();			// pushing on array with negative length
+a.length = -3;
+mytrace (a.push ("x"));
+mytrace (a[-3]);
+mytrace (a.length);
 
 
 mytrace ("## Pop");
@@ -210,6 +229,10 @@ mytrace ("# Special cases");
 a = new Array ();			// empty
 mytrace (a.pop ());
 mytrace (a);
+a = new Array ();			// empty, weird length
+a.length = "weird";
+mytrace (a.pop ());
+mytrace (a);
 a = new Array (1, "b", "c", 4);		// use parameters
 mytrace (a.pop (5));
 mytrace (a);
@@ -444,5 +467,52 @@ a = new Array ([1,2,3], [1,2,3,4], [], [
 sortall (a, compare_array_length, 0, 0);
 
 
+mytrace ("## Fake Array (Object with Array's methods)");
+
+fake = new Object();
+
+fake.join = Array.prototype.join;
+fake.toString = Array.prototype.toString;
+fake.push = Array.prototype.push;
+fake.pop = Array.prototype.pop;
+fake.shift = Array.prototype.shift;
+fake.unshift = Array.prototype.unshift;
+fake.reverse = Array.prototype.reverse;
+fake.concat = Array.prototype.concat;
+fake.slice = Array.prototype.slice;
+fake.splice = Array.prototype.splice;
+fake.sort = Array.prototype.sort;
+
+trace (fake.push);
+trace (fake.push ("a", "b", "c", "x", "z"));
+trace (fake.length + ": " + fake.join (":"));
+trace (fake.pop ());
+trace (fake.length + ": " + fake.join (":"));
+
+trace (fake.unshift ("y"));
+trace (fake.length + ": " + fake.join (":"));
+trace (fake.unshift ("z"));
+trace (fake.length + ": " + fake.join (":"));
+fake.length++;
+trace (fake.length + ": " + fake.join (":"));
+trace (fake.shift ());
+trace (fake.length + ": " + fake.join (":"));
+
+trace (fake.reverse ());
+trace (fake.length + ": " + fake.join (":"));
+
+trace (fake.concat ("a", fake).join (":"));
+trace (fake.length + ": " + fake.join (":"));
+
+trace (fake.slice (1, 3));
+trace (fake.length + ": " + fake.join (":"));
+
+trace (fake.splice (2, 3, "i", "j"));
+trace (fake.length + ": " + fake.join (":"));
+
+trace (fake.sort ());
+trace (fake.length + ": " + fake.join (":"));
+
+
 mytrace ("## Done");
 loadMovie ("FSCommand:quit", "");


More information about the Swfdec mailing list