Benjamin Otte
2007-Apr-16 02:48 UTC
[Swfdec] Branch 'as' - 3 commits - libswfdec/swfdec_as_interpret.c libswfdec/swfdec_as_object.c libswfdec/swfdec_as_object.h
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@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@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@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 { \
Seemingly Similar Threads
- 14 commits - libswfdec/swfdec_as_context.c libswfdec/swfdec_as_interpret.c libswfdec/swfdec_as_interpret.h libswfdec/swfdec_net_stream.c libswfdec/swfdec_script.c libswfdec/swfdec_sprite_movie.c libswfdec/swfdec_tag.c libswfdec/swfdec_text_field_movie.c
- Branch 'interpreter' - 3 commits - libswfdec/js libswfdec/swfdec_script.c
- Branch 'as' - 4 commits - libswfdec/Makefile.am libswfdec/swfdec_as_context.c libswfdec/swfdec_as_frame.c libswfdec/swfdec_as_interpret.c libswfdec/swfdec_as_interpret.h libswfdec/swfdec_as_object.c libswfdec/swfdec_as_types.c libswfdec/swfdec_as_types.h
- Branch 'as' - 4 commits - libswfdec/swfdec_as_interpret.c libswfdec/swfdec_as_types.c libswfdec/swfdec_as_types.h
- 6 commits - libswfdec/swfdec_as_frame.c libswfdec/swfdec_as_internal.h libswfdec/swfdec_as_interpret.c libswfdec/swfdec_as_interpret.h libswfdec/swfdec_as_object.c libswfdec/swfdec_as_script_function.c libswfdec/swfdec_flash_security.c