[Swfdec-commits] Branch 'abc' - 8 commits - swfdec/Makefile.am swfdec/swfdec_abc_function.c swfdec/swfdec_abc_global.c swfdec/swfdec_abc_interpret.c swfdec/swfdec_abc_multiname.c swfdec/swfdec_abc_multiname.h swfdec/swfdec_abc_object.c swfdec/swfdec_abc_object.h swfdec/swfdec_abc_pool.c swfdec/swfdec_abc_traits.c swfdec/swfdec_abc_traits.h swfdec/swfdec_abc_value.c swfdec/swfdec_abc_value.h swfdec/swfdec_as_types.c swfdec/swfdec_as_types.h swfdec/swfdec_sprite_movie.c

Benjamin Otte company at kemper.freedesktop.org
Tue Aug 26 13:46:12 PDT 2008


 swfdec/Makefile.am            |    2 
 swfdec/swfdec_abc_function.c  |    5 
 swfdec/swfdec_abc_global.c    |    2 
 swfdec/swfdec_abc_interpret.c |  336 ++++++++++++++++++++++++++++++++------
 swfdec/swfdec_abc_multiname.c |   17 +
 swfdec/swfdec_abc_multiname.h |    6 
 swfdec/swfdec_abc_object.c    |   95 ++++++++++
 swfdec/swfdec_abc_object.h    |   10 +
 swfdec/swfdec_abc_pool.c      |   17 -
 swfdec/swfdec_abc_traits.c    |   56 ++++--
 swfdec/swfdec_abc_traits.h    |    6 
 swfdec/swfdec_abc_value.c     |  368 ++++++++++++++++++++++++++++++++++++++++++
 swfdec/swfdec_abc_value.h     |   64 +++++++
 swfdec/swfdec_as_types.c      |   34 ---
 swfdec/swfdec_as_types.h      |    6 
 swfdec/swfdec_sprite_movie.c  |    2 
 16 files changed, 904 insertions(+), 122 deletions(-)

New commits:
commit 658f96fc119f9adbb07d81a57e6a82d9e8c24b50
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Aug 26 18:12:54 2008 +0200

    implement construct and constructprop opcodes

diff --git a/swfdec/swfdec_abc_interpret.c b/swfdec/swfdec_abc_interpret.c
index 59ca074..bb64789 100644
--- a/swfdec/swfdec_abc_interpret.c
+++ b/swfdec/swfdec_abc_interpret.c
@@ -680,7 +680,7 @@ swfdec_abc_interpret (SwfdecAbcFunction *fun, SwfdecAbcScopeChain *outer_scope)
 	  swfdec_as_stack_push_n (context, argc);
 	  if (opcode == SWFDEC_ABC_OPCODE_CALL_PROP_LEX)
 	    SWFDEC_AS_VALUE_SET_NULL (val);
-	  if (!swfdec_abc_object_call_variable (context, &tmp, &mn, argc, val, &tmp))
+	  if (!swfdec_abc_object_call_variable (context, &tmp, &mn, argc, val, val))
 	    break;
 	  swfdec_as_stack_pop_n (context, argc);
 	  if (opcode == SWFDEC_ABC_OPCODE_CALL_PROP_VOID)
@@ -717,7 +717,37 @@ swfdec_abc_interpret (SwfdecAbcFunction *fun, SwfdecAbcScopeChain *outer_scope)
 	  SWFDEC_AS_VALUE_SET_STRING (val,
 	      swfdec_abc_value_to_string (context, val));
 	}
-	/* else NULL stays the same */
+	/* else NULL: it stays the same */
+	continue;
+      case SWFDEC_ABC_OPCODE_CONSTRUCT:
+	i = swfdec_bits_get_vu32 (&bits);
+	val = swfdec_as_stack_peek (context, i + 1);
+	if (!SWFDEC_AS_VALUE_IS_OBJECT (val)) {
+	  swfdec_as_context_throw_abc (context, SWFDEC_ABC_TYPE_TYPE_ERROR,
+	      "Instantiation attempted on a non-constructor.");
+	  break;
+	}
+	if (!swfdec_abc_object_construct (SWFDEC_ABC_OBJECT (SWFDEC_AS_VALUE_GET_OBJECT (val)),
+	      i, val, val))
+	  break;
+	swfdec_as_stack_pop_n (context, i);
+	continue;
+      case SWFDEC_ABC_OPCODE_CONSTRUCT_PROP:
+	{
+	  SwfdecAsValue tmp;
+	  guint argc;
+	  i = swfdec_bits_get_vu32 (&bits);
+	  argc = swfdec_bits_get_vu32 (&bits);
+	  swfdec_as_stack_pop_n (context, argc);
+	  if (!swfdec_abc_interpret_resolve_multiname (context, &mn, &pool->multinames[i]))
+	    break;
+	  val = swfdec_as_stack_peek (context, 1);
+	  tmp = *val;
+	  swfdec_as_stack_push_n (context, argc);
+	  if (!swfdec_abc_object_construct_variable (context, &tmp, &mn, argc, val, val))
+	    break;
+	  swfdec_as_stack_pop_n (context, argc);
+	}
 	continue;
       case SWFDEC_ABC_OPCODE_CONSTRUCT_SUPER:
 	i = swfdec_bits_get_vu32 (&bits);
@@ -1239,8 +1269,6 @@ swfdec_abc_interpret (SwfdecAbcFunction *fun, SwfdecAbcScopeChain *outer_scope)
       case SWFDEC_ABC_OPCODE_COERCE_I:
       case SWFDEC_ABC_OPCODE_COERCE_U:
       case SWFDEC_ABC_OPCODE_CONCAT:
-      case SWFDEC_ABC_OPCODE_CONSTRUCT:
-      case SWFDEC_ABC_OPCODE_CONSTRUCT_PROP:
       case SWFDEC_ABC_OPCODE_CONVERT_B:
       case SWFDEC_ABC_OPCODE_CONVERT_D:
       case SWFDEC_ABC_OPCODE_CONVERT_I:
diff --git a/swfdec/swfdec_abc_object.c b/swfdec/swfdec_abc_object.c
index 5147fd8..d0597b3 100644
--- a/swfdec/swfdec_abc_object.c
+++ b/swfdec/swfdec_abc_object.c
@@ -377,7 +377,7 @@ swfdec_abc_object_init_variable (SwfdecAsContext *context, const SwfdecAsValue *
 }
 
 gboolean
-swfdec_abc_object_call_variable	(SwfdecAsContext *context, const SwfdecAsValue *object,
+swfdec_abc_object_call_variable (SwfdecAsContext *context, const SwfdecAsValue *object,
     const SwfdecAbcMultiname *mn, guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
 {
   SwfdecAbcTraits *traits;
@@ -424,6 +424,23 @@ swfdec_abc_object_call_variable	(SwfdecAsContext *context, const SwfdecAsValue *
 }
 
 gboolean
+swfdec_abc_object_construct_variable (SwfdecAsContext *context, const SwfdecAsValue *object,
+    const SwfdecAbcMultiname *mn, guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
+{
+  SwfdecAsValue tmp;
+
+  if (!swfdec_abc_object_get_variable (context, object, mn, &tmp))
+    return FALSE;
+  if (!SWFDEC_AS_VALUE_IS_OBJECT (&tmp)) {
+    swfdec_as_context_throw_abc (context, SWFDEC_ABC_TYPE_TYPE_ERROR,
+	"Instantiation attempted on a non-constructor.");
+    return FALSE;
+  }
+  return swfdec_abc_object_construct (SWFDEC_ABC_OBJECT (SWFDEC_AS_VALUE_GET_OBJECT (&tmp)),
+      argc, argv, ret);
+}
+
+gboolean
 swfdec_abc_object_default_value	(SwfdecAbcObject *object, SwfdecAsValue *default_value)
 {
   SwfdecAsContext *context;
diff --git a/swfdec/swfdec_abc_object.h b/swfdec/swfdec_abc_object.h
index 06395c4..683276d 100644
--- a/swfdec/swfdec_abc_object.h
+++ b/swfdec/swfdec_abc_object.h
@@ -92,6 +92,13 @@ gboolean		swfdec_abc_object_call_variable	(SwfdecAsContext *		context,
 							 guint				argc,
 							 SwfdecAsValue *		argv,
 							 SwfdecAsValue *		ret);
+gboolean		swfdec_abc_object_construct_variable
+							(SwfdecAsContext *		context,
+							 const SwfdecAsValue *		object,
+							 const SwfdecAbcMultiname *	mn,
+							 guint				argc,
+							 SwfdecAsValue *		argv,
+							 SwfdecAsValue *		ret);
 
 
 G_END_DECLS
commit 0976cee9297b4da790bd4bdafa294513295f3858
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Aug 26 18:12:37 2008 +0200

    only coerce when the type is not any

diff --git a/swfdec/swfdec_abc_function.c b/swfdec/swfdec_abc_function.c
index b057a6b..2405c56 100644
--- a/swfdec/swfdec_abc_function.c
+++ b/swfdec/swfdec_abc_function.c
@@ -429,7 +429,7 @@ swfdec_abc_function_call (SwfdecAbcFunction *fun, SwfdecAbcScopeChain *scope,
     return FALSE;
 
   for (i = 0; i <= MIN (argc, fun->n_args); i++) {
-    if (!swfdec_abc_traits_coerce (fun->args[i].traits, &argv[i])) {
+    if (fun->args[i].traits && !swfdec_abc_traits_coerce (fun->args[i].traits, &argv[i])) {
       swfdec_as_context_throw_abc (context, SWFDEC_ABC_TYPE_TYPE_ERROR, 
 	"Type Coercion failed: cannot convert %s to %s.",
 	swfdec_abc_value_get_type_name (&argv[i]), fun->args[i].traits->name);
commit 339b45171091c1de326ffead1360018d2037d3e0
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Aug 26 18:11:32 2008 +0200

    handle exceptions properly

diff --git a/swfdec/swfdec_abc_traits.c b/swfdec/swfdec_abc_traits.c
index 1e7deb9..24cfc1a 100644
--- a/swfdec/swfdec_abc_traits.c
+++ b/swfdec/swfdec_abc_traits.c
@@ -402,15 +402,15 @@ swfdec_abc_traits_coerce (SwfdecAbcTraits *traits, SwfdecAsValue *val)
   } else if (traits == SWFDEC_ABC_NUMBER_TRAITS (context)) {
     SWFDEC_AS_VALUE_SET_NUMBER (val,
 	swfdec_abc_value_to_number (context, val));
-    return TRUE;
+    return !context->exception;
   } else if (traits == SWFDEC_ABC_INT_TRAITS (context)) {
     SWFDEC_AS_VALUE_SET_INT (val,
 	swfdec_abc_value_to_integer (context, val));
-    return TRUE;
+    return !context->exception;
   } else if (traits == SWFDEC_ABC_UINT_TRAITS (context)) {
     SWFDEC_AS_VALUE_SET_NUMBER (val,
 	(guint) swfdec_abc_value_to_integer (context, val));
-    return TRUE;
+    return !context->exception;
   } else if (traits == SWFDEC_ABC_NUMBER_TRAITS (context)) {
     SWFDEC_AS_VALUE_SET_NUMBER (val,
 	(guint) swfdec_abc_value_to_integer (context, val));
@@ -419,8 +419,10 @@ swfdec_abc_traits_coerce (SwfdecAbcTraits *traits, SwfdecAsValue *val)
     if (SWFDEC_AS_VALUE_IS_UNDEFINED (val) || SWFDEC_AS_VALUE_IS_NULL (val)) {
       SWFDEC_AS_VALUE_SET_NULL (val);
     } else {
-      SWFDEC_AS_VALUE_SET_STRING (val, 
-	  swfdec_abc_value_to_string (context, val));
+      const char *s = swfdec_abc_value_to_string (context, val);
+      if (s == NULL)
+	return FALSE;
+      SWFDEC_AS_VALUE_SET_STRING (val, s);
     }
     return TRUE;
   } else if (traits == SWFDEC_ABC_OBJECT_TRAITS (context)) {
commit b548964fb860095571c1a28cdca8b72f82f30543
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Aug 26 15:16:56 2008 +0200

    implement setslot and newactivation opcodes

diff --git a/swfdec/swfdec_abc_interpret.c b/swfdec/swfdec_abc_interpret.c
index c892970..59ca074 100644
--- a/swfdec/swfdec_abc_interpret.c
+++ b/swfdec/swfdec_abc_interpret.c
@@ -1027,6 +1027,21 @@ swfdec_abc_interpret (SwfdecAbcFunction *fun, SwfdecAbcScopeChain *outer_scope)
 	val = swfdec_as_stack_peek (context, 1);
 	SWFDEC_AS_VALUE_SET_INT (val, swfdec_abc_value_to_integer (context, val));
 	break;
+      case SWFDEC_ABC_OPCODE_NEW_ACTIVATION:
+	{
+	  SwfdecAbcObject *object;
+	  object = swfdec_abc_object_new (fun->activation, outer_scope);
+	  if (fun->activation->construct) {
+	    SwfdecAsValue tmp;
+	    SWFDEC_AS_VALUE_SET_OBJECT (&tmp, SWFDEC_AS_OBJECT (object));
+	    if (!swfdec_abc_function_call (fun->activation->construct,
+		  outer_scope, 0, &tmp, &tmp))
+	      break;
+	  }
+	  SWFDEC_AS_VALUE_SET_OBJECT (swfdec_as_stack_push (context),
+	      SWFDEC_AS_OBJECT (object));
+	}
+	continue;
       case SWFDEC_ABC_OPCODE_NEW_CLASS:
 	{
 	  SwfdecAbcClass *classp;
@@ -1171,6 +1186,18 @@ swfdec_abc_interpret (SwfdecAbcFunction *fun, SwfdecAbcScopeChain *outer_scope)
 	    !swfdec_abc_object_set_variable (context, swfdec_as_stack_pop (context), &mn, val))
 	  break;
 	continue;
+      case SWFDEC_ABC_OPCODE_SET_SLOT:
+	{
+	  SwfdecAbcObject *object;
+	  i = swfdec_bits_get_vu32 (&bits) - 1;
+	  val = swfdec_as_stack_pop (context);
+	  if (swfdec_abc_interpreter_throw_null (context, swfdec_as_stack_peek (context, 1)))
+	    break;
+	  object = SWFDEC_ABC_OBJECT (SWFDEC_AS_VALUE_GET_OBJECT (swfdec_as_stack_pop (context)));
+	  swfdec_abc_traits_coerce (swfdec_abc_traits_get_slot_traits (object->traits, i), val);
+	  object->slots[i] = *val;
+	}
+	continue;
       case SWFDEC_ABC_OPCODE_STRICT_EQUALS:
 	{
 	  SwfdecAbcComparison comp;
@@ -1256,7 +1283,6 @@ swfdec_abc_interpret (SwfdecAbcFunction *fun, SwfdecAbcScopeChain *outer_scope)
       case SWFDEC_ABC_OPCODE_NEXT_NAME:
       case SWFDEC_ABC_OPCODE_NEXT_VALUE:
       case SWFDEC_ABC_OPCODE_NEW_ARRAY:
-      case SWFDEC_ABC_OPCODE_NEW_ACTIVATION:
       case SWFDEC_ABC_OPCODE_NEW_CATCH:
       case SWFDEC_ABC_OPCODE_NEW_OBJECT:
       case SWFDEC_ABC_OPCODE_NOP:
@@ -1266,7 +1292,6 @@ swfdec_abc_interpret (SwfdecAbcFunction *fun, SwfdecAbcScopeChain *outer_scope)
       case SWFDEC_ABC_OPCODE_RSHIFT:
       case SWFDEC_ABC_OPCODE_SEND_ENTER:
       case SWFDEC_ABC_OPCODE_SET_GLOBAL_SLOT:
-      case SWFDEC_ABC_OPCODE_SET_SLOT:
       case SWFDEC_ABC_OPCODE_SET_SUPER:
       case SWFDEC_ABC_OPCODE_SWEEP:
       case SWFDEC_ABC_OPCODE_THROW:
diff --git a/swfdec/swfdec_abc_traits.c b/swfdec/swfdec_abc_traits.c
index c924ad6..1e7deb9 100644
--- a/swfdec/swfdec_abc_traits.c
+++ b/swfdec/swfdec_abc_traits.c
@@ -442,3 +442,28 @@ swfdec_abc_traits_coerce (SwfdecAbcTraits *traits, SwfdecAsValue *val)
   return swfdec_abc_value_is_traits (val, traits);
 }
 
+SwfdecAbcTraits *
+swfdec_abc_traits_get_slot_traits (SwfdecAbcTraits *traits, guint slot)
+{
+  SwfdecAbcTrait *trait;
+  guint i, slot_id, const_id;
+
+  g_return_val_if_fail (SWFDEC_IS_ABC_TRAITS (traits), NULL);
+  g_return_val_if_fail (traits->resolved, NULL);
+  g_return_val_if_fail (slot < traits->n_slots, NULL);
+
+  while (traits->base && traits->base->n_slots > slot)
+    traits = traits->base;
+
+  const_id = SWFDEC_ABC_BINDING_NEW (SWFDEC_ABC_TRAIT_CONST, slot);
+  slot_id = SWFDEC_ABC_BINDING_NEW (SWFDEC_ABC_TRAIT_SLOT, slot);
+  for (i = 0; i < traits->n_traits; i++) {
+    trait = &traits->traits[i];
+    if (trait->type == slot_id || trait->type == const_id)
+      return trait->traits;
+  }
+
+  g_assert_not_reached ();
+  return NULL;
+}
+
diff --git a/swfdec/swfdec_abc_traits.h b/swfdec/swfdec_abc_traits.h
index b69a6b4..13722aa 100644
--- a/swfdec/swfdec_abc_traits.h
+++ b/swfdec/swfdec_abc_traits.h
@@ -134,6 +134,8 @@ const SwfdecAbcTrait *	swfdec_abc_traits_find_trait		(SwfdecAbcTraits *	traits,
 								 const char *		name);
 const SwfdecAbcTrait *	swfdec_abc_traits_find_trait_multi	(SwfdecAbcTraits *	traits,
 								 const SwfdecAbcMultiname *multi);
+SwfdecAbcTraits *	swfdec_abc_traits_get_slot_traits	(SwfdecAbcTraits *	traits,
+								 guint			slot);
 
 gboolean		swfdec_abc_traits_is_traits		(SwfdecAbcTraits *	traits,
 								 SwfdecAbcTraits *	parent);
commit 4dcba6e8e49fd209469945cbfd91793d23635d7f
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Aug 26 11:15:43 2008 +0200

    split ABC value handling into its own file and implement a bunch of functions for it

diff --git a/swfdec/swfdec_abc_global.c b/swfdec/swfdec_abc_global.c
index afcea5f..517e103 100644
--- a/swfdec/swfdec_abc_global.c
+++ b/swfdec/swfdec_abc_global.c
@@ -315,7 +315,7 @@ swfdec_abc_global_get_builtin_class (SwfdecAbcGlobal *global, guint id)
 
   traits = global->pool->instances[id];
 
-  swfdec_abc_multiname_init (&mn, traits->name, traits->ns, NULL);
+  swfdec_abc_multiname_init (&mn, traits->ns, traits->name);
   SWFDEC_AS_VALUE_SET_OBJECT (&val, SWFDEC_AS_OBJECT (global));
   if (!swfdec_abc_object_get_variable (swfdec_gc_object_get_context (global),
 	&val, &mn, &val))
diff --git a/swfdec/swfdec_abc_interpret.c b/swfdec/swfdec_abc_interpret.c
index 2fb94f5..c892970 100644
--- a/swfdec/swfdec_abc_interpret.c
+++ b/swfdec/swfdec_abc_interpret.c
@@ -747,6 +747,17 @@ swfdec_abc_interpret (SwfdecAbcFunction *fun, SwfdecAbcScopeChain *outer_scope)
 	val = swfdec_as_stack_peek (context, 1);
 	*swfdec_as_stack_push (context) = *val;
 	continue;
+      case SWFDEC_ABC_OPCODE_EQUALS:
+	{
+	  SwfdecAbcComparison comp;
+	  val = swfdec_as_stack_peek (context, 2);
+	  comp = swfdec_abc_value_equals (context, val, swfdec_as_stack_pop (context));
+	  if (comp == SWFDEC_ABC_COMPARE_THROWN)
+	    break;
+	  g_assert (comp == SWFDEC_ABC_COMPARE_EQUAL || comp == SWFDEC_ABC_COMPARE_NOT_EQUAL);
+	  SWFDEC_AS_VALUE_SET_BOOLEAN (val, comp == SWFDEC_ABC_COMPARE_EQUAL);
+	}
+	continue;
       case SWFDEC_ABC_OPCODE_FIND_PROP_STRICT:
       case SWFDEC_ABC_OPCODE_FIND_PROPERTY:
 	i = swfdec_bits_get_vu32 (&bits);
@@ -819,6 +830,150 @@ swfdec_abc_interpret (SwfdecAbcFunction *fun, SwfdecAbcScopeChain *outer_scope)
 	  break;
 	*val = SWFDEC_ABC_OBJECT (SWFDEC_AS_VALUE_GET_OBJECT (val))->slots[i - 1];
 	continue;
+      case SWFDEC_ABC_OPCODE_IFEQ:
+	{
+	  SwfdecAbcComparison comp;
+	  i = swfdec_bits_get_s24 (&bits);
+	  val = swfdec_as_stack_pop (context);
+	  comp = swfdec_abc_value_equals (context, swfdec_as_stack_pop (context), val);
+	  if (comp == SWFDEC_ABC_COMPARE_THROWN ||
+	      (comp == SWFDEC_ABC_COMPARE_EQUAL && !swfdec_abc_interpret_jump (context, &bits, i)))
+	    break;
+	}
+	continue;
+      case SWFDEC_ABC_OPCODE_IFFALSE:
+	i = swfdec_bits_get_s24 (&bits);
+	if (!swfdec_as_value_to_boolean (context, swfdec_as_stack_pop (context)) &&
+	    !swfdec_abc_interpret_jump (context, &bits, i))
+	  break;
+	continue;
+      case SWFDEC_ABC_OPCODE_IFGE:
+	{
+	  SwfdecAbcComparison comp;
+	  i = swfdec_bits_get_s24 (&bits);
+	  val = swfdec_as_stack_pop (context);
+	  comp = swfdec_abc_value_compare (context, swfdec_as_stack_pop (context), val);
+	  if (comp == SWFDEC_ABC_COMPARE_THROWN ||
+	      (comp != SWFDEC_ABC_COMPARE_GREATER && !swfdec_abc_interpret_jump (context, &bits, i)))
+	    break;
+	}
+	continue;
+      case SWFDEC_ABC_OPCODE_IFGT:
+	{
+	  SwfdecAbcComparison comp;
+	  i = swfdec_bits_get_s24 (&bits);
+	  val = swfdec_as_stack_pop (context);
+	  comp = swfdec_abc_value_compare (context, val, swfdec_as_stack_pop (context));
+	  if (comp == SWFDEC_ABC_COMPARE_THROWN ||
+	      (comp == SWFDEC_ABC_COMPARE_LOWER && !swfdec_abc_interpret_jump (context, &bits, i)))
+	    break;
+	}
+	continue;
+      case SWFDEC_ABC_OPCODE_IFLE:
+	{
+	  SwfdecAbcComparison comp;
+	  i = swfdec_bits_get_s24 (&bits);
+	  val = swfdec_as_stack_pop (context);
+	  comp = swfdec_abc_value_compare (context, val, swfdec_as_stack_pop (context));
+	  if (comp == SWFDEC_ABC_COMPARE_THROWN ||
+	      (comp == SWFDEC_ABC_COMPARE_GREATER && !swfdec_abc_interpret_jump (context, &bits, i)))
+	    break;
+	}
+	continue;
+      case SWFDEC_ABC_OPCODE_IFLT:
+	{
+	  SwfdecAbcComparison comp;
+	  i = swfdec_bits_get_s24 (&bits);
+	  val = swfdec_as_stack_pop (context);
+	  comp = swfdec_abc_value_compare (context, swfdec_as_stack_pop (context), val);
+	  if (comp == SWFDEC_ABC_COMPARE_THROWN ||
+	      (comp == SWFDEC_ABC_COMPARE_LOWER && !swfdec_abc_interpret_jump (context, &bits, i)))
+	    break;
+	}
+	continue;
+      case SWFDEC_ABC_OPCODE_IFNE:
+	{
+	  SwfdecAbcComparison comp;
+	  i = swfdec_bits_get_s24 (&bits);
+	  val = swfdec_as_stack_pop (context);
+	  comp = swfdec_abc_value_equals (context, swfdec_as_stack_pop (context), val);
+	  if (comp == SWFDEC_ABC_COMPARE_THROWN ||
+	      (comp == SWFDEC_ABC_COMPARE_NOT_EQUAL && !swfdec_abc_interpret_jump (context, &bits, i)))
+	    break;
+	}
+	continue;
+      case SWFDEC_ABC_OPCODE_IFNLE:
+	{
+	  SwfdecAbcComparison comp;
+	  i = swfdec_bits_get_s24 (&bits);
+	  val = swfdec_as_stack_pop (context);
+	  comp = swfdec_abc_value_compare (context, val, swfdec_as_stack_pop (context));
+	  if (comp == SWFDEC_ABC_COMPARE_THROWN ||
+	      (comp != SWFDEC_ABC_COMPARE_GREATER && !swfdec_abc_interpret_jump (context, &bits, i)))
+	    break;
+	}
+	continue;
+      case SWFDEC_ABC_OPCODE_IFNLT:
+	{
+	  SwfdecAbcComparison comp;
+	  i = swfdec_bits_get_s24 (&bits);
+	  val = swfdec_as_stack_pop (context);
+	  comp = swfdec_abc_value_compare (context, swfdec_as_stack_pop (context), val);
+	  if (comp == SWFDEC_ABC_COMPARE_THROWN ||
+	      (comp != SWFDEC_ABC_COMPARE_LOWER && !swfdec_abc_interpret_jump (context, &bits, i)))
+	    break;
+	}
+	continue;
+      case SWFDEC_ABC_OPCODE_IFNGE:
+	{
+	  SwfdecAbcComparison comp;
+	  i = swfdec_bits_get_s24 (&bits);
+	  val = swfdec_as_stack_pop (context);
+	  comp = swfdec_abc_value_compare (context, swfdec_as_stack_pop (context), val);
+	  if (comp == SWFDEC_ABC_COMPARE_THROWN ||
+	      (comp != SWFDEC_ABC_COMPARE_GREATER && !swfdec_abc_interpret_jump (context, &bits, i)))
+	    break;
+	}
+	continue;
+      case SWFDEC_ABC_OPCODE_IFNGT:
+	{
+	  SwfdecAbcComparison comp;
+	  i = swfdec_bits_get_s24 (&bits);
+	  val = swfdec_as_stack_pop (context);
+	  comp = swfdec_abc_value_compare (context, val, swfdec_as_stack_pop (context));
+	  if (comp == SWFDEC_ABC_COMPARE_THROWN ||
+	      (comp != SWFDEC_ABC_COMPARE_LOWER && !swfdec_abc_interpret_jump (context, &bits, i)))
+	    break;
+	}
+	continue;
+      case SWFDEC_ABC_OPCODE_IFSTRICTEQ:
+	{
+	  SwfdecAbcComparison comp;
+	  i = swfdec_bits_get_s24 (&bits);
+	  val = swfdec_as_stack_pop (context);
+	  comp = swfdec_abc_value_strict_equals (context, swfdec_as_stack_pop (context), val);
+	  if (comp == SWFDEC_ABC_COMPARE_THROWN ||
+	      (comp == SWFDEC_ABC_COMPARE_EQUAL && !swfdec_abc_interpret_jump (context, &bits, i)))
+	    break;
+	}
+	continue;
+      case SWFDEC_ABC_OPCODE_IFSTRICTNE:
+	{
+	  SwfdecAbcComparison comp;
+	  i = swfdec_bits_get_s24 (&bits);
+	  val = swfdec_as_stack_pop (context);
+	  comp = swfdec_abc_value_strict_equals (context, swfdec_as_stack_pop (context), val);
+	  if (comp == SWFDEC_ABC_COMPARE_THROWN ||
+	      (comp == SWFDEC_ABC_COMPARE_NOT_EQUAL && !swfdec_abc_interpret_jump (context, &bits, i)))
+	    break;
+	}
+	continue;
+      case SWFDEC_ABC_OPCODE_IFTRUE:
+	i = swfdec_bits_get_s24 (&bits);
+	if (swfdec_as_value_to_boolean (context, swfdec_as_stack_pop (context)) &&
+	    !swfdec_abc_interpret_jump (context, &bits, i))
+	  break;
+	continue;
       case SWFDEC_ABC_OPCODE_INIT_PROPERTY:
 	{
 	  SwfdecAbcTraits *traits;
@@ -1016,6 +1171,15 @@ swfdec_abc_interpret (SwfdecAbcFunction *fun, SwfdecAbcScopeChain *outer_scope)
 	    !swfdec_abc_object_set_variable (context, swfdec_as_stack_pop (context), &mn, val))
 	  break;
 	continue;
+      case SWFDEC_ABC_OPCODE_STRICT_EQUALS:
+	{
+	  SwfdecAbcComparison comp;
+	  val = swfdec_as_stack_peek (context, 2);
+	  comp = swfdec_abc_value_strict_equals (context, val, swfdec_as_stack_pop (context));
+	  g_assert (comp == SWFDEC_ABC_COMPARE_EQUAL || comp == SWFDEC_ABC_COMPARE_NOT_EQUAL);
+	  SWFDEC_AS_VALUE_SET_BOOLEAN (val, comp == SWFDEC_ABC_COMPARE_EQUAL);
+	}
+	continue;
       case SWFDEC_ABC_OPCODE_SWAP:
 	{
 	  SwfdecAsValue tmp = *swfdec_as_stack_peek (context, 1);
@@ -1065,7 +1229,6 @@ swfdec_abc_interpret (SwfdecAbcFunction *fun, SwfdecAbcScopeChain *outer_scope)
       case SWFDEC_ABC_OPCODE_DOUBLE_TO_ATOM:
       case SWFDEC_ABC_OPCODE_DXNS:
       case SWFDEC_ABC_OPCODE_DXNS_LATE:
-      case SWFDEC_ABC_OPCODE_EQUALS:
       case SWFDEC_ABC_OPCODE_ESC_XATTR:
       case SWFDEC_ABC_OPCODE_ESC_XELEM:
       case SWFDEC_ABC_OPCODE_FIND_DEF:
@@ -1076,20 +1239,6 @@ swfdec_abc_interpret (SwfdecAbcFunction *fun, SwfdecAbcScopeChain *outer_scope)
       case SWFDEC_ABC_OPCODE_GREATER_THAN:
       case SWFDEC_ABC_OPCODE_HAS_NEXT:
       case SWFDEC_ABC_OPCODE_HAS_NEXT2:
-      case SWFDEC_ABC_OPCODE_IFEQ:
-      case SWFDEC_ABC_OPCODE_IFFALSE:
-      case SWFDEC_ABC_OPCODE_IFGE:
-      case SWFDEC_ABC_OPCODE_IFGT:
-      case SWFDEC_ABC_OPCODE_IFLE:
-      case SWFDEC_ABC_OPCODE_IFLT:
-      case SWFDEC_ABC_OPCODE_IFNE:
-      case SWFDEC_ABC_OPCODE_IFNLE:
-      case SWFDEC_ABC_OPCODE_IFNLT:
-      case SWFDEC_ABC_OPCODE_IFNGE:
-      case SWFDEC_ABC_OPCODE_IFNGT:
-      case SWFDEC_ABC_OPCODE_IFSTRICTEQ:
-      case SWFDEC_ABC_OPCODE_IFSTRICTNE:
-      case SWFDEC_ABC_OPCODE_IFTRUE:
       case SWFDEC_ABC_OPCODE_IN:
       case SWFDEC_ABC_OPCODE_INC_LOCAL:
       case SWFDEC_ABC_OPCODE_INCLOCAL_I:
@@ -1119,7 +1268,6 @@ swfdec_abc_interpret (SwfdecAbcFunction *fun, SwfdecAbcScopeChain *outer_scope)
       case SWFDEC_ABC_OPCODE_SET_GLOBAL_SLOT:
       case SWFDEC_ABC_OPCODE_SET_SLOT:
       case SWFDEC_ABC_OPCODE_SET_SUPER:
-      case SWFDEC_ABC_OPCODE_STRICT_EQUALS:
       case SWFDEC_ABC_OPCODE_SWEEP:
       case SWFDEC_ABC_OPCODE_THROW:
       case SWFDEC_ABC_OPCODE_TIMESTAMP:
diff --git a/swfdec/swfdec_abc_multiname.c b/swfdec/swfdec_abc_multiname.c
index 346fce6..e7de0ac 100644
--- a/swfdec/swfdec_abc_multiname.c
+++ b/swfdec/swfdec_abc_multiname.c
@@ -30,15 +30,26 @@
 #include "swfdec_debug.h"
 
 void
-swfdec_abc_multiname_init (SwfdecAbcMultiname *multi, const char *name,
-    SwfdecAbcNamespace *ns, SwfdecAbcNsSet *set)
+swfdec_abc_multiname_init (SwfdecAbcMultiname *multi, SwfdecAbcNamespace *ns,
+    const char *name)
 {
   g_return_if_fail (multi != NULL);
-  g_return_if_fail (ns == NULL || set == NULL);
   g_return_if_fail (ns == NULL || ns == SWFDEC_ABC_MULTINAME_ANY || SWFDEC_IS_ABC_NAMESPACE (ns));
 
   multi->name = name;
   multi->ns = ns;
+  multi->nsset = NULL;
+}
+
+void
+swfdec_abc_multiname_init_set (SwfdecAbcMultiname *multi, SwfdecAbcNsSet *set, 
+    const char *name)
+{
+  g_return_if_fail (multi != NULL);
+  g_return_if_fail (set != NULL);
+
+  multi->name = name;
+  multi->ns = NULL;
   multi->nsset = set;
 }
 
diff --git a/swfdec/swfdec_abc_multiname.h b/swfdec/swfdec_abc_multiname.h
index 4ed3186..e2c5bc7 100644
--- a/swfdec/swfdec_abc_multiname.h
+++ b/swfdec/swfdec_abc_multiname.h
@@ -35,9 +35,11 @@ struct _SwfdecAbcMultiname {
 };
 
 void			swfdec_abc_multiname_init		(SwfdecAbcMultiname *		multi,
-								 const char *			name,
 								 SwfdecAbcNamespace *		ns,
-								 SwfdecAbcNsSet *		set);
+								 const char *			name);
+void			swfdec_abc_multiname_init_set		(SwfdecAbcMultiname *		multi,
+								 SwfdecAbcNsSet *		set,
+								 const char *			name);
 void			swfdec_abc_multiname_init_from_string	(SwfdecAbcMultiname *		multi,
 								 SwfdecAsContext *		context,
 								 const char *			string);
diff --git a/swfdec/swfdec_abc_object.c b/swfdec/swfdec_abc_object.c
index 3216505..5147fd8 100644
--- a/swfdec/swfdec_abc_object.c
+++ b/swfdec/swfdec_abc_object.c
@@ -29,7 +29,9 @@
 #include "swfdec_abc_multiname.h"
 #include "swfdec_abc_scope_chain.h"
 #include "swfdec_abc_traits.h"
+#include "swfdec_abc_value.h"
 #include "swfdec_as_context.h"
+#include "swfdec_as_strings.h"
 #include "swfdec_debug.h"
 
 enum {
@@ -420,3 +422,71 @@ swfdec_abc_object_call_variable	(SwfdecAsContext *context, const SwfdecAsValue *
     }
   }
 }
+
+gboolean
+swfdec_abc_object_default_value	(SwfdecAbcObject *object, SwfdecAsValue *default_value)
+{
+  SwfdecAsContext *context;
+  SwfdecAbcMultiname mn;
+  SwfdecAsValue val;
+
+  g_return_val_if_fail (SWFDEC_IS_ABC_OBJECT (object), FALSE);
+  g_return_val_if_fail (default_value != NULL, FALSE);
+
+  context = swfdec_gc_object_get_context (object);
+
+  /* first, call toString - if it returns a primitive, return it */
+  swfdec_abc_multiname_init (&mn, context->public_ns, SWFDEC_AS_STR_valueOf);
+  SWFDEC_AS_VALUE_SET_OBJECT (&val, SWFDEC_AS_OBJECT (object));
+  if (!swfdec_abc_object_call_variable (context, &val, &mn, 0, &val, default_value))
+    return FALSE;
+  if (!SWFDEC_AS_VALUE_IS_OBJECT (default_value))
+    return TRUE;
+
+  /* second, call valueOf - if it returns a primitive, return it */
+  swfdec_abc_multiname_init (&mn, context->public_ns, SWFDEC_AS_STR_toString);
+  SWFDEC_AS_VALUE_SET_OBJECT (&val, SWFDEC_AS_OBJECT (object));
+  if (!swfdec_abc_object_call_variable (context, &val, &mn, 0, &val, default_value))
+    return FALSE;
+  if (!SWFDEC_AS_VALUE_IS_OBJECT (default_value))
+    return TRUE;
+
+  /* Object doesn't want to be a string, complain */
+  swfdec_as_context_throw_abc (context, SWFDEC_ABC_TYPE_TYPE_ERROR, 
+      "Cannot convert %s to primitive.", object->traits->name);
+  SWFDEC_AS_VALUE_SET_UNDEFINED (default_value);
+  return FALSE;
+}
+
+const char *
+swfdec_abc_object_to_string (SwfdecAbcObject *object)
+{
+  SwfdecAsContext *context;
+  SwfdecAbcMultiname mn;
+  SwfdecAsValue val, ret;
+
+  g_return_val_if_fail (SWFDEC_IS_ABC_OBJECT (object), FALSE);
+
+  context = swfdec_gc_object_get_context (object);
+
+  /* first, call toString - if it returns a primitive, return it */
+  swfdec_abc_multiname_init (&mn, context->public_ns, SWFDEC_AS_STR_toString);
+  SWFDEC_AS_VALUE_SET_OBJECT (&val, SWFDEC_AS_OBJECT (object));
+  if (!swfdec_abc_object_call_variable (context, &val, &mn, 0, &val, &ret))
+    return NULL;
+  if (!SWFDEC_AS_VALUE_IS_OBJECT (&ret))
+    return swfdec_abc_value_to_string (context, &ret);
+
+  /* second, call valueOf - if it returns a primitive, return it */
+  swfdec_abc_multiname_init (&mn, context->public_ns, SWFDEC_AS_STR_valueOf);
+  SWFDEC_AS_VALUE_SET_OBJECT (&val, SWFDEC_AS_OBJECT (object));
+  if (!swfdec_abc_object_call_variable (context, &val, &mn, 0, &val, &ret))
+    return NULL;
+  if (!SWFDEC_AS_VALUE_IS_OBJECT (&ret))
+    return swfdec_abc_value_to_string (context, &ret);
+
+  /* Object doesn't want to be a string, complain */
+  swfdec_as_context_throw_abc (context, SWFDEC_ABC_TYPE_TYPE_ERROR, 
+      "Cannot convert %s to primitive.", object->traits->name);
+  return NULL;
+}
diff --git a/swfdec/swfdec_abc_object.h b/swfdec/swfdec_abc_object.h
index 70f81fb..06395c4 100644
--- a/swfdec/swfdec_abc_object.h
+++ b/swfdec/swfdec_abc_object.h
@@ -64,8 +64,7 @@ SwfdecAbcObject *	swfdec_abc_object_new_from_class(SwfdecAbcClass *		classp);
 
 gboolean		swfdec_abc_object_default_value	(SwfdecAbcObject *		object,
 							 SwfdecAsValue *		default_value);
-gboolean		swfdec_abc_object_to_string	(SwfdecAbcObject *		object,
-							 SwfdecAsValue *		string);
+const char *		swfdec_abc_object_to_string	(SwfdecAbcObject *		object);
 gboolean		swfdec_abc_object_call		(SwfdecAbcObject *		object,
 							 guint				argc,
 							 SwfdecAsValue *		argv,
diff --git a/swfdec/swfdec_abc_pool.c b/swfdec/swfdec_abc_pool.c
index dbd9422..176ce41 100644
--- a/swfdec/swfdec_abc_pool.c
+++ b/swfdec/swfdec_abc_pool.c
@@ -335,9 +335,8 @@ swfdec_abc_pool_parse_constants (SwfdecAbcPool *pool, SwfdecBits *bits)
 	  if (nameid >= pool->n_strings)
 	    THROW (pool, "Cpool index %u is out of range %u.", nameid, pool->n_strings);
 	  swfdec_abc_multiname_init (&pool->multinames[i],
-	      nameid == 0 ? SWFDEC_ABC_MULTINAME_ANY : pool->strings[nameid],
 	      nsid == 0 ? SWFDEC_ABC_MULTINAME_ANY : pool->namespaces[nsid],
-	      NULL);
+	      nameid == 0 ? SWFDEC_ABC_MULTINAME_ANY : pool->strings[nameid]);
 	  break;
 	case 0x10:
 	  SWFDEC_FIXME ("implement attributes");
@@ -346,14 +345,14 @@ swfdec_abc_pool_parse_constants (SwfdecAbcPool *pool, SwfdecBits *bits)
 	  if (nameid >= pool->n_strings)
 	    THROW (pool, "Cpool index %u is out of range %u.", nameid, pool->n_strings);
 	  swfdec_abc_multiname_init (&pool->multinames[i],
-	      nameid == 0 ? SWFDEC_ABC_MULTINAME_ANY : pool->strings[nameid],
-	      NULL, NULL);
+	      NULL,
+	      nameid == 0 ? SWFDEC_ABC_MULTINAME_ANY : pool->strings[nameid]);
 	  break;
 	case 0x12:
 	  SWFDEC_FIXME ("implement attributes");
 	case 0x11:
 	  swfdec_abc_multiname_init (&pool->multinames[i],
-	      NULL, NULL, NULL);
+	      NULL, NULL);
 	  break;
 	case 0x0E:
 	  SWFDEC_FIXME ("implement attributes");
@@ -364,9 +363,8 @@ swfdec_abc_pool_parse_constants (SwfdecAbcPool *pool, SwfdecBits *bits)
 	  READ_U30 (nsid, bits);
 	  if (nsid >= pool->n_nssets)
 	    THROW (pool, "Cpool index %u is out of range %u.", nsid, pool->n_nssets);
-	  swfdec_abc_multiname_init (&pool->multinames[i],
-	      nameid == 0 ? SWFDEC_ABC_MULTINAME_ANY : pool->strings[nameid],
-	      NULL, pool->nssets[nsid]);
+	  swfdec_abc_multiname_init_set (&pool->multinames[i], pool->nssets[nsid],
+	      nameid == 0 ? SWFDEC_ABC_MULTINAME_ANY : pool->strings[nameid]);
 	  break;
 	case 0x1C:
 	  SWFDEC_FIXME ("implement attributes");
@@ -374,8 +372,7 @@ swfdec_abc_pool_parse_constants (SwfdecAbcPool *pool, SwfdecBits *bits)
 	  READ_U30 (nsid, bits);
 	  if (nsid >= pool->n_nssets)
 	    THROW (pool, "Cpool index %u is out of range %u.", nsid, pool->n_nssets);
-	  swfdec_abc_multiname_init (&pool->multinames[i],
-	      NULL, NULL, pool->nssets[nsid]);
+	  swfdec_abc_multiname_init_set (&pool->multinames[i], pool->nssets[nsid], NULL);
 	  break;
 	default:
 	  THROW (pool, "Cpool entry %u is wrong type.", i);
diff --git a/swfdec/swfdec_abc_value.c b/swfdec/swfdec_abc_value.c
index dc58fc6..e36c4dc 100644
--- a/swfdec/swfdec_abc_value.c
+++ b/swfdec/swfdec_abc_value.c
@@ -119,7 +119,7 @@ swfdec_abc_value_to_number (SwfdecAsContext *context, const SwfdecAsValue *value
 gboolean
 swfdec_abc_value_to_primitive (SwfdecAsValue *dest, const SwfdecAsValue *src)
 {
-  g_return_val_if_fail (SWFDEC_IS_AS_VALUE (dest), FALSE);
+  g_return_val_if_fail (dest != NULL, FALSE);
   g_return_val_if_fail (SWFDEC_IS_AS_VALUE (src), FALSE);
 
   if (SWFDEC_AS_VALUE_IS_OBJECT (src)) {
@@ -149,13 +149,7 @@ swfdec_abc_value_to_string (SwfdecAsContext *context, const SwfdecAsValue *value
     case SWFDEC_AS_TYPE_STRING:
       return SWFDEC_AS_VALUE_GET_STRING (value);
     case SWFDEC_AS_TYPE_OBJECT:
-      {
-	SwfdecAsValue tmp;
-	if (!swfdec_abc_object_to_string (
-	      SWFDEC_ABC_OBJECT (SWFDEC_AS_VALUE_GET_OBJECT (value)), &tmp))
-	  return SWFDEC_AS_STR_EMPTY;
-	return swfdec_abc_value_to_string (context, &tmp);
-      }
+      return swfdec_abc_object_to_string (SWFDEC_ABC_OBJECT (SWFDEC_AS_VALUE_GET_OBJECT (value)));
     case SWFDEC_AS_TYPE_NAMESPACE:
       return SWFDEC_AS_VALUE_GET_NAMESPACE (value)->uri;
     case SWFDEC_AS_TYPE_INT:
@@ -222,6 +216,8 @@ swfdec_abc_value_compare (SwfdecAsContext *context, const SwfdecAsValue *lval,
       !swfdec_abc_value_to_primitive (&rtmp, rval))
     return SWFDEC_ABC_COMPARE_THROWN;
 
+  /* FIXME: need special code for XMLList here */
+
   if (SWFDEC_AS_VALUE_IS_STRING (&ltmp) && SWFDEC_AS_VALUE_IS_STRING (&rtmp)) {
     int comp = strcmp (SWFDEC_AS_VALUE_GET_STRING (&ltmp), 
 	SWFDEC_AS_VALUE_GET_STRING (&rtmp));
@@ -238,3 +234,135 @@ swfdec_abc_value_compare (SwfdecAsContext *context, const SwfdecAsValue *lval,
   }
 }
 
+SwfdecAbcComparison
+swfdec_abc_value_equals (SwfdecAsContext *context, const SwfdecAsValue *lval,
+    const SwfdecAsValue *rval)
+{
+  SwfdecAsValue tmp;
+  SwfdecAsValueType ltype, rtype;
+
+  g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), SWFDEC_ABC_COMPARE_UNDEFINED);
+  g_return_val_if_fail (lval != NULL, SWFDEC_ABC_COMPARE_UNDEFINED);
+  g_return_val_if_fail (rval != NULL, SWFDEC_ABC_COMPARE_UNDEFINED);
+
+  ltype = SWFDEC_AS_VALUE_GET_TYPE (lval);
+  rtype = SWFDEC_AS_VALUE_GET_TYPE (rval);
+
+  /* FIXME: need special code for XMLList here */
+
+  if (ltype == rtype) {
+    switch (ltype) {
+      case SWFDEC_AS_TYPE_UNDEFINED:
+      case SWFDEC_AS_TYPE_NULL:
+	return SWFDEC_ABC_COMPARE_EQUAL;
+      case SWFDEC_AS_TYPE_BOOLEAN:
+	return SWFDEC_AS_VALUE_GET_BOOLEAN (lval) == SWFDEC_AS_VALUE_GET_BOOLEAN (rval) ?
+	    SWFDEC_ABC_COMPARE_EQUAL : SWFDEC_ABC_COMPARE_NOT_EQUAL;
+      case SWFDEC_AS_TYPE_NUMBER:
+	return SWFDEC_AS_VALUE_GET_NUMBER (lval) == SWFDEC_AS_VALUE_GET_NUMBER (rval) ? 
+	    SWFDEC_ABC_COMPARE_EQUAL : SWFDEC_ABC_COMPARE_NOT_EQUAL;
+      case SWFDEC_AS_TYPE_STRING:
+	return SWFDEC_AS_VALUE_GET_STRING (lval) == SWFDEC_AS_VALUE_GET_STRING (rval) ? 
+	    SWFDEC_ABC_COMPARE_EQUAL : SWFDEC_ABC_COMPARE_NOT_EQUAL;
+      case SWFDEC_AS_TYPE_OBJECT:
+	/* FIXME: Need special code for QName and XMLList here */
+	return SWFDEC_AS_VALUE_GET_OBJECT (lval) == SWFDEC_AS_VALUE_GET_OBJECT (rval) ? 
+	    SWFDEC_ABC_COMPARE_EQUAL : SWFDEC_ABC_COMPARE_NOT_EQUAL;
+      case SWFDEC_AS_TYPE_NAMESPACE:
+	return swfdec_abc_namespace_equal (SWFDEC_AS_VALUE_GET_NAMESPACE (lval),
+	    SWFDEC_AS_VALUE_GET_NAMESPACE (rval)) ? 
+	    SWFDEC_ABC_COMPARE_EQUAL : SWFDEC_ABC_COMPARE_NOT_EQUAL;
+      case SWFDEC_AS_TYPE_INT:
+      default:
+	g_assert_not_reached ();
+	return SWFDEC_ABC_COMPARE_UNDEFINED;
+    }
+  }
+
+  if ((ltype == SWFDEC_AS_TYPE_UNDEFINED && rtype == SWFDEC_AS_TYPE_NULL) ||
+      (ltype == SWFDEC_AS_TYPE_NULL && rtype == SWFDEC_AS_TYPE_UNDEFINED))
+    return SWFDEC_ABC_COMPARE_EQUAL;
+
+  if (ltype == SWFDEC_AS_TYPE_NUMBER && rtype == SWFDEC_AS_TYPE_STRING) {
+    SWFDEC_AS_VALUE_SET_NUMBER (&tmp, swfdec_abc_value_to_number (context, rval));
+    return swfdec_abc_value_equals (context, lval, &tmp);
+  }
+  if (ltype == SWFDEC_AS_TYPE_STRING && rtype == SWFDEC_AS_TYPE_NUMBER) {
+    SWFDEC_AS_VALUE_SET_NUMBER (&tmp, swfdec_abc_value_to_number (context, lval));
+    return swfdec_abc_value_equals (context, &tmp, rval);
+  }
+
+  /* FIXME: need special code for XMLList here */
+
+  if (ltype == SWFDEC_AS_TYPE_BOOLEAN) {
+    SWFDEC_AS_VALUE_SET_NUMBER (&tmp, swfdec_abc_value_to_number (context, lval));
+    return swfdec_abc_value_equals (context, &tmp, rval);
+  }
+  if (rtype == SWFDEC_AS_TYPE_BOOLEAN) {
+    SWFDEC_AS_VALUE_SET_NUMBER (&tmp, swfdec_abc_value_to_number (context, rval));
+    return swfdec_abc_value_equals (context, lval, &tmp);
+  }
+
+  if (rtype == SWFDEC_AS_TYPE_OBJECT && 
+      (ltype == SWFDEC_AS_TYPE_NUMBER || ltype == SWFDEC_AS_TYPE_STRING)) {
+    if (!swfdec_abc_object_default_value (SWFDEC_ABC_OBJECT (SWFDEC_AS_VALUE_GET_OBJECT (rval)), &tmp))
+      return SWFDEC_ABC_COMPARE_THROWN;
+    SWFDEC_AS_VALUE_SET_NUMBER (&tmp, swfdec_abc_value_to_number (context, rval));
+    return swfdec_abc_value_equals (context, lval, &tmp);
+  }
+  if (ltype == SWFDEC_AS_TYPE_OBJECT && 
+      (rtype == SWFDEC_AS_TYPE_NUMBER || rtype == SWFDEC_AS_TYPE_STRING)) {
+    if (!swfdec_abc_object_default_value (SWFDEC_ABC_OBJECT (SWFDEC_AS_VALUE_GET_OBJECT (lval)), &tmp))
+      return SWFDEC_ABC_COMPARE_THROWN;
+    SWFDEC_AS_VALUE_SET_NUMBER (&tmp, swfdec_abc_value_to_number (context, lval));
+    return swfdec_abc_value_equals (context, &tmp, rval);
+  }
+  
+  return SWFDEC_ABC_COMPARE_NOT_EQUAL;
+}
+
+SwfdecAbcComparison
+swfdec_abc_value_strict_equals (SwfdecAsContext *context, const SwfdecAsValue *lval,
+    const SwfdecAsValue *rval)
+{
+  SwfdecAsValueType ltype, rtype;
+
+  g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), SWFDEC_ABC_COMPARE_UNDEFINED);
+  g_return_val_if_fail (lval != NULL, SWFDEC_ABC_COMPARE_UNDEFINED);
+  g_return_val_if_fail (rval != NULL, SWFDEC_ABC_COMPARE_UNDEFINED);
+
+  ltype = SWFDEC_AS_VALUE_GET_TYPE (lval);
+  rtype = SWFDEC_AS_VALUE_GET_TYPE (rval);
+
+  /* FIXME: need special code for XMLList here */
+
+  if (ltype == rtype) {
+    switch (ltype) {
+      case SWFDEC_AS_TYPE_UNDEFINED:
+      case SWFDEC_AS_TYPE_NULL:
+	return SWFDEC_ABC_COMPARE_EQUAL;
+      case SWFDEC_AS_TYPE_BOOLEAN:
+	return SWFDEC_AS_VALUE_GET_BOOLEAN (lval) == SWFDEC_AS_VALUE_GET_BOOLEAN (rval) ?
+	    SWFDEC_ABC_COMPARE_EQUAL : SWFDEC_ABC_COMPARE_NOT_EQUAL;
+      case SWFDEC_AS_TYPE_NUMBER:
+	return SWFDEC_AS_VALUE_GET_NUMBER (lval) == SWFDEC_AS_VALUE_GET_NUMBER (rval) ? 
+	    SWFDEC_ABC_COMPARE_EQUAL : SWFDEC_ABC_COMPARE_NOT_EQUAL;
+      case SWFDEC_AS_TYPE_STRING:
+	return SWFDEC_AS_VALUE_GET_STRING (lval) == SWFDEC_AS_VALUE_GET_STRING (rval) ? 
+	    SWFDEC_ABC_COMPARE_EQUAL : SWFDEC_ABC_COMPARE_NOT_EQUAL;
+      case SWFDEC_AS_TYPE_OBJECT:
+	/* FIXME: Need special code for XMLList here */
+	return SWFDEC_AS_VALUE_GET_OBJECT (lval) == SWFDEC_AS_VALUE_GET_OBJECT (rval) ? 
+	    SWFDEC_ABC_COMPARE_EQUAL : SWFDEC_ABC_COMPARE_NOT_EQUAL;
+      case SWFDEC_AS_TYPE_NAMESPACE:
+	return SWFDEC_AS_VALUE_GET_NAMESPACE (lval) == SWFDEC_AS_VALUE_GET_NAMESPACE (rval) ? 
+	    SWFDEC_ABC_COMPARE_EQUAL : SWFDEC_ABC_COMPARE_NOT_EQUAL;
+      case SWFDEC_AS_TYPE_INT:
+      default:
+	g_assert_not_reached ();
+	return SWFDEC_ABC_COMPARE_UNDEFINED;
+    }
+  }
+  return SWFDEC_ABC_COMPARE_NOT_EQUAL;
+}
+
diff --git a/swfdec/swfdec_abc_value.h b/swfdec/swfdec_abc_value.h
index dfccd87..f6b9ee1 100644
--- a/swfdec/swfdec_abc_value.h
+++ b/swfdec/swfdec_abc_value.h
@@ -28,10 +28,11 @@ G_BEGIN_DECLS
 
 typedef enum {
   SWFDEC_ABC_COMPARE_UNDEFINED,
+  SWFDEC_ABC_COMPARE_NOT_EQUAL = SWFDEC_ABC_COMPARE_UNDEFINED,
   SWFDEC_ABC_COMPARE_THROWN,
   SWFDEC_ABC_COMPARE_LOWER,
   SWFDEC_ABC_COMPARE_EQUAL,
-  SWFDEC_ABC_COMPARE_GREATER
+  SWFDEC_ABC_COMPARE_GREATER,
 } SwfdecAbcComparison;
 
 gboolean		swfdec_abc_value_to_boolean	(SwfdecAsContext *	context,
@@ -51,6 +52,12 @@ const char *		swfdec_abc_value_get_type_name	(const SwfdecAsValue *	value);
 SwfdecAbcComparison	swfdec_abc_value_compare	(SwfdecAsContext *	context,
 							 const SwfdecAsValue *	lval,
 							 const SwfdecAsValue *	rval);
+SwfdecAbcComparison	swfdec_abc_value_equals		(SwfdecAsContext *	context,
+							 const SwfdecAsValue *	lval,
+							 const SwfdecAsValue *	rval);
+SwfdecAbcComparison	swfdec_abc_value_strict_equals	(SwfdecAsContext *	context,
+							 const SwfdecAsValue *	lval,
+							 const SwfdecAsValue *	rval);
 
 
 G_END_DECLS
commit 99fc769d0a73d48f7190e316d426dec1488cd1ac
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Aug 25 13:15:30 2008 +0200

    add a seperate header for ABC functions on SwfdecAsValue

diff --git a/swfdec/Makefile.am b/swfdec/Makefile.am
index 6844454..21e5355 100644
--- a/swfdec/Makefile.am
+++ b/swfdec/Makefile.am
@@ -23,6 +23,7 @@ libswfdec_source_files = \
 	swfdec_abc_scope_chain.c \
 	swfdec_abc_script.c \
 	swfdec_abc_traits.c \
+	swfdec_abc_value.c \
 	swfdec_access.c \
 	swfdec_accessibility.c \
 	swfdec_actor.c \
@@ -257,6 +258,7 @@ noinst_HEADERS = \
 	swfdec_abc_script.h \
 	swfdec_abc_traits.h \
 	swfdec_abc_types.h \
+	swfdec_abc_value.h \
 	swfdec_access.h \
 	swfdec_actor.h \
 	swfdec_amf.h \
diff --git a/swfdec/swfdec_abc_function.c b/swfdec/swfdec_abc_function.c
index d0e58d6..b057a6b 100644
--- a/swfdec/swfdec_abc_function.c
+++ b/swfdec/swfdec_abc_function.c
@@ -28,6 +28,7 @@
 #include "swfdec_abc_internal.h"
 #include "swfdec_abc_interpret.h"
 #include "swfdec_abc_traits.h"
+#include "swfdec_abc_value.h"
 #include "swfdec_as_context.h"
 #include "swfdec_as_frame_internal.h"
 #include "swfdec_as_strings.h" /* swfdec_abc_function_describe */
@@ -431,7 +432,7 @@ swfdec_abc_function_call (SwfdecAbcFunction *fun, SwfdecAbcScopeChain *scope,
     if (!swfdec_abc_traits_coerce (fun->args[i].traits, &argv[i])) {
       swfdec_as_context_throw_abc (context, SWFDEC_ABC_TYPE_TYPE_ERROR, 
 	"Type Coercion failed: cannot convert %s to %s.",
-	swfdec_as_value_get_type_name (&argv[i]), fun->args[i].traits->name);
+	swfdec_abc_value_get_type_name (&argv[i]), fun->args[i].traits->name);
       return FALSE;
     }
   }
diff --git a/swfdec/swfdec_abc_interpret.c b/swfdec/swfdec_abc_interpret.c
index 7413056..2fb94f5 100644
--- a/swfdec/swfdec_abc_interpret.c
+++ b/swfdec/swfdec_abc_interpret.c
@@ -32,6 +32,7 @@
 #include "swfdec_abc_scope_chain.h"
 #include "swfdec_abc_script.h"
 #include "swfdec_abc_traits.h"
+#include "swfdec_abc_value.h"
 #include "swfdec_as_context.h"
 #include "swfdec_as_frame_internal.h"
 #include "swfdec_as_internal.h"
@@ -246,7 +247,7 @@ swfdec_abc_interpret_resolve_multiname (SwfdecAsContext *context,
 	SWFDEC_ABC_OBJECT (SWFDEC_AS_VALUE_GET_OBJECT (val))->traits == SWFDEC_ABC_QNAME_TRAITS (context)) {
       SWFDEC_FIXME ("implement Qname multiname resolution");
     }
-    target->name = swfdec_as_value_to_string (context, val);
+    target->name = swfdec_abc_value_to_string (context, val);
   } else {
     target->name = source->name;
   }
@@ -324,7 +325,7 @@ swfdec_as_value_has_property (SwfdecAsContext *context, const SwfdecAsValue *val
   if (SWFDEC_AS_VALUE_IS_OBJECT (value)) {
     o = SWFDEC_AS_VALUE_GET_OBJECT (value);
   } else {
-    traits = swfdec_as_value_to_traits (context, value);
+    traits = swfdec_abc_value_to_traits (context, value);
     if (swfdec_abc_traits_find_trait_multi (traits, mn))
       return TRUE;
     o = swfdec_as_value_to_prototype (context, value);
@@ -626,8 +627,8 @@ swfdec_abc_interpret (SwfdecAbcFunction *fun, SwfdecAbcScopeChain *outer_scope)
 	  SwfdecAbcTraits *ltraits, *rtraits;
 	  rhs = swfdec_as_stack_pop (context);
 	  lhs = swfdec_as_stack_peek (context, 1);
-	  ltraits = swfdec_as_value_to_traits (context, lhs);
-	  rtraits = swfdec_as_value_to_traits (context, rhs);
+	  ltraits = swfdec_abc_value_to_traits (context, lhs);
+	  rtraits = swfdec_abc_value_to_traits (context, rhs);
 	  if (SWFDEC_AS_VALUE_IS_NUMBER (lhs) && SWFDEC_AS_VALUE_IS_NUMBER (rhs)) {
 	    SWFDEC_AS_VALUE_SET_NUMBER (lhs,
 		SWFDEC_AS_VALUE_GET_NUMBER (lhs) + SWFDEC_AS_VALUE_GET_NUMBER (rhs));
@@ -636,8 +637,8 @@ swfdec_abc_interpret (SwfdecAbcFunction *fun, SwfdecAbcScopeChain *outer_scope)
 	      (ltraits == SWFDEC_ABC_DATE_TRAITS (context)) ||
 	      (rtraits == SWFDEC_ABC_DATE_TRAITS (context))) {
 	    SWFDEC_AS_VALUE_SET_STRING (lhs, swfdec_as_str_concat (context, 
-		swfdec_as_value_to_string (context, lhs), 
-		swfdec_as_value_to_string (context, rhs)));
+		swfdec_abc_value_to_string (context, lhs), 
+		swfdec_abc_value_to_string (context, rhs)));
 	    continue;
 	  }
 	  if ((ltraits == SWFDEC_ABC_XML_TRAITS (context) || ltraits == SWFDEC_ABC_XML_LIST_TRAITS (context)) &&
@@ -650,18 +651,18 @@ swfdec_abc_interpret (SwfdecAbcFunction *fun, SwfdecAbcScopeChain *outer_scope)
 	  swfdec_as_value_to_primitive (&rtmp);
 	  if (SWFDEC_AS_VALUE_IS_STRING (&ltmp) || SWFDEC_AS_VALUE_IS_STRING (&rtmp)) {
 	    SWFDEC_AS_VALUE_SET_STRING (lhs, swfdec_as_str_concat (context, 
-		swfdec_as_value_to_string (context, &ltmp), 
-		swfdec_as_value_to_string (context, &rtmp)));
+		swfdec_abc_value_to_string (context, &ltmp), 
+		swfdec_abc_value_to_string (context, &rtmp)));
 	  } else {
 	    SWFDEC_AS_VALUE_SET_NUMBER (lhs,
-		swfdec_as_value_to_number (context, lhs) + swfdec_as_value_to_number (context, rhs));
+		swfdec_abc_value_to_number (context, lhs) + swfdec_abc_value_to_number (context, rhs));
 	  }
 	}
 	continue;
       case SWFDEC_ABC_OPCODE_ADD_I:
 	val = swfdec_as_stack_peek (context, 2);
-	SWFDEC_AS_VALUE_SET_INT (val, swfdec_as_value_to_integer (context, val) +
-	      swfdec_as_value_to_integer (context, swfdec_as_stack_pop (context)));
+	SWFDEC_AS_VALUE_SET_INT (val, swfdec_abc_value_to_integer (context, val) +
+	      swfdec_abc_value_to_integer (context, swfdec_as_stack_pop (context)));
 	break;
       case SWFDEC_ABC_OPCODE_CALL_PROPERTY:
       case SWFDEC_ABC_OPCODE_CALL_PROP_LEX:
@@ -696,7 +697,7 @@ swfdec_abc_interpret (SwfdecAbcFunction *fun, SwfdecAbcScopeChain *outer_scope)
 	  if (!swfdec_abc_traits_coerce (traits, val)) {
 	    swfdec_as_context_throw_abc (context, SWFDEC_ABC_TYPE_REFERENCE_ERROR,
 		"Type Coercion failed: cannot convert %s to %s.", 
-		swfdec_as_value_get_type_name (val), traits->name);
+		swfdec_abc_value_get_type_name (val), traits->name);
 	    break;
 	  }
 	}
@@ -714,7 +715,7 @@ swfdec_abc_interpret (SwfdecAbcFunction *fun, SwfdecAbcScopeChain *outer_scope)
 	  SWFDEC_AS_VALUE_SET_NULL (val);
 	} else if (!SWFDEC_AS_VALUE_IS_NULL (val)) {
 	  SWFDEC_AS_VALUE_SET_STRING (val,
-	      swfdec_as_value_to_string (context, val));
+	      swfdec_abc_value_to_string (context, val));
 	}
 	/* else NULL stays the same */
 	continue;
@@ -739,8 +740,8 @@ swfdec_abc_interpret (SwfdecAbcFunction *fun, SwfdecAbcScopeChain *outer_scope)
 	continue;
       case SWFDEC_ABC_OPCODE_DIVIDE:
 	val = swfdec_as_stack_peek (context, 1);
-	SWFDEC_AS_VALUE_SET_NUMBER (val, swfdec_as_value_to_number (context, val) 
-	    / swfdec_as_value_to_number (context, swfdec_as_stack_pop (context)));
+	SWFDEC_AS_VALUE_SET_NUMBER (val, swfdec_abc_value_to_number (context, val) 
+	    / swfdec_abc_value_to_number (context, swfdec_as_stack_pop (context)));
 	continue;
       case SWFDEC_ABC_OPCODE_DUP:
 	val = swfdec_as_stack_peek (context, 1);
@@ -827,7 +828,7 @@ swfdec_abc_interpret (SwfdecAbcFunction *fun, SwfdecAbcScopeChain *outer_scope)
 	  if (!swfdec_abc_interpret_resolve_multiname (context, &mn, &pool->multinames[i]))
 	    break;
 	  object = swfdec_as_stack_pop (context);
-	  traits = swfdec_as_value_to_traits (context, object);
+	  traits = swfdec_abc_value_to_traits (context, object);
 	  /* FIXME: do we capture init vs set right? */
 	  if (fun == traits->construct) {
 	    if (!swfdec_abc_object_init_variable (context, object, &mn, val))
@@ -850,26 +851,26 @@ swfdec_abc_interpret (SwfdecAbcFunction *fun, SwfdecAbcScopeChain *outer_scope)
       case SWFDEC_ABC_OPCODE_MODULO:
 	val = swfdec_as_stack_peek (context, 2);
 	SWFDEC_AS_VALUE_SET_NUMBER (val, fmod (
-	      swfdec_as_value_to_number (context, val),
-	      swfdec_as_value_to_number (context, swfdec_as_stack_pop (context))));
+	      swfdec_abc_value_to_number (context, val),
+	      swfdec_abc_value_to_number (context, swfdec_as_stack_pop (context))));
 	break;
       case SWFDEC_ABC_OPCODE_MULTIPLY:
 	val = swfdec_as_stack_peek (context, 2);
-	SWFDEC_AS_VALUE_SET_NUMBER (val, swfdec_as_value_to_number (context, val) *
-	      swfdec_as_value_to_number (context, swfdec_as_stack_pop (context)));
+	SWFDEC_AS_VALUE_SET_NUMBER (val, swfdec_abc_value_to_number (context, val) *
+	      swfdec_abc_value_to_number (context, swfdec_as_stack_pop (context)));
 	break;
       case SWFDEC_ABC_OPCODE_MULTIPLY_I:
 	val = swfdec_as_stack_peek (context, 2);
-	SWFDEC_AS_VALUE_SET_INT (val, swfdec_as_value_to_integer (context, val) *
-	      swfdec_as_value_to_integer (context, swfdec_as_stack_pop (context)));
+	SWFDEC_AS_VALUE_SET_INT (val, swfdec_abc_value_to_integer (context, val) *
+	      swfdec_abc_value_to_integer (context, swfdec_as_stack_pop (context)));
 	break;
       case SWFDEC_ABC_OPCODE_NEGATE:
 	val = swfdec_as_stack_peek (context, 1);
-	SWFDEC_AS_VALUE_SET_NUMBER (val, swfdec_as_value_to_number (context, val));
+	SWFDEC_AS_VALUE_SET_NUMBER (val, swfdec_abc_value_to_number (context, val));
 	break;
       case SWFDEC_ABC_OPCODE_NEGATE_I:
 	val = swfdec_as_stack_peek (context, 1);
-	SWFDEC_AS_VALUE_SET_INT (val, swfdec_as_value_to_integer (context, val));
+	SWFDEC_AS_VALUE_SET_INT (val, swfdec_abc_value_to_integer (context, val));
 	break;
       case SWFDEC_ABC_OPCODE_NEW_CLASS:
 	{
@@ -880,7 +881,7 @@ swfdec_abc_interpret (SwfdecAbcFunction *fun, SwfdecAbcScopeChain *outer_scope)
 	  if (!swfdec_abc_traits_coerce (SWFDEC_ABC_CLASS_TRAITS (context), val)) {
 	    swfdec_as_context_throw_abc (context, SWFDEC_ABC_TYPE_REFERENCE_ERROR,
 		"Type Coercion failed: cannot convert %s to %s.", 
-		swfdec_as_value_get_type_name (val), "Class");
+		swfdec_abc_value_get_type_name (val), "Class");
 	    break;
 	  }
 	  chain = swfdec_abc_scope_chain_new (context, outer_scope, 
@@ -960,13 +961,13 @@ swfdec_abc_interpret (SwfdecAbcFunction *fun, SwfdecAbcScopeChain *outer_scope)
 	continue;
       case SWFDEC_ABC_OPCODE_SUBTRACT:
 	val = swfdec_as_stack_peek (context, 2);
-	SWFDEC_AS_VALUE_SET_NUMBER (val, swfdec_as_value_to_number (context, val) -
-	      swfdec_as_value_to_number (context, swfdec_as_stack_pop (context)));
+	SWFDEC_AS_VALUE_SET_NUMBER (val, swfdec_abc_value_to_number (context, val) -
+	      swfdec_abc_value_to_number (context, swfdec_as_stack_pop (context)));
 	break;
       case SWFDEC_ABC_OPCODE_SUBTRACT_I:
 	val = swfdec_as_stack_peek (context, 2);
-	SWFDEC_AS_VALUE_SET_INT (val, swfdec_as_value_to_integer (context, val) -
-	      swfdec_as_value_to_integer (context, swfdec_as_stack_pop (context)));
+	SWFDEC_AS_VALUE_SET_INT (val, swfdec_abc_value_to_integer (context, val) -
+	      swfdec_abc_value_to_integer (context, swfdec_as_stack_pop (context)));
 	break;
       case SWFDEC_ABC_OPCODE_PUSH_TRUE:
 	SWFDEC_AS_VALUE_SET_BOOLEAN (swfdec_as_stack_push (context), TRUE);
diff --git a/swfdec/swfdec_abc_object.c b/swfdec/swfdec_abc_object.c
index 9e58519..3216505 100644
--- a/swfdec/swfdec_abc_object.c
+++ b/swfdec/swfdec_abc_object.c
@@ -216,7 +216,7 @@ swfdec_abc_object_get_variable (SwfdecAsContext *context, const SwfdecAsValue *o
   g_return_val_if_fail (mn != NULL, FALSE);
   g_return_val_if_fail (value != NULL, FALSE);
 
-  traits = swfdec_as_value_to_traits (context, object);
+  traits = swfdec_abc_value_to_traits (context, object);
   trait = swfdec_abc_traits_find_trait_multi (traits, mn);
   if (!trait) {
     if (!SWFDEC_AS_VALUE_IS_OBJECT (object) || traits->sealed ||
@@ -285,7 +285,7 @@ swfdec_abc_object_set_variable_full (SwfdecAsContext *context, const SwfdecAsVal
   SwfdecAbcTraits *traits;
   const SwfdecAbcTrait *trait;
 
-  traits = swfdec_as_value_to_traits (context, object);
+  traits = swfdec_abc_value_to_traits (context, object);
   trait = swfdec_abc_traits_find_trait_multi (traits, mn);
   if (trait == NULL) {
     if (!SWFDEC_AS_VALUE_IS_OBJECT (object) || traits->sealed ||
@@ -389,7 +389,7 @@ swfdec_abc_object_call_variable	(SwfdecAsContext *context, const SwfdecAsValue *
 	"%s is not a function.", mn->name);
     return FALSE;
   }
-  traits = swfdec_as_value_to_traits (context, object);
+  traits = swfdec_abc_value_to_traits (context, object);
   trait = swfdec_abc_traits_find_trait_multi (traits, mn);
   if (trait == SWFDEC_ABC_TRAIT_AMBIGUOUS) {
     swfdec_as_context_throw_abc (context, SWFDEC_ABC_TYPE_REFERENCE_ERROR,
diff --git a/swfdec/swfdec_abc_object.h b/swfdec/swfdec_abc_object.h
index 018a756..70f81fb 100644
--- a/swfdec/swfdec_abc_object.h
+++ b/swfdec/swfdec_abc_object.h
@@ -62,6 +62,10 @@ SwfdecAbcObject *	swfdec_abc_object_new		(SwfdecAbcTraits *		traits,
 							 SwfdecAbcScopeChain *		scopes);
 SwfdecAbcObject *	swfdec_abc_object_new_from_class(SwfdecAbcClass *		classp);
 
+gboolean		swfdec_abc_object_default_value	(SwfdecAbcObject *		object,
+							 SwfdecAsValue *		default_value);
+gboolean		swfdec_abc_object_to_string	(SwfdecAbcObject *		object,
+							 SwfdecAsValue *		string);
 gboolean		swfdec_abc_object_call		(SwfdecAbcObject *		object,
 							 guint				argc,
 							 SwfdecAsValue *		argv,
diff --git a/swfdec/swfdec_abc_traits.c b/swfdec/swfdec_abc_traits.c
index 5585108..c924ad6 100644
--- a/swfdec/swfdec_abc_traits.c
+++ b/swfdec/swfdec_abc_traits.c
@@ -32,6 +32,7 @@
 #include "swfdec_abc_multiname.h"
 #include "swfdec_abc_namespace.h"
 #include "swfdec_abc_object.h"
+#include "swfdec_abc_value.h"
 #include "swfdec_as_context.h"
 #include "swfdec_as_strings.h"
 #include "swfdec_debug.h"
@@ -335,7 +336,7 @@ swfdec_abc_traits_is_traits (SwfdecAbcTraits *traits, SwfdecAbcTraits *parent)
 }
 
 SwfdecAbcTraits *
-swfdec_as_value_to_traits (SwfdecAsContext *context, const SwfdecAsValue *value)
+swfdec_abc_value_to_traits (SwfdecAsContext *context, const SwfdecAsValue *value)
 {
   g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), NULL);
   g_return_val_if_fail (value != NULL, NULL);
@@ -371,7 +372,7 @@ swfdec_as_value_to_traits (SwfdecAsContext *context, const SwfdecAsValue *value)
 }
 
 gboolean
-swfdec_as_value_is_traits (const SwfdecAsValue *value, SwfdecAbcTraits *traits)
+swfdec_abc_value_is_traits (const SwfdecAsValue *value, SwfdecAbcTraits *traits)
 {
   SwfdecAsContext *context;
   SwfdecAbcTraits *vtraits;
@@ -380,7 +381,7 @@ swfdec_as_value_is_traits (const SwfdecAsValue *value, SwfdecAbcTraits *traits)
   g_return_val_if_fail (SWFDEC_IS_ABC_TRAITS (traits), FALSE);
 
   context = swfdec_gc_object_get_context (traits);
-  vtraits = swfdec_as_value_to_traits (context, value);
+  vtraits = swfdec_abc_value_to_traits (context, value);
   return swfdec_abc_traits_is_traits (vtraits, traits);
 }
 
@@ -396,30 +397,30 @@ swfdec_abc_traits_coerce (SwfdecAbcTraits *traits, SwfdecAsValue *val)
 
   if (traits == SWFDEC_ABC_BOOLEAN_TRAITS (context)) {
     SWFDEC_AS_VALUE_SET_BOOLEAN (val,
-	swfdec_as_value_to_boolean (context, val));
+	swfdec_abc_value_to_boolean (context, val));
     return TRUE;
   } else if (traits == SWFDEC_ABC_NUMBER_TRAITS (context)) {
     SWFDEC_AS_VALUE_SET_NUMBER (val,
-	swfdec_as_value_to_number (context, val));
+	swfdec_abc_value_to_number (context, val));
     return TRUE;
   } else if (traits == SWFDEC_ABC_INT_TRAITS (context)) {
     SWFDEC_AS_VALUE_SET_INT (val,
-	swfdec_as_value_to_integer (context, val));
+	swfdec_abc_value_to_integer (context, val));
     return TRUE;
   } else if (traits == SWFDEC_ABC_UINT_TRAITS (context)) {
     SWFDEC_AS_VALUE_SET_NUMBER (val,
-	(guint) swfdec_as_value_to_integer (context, val));
+	(guint) swfdec_abc_value_to_integer (context, val));
     return TRUE;
   } else if (traits == SWFDEC_ABC_NUMBER_TRAITS (context)) {
     SWFDEC_AS_VALUE_SET_NUMBER (val,
-	(guint) swfdec_as_value_to_integer (context, val));
+	(guint) swfdec_abc_value_to_integer (context, val));
     return TRUE;
   } else if (traits == SWFDEC_ABC_STRING_TRAITS (context)) {
     if (SWFDEC_AS_VALUE_IS_UNDEFINED (val) || SWFDEC_AS_VALUE_IS_NULL (val)) {
       SWFDEC_AS_VALUE_SET_NULL (val);
     } else {
       SWFDEC_AS_VALUE_SET_STRING (val, 
-	  swfdec_as_value_to_string (context, val));
+	  swfdec_abc_value_to_string (context, val));
     }
     return TRUE;
   } else if (traits == SWFDEC_ABC_OBJECT_TRAITS (context)) {
@@ -438,6 +439,6 @@ swfdec_abc_traits_coerce (SwfdecAbcTraits *traits, SwfdecAsValue *val)
     return TRUE;
   }
 
-  return swfdec_as_value_is_traits (val, traits);
+  return swfdec_abc_value_is_traits (val, traits);
 }
 
diff --git a/swfdec/swfdec_abc_traits.h b/swfdec/swfdec_abc_traits.h
index a1a09a1..b69a6b4 100644
--- a/swfdec/swfdec_abc_traits.h
+++ b/swfdec/swfdec_abc_traits.h
@@ -140,9 +140,9 @@ gboolean		swfdec_abc_traits_is_traits		(SwfdecAbcTraits *	traits,
 gboolean		swfdec_abc_traits_coerce		(SwfdecAbcTraits *	traits,
 								 SwfdecAsValue *	val);
 /* FIXME: kinda wrong header */
-SwfdecAbcTraits *	swfdec_as_value_to_traits		(SwfdecAsContext *	context,
+SwfdecAbcTraits *	swfdec_abc_value_to_traits		(SwfdecAsContext *	context,
 								 const SwfdecAsValue *	value);
-gboolean		swfdec_as_value_is_traits		(const SwfdecAsValue *	value,
+gboolean		swfdec_abc_value_is_traits		(const SwfdecAsValue *	value,
 								 SwfdecAbcTraits *	traits);
 
 
diff --git a/swfdec/swfdec_abc_value.c b/swfdec/swfdec_abc_value.c
new file mode 100644
index 0000000..dc58fc6
--- /dev/null
+++ b/swfdec/swfdec_abc_value.c
@@ -0,0 +1,240 @@
+/* Swfdec
+ * Copyright (C) 2008 Benjamin Otte <otte at gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "swfdec_abc_value.h"
+
+#include <math.h>
+#include <string.h>
+
+#include "swfdec_abc_namespace.h"
+#include "swfdec_abc_object.h"
+#include "swfdec_abc_traits.h"
+#include "swfdec_as_context.h"
+#include "swfdec_as_strings.h"
+#include "swfdec_debug.h"
+
+gboolean
+swfdec_abc_value_to_boolean (SwfdecAsContext *context, const SwfdecAsValue *value)
+{
+  g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), FALSE);
+  g_return_val_if_fail (SWFDEC_IS_AS_VALUE (value), FALSE);
+
+  switch (SWFDEC_AS_VALUE_GET_TYPE (value)) {
+    case SWFDEC_AS_TYPE_UNDEFINED:
+    case SWFDEC_AS_TYPE_NULL:
+      return FALSE;
+    case SWFDEC_AS_TYPE_BOOLEAN:
+      return SWFDEC_AS_VALUE_GET_BOOLEAN (value);
+    case SWFDEC_AS_TYPE_NUMBER:
+      {
+	double d = SWFDEC_AS_VALUE_GET_NUMBER (value);
+	return !isnan (d) && d != 0.0;
+      }
+    case SWFDEC_AS_TYPE_STRING:
+      return SWFDEC_AS_VALUE_GET_STRING (value) != SWFDEC_AS_STR_EMPTY;
+    case SWFDEC_AS_TYPE_OBJECT:
+    case SWFDEC_AS_TYPE_NAMESPACE:
+      return TRUE;
+    case SWFDEC_AS_TYPE_INT:
+    default:
+      g_assert_not_reached ();
+      return FALSE;
+  }
+}
+
+int
+swfdec_abc_value_to_integer (SwfdecAsContext *context, const SwfdecAsValue *value)
+{
+  double d;
+
+  g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), 0);
+  g_return_val_if_fail (SWFDEC_IS_AS_VALUE (value), 0);
+
+  d = swfdec_abc_value_to_number (context, value);
+
+  if (!isfinite (d))
+    return 0;
+  if (d < 0) {
+    d = fmod (-d, 4294967296.0);
+    return - (guint) d;
+  } else {
+    d = fmod (d, 4294967296.0);
+    return (guint) d;
+  }
+}
+
+double
+swfdec_abc_value_to_number (SwfdecAsContext *context, const SwfdecAsValue *value)
+{
+  g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), 0.0);
+  g_return_val_if_fail (SWFDEC_IS_AS_VALUE (value), 0.0);
+
+  switch (SWFDEC_AS_VALUE_GET_TYPE (value)) {
+    case SWFDEC_AS_TYPE_UNDEFINED:
+    case SWFDEC_AS_TYPE_NULL:
+      return NAN;
+    case SWFDEC_AS_TYPE_BOOLEAN:
+      return SWFDEC_AS_VALUE_GET_BOOLEAN (value) ? 1.0 : 0.0;
+    case SWFDEC_AS_TYPE_NUMBER:
+      return SWFDEC_AS_VALUE_GET_NUMBER (value);
+    case SWFDEC_AS_TYPE_STRING:
+      return swfdec_as_string_to_number (context, SWFDEC_AS_VALUE_GET_STRING (value));
+    case SWFDEC_AS_TYPE_OBJECT:
+      {
+	SwfdecAsValue tmp;
+	if (!swfdec_abc_object_default_value (
+	      SWFDEC_ABC_OBJECT (SWFDEC_AS_VALUE_GET_OBJECT (value)), &tmp))
+	  return NAN;
+	return swfdec_abc_value_to_number (context, &tmp);
+      }
+    case SWFDEC_AS_TYPE_NAMESPACE:
+      return swfdec_as_string_to_number (context, SWFDEC_AS_VALUE_GET_NAMESPACE (value)->uri);
+    case SWFDEC_AS_TYPE_INT:
+    default:
+      g_assert_not_reached ();
+      return FALSE;
+  }
+}
+
+gboolean
+swfdec_abc_value_to_primitive (SwfdecAsValue *dest, const SwfdecAsValue *src)
+{
+  g_return_val_if_fail (SWFDEC_IS_AS_VALUE (dest), FALSE);
+  g_return_val_if_fail (SWFDEC_IS_AS_VALUE (src), FALSE);
+
+  if (SWFDEC_AS_VALUE_IS_OBJECT (src)) {
+    return swfdec_abc_object_default_value
+      (SWFDEC_ABC_OBJECT (SWFDEC_AS_VALUE_GET_OBJECT (src)), dest);
+  } else if (dest != src) {
+    *dest = *src;
+  }
+  return TRUE;
+}
+
+const char *
+swfdec_abc_value_to_string (SwfdecAsContext *context, const SwfdecAsValue *value)
+{
+  g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), SWFDEC_AS_STR_EMPTY);
+  g_return_val_if_fail (SWFDEC_IS_AS_VALUE (value), SWFDEC_AS_STR_EMPTY);
+
+  switch (SWFDEC_AS_VALUE_GET_TYPE (value)) {
+    case SWFDEC_AS_TYPE_UNDEFINED:
+      return SWFDEC_AS_STR_undefined;
+    case SWFDEC_AS_TYPE_NULL:
+      return SWFDEC_AS_STR_null;
+    case SWFDEC_AS_TYPE_BOOLEAN:
+      return SWFDEC_AS_VALUE_GET_BOOLEAN (value) ? SWFDEC_AS_STR_true : SWFDEC_AS_STR_false;
+    case SWFDEC_AS_TYPE_NUMBER:
+      return swfdec_as_double_to_string (context, SWFDEC_AS_VALUE_GET_NUMBER (value));
+    case SWFDEC_AS_TYPE_STRING:
+      return SWFDEC_AS_VALUE_GET_STRING (value);
+    case SWFDEC_AS_TYPE_OBJECT:
+      {
+	SwfdecAsValue tmp;
+	if (!swfdec_abc_object_to_string (
+	      SWFDEC_ABC_OBJECT (SWFDEC_AS_VALUE_GET_OBJECT (value)), &tmp))
+	  return SWFDEC_AS_STR_EMPTY;
+	return swfdec_abc_value_to_string (context, &tmp);
+      }
+    case SWFDEC_AS_TYPE_NAMESPACE:
+      return SWFDEC_AS_VALUE_GET_NAMESPACE (value)->uri;
+    case SWFDEC_AS_TYPE_INT:
+    default:
+      g_assert_not_reached ();
+      return FALSE;
+  }
+}
+
+const char *
+swfdec_abc_value_get_type_name (const SwfdecAsValue *value)
+{
+  g_return_val_if_fail (SWFDEC_IS_AS_VALUE (value), NULL);
+
+  switch (value->type) {
+    case SWFDEC_AS_TYPE_STRING:
+      return SWFDEC_AS_STR_String;
+    case SWFDEC_AS_TYPE_UNDEFINED:
+      return SWFDEC_AS_STR_void;
+    case SWFDEC_AS_TYPE_BOOLEAN:
+      return SWFDEC_AS_STR_Boolean;
+    case SWFDEC_AS_TYPE_NULL:
+      return SWFDEC_AS_STR_null;
+    case SWFDEC_AS_TYPE_NUMBER:
+      return SWFDEC_AS_STR_Number;
+    case SWFDEC_AS_TYPE_OBJECT:
+      {
+	SwfdecAsObject *object = SWFDEC_AS_VALUE_GET_OBJECT (value);
+	if (SWFDEC_IS_ABC_OBJECT (object))
+	  return SWFDEC_ABC_OBJECT (object)->traits->name;
+	return SWFDEC_AS_STR_Object;
+      }
+    case SWFDEC_AS_TYPE_NAMESPACE:
+      return SWFDEC_AS_STR_Namespace;
+    case SWFDEC_AS_TYPE_INT:
+    default:
+      g_assert_not_reached ();
+      return NULL;
+  }
+}
+
+/**
+ * swfdec_abc_value_compare:
+ * @context: the context the values beliong to
+ * @lval: the left-side value of the comparison
+ * @rval: the right-side value of the comparison
+ *
+ * Does the ABC lower-or-equal comparison, as in @lval <= @rval. Be aware that
+ * this function can throw an exception.
+ *
+ * Returns: see #SwfdecAbcComparison
+ **/
+SwfdecAbcComparison
+swfdec_abc_value_compare (SwfdecAsContext *context, const SwfdecAsValue *lval,
+    const SwfdecAsValue *rval)
+{
+  SwfdecAsValue ltmp, rtmp;
+
+  g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), SWFDEC_ABC_COMPARE_UNDEFINED);
+  g_return_val_if_fail (lval != NULL, SWFDEC_ABC_COMPARE_UNDEFINED);
+  g_return_val_if_fail (rval != NULL, SWFDEC_ABC_COMPARE_UNDEFINED);
+
+  if (!swfdec_abc_value_to_primitive (&ltmp, lval) ||
+      !swfdec_abc_value_to_primitive (&rtmp, rval))
+    return SWFDEC_ABC_COMPARE_THROWN;
+
+  if (SWFDEC_AS_VALUE_IS_STRING (&ltmp) && SWFDEC_AS_VALUE_IS_STRING (&rtmp)) {
+    int comp = strcmp (SWFDEC_AS_VALUE_GET_STRING (&ltmp), 
+	SWFDEC_AS_VALUE_GET_STRING (&rtmp));
+    return (comp < 0) ? SWFDEC_ABC_COMPARE_LOWER : 
+      (comp > 0 ? SWFDEC_ABC_COMPARE_GREATER : SWFDEC_ABC_COMPARE_EQUAL);
+  } else {
+    double l = swfdec_as_value_to_number (context, &ltmp);
+    double r = swfdec_as_value_to_number (context, &rtmp);
+    if (isnan (l) || isnan (r))
+      return SWFDEC_ABC_COMPARE_UNDEFINED;
+
+    return (l < r) ? SWFDEC_ABC_COMPARE_LOWER : 
+      (l > r ? SWFDEC_ABC_COMPARE_GREATER : SWFDEC_ABC_COMPARE_EQUAL);
+  }
+}
+
diff --git a/swfdec/swfdec_abc_value.h b/swfdec/swfdec_abc_value.h
new file mode 100644
index 0000000..dfccd87
--- /dev/null
+++ b/swfdec/swfdec_abc_value.h
@@ -0,0 +1,57 @@
+/* Swfdec
+ * Copyright (C) 2008 Benjamin Otte <otte at gnome.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+
+#ifndef _SWFDEC_ABC_VALUE_H_
+#define _SWFDEC_ABC_VALUE_H_
+
+#include <swfdec/swfdec_abc_types.h>
+#include <swfdec/swfdec_as_types.h>
+
+G_BEGIN_DECLS
+
+
+typedef enum {
+  SWFDEC_ABC_COMPARE_UNDEFINED,
+  SWFDEC_ABC_COMPARE_THROWN,
+  SWFDEC_ABC_COMPARE_LOWER,
+  SWFDEC_ABC_COMPARE_EQUAL,
+  SWFDEC_ABC_COMPARE_GREATER
+} SwfdecAbcComparison;
+
+gboolean		swfdec_abc_value_to_boolean	(SwfdecAsContext *	context,
+							 const SwfdecAsValue *	value);
+int			swfdec_abc_value_to_integer	(SwfdecAsContext *	context,
+							 const SwfdecAsValue *	value);
+double			swfdec_abc_value_to_number	(SwfdecAsContext *	context,
+							 const SwfdecAsValue *	value);
+SwfdecAsObject *	swfdec_abc_value_to_object	(SwfdecAsContext *	context,
+							 const SwfdecAsValue *	value);
+gboolean		swfdec_abc_value_to_primitive	(SwfdecAsValue *	dest,
+							 const SwfdecAsValue *	src);
+const char *		swfdec_abc_value_to_string	(SwfdecAsContext *	context,
+							 const SwfdecAsValue *	value);
+const char *		swfdec_abc_value_get_type_name	(const SwfdecAsValue *	value);
+
+SwfdecAbcComparison	swfdec_abc_value_compare	(SwfdecAsContext *	context,
+							 const SwfdecAsValue *	lval,
+							 const SwfdecAsValue *	rval);
+
+
+G_END_DECLS
+#endif
diff --git a/swfdec/swfdec_as_types.c b/swfdec/swfdec_as_types.c
index 2ca4a5f..92850a3 100644
--- a/swfdec/swfdec_as_types.c
+++ b/swfdec/swfdec_as_types.c
@@ -458,39 +458,7 @@ swfdec_as_value_to_debug (const SwfdecAsValue *value)
   }
 }
 
-const char *
-swfdec_as_value_get_type_name (const SwfdecAsValue *value)
-{
-  g_return_val_if_fail (SWFDEC_IS_AS_VALUE (value), NULL);
-
-  switch (value->type) {
-    case SWFDEC_AS_TYPE_STRING:
-      return SWFDEC_AS_STR_String;
-    case SWFDEC_AS_TYPE_UNDEFINED:
-      return SWFDEC_AS_STR_void;
-    case SWFDEC_AS_TYPE_BOOLEAN:
-      return SWFDEC_AS_STR_Boolean;
-    case SWFDEC_AS_TYPE_NULL:
-      return SWFDEC_AS_STR_null;
-    case SWFDEC_AS_TYPE_NUMBER:
-      return SWFDEC_AS_STR_Number;
-    case SWFDEC_AS_TYPE_OBJECT:
-      {
-	SwfdecAsObject *object = SWFDEC_AS_VALUE_GET_OBJECT (value);
-	if (SWFDEC_IS_ABC_OBJECT (object))
-	  return SWFDEC_ABC_OBJECT (object)->traits->name;
-	return SWFDEC_AS_STR_Object;
-      }
-    case SWFDEC_AS_TYPE_NAMESPACE:
-      return SWFDEC_AS_STR_Namespace;
-    case SWFDEC_AS_TYPE_INT:
-    default:
-      g_assert_not_reached ();
-      return NULL;
-  }
-}
-
-static double
+double
 swfdec_as_string_to_number (SwfdecAsContext *context, const char *s)
 {
   char *end;
diff --git a/swfdec/swfdec_as_types.h b/swfdec/swfdec_as_types.h
index f291ddd..54f7324 100644
--- a/swfdec/swfdec_as_types.h
+++ b/swfdec/swfdec_as_types.h
@@ -69,7 +69,8 @@ struct _SwfdecAsValue {
   } value;
 };
 
-#define SWFDEC_IS_AS_VALUE(val) ((val) != NULL && (val)->type <= SWFDEC_TYPE_ABC_NAMESPACE)
+#define SWFDEC_AS_VALUE_GET_TYPE(val) ((val)->type)
+#define SWFDEC_IS_AS_VALUE(val) ((val) != NULL && SWFDEC_AS_VALUE_GET_TYPE (val) <= SWFDEC_AS_TYPE_NAMESPACE)
 
 #define SWFDEC_AS_VALUE_IS_UNDEFINED(val) ((val)->type == SWFDEC_AS_TYPE_UNDEFINED)
 #define SWFDEC_AS_VALUE_SET_UNDEFINED(val) (val)->type = SWFDEC_AS_TYPE_UNDEFINED
@@ -139,7 +140,6 @@ SwfdecAsObject *swfdec_as_value_to_object	(SwfdecAsContext *	context,
 void		swfdec_as_value_to_primitive	(SwfdecAsValue *	value);
 const char *	swfdec_as_value_to_string	(SwfdecAsContext *	context,
 						 const SwfdecAsValue *	value);
-const char *	swfdec_as_value_get_type_name	(const SwfdecAsValue *	value);
 char *		swfdec_as_value_to_debug	(const SwfdecAsValue *	value);
 
 /* special conversion functions */
@@ -148,6 +148,8 @@ const char *	swfdec_as_integer_to_string	(SwfdecAsContext *      context,
 int		swfdec_as_double_to_integer	(double			d);
 const char *	swfdec_as_double_to_string	(SwfdecAsContext *	context,
 						 double			d);
+double		swfdec_as_string_to_number	(SwfdecAsContext *	context,
+						 const char *		s);
 const char *	swfdec_as_str_concat		(SwfdecAsContext *	cx,
 						 const char *		s1,
 						 const char *		s2);
diff --git a/swfdec/swfdec_sprite_movie.c b/swfdec/swfdec_sprite_movie.c
index 7a2b5b8..2ced46a 100644
--- a/swfdec/swfdec_sprite_movie.c
+++ b/swfdec/swfdec_sprite_movie.c
@@ -549,7 +549,7 @@ swfdec_sprite_movie_perform_one_action (SwfdecSpriteMovie *movie, guint tag, Swf
 	  swfdec_sandbox_use (sandbox);
 	  swfdec_abc_multiname_init_from_string (&mn, context, s);
 	  swfdec_as_context_get_abc_variable (context, &mn, &val);
-	  if (swfdec_as_value_is_traits (&val, SWFDEC_ABC_CLASS_TRAITS (context))) {
+	  if (swfdec_abc_value_is_traits (&val, SWFDEC_ABC_CLASS_TRAITS (context))) {
 	    swfdec_resource_add_abc_class (mov->resource, id, 
 		SWFDEC_ABC_CLASS (SWFDEC_AS_VALUE_GET_OBJECT (&val)));
 	  } else {
commit c80e955af5fa8e57b56f8c76fb8e24bdbf35f9e2
Author: Benjamin Otte <otte at gnome.org>
Date:   Sat Aug 23 18:51:42 2008 +0200

    implement add_i, modulo, multiply(_i), negate(_i) and subtract(_i) opcodes

diff --git a/swfdec/swfdec_abc_interpret.c b/swfdec/swfdec_abc_interpret.c
index 7224c1d..7413056 100644
--- a/swfdec/swfdec_abc_interpret.c
+++ b/swfdec/swfdec_abc_interpret.c
@@ -658,6 +658,11 @@ swfdec_abc_interpret (SwfdecAbcFunction *fun, SwfdecAbcScopeChain *outer_scope)
 	  }
 	}
 	continue;
+      case SWFDEC_ABC_OPCODE_ADD_I:
+	val = swfdec_as_stack_peek (context, 2);
+	SWFDEC_AS_VALUE_SET_INT (val, swfdec_as_value_to_integer (context, val) +
+	      swfdec_as_value_to_integer (context, swfdec_as_stack_pop (context)));
+	break;
       case SWFDEC_ABC_OPCODE_CALL_PROPERTY:
       case SWFDEC_ABC_OPCODE_CALL_PROP_LEX:
       case SWFDEC_ABC_OPCODE_CALL_PROP_VOID:
@@ -842,6 +847,30 @@ swfdec_abc_interpret (SwfdecAbcFunction *fun, SwfdecAbcScopeChain *outer_scope)
 	i = swfdec_bits_get_vu32 (&bits);
 	SWFDEC_AS_VALUE_SET_UNDEFINED (&locals[i]);
 	continue;
+      case SWFDEC_ABC_OPCODE_MODULO:
+	val = swfdec_as_stack_peek (context, 2);
+	SWFDEC_AS_VALUE_SET_NUMBER (val, fmod (
+	      swfdec_as_value_to_number (context, val),
+	      swfdec_as_value_to_number (context, swfdec_as_stack_pop (context))));
+	break;
+      case SWFDEC_ABC_OPCODE_MULTIPLY:
+	val = swfdec_as_stack_peek (context, 2);
+	SWFDEC_AS_VALUE_SET_NUMBER (val, swfdec_as_value_to_number (context, val) *
+	      swfdec_as_value_to_number (context, swfdec_as_stack_pop (context)));
+	break;
+      case SWFDEC_ABC_OPCODE_MULTIPLY_I:
+	val = swfdec_as_stack_peek (context, 2);
+	SWFDEC_AS_VALUE_SET_INT (val, swfdec_as_value_to_integer (context, val) *
+	      swfdec_as_value_to_integer (context, swfdec_as_stack_pop (context)));
+	break;
+      case SWFDEC_ABC_OPCODE_NEGATE:
+	val = swfdec_as_stack_peek (context, 1);
+	SWFDEC_AS_VALUE_SET_NUMBER (val, swfdec_as_value_to_number (context, val));
+	break;
+      case SWFDEC_ABC_OPCODE_NEGATE_I:
+	val = swfdec_as_stack_peek (context, 1);
+	SWFDEC_AS_VALUE_SET_INT (val, swfdec_as_value_to_integer (context, val));
+	break;
       case SWFDEC_ABC_OPCODE_NEW_CLASS:
 	{
 	  SwfdecAbcClass *classp;
@@ -929,6 +958,16 @@ swfdec_abc_interpret (SwfdecAbcFunction *fun, SwfdecAbcScopeChain *outer_scope)
 	i = swfdec_bits_get_vu32 (&bits);
 	SWFDEC_AS_VALUE_SET_STRING (swfdec_as_stack_push (context), pool->strings[i]);
 	continue;
+      case SWFDEC_ABC_OPCODE_SUBTRACT:
+	val = swfdec_as_stack_peek (context, 2);
+	SWFDEC_AS_VALUE_SET_NUMBER (val, swfdec_as_value_to_number (context, val) -
+	      swfdec_as_value_to_number (context, swfdec_as_stack_pop (context)));
+	break;
+      case SWFDEC_ABC_OPCODE_SUBTRACT_I:
+	val = swfdec_as_stack_peek (context, 2);
+	SWFDEC_AS_VALUE_SET_INT (val, swfdec_as_value_to_integer (context, val) -
+	      swfdec_as_value_to_integer (context, swfdec_as_stack_pop (context)));
+	break;
       case SWFDEC_ABC_OPCODE_PUSH_TRUE:
 	SWFDEC_AS_VALUE_SET_BOOLEAN (swfdec_as_stack_push (context), TRUE);
 	continue;
@@ -985,7 +1024,6 @@ swfdec_abc_interpret (SwfdecAbcFunction *fun, SwfdecAbcScopeChain *outer_scope)
 	continue;
       case SWFDEC_ABC_OPCODE_ABS_JUMP:
       case SWFDEC_ABC_OPCODE_ADD_D:
-      case SWFDEC_ABC_OPCODE_ADD_I:
       case SWFDEC_ABC_OPCODE_ALLOC:
       case SWFDEC_ABC_OPCODE_AS_TYPE:
       case SWFDEC_ABC_OPCODE_AS_TYPE_LATE:
@@ -1065,11 +1103,6 @@ swfdec_abc_interpret (SwfdecAbcFunction *fun, SwfdecAbcScopeChain *outer_scope)
       case SWFDEC_ABC_OPCODE_LOOKUP_SWITCH:
       case SWFDEC_ABC_OPCODE_LSHIFT:
       case SWFDEC_ABC_OPCODE_MARK:
-      case SWFDEC_ABC_OPCODE_MODULO:
-      case SWFDEC_ABC_OPCODE_MULTIPLY:
-      case SWFDEC_ABC_OPCODE_MULTIPLY_I:
-      case SWFDEC_ABC_OPCODE_NEGATE:
-      case SWFDEC_ABC_OPCODE_NEGATE_I:
       case SWFDEC_ABC_OPCODE_NEXT_NAME:
       case SWFDEC_ABC_OPCODE_NEXT_VALUE:
       case SWFDEC_ABC_OPCODE_NEW_ARRAY:
@@ -1086,8 +1119,6 @@ swfdec_abc_interpret (SwfdecAbcFunction *fun, SwfdecAbcScopeChain *outer_scope)
       case SWFDEC_ABC_OPCODE_SET_SLOT:
       case SWFDEC_ABC_OPCODE_SET_SUPER:
       case SWFDEC_ABC_OPCODE_STRICT_EQUALS:
-      case SWFDEC_ABC_OPCODE_SUBTRACT:
-      case SWFDEC_ABC_OPCODE_SUBTRACT_I:
       case SWFDEC_ABC_OPCODE_SWEEP:
       case SWFDEC_ABC_OPCODE_THROW:
       case SWFDEC_ABC_OPCODE_TIMESTAMP:
commit 52555c8820cbd4363e8bb4cc079152fa52114e4c
Author: Benjamin Otte <otte at gnome.org>
Date:   Sat Aug 23 18:12:48 2008 +0200

    implement debug, debugfile and debugline opcodes (by ignoring them)

diff --git a/swfdec/swfdec_abc_interpret.c b/swfdec/swfdec_abc_interpret.c
index a363488..7224c1d 100644
--- a/swfdec/swfdec_abc_interpret.c
+++ b/swfdec/swfdec_abc_interpret.c
@@ -722,6 +722,16 @@ swfdec_abc_interpret (SwfdecAbcFunction *fun, SwfdecAbcScopeChain *outer_scope)
 	    outer_scope ? outer_scope->base : NULL, i, val, val);
 	swfdec_as_stack_pop_n (context, i + 1);
 	continue;
+      case SWFDEC_ABC_OPCODE_DEBUG:
+	/* type = */ swfdec_bits_get_u8 (&bits);
+	/* name = */ swfdec_bits_get_vu32 (&bits);
+	/* register = */ swfdec_bits_get_u8 (&bits);
+	/* extra = */ swfdec_bits_get_vu32 (&bits);
+	break;
+      case SWFDEC_ABC_OPCODE_DEBUG_FILE:
+      case SWFDEC_ABC_OPCODE_DEBUG_LINE:
+	i = swfdec_bits_get_vu32 (&bits);
+	continue;
       case SWFDEC_ABC_OPCODE_DIVIDE:
 	val = swfdec_as_stack_peek (context, 1);
 	SWFDEC_AS_VALUE_SET_NUMBER (val, swfdec_as_value_to_number (context, val) 
@@ -1007,9 +1017,6 @@ swfdec_abc_interpret (SwfdecAbcFunction *fun, SwfdecAbcScopeChain *outer_scope)
       case SWFDEC_ABC_OPCODE_CONVERT_O:
       case SWFDEC_ABC_OPCODE_CONVERT_S:
       case SWFDEC_ABC_OPCODE_CONVERT_U:
-      case SWFDEC_ABC_OPCODE_DEBUG:
-      case SWFDEC_ABC_OPCODE_DEBUG_FILE:
-      case SWFDEC_ABC_OPCODE_DEBUG_LINE:
       case SWFDEC_ABC_OPCODE_DEC_LOCAL:
       case SWFDEC_ABC_OPCODE_DECLOCAL_I:
       case SWFDEC_ABC_OPCODE_DECODE:


More information about the Swfdec-commits mailing list