[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