[Swfdec] 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 Sep 10 13:00:52 PDT 2007


 libswfdec/swfdec_as_interpret.c |    4 
 libswfdec/swfdec_as_object.c    |  185 +++++++++++++++++++++++++++-------------
 libswfdec/swfdec_as_object.h    |    1 
 3 files changed, 128 insertions(+), 62 deletions(-)

New commits:
diff-tree 890b14c29384f9610b68eaf44e4fedfcc6580618 (from b971a7a434b0b1535eff0ced3eba031fdafdb09f)
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Sep 10 22:00:48 2007 +0200

    rewrite (un)watch functions

diff --git a/libswfdec/swfdec_as_object.c b/libswfdec/swfdec_as_object.c
index 1fbf1d0..a331030 100644
--- a/libswfdec/swfdec_as_object.c
+++ b/libswfdec/swfdec_as_object.c
@@ -113,11 +113,14 @@ struct _SwfdecAsVariable {
   SwfdecAsValue     	value;		/* value of property */
   SwfdecAsFunction *	get;		/* getter set with swfdec_as_object_add_property */
   SwfdecAsFunction *	set;		/* setter or %NULL */
-  SwfdecAsFunction *	watch;		/* watcher or %NULL */
-  SwfdecAsValue *	watch_data;	/* user data to watcher */
-  gint8			watch_recurse;	/* times the watch function has been called without returning */
 };
 
+typedef struct {
+  SwfdecAsFunction *	watch;		/* watcher or %NULL */
+  SwfdecAsValue		watch_data;	/* user data to watcher */
+  guint			refcount;	/* refcount - misused for recursion detection */
+} SwfdecAsWatch;
+
 G_DEFINE_TYPE (SwfdecAsObject, swfdec_as_object, G_TYPE_OBJECT)
 
 static void
@@ -141,22 +144,28 @@ swfdec_as_object_mark_property (gpointer
     if (var->set)
       swfdec_as_object_mark (SWFDEC_AS_OBJECT (var->set));
   } else {
-    if (var->watch) {
-      swfdec_as_object_mark (SWFDEC_AS_OBJECT (var->watch));
-      if (var->watch_data) {
-	swfdec_as_value_mark (var->watch_data);
-      }
-    }
     swfdec_as_value_mark (&var->value);
   }
 }
 
 static void
+swfdec_as_object_mark_watch (gpointer key, gpointer value, gpointer unused)
+{
+  SwfdecAsWatch *watch = value;
+
+  swfdec_as_string_mark (key);
+  swfdec_as_object_mark (SWFDEC_AS_OBJECT (watch->watch));
+  swfdec_as_value_mark (&watch->watch_data);
+}
+
+static void
 swfdec_as_object_do_mark (SwfdecAsObject *object)
 {
   if (object->prototype)
     swfdec_as_object_mark (object->prototype);
   g_hash_table_foreach (object->properties, swfdec_as_object_mark_property, NULL);
+  if (object->watches)
+    g_hash_table_foreach (object->watches, swfdec_as_object_mark_watch, NULL);
 }
 
 static void
@@ -233,6 +242,52 @@ swfdec_as_object_do_get (SwfdecAsObject 
   return TRUE;
 }
 
+static SwfdecAsWatch *
+swfdec_as_watch_new (SwfdecAsFunction *function)
+{
+  SwfdecAsWatch *watch;
+
+  if (!swfdec_as_context_use_mem (SWFDEC_AS_OBJECT (function)->context, 
+	sizeof (SwfdecAsWatch)))
+    return NULL;
+
+  watch = g_slice_new (SwfdecAsWatch);
+  watch->refcount = 1;
+  watch->watch = function;
+  SWFDEC_AS_VALUE_SET_UNDEFINED (&watch->watch_data);
+  return watch;
+}
+
+static inline gboolean
+swfdec_as_watch_can_recurse (SwfdecAsWatch *watch)
+{
+  guint version;
+
+  version = SWFDEC_AS_OBJECT (watch->watch)->context->version;
+  if (version <= 6) {
+    return watch->refcount <= 1;
+  } else {
+    return watch->refcount <= 64 + 1;
+  }
+}
+
+static inline void
+swfdec_as_watch_ref (SwfdecAsWatch *watch)
+{
+  watch->refcount++;
+}
+
+static inline void
+swfdec_as_watch_unref (SwfdecAsWatch *watch)
+{
+  watch->refcount--;
+  if (watch->refcount == 0) {
+    swfdec_as_context_unuse_mem (SWFDEC_AS_OBJECT (watch->watch)->context, 
+	sizeof (SwfdecAsWatch));
+    g_slice_free (SwfdecAsWatch, watch);
+  }
+}
+
 static void
 swfdec_as_object_do_set (SwfdecAsObject *object, const char *variable, 
     const SwfdecAsValue *val, guint flags)
@@ -285,23 +340,29 @@ swfdec_as_object_do_set (SwfdecAsObject 
       swfdec_as_context_run (object->context);
     }
   } else { 
-    if (var->watch) {
-      SwfdecAsValue ret, args[4];
-      SWFDEC_AS_VALUE_SET_STRING (&args[0], variable);
-      args[1] = var->value;
-      args[2] = *val;
-      if (var->watch_data) {
-	args[3] = *var->watch_data;
-      } else {
-	SWFDEC_AS_VALUE_SET_UNDEFINED (&args[3]);
-      }
-      if (var->watch_recurse <= (object->context->version <= 6 ? 0 : 64)) {
-	var->watch_recurse++;
-	swfdec_as_function_call (var->watch, object, 4, args, &ret);
+    if (object->watches) {
+      SwfdecAsValue ret = *val;
+      SwfdecAsWatch *watch = g_hash_table_lookup (object->watches, variable);
+      /* FIXME: figure out if this limit here is correct. Add a watch in Flash 7 
+       * and set a variable using Flash 6 */
+      if (watch && swfdec_as_watch_can_recurse (watch)) {
+	SwfdecAsValue args[4];
+	SWFDEC_AS_VALUE_SET_STRING (&args[0], variable);
+	args[1] = var->value;
+	args[2] = *val;
+	args[3] = watch->watch_data;
+	swfdec_as_watch_ref (watch);
+	swfdec_as_function_call (watch->watch, object, 4, args, &ret);
 	swfdec_as_context_run (object->context);
-	var->value = ret;
-	var->watch_recurse--;
+	swfdec_as_watch_unref (watch);
+	var = swfdec_as_object_hash_lookup (object, variable);
+	if (var == NULL) {
+	  var = swfdec_as_object_hash_create (object, variable, flags);
+	  if (var == NULL)
+	    return;
+	}
       }
+      var->value = ret;
     } else {
       var->value = *val;
     }
@@ -329,12 +390,8 @@ swfdec_as_object_do_set_flags (SwfdecAsO
 static void
 swfdec_as_object_free_property (gpointer key, gpointer value, gpointer data)
 {
-  SwfdecAsVariable *var = value;
   SwfdecAsObject *object = data;
 
-  if (var->watch_data)
-    g_free (var->watch_data);
-
   swfdec_as_context_unuse_mem (object->context, sizeof (SwfdecAsVariable));
   g_slice_free (SwfdecAsVariable, value);
 }
@@ -601,6 +658,19 @@ swfdec_as_object_add (SwfdecAsObject *ob
   }
 }
 
+/* This is a huge hack design-wise, but we can't use watch->watch, 
+ * it might be gone already */
+static gboolean
+swfdec_as_object_steal_watches (gpointer key, gpointer value, gpointer object)
+{
+  SwfdecAsWatch *watch = value;
+
+  g_assert (watch->refcount == 1);
+  watch->watch = (SwfdecAsFunction *) object;
+  swfdec_as_watch_unref (watch);
+  return TRUE;
+}
+
 void
 swfdec_as_object_collect (SwfdecAsObject *object)
 {
@@ -610,6 +680,10 @@ swfdec_as_object_collect (SwfdecAsObject
   g_hash_table_foreach (object->properties, swfdec_as_object_free_property, object);
   g_hash_table_destroy (object->properties);
   object->properties = NULL;
+  if (object->watches) {
+    g_hash_table_foreach_steal (object->watches, swfdec_as_object_steal_watches, object);
+    object->watches = NULL;
+  }
   if (object->size)
     swfdec_as_context_unuse_mem (object->context, object->size);
   g_object_unref (object);
@@ -1220,7 +1294,7 @@ void
 swfdec_as_object_watch (SwfdecAsContext *cx, SwfdecAsObject *object,
     guint argc, SwfdecAsValue *argv, SwfdecAsValue *retval)
 {
-  SwfdecAsVariable *var;
+  SwfdecAsWatch *watch;
   const char *name;
 
   SWFDEC_AS_VALUE_SET_BOOLEAN (retval, FALSE);
@@ -1230,34 +1304,30 @@ swfdec_as_object_watch (SwfdecAsContext 
 
   name = swfdec_as_value_to_string (cx, &argv[0]);
 
-  if (!(var = swfdec_as_object_hash_lookup (object, name))) {
-    SwfdecAsValue val;
-    SWFDEC_AS_VALUE_SET_UNDEFINED (&val);
-    swfdec_as_object_set_variable (object, name, &val);
-    if (!(var = swfdec_as_object_hash_lookup (object, name)))
-      return;
-  }
-
-  if (var->get != NULL)
-    return;
-
   if (!SWFDEC_AS_VALUE_IS_OBJECT (&argv[1]))
     return;
 
   if (!SWFDEC_IS_AS_FUNCTION (SWFDEC_AS_VALUE_GET_OBJECT (&argv[1])))
     return;
 
-  var->watch = SWFDEC_AS_FUNCTION (SWFDEC_AS_VALUE_GET_OBJECT (&argv[1]));
+  if (object->watches == NULL) {
+    object->watches = g_hash_table_new_full (g_direct_hash, g_direct_equal, 
+	NULL, (GDestroyNotify) swfdec_as_watch_unref);
+    watch = NULL;
+  } else {
+    watch = g_hash_table_lookup (object->watches, name);
+  }
+  if (watch == NULL) {
+    watch = swfdec_as_watch_new (SWFDEC_AS_FUNCTION (SWFDEC_AS_VALUE_GET_OBJECT (&argv[1])));
+    if (watch == NULL)
+      return;
+    g_hash_table_insert (object->watches, (char *) name, watch);
+  }
 
   if (argc >= 3) {
-    if (!var->watch_data)
-      var->watch_data = g_malloc (sizeof (SwfdecAsValue));
-    *var->watch_data = argv[2];
+    watch->watch_data = argv[2];
   } else {
-    if (var->watch_data) {
-      g_free (var->watch_data);
-      var->watch_data = NULL;
-    }
+    SWFDEC_AS_VALUE_SET_UNDEFINED (&watch->watch_data);
   }
 
   SWFDEC_AS_VALUE_SET_BOOLEAN (retval, TRUE);
@@ -1268,7 +1338,6 @@ void
 swfdec_as_object_unwatch (SwfdecAsContext *cx, SwfdecAsObject *object,
     guint argc, SwfdecAsValue *argv, SwfdecAsValue *retval)
 {
-  SwfdecAsVariable *var;
   const char *name;
 
   SWFDEC_AS_VALUE_SET_BOOLEAN (retval, FALSE);
@@ -1277,20 +1346,16 @@ swfdec_as_object_unwatch (SwfdecAsContex
     return;
 
   name = swfdec_as_value_to_string (cx, &argv[0]);
+  if (object->watches != NULL && 
+      g_hash_table_remove (object->watches, name)) {
 
-  if (!(var = swfdec_as_object_hash_lookup (object, name)))
-    return;
-
-  if (var->watch == NULL)
-    return;
+    SWFDEC_AS_VALUE_SET_BOOLEAN (retval, TRUE);
 
-  var->watch = NULL;
-  if (var->watch_data) {
-    g_free (var->watch_data);
-    var->watch_data = NULL;
+    if (g_hash_table_size (object->watches) == 0) {
+      g_hash_table_destroy (object->watches);
+      object->watches = NULL;
+    }
   }
-
-  SWFDEC_AS_VALUE_SET_BOOLEAN (retval, TRUE);
 }
 
 static void
diff --git a/libswfdec/swfdec_as_object.h b/libswfdec/swfdec_as_object.h
index a61bc4b..425fa13 100644
--- a/libswfdec/swfdec_as_object.h
+++ b/libswfdec/swfdec_as_object.h
@@ -61,6 +61,7 @@ struct _SwfdecAsObject {
   /*< private >*/
   SwfdecAsObject *	prototype;	/* prototype object (referred to as __proto__) */
   GHashTable *		properties;	/* string->SwfdecAsVariable mapping or NULL when not in GC */
+  GHashTable *		watches;	/* string->WatchData mapping or NULL when not watching anything */
   guint8		flags;		/* GC flags */
   gsize			size;		/* size reserved in GC */
 };
diff-tree b971a7a434b0b1535eff0ced3eba031fdafdb09f (from parents)
Merge: 4b2f425542c29b11f71db53a8c841349bff78990 a6ede17fba471801fc53b4fbfb385b70db669892
Author: Benjamin Otte <otte at gnome.org>
Date:   Mon Sep 10 16:19:04 2007 +0200

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

diff-tree 4b2f425542c29b11f71db53a8c841349bff78990 (from f443e1a8281d0db546c00ec8ddb836ac9802862e)
Author: Benjamin Otte <otte at gnome.org>
Date:   Sun Sep 9 21:58:48 2007 +0200

    don't ERROR about missing functions, just WARN

diff --git a/libswfdec/swfdec_as_interpret.c b/libswfdec/swfdec_as_interpret.c
index 71a5663..564c35a 100644
--- a/libswfdec/swfdec_as_interpret.c
+++ b/libswfdec/swfdec_as_interpret.c
@@ -801,7 +801,7 @@ swfdec_action_call_function (SwfdecAsCon
     SWFDEC_AS_VALUE_SET_UNDEFINED (fun);
   }
   if (!swfdec_action_call (cx, n_args)) {
-    SWFDEC_ERROR ("no function named %s", name);
+    SWFDEC_WARNING ("no function named %s", name);
   }
 }
 
@@ -855,7 +855,7 @@ swfdec_action_call_method (SwfdecAsConte
       }
     }
   } else {
-    SWFDEC_ERROR ("no function named %s on object %s", name ? name : "unknown", obj ? G_OBJECT_TYPE_NAME(obj) : "unknown");
+    SWFDEC_WARNING ("no function named %s on object %s", name ? name : "unknown", obj ? G_OBJECT_TYPE_NAME(obj) : "unknown");
   }
 }
 


More information about the Swfdec mailing list