Benjamin Otte
2007-Sep-10 20:00 UTC
[Swfdec] 3 commits - libswfdec/swfdec_as_interpret.c libswfdec/swfdec_as_object.c libswfdec/swfdec_as_object.h
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 at 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"); } }
Apparently Analagous Threads
- 5 commits - libswfdec/swfdec_as_array.c libswfdec/swfdec_as_array.h libswfdec/swfdec_as_date.c libswfdec/swfdec_as_date.h libswfdec/swfdec_as_initialize.as libswfdec/swfdec_as_interpret.c libswfdec/swfdec_as_object.c libswfdec/swfdec_filter.c
- 8 commits - libswfdec/swfdec_as_function.c libswfdec/swfdec_as_initialize.as libswfdec/swfdec_as_initialize.h libswfdec/swfdec_as_object.c libswfdec/swfdec_as_strings.c test/trace
- 2 commits - libswfdec/swfdec_as_array.c libswfdec/swfdec_as_object.c libswfdec/swfdec_as_object.h libswfdec/swfdec_as_super.c libswfdec/swfdec_as_with.c libswfdec/swfdec_movie.c libswfdec/swfdec_player.c libswfdec/swfdec_sprite_movie.c
- Branch 'as' - 9 commits - libswfdec/swfdec_as_frame.c libswfdec/swfdec_as_function.c libswfdec/swfdec_as_function.h libswfdec/swfdec_as_interpret.c libswfdec/swfdec_as_native_function.c libswfdec/swfdec_as_object.c libswfdec/swfdec_as_script_function.c
- 2 commits - libswfdec/swfdec_as_object.c test/trace