Benjamin Otte
2007-Feb-01 05:41 UTC
[Swfdec] Branch 'interpreter' - 9 commits - libswfdec/js libswfdec/swfdec_script.c libswfdec/swfdec_script.h player/swfdec_debug_stack.c test/trace
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@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@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@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@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@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@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@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@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@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,
Possibly Parallel Threads
- 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 'interpreter' - 3 commits - libswfdec/js libswfdec/swfdec_script.c
- 109 commits - configure.ac libswfdec/js libswfdec/Makefile.am libswfdec/swfdec_bits.c libswfdec/swfdec_bits.h libswfdec/swfdec_buffer.c libswfdec/swfdec_button_movie.c libswfdec/swfdec_codec_screen.c libswfdec/swfdec_color.c libswfdec/swfdec_color.h
- 11 commits - libswfdec/swfdec_font.c libswfdec/swfdec_font.h libswfdec/swfdec_js_movie.c libswfdec/swfdec_script.c libswfdec/swfdec_script.h test/.gitignore test/trace
- 11 commits - configure.ac libswfdec/swfdec_js_movie.c libswfdec/swfdec_root_movie.c libswfdec/swfdec_root_movie.h libswfdec/swfdec_script.c libswfdec/swfdec_sprite.c libswfdec/swfdec_sprite.h libswfdec/swfdec_sprite_movie.c libswfdec/swfdec_swf_decoder.c