[Swfdec] Branch 'as' - 3 commits - libswfdec/swfdec_as_interpret.c libswfdec/swfdec_as_object.c libswfdec/swfdec_as_object.h

Benjamin Otte company at kemper.freedesktop.org
Mon Apr 16 02:48:00 PDT 2007


 libswfdec/swfdec_as_interpret.c |  108 ++++++++++++++++++++++------------------
 libswfdec/swfdec_as_object.c    |   97 ++++++++++++++++++++++++++++++++++-
 libswfdec/swfdec_as_object.h    |   13 ++++
 3 files changed, 167 insertions(+), 51 deletions(-)

New commits:
diff-tree 5b8588a3f805a71549ee71acc97ce27a3845383e (from a843e801169afd960d58def92a2adf5eaf69dbfb)
Author: Benjamin Otte <otte at gnome.org>
Date:   Sun Apr 15 17:12:49 2007 +0200

    add support for native properties

diff --git a/libswfdec/swfdec_as_object.c b/libswfdec/swfdec_as_object.c
index 9a90393..afd0a18 100644
--- a/libswfdec/swfdec_as_object.c
+++ b/libswfdec/swfdec_as_object.c
@@ -240,8 +240,12 @@ swfdec_as_object_set_variable (SwfdecAsO
   if (var == NULL ||
       var->flags & SWFDEC_AS_VARIABLE_READONLY)
     return;
-  g_assert ((var->flags & SWFDEC_AS_VARIABLE_NATIVE) == 0);
-  var->value.value = *value;
+  if ((var->flags & SWFDEC_AS_VARIABLE_NATIVE)) {
+    g_return_if_fail (var->value.funcs.set != NULL);
+    var->value.funcs.set (object, value);
+  } else {
+    var->value.value = *value;
+  }
 }
 
 void
@@ -261,8 +265,12 @@ swfdec_as_object_get_variable (SwfdecAsO
       object = object->prototype;
       continue;
     }
-    g_assert ((var->flags & SWFDEC_AS_VARIABLE_NATIVE) == 0);
-    *value = var->value.value;
+    if ((var->flags & SWFDEC_AS_VARIABLE_NATIVE)) {
+      SWFDEC_AS_VALUE_SET_UNDEFINED (value); /* just to be sure */
+      var->value.funcs.get (object, value);
+    } else {
+      *value = var->value.value;
+    }
     return;
   }
   if (i == 256) {
@@ -420,6 +428,44 @@ swfdec_as_object_add_function (SwfdecAsO
 }
 
 /**
+ * swfdec_as_object_add_variable:
+ * @object: a #SwfdecAsObject
+ * @name: name of the function. The string does not have to be 
+ *        garbage-collected.
+ * @set: function to set this value or %NULL if the value should be read-only
+ * @get: function to get the value.
+ *
+ * Adds a new property with name @name to @object. The property is native, so
+ * the value is not managed by the script engine, but the @set and @get 
+ * function are used to access the value. The variable will not be enumerated
+ * and cannot be deleted.
+ **/
+void
+swfdec_as_object_add_variable (SwfdecAsObject *object, const char *name,
+    SwfdecAsVariableSetter set, SwfdecAsVariableGetter get)
+{
+  SwfdecAsVariable *var;
+  SwfdecAsValue variable;
+
+  g_return_if_fail (SWFDEC_IS_AS_OBJECT (object));
+  g_return_if_fail (name != NULL);
+  g_return_if_fail (get != NULL);
+
+  name = swfdec_as_context_get_string (object->context, name);
+  SWFDEC_AS_VALUE_SET_STRING (&variable, name);
+  var = swfdec_as_object_lookup (object, &variable, TRUE);
+  if (var == NULL)
+    return;
+  var->flags = SWFDEC_AS_VARIABLE_NATIVE | SWFDEC_AS_VARIABLE_PERMANENT |
+    SWFDEC_AS_VARIABLE_DONT_ENUM;
+  if (set == NULL)
+    var->flags |= SWFDEC_AS_VARIABLE_READONLY;
+  g_assert ((var->flags & SWFDEC_AS_VARIABLE_NATIVE) == 0);
+  var->value.funcs.get = get;
+  var->value.funcs.set = set;
+}
+
+/**
  * swfdec_as_object_run:
  * @object: a #SwfdecAsObject
  * @script: script to execute
diff --git a/libswfdec/swfdec_as_object.h b/libswfdec/swfdec_as_object.h
index c80aec0..9c184c9 100644
--- a/libswfdec/swfdec_as_object.h
+++ b/libswfdec/swfdec_as_object.h
@@ -154,6 +154,10 @@ SwfdecAsFunction *swfdec_as_object_add_f
 						 const char *		name,
 						 SwfdecAsNative		native,
 						 guint			min_args);
+void		swfdec_as_object_add_variable	(SwfdecAsObject *	object,
+						 const char *		name,
+						 SwfdecAsVariableSetter	set,
+						 SwfdecAsVariableGetter get);
 
 void		swfdec_as_object_run		(SwfdecAsObject *       object,
 						 SwfdecScript *		script);
diff-tree a843e801169afd960d58def92a2adf5eaf69dbfb (from e189e59badf2f2ec5a6645c405f795f99cbc52ec)
Author: Benjamin Otte <otte at gnome.org>
Date:   Sun Apr 15 16:46:04 2007 +0200

    implement Less and Equals

diff --git a/libswfdec/swfdec_as_interpret.c b/libswfdec/swfdec_as_interpret.c
index dfcefb1..7ea1f82 100644
--- a/libswfdec/swfdec_as_interpret.c
+++ b/libswfdec/swfdec_as_interpret.c
@@ -1016,18 +1016,14 @@ swfdec_action_random_number (SwfdecAsCon
     SWFDEC_AS_VALUE_SET_NUMBER (val, g_rand_int_range (cx->rand, 0, max));
 }
 
-#if 0
 static void
 swfdec_action_old_compare (SwfdecAsContext *cx, guint action, const guint8 *data, guint len)
 {
-  jsval rval, lval;
   double l, r;
-  void cond;
+  gboolean cond;
 
-  rval = cx->fp->sp[-1];
-  lval = cx->fp->sp[-2];
-  l = swfdec_value_to_number (cx, lval);
-  r = swfdec_value_to_number (cx, rval);
+  l = swfdec_as_value_to_number (cx, swfdec_as_stack_peek (cx->frame->stack, 2));
+  r = swfdec_as_value_to_number (cx, swfdec_as_stack_peek (cx->frame->stack, 1));
   switch (action) {
     case 0x0e:
       cond = l == r;
@@ -1037,17 +1033,15 @@ swfdec_action_old_compare (SwfdecAsConte
       break;
     default: 
       g_assert_not_reached ();
-      return JS_FALSE;
+      return;
   }
-  cx->fp->sp--;
-  if (((SwfdecScript *) cx->fp->swf)->version < 5) {
-    cx->fp->sp[-1] = INT_TO_JSVAL (cond ? 1 : 0);
+  swfdec_as_stack_pop (cx->frame->stack);
+  if (cx->version < 5) {
+    SWFDEC_AS_VALUE_SET_NUMBER (swfdec_as_stack_peek (cx->frame->stack, 1), cond ? 1 : 0);
   } else {
-    cx->fp->sp[-1] = BOOLEAN_TO_JSVAL (cond);
+    SWFDEC_AS_VALUE_SET_BOOLEAN (swfdec_as_stack_peek (cx->frame->stack, 1), cond);
   }
-  return JS_TRUE;
 }
-#endif
 
 static void
 swfdec_action_equals2 (SwfdecAsContext *cx, guint action, const guint8 *data, guint len)
@@ -2160,10 +2154,8 @@ const SwfdecActionSpec swfdec_as_actions
   [SWFDEC_AS_ACTION_SUBTRACT] = { "Subtract", NULL, 2, 1, { NULL, swfdec_action_binary, swfdec_action_binary, swfdec_action_binary, swfdec_action_binary } },
   [SWFDEC_AS_ACTION_MULTIPLY] = { "Multiply", NULL, 2, 1, { NULL, swfdec_action_binary, swfdec_action_binary, swfdec_action_binary, swfdec_action_binary } },
   [SWFDEC_AS_ACTION_DIVIDE] = { "Divide", NULL, 2, 1, { NULL, swfdec_action_binary, swfdec_action_binary, swfdec_action_binary, swfdec_action_binary } },
-#if 0
-  [0x0e] = { "Equals", NULL, 2, 1, { NULL, swfdec_action_old_compare, swfdec_action_old_compare, swfdec_action_old_compare, swfdec_action_old_compare } },
-  [0x0f] = { "Less", NULL, 2, 1, { NULL, swfdec_action_old_compare, swfdec_action_old_compare, swfdec_action_old_compare, swfdec_action_old_compare } },
-#endif
+  [SWFDEC_AS_ACTION_EQUALS] = { "Equals", NULL, 2, 1, { NULL, swfdec_action_old_compare, swfdec_action_old_compare, swfdec_action_old_compare, swfdec_action_old_compare } },
+  [SWFDEC_AS_ACTION_LESS] = { "Less", NULL, 2, 1, { NULL, swfdec_action_old_compare, swfdec_action_old_compare, swfdec_action_old_compare, swfdec_action_old_compare } },
   [SWFDEC_AS_ACTION_AND] = { "And", NULL, 2, 1, { NULL, /* FIXME */NULL, swfdec_action_logical, swfdec_action_logical, swfdec_action_logical } },
   [SWFDEC_AS_ACTION_OR] = { "Or", NULL, 2, 1, { NULL, /* FIXME */NULL, swfdec_action_logical, swfdec_action_logical, swfdec_action_logical } },
   [SWFDEC_AS_ACTION_NOT] = { "Not", NULL, 1, 1, { NULL, swfdec_action_not_4, swfdec_action_not_5, swfdec_action_not_5, swfdec_action_not_5 } },
diff-tree e189e59badf2f2ec5a6645c405f795f99cbc52ec (from 5f393d7cbd7fadf4d9e3f49822c295f78678ff30)
Author: Benjamin Otte <otte at gnome.org>
Date:   Sun Apr 15 16:12:29 2007 +0200

    implement Enumerate and Enumerate2
    
    (untested)

diff --git a/libswfdec/swfdec_as_interpret.c b/libswfdec/swfdec_as_interpret.c
index 9fca9af..dfcefb1 100644
--- a/libswfdec/swfdec_as_interpret.c
+++ b/libswfdec/swfdec_as_interpret.c
@@ -1790,40 +1790,60 @@ swfdec_action_extends (SwfdecAsContext *
     return JS_FALSE;
   return JS_TRUE;
 }
+#endif
+
+static gboolean
+swfdec_action_do_enumerate (SwfdecAsObject *object, const SwfdecAsValue *val,
+    SwfdecAsVariable *var, gpointer stackp)
+{
+  SwfdecAsStack *stack = stackp;
+
+  if (var->flags | SWFDEC_AS_VARIABLE_DONT_ENUM)
+    return TRUE;
+  swfdec_as_stack_ensure_left (stack, 1);
+  *swfdec_as_stack_push (stack) = *val;
+  return TRUE;
+}
+
+static void
+swfdec_action_enumerate (SwfdecAsContext *cx, guint action, const guint8 *data, guint len)
+{
+  SwfdecAsValue *val;
+  SwfdecAsStack *stack;
+  SwfdecAsObject *obj;
+
+  stack = cx->frame->stack;
+  val = swfdec_as_stack_peek (stack, 1);
+
+  swfdec_as_interpret_eval (cx, NULL, val);
+  if (!SWFDEC_AS_VALUE_IS_OBJECT (val)) {
+    SWFDEC_ERROR ("Enumerate not pointing to an object");
+    SWFDEC_AS_VALUE_SET_NULL (val);
+    return;
+  }
+  obj = SWFDEC_AS_VALUE_GET_OBJECT (val);
+  SWFDEC_AS_VALUE_SET_NULL (val);
+  swfdec_as_object_foreach (obj, swfdec_action_do_enumerate, stack);
+}
 
 static void
 swfdec_action_enumerate2 (SwfdecAsContext *cx, guint action, const guint8 *data, guint len)
 {
-  JSObject *obj;
-  JSIdArray *array;
-  guint i;
+  SwfdecAsValue *val;
+  SwfdecAsStack *stack;
+  SwfdecAsObject *obj;
 
-  if (!JSVAL_IS_OBJECT (cx->fp->sp[-1]) || cx->fp->sp[-1] == JSVAL_NULL) {
+  stack = cx->frame->stack;
+  val = swfdec_as_stack_peek (stack, 1);
+  if (!SWFDEC_AS_VALUE_IS_OBJECT (val)) {
     SWFDEC_ERROR ("Enumerate2 called without an object");
-    cx->fp->sp[-1] = JSVAL_NULL;
-    return JS_TRUE;
-  }
-  obj = JSVAL_TO_OBJECT (cx->fp->sp[-1]);
-  cx->fp->sp[-1] = JSVAL_NULL;
-  array = JS_Enumerate (cx, obj);
-  if (!array)
-    return JS_FALSE;
-  if ((guint) (cx->fp->spend - cx->fp->sp) < array->length) {
-    SWFDEC_ERROR ("FIXME: not enough stack space, need %u, got %td",
-	array->length, cx->fp->spend - cx->fp->sp);
-    JS_DestroyIdArray (cx, array);
-    return JS_FALSE;
-  }
-  for (i = 0; i < array->length; i++) {
-    if (!JS_IdToValue (cx, array->vector[i], cx->fp->sp++)) {
-      JS_DestroyIdArray (cx, array);
-      return JS_FALSE;
-    }
+    SWFDEC_AS_VALUE_SET_NULL (val);
+    return;
   }
-  JS_DestroyIdArray (cx, array);
-  return JS_TRUE;
+  obj = SWFDEC_AS_VALUE_GET_OBJECT (val);
+  SWFDEC_AS_VALUE_SET_NULL (val);
+  swfdec_as_object_foreach (obj, swfdec_action_do_enumerate, stack);
 }
-#endif
 
 static void
 swfdec_action_logical (SwfdecAsContext *cx, guint action, const guint8 *data, guint len)
@@ -2204,7 +2224,7 @@ const SwfdecActionSpec swfdec_as_actions
 #if 0
   [0x45] = { "TargetPath", NULL, 1, 1, { NULL, NULL, swfdec_action_target_path, swfdec_action_target_path, swfdec_action_target_path } },
 #endif
-  [SWFDEC_AS_ACTION_ENUMERATE] = { "Enumerate", NULL },
+  [SWFDEC_AS_ACTION_ENUMERATE] = { "Enumerate", NULL, 1, -1, { NULL, NULL, swfdec_action_enumerate, swfdec_action_enumerate, swfdec_action_enumerate } },
   [SWFDEC_AS_ACTION_ADD2] = { "Add2", NULL, 2, 1, { NULL, NULL, swfdec_action_add2, swfdec_action_add2, swfdec_action_add2 } },
   [SWFDEC_AS_ACTION_LESS2] = { "Less2", NULL, 2, 1, { NULL, NULL, swfdec_action_new_comparison_6, swfdec_action_new_comparison_6, swfdec_action_new_comparison_7 } },
   [SWFDEC_AS_ACTION_EQUALS2] = { "Equals2", NULL, 2, 1, { NULL, NULL, swfdec_action_equals2, swfdec_action_equals2, swfdec_action_equals2 } },
@@ -2220,9 +2240,11 @@ const SwfdecActionSpec swfdec_as_actions
 #if 0
   [0x53] = { "NewMethod", NULL, -1, 1, { NULL, NULL, swfdec_action_new_method, swfdec_action_new_method, swfdec_action_new_method } },
   /* version 6 */
-  [0x54] = { "InstanceOf", NULL },
-  [0x55] = { "Enumerate2", NULL, 1, -1, { NULL, NULL, NULL, swfdec_action_enumerate2, swfdec_action_enumerate2 } },
+#endif
+  [SWFDEC_AS_ACTION_INSTANCE_OF] = { "InstanceOf", NULL },
+  [SWFDEC_AS_ACTION_ENUMERATE2] = { "Enumerate2", NULL, 1, -1, { NULL, NULL, NULL, swfdec_action_enumerate2, swfdec_action_enumerate2 } },
   /* version 5 */
+#if 0
   [0x60] = { "BitAnd", NULL, 2, 1, { NULL, NULL, swfdec_action_bitwise, swfdec_action_bitwise, swfdec_action_bitwise } },
   [0x61] = { "BitOr", NULL, 2, 1, { NULL, NULL, swfdec_action_bitwise, swfdec_action_bitwise, swfdec_action_bitwise } },
   [0x62] = { "BitXor", NULL, 2, 1, { NULL, NULL, swfdec_action_bitwise, swfdec_action_bitwise, swfdec_action_bitwise } },
diff --git a/libswfdec/swfdec_as_object.c b/libswfdec/swfdec_as_object.c
index ff9abbd..9a90393 100644
--- a/libswfdec/swfdec_as_object.c
+++ b/libswfdec/swfdec_as_object.c
@@ -92,6 +92,34 @@ swfdec_as_object_do_delete (SwfdecAsObje
   swfdec_as_object_free_property (NULL, var, object);
 }
 
+typedef struct {
+  SwfdecAsObject *		object;
+  SwfdecAsVariableForeach	func;
+  gpointer			data;
+  gboolean			retval;
+} ForeachData;
+
+static void
+swfdec_as_object_hash_foreach (gpointer key, gpointer value, gpointer data)
+{
+  ForeachData *fdata = data;
+
+  if (!fdata->retval)
+    return;
+
+  fdata->retval = fdata->func (fdata->object, key, value, fdata->data);
+}
+
+/* FIXME: does not do Adobe Flash's order for Enumerate actions */
+static gboolean
+swfdec_as_object_do_foreach (SwfdecAsObject *object, SwfdecAsVariableForeach func, gpointer data)
+{
+  ForeachData fdata = { object, func, data, TRUE };
+
+  g_hash_table_foreach (object->properties, swfdec_as_object_hash_foreach, &fdata);
+  return fdata.retval;
+}
+
 static void
 swfdec_as_object_class_init (SwfdecAsObjectClass *klass)
 {
@@ -102,6 +130,7 @@ swfdec_as_object_class_init (SwfdecAsObj
   klass->mark = swfdec_as_object_do_mark;
   klass->get = swfdec_as_object_do_get;
   klass->delete = swfdec_as_object_do_delete;
+  klass->foreach = swfdec_as_object_do_foreach;
 }
 
 static void
@@ -339,6 +368,20 @@ swfdec_as_object_unset_variable_flags (S
   var->flags &= ~flags;
 }
 
+gboolean
+swfdec_as_object_foreach (SwfdecAsObject *object, SwfdecAsVariableForeach func,
+    gpointer data)
+{
+  SwfdecAsObjectClass *klass;
+
+  g_return_val_if_fail (SWFDEC_IS_AS_OBJECT (object), FALSE);
+  g_return_val_if_fail (func != NULL, FALSE);
+
+  klass = SWFDEC_AS_OBJECT_GET_CLASS (object);
+  g_return_val_if_fail (klass->foreach != NULL, FALSE);
+  return klass->foreach (object, func, data);
+}
+
 /*** SIMPLIFICATIONS ***/
 
 /**
diff --git a/libswfdec/swfdec_as_object.h b/libswfdec/swfdec_as_object.h
index cdd98e8..c80aec0 100644
--- a/libswfdec/swfdec_as_object.h
+++ b/libswfdec/swfdec_as_object.h
@@ -37,6 +37,8 @@ typedef struct _SwfdecAsObjectClass Swfd
 typedef struct _SwfdecAsVariable SwfdecAsVariable;
 typedef void (* SwfdecAsVariableSetter) (SwfdecAsObject *object, const SwfdecAsValue *value);
 typedef void (* SwfdecAsVariableGetter) (SwfdecAsObject *object, SwfdecAsValue *value);
+typedef gboolean (* SwfdecAsVariableForeach) (SwfdecAsObject *object, 
+    const SwfdecAsValue *variable, SwfdecAsVariable *value, gpointer data);
 
 struct _SwfdecAsVariable {
   guint			flags;		/* SwfdecAsVariableFlag values */
@@ -85,6 +87,10 @@ struct _SwfdecAsObjectClass {
   /* delete the variable - it does exists */
   void			(* delete)		(SwfdecAsObject *       object,
 						 const SwfdecAsValue *	variable);
+  /* call with every variable until func returns FALSE */
+  gboolean		(* foreach)		(SwfdecAsObject *	object,
+						 SwfdecAsVariableForeach func,
+						 gpointer		data);
 };
 
 GType		swfdec_as_object_get_type	(void);
@@ -118,6 +124,9 @@ void		swfdec_as_object_unset_variable_fl
 						(SwfdecAsObject *       object,
 						 const SwfdecAsValue *	variable,
 						 SwfdecAsVariableFlag	flags);
+gboolean	swfdec_as_object_foreach	(SwfdecAsObject *       object,
+						 SwfdecAsVariableForeach func,
+						 gpointer		data);
 
 /* shortcuts, you probably don't want to bind them */
 #define swfdec_as_object_set(object, name, value) G_STMT_START { \


More information about the Swfdec mailing list