[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