[Swfdec] Branch 'interpreter' - 9 commits - libswfdec/js
libswfdec/swfdec_script.c libswfdec/swfdec_script.h
player/swfdec_debug_stack.c test/trace
Benjamin Otte
company at kemper.freedesktop.org
Thu Feb 1 05:41:44 PST 2007
libswfdec/js/jsnum.c | 10 ++++
libswfdec/swfdec_script.c | 86 ++++++++++++++++++++++++++++---------
libswfdec/swfdec_script.h | 2
player/swfdec_debug_stack.c | 33 +++++++++++++-
test/trace/Makefile.am | 8 +++
test/trace/number.swf |binary
test/trace/number.swf.trace | 9 +++
test/trace/object-math-5.swf |binary
test/trace/object-math-5.swf.trace | 17 +++++++
test/trace/object-math-6.swf |binary
test/trace/object-math-6.swf.trace | 17 +++++++
test/trace/object-math-7.swf |binary
test/trace/object-math-7.swf.trace | 17 +++++++
13 files changed, 178 insertions(+), 21 deletions(-)
New commits:
diff-tree 18aff9069e571bda0bf49290c7ad415597d1d16e (from 81d2a042d8772f2837e088c2fba410ea9b0df082)
Author: Benjamin Otte <otte at gnome.org>
Date: Thu Feb 1 14:38:22 2007 +0100
add another test that resulted from trying various stuff
diff --git a/test/trace/Makefile.am b/test/trace/Makefile.am
index a5d85ea..d931702 100644
--- a/test/trace/Makefile.am
+++ b/test/trace/Makefile.am
@@ -76,6 +76,8 @@ EXTRA_DIST = \
name2.swf.trace \
names.swf \
names.swf.trace \
+ number.swf \
+ number.swf.trace \
object-math-5.swf \
object-math-5.swf.trace \
object-math-6.swf \
diff --git a/test/trace/number.swf b/test/trace/number.swf
new file mode 100755
index 0000000..bf729ef
Binary files /dev/null and b/test/trace/number.swf differ
diff --git a/test/trace/number.swf.trace b/test/trace/number.swf.trace
new file mode 100755
index 0000000..de6a5e2
--- /dev/null
+++ b/test/trace/number.swf.trace
@@ -0,0 +1,9 @@
+Check various things with Number class and prototypes
+[type Function]
+[type Object]
+[type Function]
+NaN
+42
+1234
+4
+undefined
diff-tree 81d2a042d8772f2837e088c2fba410ea9b0df082 (from b6dcac3542c5de3b38b7505ea44be99c95b50de9)
Author: Benjamin Otte <otte at gnome.org>
Date: Thu Feb 1 14:37:13 2007 +0100
various fixes for tests
- apparently all objects evaluate to NaN in Flash 7
- handle error case ValueToObject == NULL in CallMethod
- walk the whole scope chain in CallFunction when trying to find the function
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index ad08eef..39b3b8b 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -161,7 +161,7 @@ swfdec_action_to_number (JSContext *cx,
static JSBool
swfdec_value_to_number_7 (JSContext *cx, jsval val, double *d)
{
- if (JSVAL_IS_NULL (val)) {
+ if (JSVAL_IS_OBJECT (val)) {
*d = *cx->runtime->jsNaN;
return JS_TRUE;
} else {
@@ -550,8 +550,10 @@ swfdec_action_call_function (JSContext *
JSStackFrame *fp = cx->fp;
const char *s;
guint32 n_args;
- JSObject *obj;
+ JSObject *obj, *pobj;
+ JSProperty *prop;
jsval fun;
+ JSAtom *atom;
s = swfdec_js_to_string (cx, fp->sp[-1]);
if (s == NULL)
@@ -561,7 +563,9 @@ swfdec_action_call_function (JSContext *
if (n_args + 2 > (guint) (fp->sp - fp->spbase))
return JS_FALSE;
- obj = OBJ_THIS_OBJECT (cx, cx->fp->scopeChain);
+ if (!(atom = js_Atomize (cx, s, strlen (s), 0)) ||
+ !js_FindProperty (cx, (jsid) atom, &obj, &pobj, &prop))
+ return JS_FALSE;
if (!JS_GetProperty (cx, obj, s, &fun))
return JS_FALSE;
fp->sp[-1] = fun;
@@ -589,6 +593,8 @@ swfdec_action_call_method (JSContext *cx
if (!JS_ValueToObject (cx, fp->sp[-2], &obj))
return JS_FALSE;
+ if (obj == NULL)
+ goto fail;
if (s[0] == '\0') {
fun = OBJECT_TO_JSVAL (obj);
} else {
@@ -600,6 +606,11 @@ swfdec_action_call_method (JSContext *cx
fp->sp[-2] = OBJECT_TO_JSVAL (obj);
swfdec_action_call (cx, n_args, 0);
return JS_TRUE;
+
+fail:
+ fp->sp -= 2 + n_args;
+ fp->sp[-1] = JSVAL_VOID;
+ return JS_TRUE;
}
static JSBool
diff-tree b6dcac3542c5de3b38b7505ea44be99c95b50de9 (from c806924bb1038dd655fef7d2ede3dad8d61dffe6)
Author: Benjamin Otte <otte at gnome.org>
Date: Thu Feb 1 14:30:42 2007 +0100
toString is supposed to output [type Object] for numbers
diff --git a/libswfdec/js/jsnum.c b/libswfdec/js/jsnum.c
index 1e92a7a..d9063f4 100644
--- a/libswfdec/js/jsnum.c
+++ b/libswfdec/js/jsnum.c
@@ -249,6 +249,15 @@ IntToString(jsint i, char *buf, size_t b
static JSBool
num_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
+ JSString *string;
+
+ string = JS_InternString (cx, "[type Object]");
+ if (string == NULL)
+ return JS_FALSE;
+
+ *rval = STRING_TO_JSVAL (string);
+ return JS_TRUE;
+#if 0
jsval v;
jsdouble d;
jsint base;
@@ -286,6 +295,7 @@ num_toString(JSContext *cx, JSObject *ob
return JS_FALSE;
*rval = STRING_TO_JSVAL(str);
return JS_TRUE;
+#endif
}
static JSBool
diff-tree c806924bb1038dd655fef7d2ede3dad8d61dffe6 (from dad7fc07302b9f0b6a13ce837e5ef997d95e75c2)
Author: Benjamin Otte <otte at gnome.org>
Date: Thu Feb 1 13:13:15 2007 +0100
add test for mathematical operations + - * / on objects
diff --git a/test/trace/Makefile.am b/test/trace/Makefile.am
index 27f0cac..a5d85ea 100644
--- a/test/trace/Makefile.am
+++ b/test/trace/Makefile.am
@@ -76,6 +76,12 @@ EXTRA_DIST = \
name2.swf.trace \
names.swf \
names.swf.trace \
+ object-math-5.swf \
+ object-math-5.swf.trace \
+ object-math-6.swf \
+ object-math-6.swf.trace \
+ object-math-7.swf \
+ object-math-7.swf.trace \
order.swf \
order.swf.trace \
rotation-5.swf \
diff --git a/test/trace/object-math-5.swf b/test/trace/object-math-5.swf
new file mode 100755
index 0000000..7ceac67
Binary files /dev/null and b/test/trace/object-math-5.swf differ
diff --git a/test/trace/object-math-5.swf.trace b/test/trace/object-math-5.swf.trace
new file mode 100755
index 0000000..03b77fa
--- /dev/null
+++ b/test/trace/object-math-5.swf.trace
@@ -0,0 +1,17 @@
+Check mathematical operations with objects in Flash 5
+2
+2
+2
+2
+2
+-2
+-2
+2
+0
+0
+0
+0
+Infinity
+0
+0
+Infinity
diff --git a/test/trace/object-math-6.swf b/test/trace/object-math-6.swf
new file mode 100755
index 0000000..5f98f7c
Binary files /dev/null and b/test/trace/object-math-6.swf differ
diff --git a/test/trace/object-math-6.swf.trace b/test/trace/object-math-6.swf.trace
new file mode 100755
index 0000000..87fc74d
--- /dev/null
+++ b/test/trace/object-math-6.swf.trace
@@ -0,0 +1,17 @@
+Check mathematical operations with objects in Flash 6
+NaN
+NaN
+2
+2
+NaN
+NaN
+-2
+2
+NaN
+NaN
+0
+0
+Infinity
+NaN
+0
+Infinity
diff --git a/test/trace/object-math-7.swf b/test/trace/object-math-7.swf
new file mode 100755
index 0000000..9d9392a
Binary files /dev/null and b/test/trace/object-math-7.swf differ
diff --git a/test/trace/object-math-7.swf.trace b/test/trace/object-math-7.swf.trace
new file mode 100755
index 0000000..751247d
--- /dev/null
+++ b/test/trace/object-math-7.swf.trace
@@ -0,0 +1,17 @@
+Check mathematical operations with objects in Flash 7
+NaN
+NaN
+NaN
+NaN
+NaN
+NaN
+NaN
+NaN
+NaN
+NaN
+NaN
+NaN
+Infinity
+NaN
+NaN
+Infinity
diff-tree dad7fc07302b9f0b6a13ce837e5ef997d95e75c2 (from 1677a15cf65bf31fffa806f5e56c5b61e6ae4ffa)
Author: Benjamin Otte <otte at gnome.org>
Date: Thu Feb 1 12:49:46 2007 +0100
fix object to number conversions in Flash 6
Flash <=5 converts all objects to 0
Flash 6 converts non-null objects to NaN and null objects to 0
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index d79a3d1..ad08eef 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -151,6 +151,8 @@ swfdec_action_to_number (JSContext *cx,
if (!JS_ValueToNumber (cx, val, &d))
return 0;
return isnan (d) ? 0 : d;
+ } else if (JSVAL_IS_OBJECT(val) && (((SwfdecScript *) cx->fp->swf)->version >= 6)) {
+ return JSVAL_IS_NULL (val) ? 0 : *cx->runtime->jsNaN;
} else {
return 0;
}
@@ -727,6 +729,8 @@ swfdec_action_binary (JSContext *cx, gui
l = l * r;
break;
case 0x0d:
+ if (isnan (r))
+ r = 0;
if (r == 0 && ((SwfdecScript *) cx->fp->swf)->version < 5) {
JSString *str = JS_InternString (cx, "#ERROR#");
if (str == NULL)
@@ -734,7 +738,7 @@ swfdec_action_binary (JSContext *cx, gui
cx->fp->sp[-1] = STRING_TO_JSVAL (str);
return JS_TRUE;
} else if (((SwfdecScript *) cx->fp->swf)->version >= 7 &&
- (r == 0 || isnan (r))) {
+ r == 0) {
cx->fp->sp[-1] = DOUBLE_TO_JSVAL (r < 0 ?
cx->runtime->jsNegativeInfinity :
cx->runtime->jsPositiveInfinity);
diff-tree 1677a15cf65bf31fffa806f5e56c5b61e6ae4ffa (from f7160413607ea6b82e876fb453c1c4303d3479d5)
Author: Benjamin Otte <otte at gnome.org>
Date: Thu Feb 1 12:29:09 2007 +0100
fix to_number conversions for null in Flash 7
Flash 7 seems to treat null as NaN as opposed to SpiderMonkey, where null is 0.
This patch fixes mathematical operations to do this correctly.
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index 4c0b163..d79a3d1 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -156,6 +156,17 @@ swfdec_action_to_number (JSContext *cx,
}
}
+static JSBool
+swfdec_value_to_number_7 (JSContext *cx, jsval val, double *d)
+{
+ if (JSVAL_IS_NULL (val)) {
+ *d = *cx->runtime->jsNaN;
+ return JS_TRUE;
+ } else {
+ return JS_ValueToNumber (cx, val, d);
+ }
+}
+
/*** ALL THE ACTION IS HERE ***/
static JSBool
@@ -700,8 +711,8 @@ swfdec_action_binary (JSContext *cx, gui
l = swfdec_action_to_number (cx, lval);
r = swfdec_action_to_number (cx, rval);
} else {
- if (!JS_ValueToNumber(cx, lval, &l) ||
- !JS_ValueToNumber(cx, rval, &r))
+ if (!swfdec_value_to_number_7 (cx, lval, &l) ||
+ !swfdec_value_to_number_7 (cx, rval, &r))
return JS_FALSE;
}
cx->fp->sp--;
@@ -722,9 +733,8 @@ swfdec_action_binary (JSContext *cx, gui
return JS_FALSE;
cx->fp->sp[-1] = STRING_TO_JSVAL (str);
return JS_TRUE;
- }
- if (((SwfdecScript *) cx->fp->swf)->version >= 7 &&
- JSVAL_IS_VOID (rval)) {
+ } else if (((SwfdecScript *) cx->fp->swf)->version >= 7 &&
+ (r == 0 || isnan (r))) {
cx->fp->sp[-1] = DOUBLE_TO_JSVAL (r < 0 ?
cx->runtime->jsNegativeInfinity :
cx->runtime->jsPositiveInfinity);
@@ -790,14 +800,6 @@ swfdec_action_add2_7 (JSContext *cx, gui
rval = cx->fp->sp[-1];
lval = cx->fp->sp[-2];
- if (!JSVAL_IS_PRIMITIVE (rval)) {
- if (!OBJ_DEFAULT_VALUE (cx, JSVAL_TO_OBJECT (rval), 0 , &rval))
- return JS_FALSE;
- }
- if (!JSVAL_IS_PRIMITIVE (lval)) {
- if (!OBJ_DEFAULT_VALUE (cx, JSVAL_TO_OBJECT (lval), 0 , &lval))
- return JS_FALSE;
- }
if ((cond = JSVAL_IS_STRING (lval)) || JSVAL_IS_STRING (rval)) {
JSString *str, *str2;
if (cond) {
@@ -816,8 +818,8 @@ swfdec_action_add2_7 (JSContext *cx, gui
cx->fp->sp[-1] = STRING_TO_JSVAL (str);
} else {
double d, d2;
- if (!JS_ValueToNumber(cx, lval, &d) ||
- !JS_ValueToNumber(cx, rval, &d2))
+ if (!swfdec_value_to_number_7 (cx, lval, &d) ||
+ !swfdec_value_to_number_7 (cx, rval, &d2))
return JS_FALSE;
d += d2;
cx->fp->sp--;
diff-tree f7160413607ea6b82e876fb453c1c4303d3479d5 (from ecffa559b35162ca6e2cb8bc20fe9f2ee7c43ba6)
Author: Benjamin Otte <otte at gnome.org>
Date: Thu Feb 1 11:35:42 2007 +0100
allow calling functions on numbers and strings by converting them to proper objects
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index 85e6f7c..4c0b163 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -574,9 +574,8 @@ swfdec_action_call_method (JSContext *cx
if (n_args + 3 > (guint) (fp->sp - fp->spbase))
return JS_FALSE;
- if (!JSVAL_IS_OBJECT (fp->sp[-2]) || JSVAL_IS_NULL (fp->sp[-2]))
- goto fail;
- obj = JSVAL_TO_OBJECT (fp->sp[-2]);
+ if (!JS_ValueToObject (cx, fp->sp[-2], &obj))
+ return JS_FALSE;
if (s[0] == '\0') {
fun = OBJECT_TO_JSVAL (obj);
} else {
@@ -588,11 +587,6 @@ swfdec_action_call_method (JSContext *cx
fp->sp[-2] = OBJECT_TO_JSVAL (obj);
swfdec_action_call (cx, n_args, 0);
return JS_TRUE;
-
-fail:
- fp->sp -= 2 + n_args;
- fp->sp[-1] = JSVAL_VOID;
- return JS_TRUE;
}
static JSBool
diff-tree ecffa559b35162ca6e2cb8bc20fe9f2ee7c43ba6 (from 320efb52606b8b376880b9c3bc222a1f9810896a)
Author: Benjamin Otte <otte at gnome.org>
Date: Thu Feb 1 11:35:08 2007 +0100
add a column for the type of the object on the stack
diff --git a/player/swfdec_debug_stack.c b/player/swfdec_debug_stack.c
index 2eef4ed..5b25626 100644
--- a/player/swfdec_debug_stack.c
+++ b/player/swfdec_debug_stack.c
@@ -30,17 +30,37 @@ G_DEFINE_TYPE (SwfdecDebugStack, swfdec_
enum {
COLUMN_LINE,
+ COLUMN_TYPE,
COLUMN_CONTENT,
N_COLUMNS
};
+static const char *
+swfdec_get_jsval_type (JSContext *cx, jsval val)
+{
+ if (JSVAL_IS_VOID (val))
+ return "undefined";
+ if (JSVAL_IS_NULL (val))
+ return "null";
+ if (JSVAL_IS_INT (val))
+ return "Integer";
+ if (JSVAL_IS_DOUBLE (val))
+ return "Double";
+ if (JSVAL_IS_BOOLEAN (val))
+ return "Boolean";
+ if (JSVAL_IS_STRING (val))
+ return "String";
+ g_assert (JSVAL_IS_OBJECT (val));
+ return "Object";
+}
+
static void
swfdec_debug_stack_set_model (SwfdecDebugStack *debug)
{
JSStackFrame *frame = NULL;
guint i, min, max;
GtkListStore *store = gtk_list_store_new (N_COLUMNS, G_TYPE_UINT,
- G_TYPE_STRING);
+ G_TYPE_STRING, G_TYPE_STRING);
GtkTreeIter iter;
JS_FrameIterator (debug->manager->player->jscx, &frame);
@@ -49,7 +69,9 @@ swfdec_debug_stack_set_model (SwfdecDebu
for (i = min; i <= max; i++) {
const char *s = swfdec_js_to_string (debug->manager->player->jscx, frame->sp[-i]);
gtk_list_store_append (store, &iter);
- gtk_list_store_set (store, &iter, COLUMN_LINE, i, COLUMN_CONTENT, s, -1);
+ gtk_list_store_set (store, &iter, COLUMN_LINE, i,
+ COLUMN_TYPE, swfdec_get_jsval_type (debug->manager->player->jscx, frame->sp[-i]),
+ COLUMN_CONTENT, s, -1);
}
gtk_tree_view_set_model (GTK_TREE_VIEW (debug), GTK_TREE_MODEL (store));
@@ -119,6 +141,13 @@ swfdec_debug_stack_add_columns (GtkTreeV
gtk_tree_view_append_column (treeview, column);
renderer = gtk_cell_renderer_text_new ();
+ column = gtk_tree_view_column_new_with_attributes ("Type", renderer,
+ "text", COLUMN_TYPE, NULL);
+ gtk_tree_view_column_set_sort_column_id (column, COLUMN_TYPE);
+ gtk_tree_view_column_set_resizable (column, TRUE);
+ gtk_tree_view_append_column (treeview, column);
+
+ renderer = gtk_cell_renderer_text_new ();
column = gtk_tree_view_column_new_with_attributes ("Content", renderer,
"text", COLUMN_CONTENT, NULL);
gtk_tree_view_column_set_sort_column_id (column, COLUMN_CONTENT);
diff-tree 320efb52606b8b376880b9c3bc222a1f9810896a (from ae64862c94f18618313c90c28b4071d84693b7b5)
Author: Benjamin Otte <otte at gnome.org>
Date: Wed Jan 31 23:33:40 2007 +0100
implement ConstantPool inheritance for DefineFunction
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index 46ba618..85e6f7c 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -97,6 +97,26 @@ swfdec_constant_pool_free (SwfdecConstan
g_ptr_array_free (pool, TRUE);
}
+/* FIXME: this is a bit hacky */
+static SwfdecBuffer *
+swfdec_constant_pool_get_area (SwfdecScript *script, SwfdecConstantPool *pool)
+{
+ guint8 *start;
+ SwfdecBuffer *buffer;
+ guint len;
+
+ if (pool->len == 0)
+ return NULL;
+ start = (guint8 *) g_ptr_array_index (pool, 0) - 5;
+ buffer = script->buffer;
+ g_assert (start >= buffer->data);
+ g_assert (start + 3 < buffer->data + buffer->length);
+ g_assert (*start == 0x88);
+ len = 3 + (start[1] | start[2] << 8);
+ g_assert (start + len < buffer->data + buffer->length);
+ return swfdec_buffer_new_subbuffer (buffer, start - buffer->data, len);
+}
+
/*** SUPPORT FUNCTIONS ***/
static SwfdecMovie *
@@ -1334,6 +1354,10 @@ swfdec_action_define_function (JSContext
&bits, *function_name ? function_name : "<lambda>",
((SwfdecScript *) cx->fp->swf)->version);
swfdec_buffer_unref (buffer);
+ if (cx->fp->constant_pool) {
+ script->constant_pool = swfdec_constant_pool_get_area (cx->fp->swf,
+ cx->fp->constant_pool);
+ }
}
if (script == NULL) {
SWFDEC_ERROR ("failed to create script");
@@ -1638,6 +1662,7 @@ swfdec_action_print_push (guint action,
return g_string_free (string, FALSE);
}
+/* NB: constant pool actions are special in that they are called at init time */
static char *
swfdec_action_print_constant_pool (guint action, const guint8 *data, guint len)
{
@@ -2010,6 +2035,8 @@ swfdec_script_unref (SwfdecScript *scrip
return;
swfdec_buffer_unref (script->buffer);
+ if (script->constant_pool)
+ swfdec_buffer_unref (script->constant_pool);
g_free (script->name);
g_free (script);
}
@@ -2068,6 +2095,16 @@ swfdec_script_interpret (SwfdecScript *s
ok = JS_FALSE;
goto out;
}
+ /* initialize the constant pool */
+ if (script->constant_pool) {
+ spec = actions + 0x88;
+ ok = spec->exec[version] (cx, 0x88, script->constant_pool->data + 3,
+ script->constant_pool->length - 3);
+ if (!ok) {
+ SWFDEC_WARNING ("Constant pool initialization failed");
+ goto out;
+ }
+ }
while (TRUE) {
/* check pc */
diff --git a/libswfdec/swfdec_script.h b/libswfdec/swfdec_script.h
index 1cea4a7..e202aa0 100644
--- a/libswfdec/swfdec_script.h
+++ b/libswfdec/swfdec_script.h
@@ -39,6 +39,8 @@ struct _SwfdecScript {
char * name; /* name identifying this script */
unsigned int version; /* version of the script */
gpointer debugger; /* debugger owning us or NULL */
+ /* needed by functions */
+ SwfdecBuffer * constant_pool; /* constant pool action */
};
SwfdecScript * swfdec_script_new (SwfdecBits * bits,
More information about the Swfdec
mailing list