Benjamin Otte
2007-Feb-19 11:35 UTC
[Swfdec] 22 commits - libswfdec/js libswfdec/swfdec_debugger.c libswfdec/swfdec_js.c libswfdec/swfdec_js_global.c libswfdec/swfdec_js_movie.c libswfdec/swfdec_movie.c libswfdec/swfdec_player.c libswfdec/swfdec_player_internal.h libswfdec/swfdec_script.c libswfdec/swfdec_script.h libswfdec/swfdec_tag.c player/swfdec_debug_script.c test/trace
libswfdec/js/jsfun.c | 7 + libswfdec/js/jsobj.c | 12 +- libswfdec/swfdec_debugger.c | 5 libswfdec/swfdec_js.c | 10 + libswfdec/swfdec_js_global.c | 165 +++++++++++++++++++++++++++++++- libswfdec/swfdec_js_movie.c | 51 +++++++-- libswfdec/swfdec_movie.c | 8 + libswfdec/swfdec_player.c | 23 +--- libswfdec/swfdec_player_internal.h | 3 libswfdec/swfdec_script.c | 77 +++++++++----- libswfdec/swfdec_script.h | 2 libswfdec/swfdec_tag.c | 1 player/swfdec_debug_script.c | 2 test/trace/Makefile.am | 14 ++ test/trace/function-undefined.swf |binary test/trace/function-undefined.swf.trace | 2 test/trace/local.swf |binary test/trace/local.swf.trace | 3 test/trace/parent-root.swf |binary test/trace/parent-root.swf.trace | 2 test/trace/preload.swf |binary test/trace/preload.swf.trace | 4 test/trace/setinterval-clear.swf |binary test/trace/setinterval-clear.swf.trace | 3 test/trace/setinterval.swf |binary test/trace/setinterval.swf.trace | 21 ++++ test/trace/setinterval2.swf |binary test/trace/setinterval2.swf.trace | 5 28 files changed, 356 insertions(+), 64 deletions(-) New commits: diff-tree 185d07d2ed05ec0bf1970484d27642703177702e (from a3a877f6e2f219f403100c3d994bccd3a2cc72bc) Author: Benjamin Otte <otte@gnome.org> Date: Mon Feb 19 20:35:26 2007 +0100 add test for local scope using DefineLocal diff --git a/test/trace/Makefile.am b/test/trace/Makefile.am index 4d11f13..ea517f7 100644 --- a/test/trace/Makefile.am +++ b/test/trace/Makefile.am @@ -74,6 +74,8 @@ EXTRA_DIST = \ load-4.swf.trace \ load-5.swf \ load-5.swf.trace \ + local.swf \ + local.swf.trace \ name.swf \ name.swf.trace \ name2.swf \ diff --git a/test/trace/local.swf b/test/trace/local.swf new file mode 100755 index 0000000..0c3d5ab Binary files /dev/null and b/test/trace/local.swf differ diff --git a/test/trace/local.swf.trace b/test/trace/local.swf.trace new file mode 100755 index 0000000..9aaac5c --- /dev/null +++ b/test/trace/local.swf.trace @@ -0,0 +1,3 @@ +Test behaviour of DefineLocal +7 +undefined diff-tree a3a877f6e2f219f403100c3d994bccd3a2cc72bc (from a986921e1731e82386bbeb8bd5e2e765acc58c6b) Author: Benjamin Otte <otte@gnome.org> Date: Mon Feb 19 20:33:56 2007 +0100 It looks like Flash doesn't create a local scope for the entry scripts, so don't do it either the good thing about this: make check passes diff --git a/libswfdec/swfdec_js.c b/libswfdec/swfdec_js.c index 9d6782a..e6ce8a5 100644 --- a/libswfdec/swfdec_js.c +++ b/libswfdec/swfdec_js.c @@ -338,7 +338,7 @@ swfdec_js_eval_set_property (JSContext * if (obj == NULL) { if (cx->fp == NULL || cx->fp->scopeChain == NULL) return JS_FALSE; - obj = JS_GetParent (cx, cx->fp->scopeChain); + obj = cx->fp->thisp; } return OBJ_SET_PROPERTY (cx, obj, (jsid) atom, ret); } diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c index d46687f..824861b 100644 --- a/libswfdec/swfdec_script.c +++ b/libswfdec/swfdec_script.c @@ -1643,11 +1643,11 @@ swfdec_action_define_local (JSContext *c { const char *name; - g_assert (cx->fp->callobj != NULL); + g_assert (cx->fp->scopeChain != NULL); name = swfdec_js_to_string (cx, cx->fp->sp[-2]); if (name == NULL) return JS_FALSE; - if (!JS_SetProperty (cx, cx->fp->callobj, name, &cx->fp->sp[-1])) + if (!JS_SetProperty (cx, cx->fp->scopeChain, name, &cx->fp->sp[-1])) return JS_FALSE; cx->fp->sp -= 2; return JS_TRUE; @@ -1659,11 +1659,11 @@ swfdec_action_define_local2 (JSContext * const char *name; jsval val = JSVAL_VOID; - g_assert (cx->fp->callobj != NULL); + g_assert (cx->fp->scopeChain != NULL); name = swfdec_js_to_string (cx, cx->fp->sp[-1]); if (name == NULL) return JS_FALSE; - if (!JS_SetProperty (cx, cx->fp->callobj, name, &val)) + if (!JS_SetProperty (cx, cx->fp->scopeChain, name, &val)) return JS_FALSE; cx->fp->sp--; return JS_TRUE; @@ -2593,9 +2593,9 @@ swfdec_script_execute (SwfdecScript *scr return JSVAL_VOID; oldfp = cx->fp; - frame.callobj = frame.argsobj = NULL; + frame.callobj = NULL; frame.script = NULL; - frame.varobj = NULL; + frame.varobj = frame.argsobj = NULL; frame.fun = swfdec_script_ensure_function (script, scriptable); frame.swf = script; frame.constant_pool = NULL; @@ -2606,7 +2606,6 @@ swfdec_script_execute (SwfdecScript *scr frame.sharpArray = NULL; frame.rval = JSVAL_VOID; frame.down = NULL; - frame.scopeChain = NULL; frame.pc = NULL; frame.sp = oldfp ? oldfp->sp : NULL; frame.spbase = NULL; @@ -2614,7 +2613,8 @@ swfdec_script_execute (SwfdecScript *scr frame.flags = 0; frame.dormantNext = NULL; frame.objAtomMap = NULL; - + /* no local scope here */ + frame.scopeChain = obj; /* allocate stack for variables */ frame.nvars = 4; frame.vars = js_AllocStack (cx, frame.nvars, &mark); @@ -2622,9 +2622,6 @@ swfdec_script_execute (SwfdecScript *scr return JS_FALSE; } frame.vars[0] = frame.vars[1] = frame.vars[2] = frame.vars[3] = JSVAL_VOID; - /* create a call object */ - if (!js_GetCallObject(cx, &frame, obj)) - return JS_FALSE; if (oldfp) { g_assert (!oldfp->dormantNext); @@ -2643,11 +2640,6 @@ swfdec_script_execute (SwfdecScript *scr if (frame.constant_pool) swfdec_constant_pool_free (frame.constant_pool); - if (frame.callobj) - ok &= js_PutCallObject(cx, &frame); - if (frame.argsobj) - ok &= js_PutArgsObject(cx, &frame); - cx->fp = oldfp; if (oldfp) { g_assert (cx->dormantFrameChain == oldfp); diff-tree a986921e1731e82386bbeb8bd5e2e765acc58c6b (from 8a66540298c89725624385a022580e593d6da3a4) Author: Benjamin Otte <otte@gnome.org> Date: Mon Feb 19 18:47:46 2007 +0100 implement setInterval and clearInterval diff --git a/libswfdec/swfdec_js.c b/libswfdec/swfdec_js.c index 481ec48..9d6782a 100644 --- a/libswfdec/swfdec_js.c +++ b/libswfdec/swfdec_js.c @@ -113,6 +113,8 @@ swfdec_js_init_player (SwfdecPlayer *pla swfdec_js_add_sound (player); } +typedef struct _SwfdecJSInterval SwfdecJSInterval; +extern void swfdec_js_interval_free (SwfdecJSInterval *interval); /** * swfdec_js_finish_player: * @player: a #SwfdecPlayer @@ -122,6 +124,8 @@ swfdec_js_init_player (SwfdecPlayer *pla void swfdec_js_finish_player (SwfdecPlayer *player) { + while (player->intervals) + swfdec_js_interval_free (player->intervals->data); if (player->jscx) { JS_DestroyContext(player->jscx); player->jsobj = NULL; diff --git a/libswfdec/swfdec_js_global.c b/libswfdec/swfdec_js_global.c index 328d74d..06e83e1 100644 --- a/libswfdec/swfdec_js_global.c +++ b/libswfdec/swfdec_js_global.c @@ -1,5 +1,5 @@ /* Swfdec - * Copyright (C) 2006 Benjamin Otte <otte@gnome.org> + * Copyright (C) 2006-2007 Benjamin Otte <otte@gnome.org> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -25,6 +25,159 @@ #include "swfdec_js.h" #include "swfdec_debug.h" #include "swfdec_player_internal.h" +#include "js/jsatom.h" +#include "js/jsfun.h" +#include "js/jsinterp.h" +#include "js/jsobj.h" + +/*** INTERVAL ***/ + +typedef struct _SwfdecJSInterval SwfdecJSInterval; +struct _SwfdecJSInterval { + SwfdecTimeout timeout; + SwfdecPlayer * player; /* needed so it can be readded */ + unsigned int id; /* id this interval is identified with */ + unsigned int msecs; /* interval in milliseconds */ + unsigned int n_args; /* number of arguments to call function with */ + jsval vals[0]; /* values: 0 is function, 1 is object, 2-n are arguments */ +}; + +void +swfdec_js_interval_free (SwfdecJSInterval *interval) +{ + JSContext *cx = interval->player->jscx; + guint i; + + swfdec_player_remove_timeout (interval->player, &interval->timeout); + interval->player->intervals = + g_list_remove (interval->player->intervals, interval); + for (i = 0; i < interval->n_args + 2; i++) { + JS_RemoveRoot (cx, &interval->vals[i]); + } + g_free (interval); +} + +static void +swfdec_js_interval_trigger (SwfdecTimeout *timeout) +{ + SwfdecJSInterval *interval = (SwfdecJSInterval *) timeout; + JSContext *cx = interval->player->jscx; + jsval fun, rval; + + timeout->timestamp += SWFDEC_MSECS_TO_TICKS (interval->msecs); + swfdec_player_add_timeout (interval->player, timeout); + g_assert (JSVAL_IS_OBJECT (interval->vals[1])); + if (JSVAL_IS_STRING (interval->vals[0])) { + JSAtom *atom = js_AtomizeString (cx, JSVAL_TO_STRING (interval->vals[0]), 0); + if (!atom) + return; + if (!js_GetProperty (cx, JSVAL_TO_OBJECT (interval->vals[1]), + (jsid) atom, &fun)) + return; + } else { + fun = interval->vals[0]; + } + js_InternalCall (cx, JSVAL_TO_OBJECT (interval->vals[1]), fun, + interval->n_args, &interval->vals[2], &rval); +} + +static SwfdecJSInterval * +swfdec_js_interval_new (guint n_args) +{ + SwfdecJSInterval *ret = g_malloc (sizeof (SwfdecJSInterval) + sizeof (jsval) * (2 + n_args)); + + ret->timeout.callback = swfdec_js_interval_trigger; + ret->n_args = n_args; + return ret; +} + +static JSBool +swfdec_js_global_setInterval (JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) +{ + SwfdecPlayer *player = JS_GetContextPrivate (cx); + JSObject *object; + jsval fun; + unsigned int i, n_args, first_arg, msecs; + SwfdecJSInterval *interval; + + if (!JSVAL_IS_OBJECT (argv[0])) { + SWFDEC_WARNING ("first argument to setInterval is not an object"); + return JS_TRUE; + } + object = JSVAL_TO_OBJECT (argv[0]); + if (JS_GetClass (object) == &js_FunctionClass) { + fun = argv[0]; + object = JS_GetParent (cx, object); + if (object == NULL) { + SWFDEC_WARNING ("function has no parent?!"); + return JS_TRUE; + } + first_arg = 2; + } else { + if (argc < 3) { + SWFDEC_WARNING ("setInterval needs 3 arguments when not called with function"); + return JS_TRUE; + } + if (!JSVAL_IS_STRING (argv[1])) { + SWFDEC_WARNING ("function name passed to setInterval is not a string"); + return JS_TRUE; + } + fun = argv[1]; + first_arg = 3; + } + if (!JS_ValueToECMAUint32 (cx, argv[first_arg - 1], &msecs)) + return JS_FALSE; +#define MIN_INTERVAL_TIME 10 + if (msecs < MIN_INTERVAL_TIME) { + SWFDEC_INFO ("interval duration is %u, making it %u msecs", msecs, MIN_INTERVAL_TIME); + msecs = MIN_INTERVAL_TIME; + } + n_args = argc - first_arg; + interval = swfdec_js_interval_new (n_args); + interval->player = player; + interval->id = ++player->interval_id; + interval->msecs = msecs; + interval->vals[0] = fun; + interval->vals[1] = OBJECT_TO_JSVAL (object); + memcpy (&interval->vals[2], &argv[first_arg], n_args); + for (i = 0; i < n_args + 2; i++) { + if (!JS_AddRoot (cx, &interval->vals[i])) { + /* FIXME: is it save roots that weren't added before? */ + swfdec_js_interval_free (interval); + return JS_FALSE; + } + } + interval->timeout.timestamp = player->time + SWFDEC_MSECS_TO_TICKS (interval->msecs); + swfdec_player_add_timeout (player, &interval->timeout); + interval->player->intervals = + g_list_prepend (interval->player->intervals, interval); + *rval = INT_TO_JSVAL (interval->id); + return JS_TRUE; +} + +static JSBool +swfdec_js_global_clearInterval (JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) +{ + SwfdecPlayer *player = JS_GetContextPrivate (cx); + guint id; + GList *walk; + + if (!JSVAL_IS_INT (argv[0])) { + SWFDEC_WARNING ("argument is not an int"); + return JS_TRUE; + } + id = JSVAL_TO_INT (argv[0]); + for (walk = player->intervals; walk; walk = walk->next) { + SwfdecJSInterval *interval = walk->data; + if (interval->id != id) + continue; + swfdec_js_interval_free (interval); + break; + } + return JS_TRUE; +} + +/*** VARIOUS ***/ JSBool swfdec_js_global_eval (JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) @@ -80,10 +233,12 @@ swfdec_js_stopAllSounds (JSContext *cx, } static JSFunctionSpec global_methods[] = { - { "eval", swfdec_js_global_eval, 1, 0, 0 }, - { "random", swfdec_js_random, 1, 0, 0 }, - { "stopAllSounds", swfdec_js_stopAllSounds,0, 0, 0 }, - { "trace", swfdec_js_trace, 1, 0, 0 }, + { "clearInterval", swfdec_js_global_clearInterval, 1, 0, 0 }, + { "eval", swfdec_js_global_eval, 1, 0, 0 }, + { "random", swfdec_js_random, 1, 0, 0 }, + { "setInterval", swfdec_js_global_setInterval, 2, 0, 0 }, + { "stopAllSounds", swfdec_js_stopAllSounds, 0, 0, 0 }, + { "trace", swfdec_js_trace, 1, 0, 0 }, { NULL, NULL, 0, 0, 0 } }; diff --git a/libswfdec/swfdec_player_internal.h b/libswfdec/swfdec_player_internal.h index 7aa499d..ebc5fe9 100644 --- a/libswfdec/swfdec_player_internal.h +++ b/libswfdec/swfdec_player_internal.h @@ -80,6 +80,8 @@ struct _SwfdecPlayer /* iterating */ GList * movies; /* list of all moveis that want to be iterated */ SwfdecRingBuffer * actions; /* all actions we've queued up so far */ + unsigned int interval_id; /* id returned from setInterval call */ + GList * intervals; /* all currently running intervals */ }; struct _SwfdecPlayerClass diff-tree 8a66540298c89725624385a022580e593d6da3a4 (from 06ed0ce6ffaa57e8b70054dcf0c1d3f3dcc0adb0) Author: Benjamin Otte <otte@gnome.org> Date: Mon Feb 19 18:47:21 2007 +0100 add tests for setInterval/clearInterval diff --git a/test/trace/Makefile.am b/test/trace/Makefile.am index 1330d92..4d11f13 100644 --- a/test/trace/Makefile.am +++ b/test/trace/Makefile.am @@ -100,6 +100,12 @@ EXTRA_DIST = \ scope.swf.trace \ scope2.swf \ scope2.swf.trace \ + setinterval.swf \ + setinterval.swf.trace + setinterval2.swf \ + setinterval2.swf.trace \ + setinterval-clear.swf \ + setinterval-clear.swf.trace \ setvariable.swf \ setvariable.swf.trace \ transform.swf \ diff --git a/test/trace/setinterval-clear.swf b/test/trace/setinterval-clear.swf new file mode 100755 index 0000000..963a581 Binary files /dev/null and b/test/trace/setinterval-clear.swf differ diff --git a/test/trace/setinterval-clear.swf.trace b/test/trace/setinterval-clear.swf.trace new file mode 100755 index 0000000..38e2f4a --- /dev/null +++ b/test/trace/setinterval-clear.swf.trace @@ -0,0 +1,3 @@ +Test clearInterval works +1 +2 diff --git a/test/trace/setinterval.swf b/test/trace/setinterval.swf new file mode 100755 index 0000000..2cda24a Binary files /dev/null and b/test/trace/setinterval.swf differ diff --git a/test/trace/setinterval.swf.trace b/test/trace/setinterval.swf.trace new file mode 100755 index 0000000..4f6bc44 --- /dev/null +++ b/test/trace/setinterval.swf.trace @@ -0,0 +1,21 @@ +Test setInterval works +tick: 1 +tick: 3 +tick: 1 +tick: 3 +tick: 1 +tick: 3 +tick: 1 +tick: 3 +tick: 1 +tick: 3 +tick: 1 +tick: 3 +tick: 1 +tick: 3 +tick: 1 +tick: 3 +tick: 1 +tick: 3 +tick: 1 +tick: 3 diff --git a/test/trace/setinterval2.swf b/test/trace/setinterval2.swf new file mode 100755 index 0000000..c768b9e Binary files /dev/null and b/test/trace/setinterval2.swf differ diff --git a/test/trace/setinterval2.swf.trace b/test/trace/setinterval2.swf.trace new file mode 100755 index 0000000..54adc6e --- /dev/null +++ b/test/trace/setinterval2.swf.trace @@ -0,0 +1,5 @@ +Test some error conditions of setInterval +undefined +1 +hi +boo diff-tree 06ed0ce6ffaa57e8b70054dcf0c1d3f3dcc0adb0 (from 23a6d3a178edeb4b3f0c822f6e4eafb880b2d561) Author: Benjamin Otte <otte@gnome.org> Date: Mon Feb 19 18:45:18 2007 +0100 add check to ensure preloading works diff --git a/test/trace/Makefile.am b/test/trace/Makefile.am index 73bded0..1330d92 100644 --- a/test/trace/Makefile.am +++ b/test/trace/Makefile.am @@ -92,6 +92,8 @@ EXTRA_DIST = \ order.swf.trace \ parent-root.swf \ parent-root.swf.trace \ + preload.swf \ + preload.swf.trace \ rotation-5.swf \ rotation-5.swf.trace \ scope.swf \ diff --git a/test/trace/preload.swf b/test/trace/preload.swf new file mode 100755 index 0000000..c613e65 Binary files /dev/null and b/test/trace/preload.swf differ diff --git a/test/trace/preload.swf.trace b/test/trace/preload.swf.trace new file mode 100755 index 0000000..7e648bf --- /dev/null +++ b/test/trace/preload.swf.trace @@ -0,0 +1,4 @@ +_level0 + +_level0 + diff-tree 23a6d3a178edeb4b3f0c822f6e4eafb880b2d561 (from 77b34b229da25f92968a27d4ed759f154b6519b2) Author: Benjamin Otte <otte@gnome.org> Date: Mon Feb 19 18:44:59 2007 +0100 Freeing of timeouts doesn't work - revert to old system diff --git a/libswfdec/swfdec_player.c b/libswfdec/swfdec_player.c index 0b52aeb..0717ff5 100644 --- a/libswfdec/swfdec_player.c +++ b/libswfdec/swfdec_player.c @@ -101,20 +101,6 @@ swfdec_player_get_next_event_time (Swfde } } -static int -swfdec_timeout_compare (gconstpointer a, gconstpointer b) -{ - const SwfdecTimeout *ta = a; - const SwfdecTimeout *tb = b; - - /* FIXME: not overflow-safe */ - if (ta->timestamp < tb->timestamp) - return -1; - if (ta->timestamp > tb->timestamp) - return 1; - return 0; -} - /** * swfdec_player_add_timeout: * @player: a #SwfdecPlayer @@ -143,6 +129,7 @@ swfdec_timeout_compare (gconstpointer a, void swfdec_player_add_timeout (SwfdecPlayer *player, SwfdecTimeout *timeout) { + GList *walk; SwfdecTick next_tick; g_return_if_fail (SWFDEC_IS_PLAYER (player)); @@ -152,7 +139,13 @@ swfdec_player_add_timeout (SwfdecPlayer SWFDEC_LOG ("adding timeout %p", timeout); next_tick = swfdec_player_get_next_event_time (player); - player->timeouts = g_list_insert_sorted (player->timeouts, timeout, swfdec_timeout_compare); + /* the order is important, on events with the same time, we make sure the new one is last */ + for (walk = player->timeouts; walk; walk = walk->next) { + SwfdecTimeout *cur = walk->data; + if (cur->timestamp > timeout->timestamp) + break; + } + player->timeouts = g_list_insert_before (player->timeouts, walk, timeout); if (next_tick != swfdec_player_get_next_event_time (player)) g_object_notify (G_OBJECT (player), "next-event"); } @@ -329,7 +322,6 @@ swfdec_player_set_property (GObject *obj static void swfdec_player_dispose (GObject *object) { - GList *walk; SwfdecPlayer *player = SWFDEC_PLAYER (object); swfdec_player_stop_all_sounds (player); @@ -337,28 +329,16 @@ swfdec_player_dispose (GObject *object) g_list_foreach (player->roots, (GFunc) swfdec_movie_destroy, NULL); g_list_free (player->roots); - if (player->rate) { - swfdec_player_remove_timeout (player, &player->iterate_timeout); - } - walk = player->timeouts; - while (walk) { - SwfdecTimeout *timeout = walk->data; - walk = walk->next; - if (timeout->free) { - /* all the others must remove themselves */ - timeout->free (timeout); - swfdec_player_remove_timeout (player, timeout); - } - } swfdec_js_finish_player (player); g_assert (swfdec_ring_buffer_pop (player->actions) == NULL); swfdec_ring_buffer_free (player->actions); g_assert (player->movies == NULL); g_assert (player->audio == NULL); + if (player->rate) { + swfdec_player_remove_timeout (player, &player->iterate_timeout); + } g_assert (player->timeouts == NULL); - g_list_free (player->timeouts); - player->timeouts = NULL; swfdec_cache_unref (player->cache); G_OBJECT_CLASS (swfdec_player_parent_class)->dispose (object); diff-tree 77b34b229da25f92968a27d4ed759f154b6519b2 (from ea81d2b805d5db2b7506c1c817efb5f9b8041b3c) Author: Benjamin Otte <otte@gnome.org> Date: Mon Feb 19 18:44:12 2007 +0100 arguments.toString() returns the empty string diff --git a/libswfdec/js/jsobj.c b/libswfdec/js/jsobj.c index 396c724..860e38c 100644 --- a/libswfdec/js/jsobj.c +++ b/libswfdec/js/jsobj.c @@ -913,13 +913,21 @@ js_obj_toString(JSContext *cx, JSObject size_t nchars; const char *clazz, *prefix; JSString *str; + JSClass *clasp; #if JS_HAS_INITIALIZERS if (cx->version == JSVERSION_1_2) return js_obj_toSource(cx, obj, argc, argv, rval); #endif - clazz = OBJ_GET_CLASS(cx, obj)->name; + clasp = OBJ_GET_CLASS(cx, obj); + clazz = clasp->name; + /* special case in here (woohoo) */ + if (clasp == &js_ArgumentsClass) { + *rval = STRING_TO_JSVAL(cx->runtime->emptyString); + return JS_TRUE; + } + nchars = 9 + strlen(clazz); /* 9 for "[object ]" */ chars = (jschar *) JS_malloc(cx, (nchars + 1) * sizeof(jschar)); if (!chars) diff-tree ea81d2b805d5db2b7506c1c817efb5f9b8041b3c (from 0ff56e6acbc042b3b914242565414a349796ca6f) Author: Benjamin Otte <otte@gnome.org> Date: Mon Feb 19 17:38:24 2007 +0100 shuffle disposing around again so timeouts get properly removed diff --git a/libswfdec/swfdec_player.c b/libswfdec/swfdec_player.c index fa5633a..0b52aeb 100644 --- a/libswfdec/swfdec_player.c +++ b/libswfdec/swfdec_player.c @@ -337,20 +337,26 @@ swfdec_player_dispose (GObject *object) g_list_foreach (player->roots, (GFunc) swfdec_movie_destroy, NULL); g_list_free (player->roots); + if (player->rate) { + swfdec_player_remove_timeout (player, &player->iterate_timeout); + } + walk = player->timeouts; + while (walk) { + SwfdecTimeout *timeout = walk->data; + walk = walk->next; + if (timeout->free) { + /* all the others must remove themselves */ + timeout->free (timeout); + swfdec_player_remove_timeout (player, timeout); + } + } swfdec_js_finish_player (player); g_assert (swfdec_ring_buffer_pop (player->actions) == NULL); swfdec_ring_buffer_free (player->actions); g_assert (player->movies == NULL); g_assert (player->audio == NULL); - if (player->rate) { - swfdec_player_remove_timeout (player, &player->iterate_timeout); - } - for (walk = player->timeouts; walk; walk = walk->next) { - SwfdecTimeout *timeout = walk->data; - g_assert (timeout->free); /* all the others must have removed themselves above */ - timeout->free (timeout); - } + g_assert (player->timeouts == NULL); g_list_free (player->timeouts); player->timeouts = NULL; swfdec_cache_unref (player->cache); diff-tree 0ff56e6acbc042b3b914242565414a349796ca6f (from a1ad80fa10c826ede2378b0c61983daf8ed8a223) Author: Benjamin Otte <otte@gnome.org> Date: Mon Feb 19 17:37:57 2007 +0100 register variables are 1-indexed We keep a register 0 around anyway to ease actions accessing registers, since those commands are 0-indexed. diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c index cebac2f..d46687f 100644 --- a/libswfdec/swfdec_script.c +++ b/libswfdec/swfdec_script.c @@ -1452,11 +1452,11 @@ swfdec_action_do_define_function (JSCont if (fun == NULL) return JS_FALSE; if (v2) { - fun->nvars = swfdec_bits_get_u8 (&bits); + fun->nvars = swfdec_bits_get_u8 (&bits) + 1; flags = swfdec_bits_get_u16 (&bits); preloads = g_new0 (guint8, n_args); } else { - fun->nvars = 4; + fun->nvars = 5; } for (i = 0; i < n_args; i++) { JSAtom *atom; @@ -2376,7 +2376,7 @@ swfdec_script_interpret (SwfdecScript *s } } if (script->flags) { - guint preload_reg = 0; + guint preload_reg = 1; SwfdecPlayer *player = JS_GetContextPrivate (cx); if (script->flags & SWFDEC_SCRIPT_PRELOAD_THIS) fp->vars[preload_reg++] = OBJECT_TO_JSVAL (fp->thisp); diff-tree a1ad80fa10c826ede2378b0c61983daf8ed8a223 (from 20654e6ae4379f8c7fbf3508e8990292d83a94df) Author: Benjamin Otte <otte@gnome.org> Date: Mon Feb 19 15:41:25 2007 +0100 allow timeouts to be destroyed by a destroy function This is in preparation for setInterval/clearInterval support diff --git a/libswfdec/swfdec_player.c b/libswfdec/swfdec_player.c index a1b9660..fa5633a 100644 --- a/libswfdec/swfdec_player.c +++ b/libswfdec/swfdec_player.c @@ -329,6 +329,7 @@ swfdec_player_set_property (GObject *obj static void swfdec_player_dispose (GObject *object) { + GList *walk; SwfdecPlayer *player = SWFDEC_PLAYER (object); swfdec_player_stop_all_sounds (player); @@ -345,7 +346,13 @@ swfdec_player_dispose (GObject *object) if (player->rate) { swfdec_player_remove_timeout (player, &player->iterate_timeout); } - g_assert (player->timeouts == NULL); + for (walk = player->timeouts; walk; walk = walk->next) { + SwfdecTimeout *timeout = walk->data; + g_assert (timeout->free); /* all the others must have removed themselves above */ + timeout->free (timeout); + } + g_list_free (player->timeouts); + player->timeouts = NULL; swfdec_cache_unref (player->cache); G_OBJECT_CLASS (swfdec_player_parent_class)->dispose (object); diff --git a/libswfdec/swfdec_player_internal.h b/libswfdec/swfdec_player_internal.h index be548b4..7aa499d 100644 --- a/libswfdec/swfdec_player_internal.h +++ b/libswfdec/swfdec_player_internal.h @@ -34,6 +34,7 @@ typedef struct _SwfdecTimeout SwfdecTime struct _SwfdecTimeout { SwfdecTick timestamp; /* timestamp at which this thing is supposed to trigger */ void (* callback) (SwfdecTimeout *advance); + void (* free) (SwfdecTimeout *advance); }; struct _SwfdecPlayer diff-tree 20654e6ae4379f8c7fbf3508e8990292d83a94df (from 163927d06c825430b89ed775925a6b9eb7578f22) Author: Benjamin Otte <otte@gnome.org> Date: Mon Feb 19 13:38:09 2007 +0100 various small fixes - script functions are heavyweight (otherwise they get inlined by jsinterp.c) - implement suppression of arguments property and suppress by default This way scripts get no argumens object when executed - initialize some variables to NULL in swfdec_script_execute that get later set when initializing the call object diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c index 60b58f1..cebac2f 100644 --- a/libswfdec/swfdec_script.c +++ b/libswfdec/swfdec_script.c @@ -1442,10 +1442,12 @@ swfdec_action_do_define_function (JSCont n_args = swfdec_bits_get_u16 (&bits); if (*function_name == '\0') { /* anonymous function */ - fun = JS_NewFunction (cx, NULL, n_args, JSFUN_LAMBDA, cx->fp->thisp, NULL); + fun = JS_NewFunction (cx, NULL, n_args, JSFUN_LAMBDA | JSFUN_HEAVYWEIGHT, + cx->fp->thisp, NULL); } else { /* named function */ - fun = JS_NewFunction (cx, NULL, n_args, 0, cx->fp->thisp, function_name); + fun = JS_NewFunction (cx, NULL, n_args, JSFUN_HEAVYWEIGHT, + cx->fp->thisp, function_name); } if (fun == NULL) return JS_FALSE; @@ -2284,6 +2286,9 @@ swfdec_script_new (SwfdecBits *bits, con script->refcount = 1; script->name = g_strdup (name ? name : "Unnamed script"); script->version = version; + /* These flags are the default arguments used by scripts read from a file. + * DefineFunction and friends override this */ + script->flags = SWFDEC_SCRIPT_SUPPRESS_ARGS; if (!swfdec_script_foreach_internal (bits, validate_action, script)) { /* assign a random buffer here so we have something to unref */ @@ -2375,8 +2380,16 @@ swfdec_script_interpret (SwfdecScript *s SwfdecPlayer *player = JS_GetContextPrivate (cx); if (script->flags & SWFDEC_SCRIPT_PRELOAD_THIS) fp->vars[preload_reg++] = OBJECT_TO_JSVAL (fp->thisp); - if (script->flags & SWFDEC_SCRIPT_PRELOAD_ARGS) - + if (script->flags & SWFDEC_SCRIPT_PRELOAD_ARGS) { + if (!JS_GetProperty (cx, fp->scopeChain, "arguments", &fp->vars[preload_reg++])) { + ok = JS_FALSE; + goto out; + } + } + if (script->flags & SWFDEC_SCRIPT_SUPPRESS_ARGS) { + /* FIXME: keep in sync with jsfun.c */ + fp->flags |= JS_BIT (JSFRAME_OVERRIDE_SHIFT); + } if (script->flags & SWFDEC_SCRIPT_PRELOAD_SUPER || script->flags & SWFDEC_SCRIPT_PRELOAD_ROOT || script->flags & SWFDEC_SCRIPT_PRELOAD_PARENT) { @@ -2582,7 +2595,7 @@ swfdec_script_execute (SwfdecScript *scr frame.callobj = frame.argsobj = NULL; frame.script = NULL; - frame.varobj = obj; + frame.varobj = NULL; frame.fun = swfdec_script_ensure_function (script, scriptable); frame.swf = script; frame.constant_pool = NULL; @@ -2593,7 +2606,7 @@ swfdec_script_execute (SwfdecScript *scr frame.sharpArray = NULL; frame.rval = JSVAL_VOID; frame.down = NULL; - frame.scopeChain = obj; + frame.scopeChain = NULL; frame.pc = NULL; frame.sp = oldfp ? oldfp->sp : NULL; frame.spbase = NULL; @@ -2630,6 +2643,11 @@ swfdec_script_execute (SwfdecScript *scr if (frame.constant_pool) swfdec_constant_pool_free (frame.constant_pool); + if (frame.callobj) + ok &= js_PutCallObject(cx, &frame); + if (frame.argsobj) + ok &= js_PutArgsObject(cx, &frame); + cx->fp = oldfp; if (oldfp) { g_assert (cx->dormantFrameChain == oldfp); diff-tree 163927d06c825430b89ed775925a6b9eb7578f22 (from bdb4e1d3d5946d82bd320c8a6b8090de02547aa8) Author: Benjamin Otte <otte@gnome.org> Date: Mon Feb 19 13:35:44 2007 +0100 Do not lookup flags from bytecode when using Flash bytecodes diff --git a/libswfdec/js/jsobj.c b/libswfdec/js/jsobj.c index 112bdc8..396c724 100644 --- a/libswfdec/js/jsobj.c +++ b/libswfdec/js/jsobj.c @@ -2469,7 +2469,7 @@ js_LookupPropertyWithFlags(JSContext *cx if (clasp->flags & JSCLASS_NEW_RESOLVE) { newresolve = (JSNewResolveOp)resolve; - if (cx->fp && (pc = cx->fp->pc)) { + if (cx->fp && cx->fp->script && (pc = cx->fp->pc)) { cs = &js_CodeSpec[*pc]; format = cs->format; if ((format & JOF_MODEMASK) != JOF_NAME) diff-tree bdb4e1d3d5946d82bd320c8a6b8090de02547aa8 (from 010c30904ac1e78dbbd34fc865a537b506b223b1) Author: Benjamin Otte <otte@gnome.org> Date: Mon Feb 19 11:04:22 2007 +0100 named functions belong to this, not to the scope chain fixes function2.swf test diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c index d923039..60b58f1 100644 --- a/libswfdec/swfdec_script.c +++ b/libswfdec/swfdec_script.c @@ -1530,7 +1530,7 @@ swfdec_action_do_define_function (JSCont *cx->fp->sp++ = OBJECT_TO_JSVAL (fun->object); } else { jsval val = OBJECT_TO_JSVAL (fun->object); - if (!JS_SetProperty (cx, OBJ_THIS_OBJECT (cx, cx->fp->scopeChain), function_name, &val)) + if (!JS_SetProperty (cx, cx->fp->thisp, function_name, &val)) return JS_FALSE; } diff-tree 010c30904ac1e78dbbd34fc865a537b506b223b1 (from 23429b410bd475e0bc85db66160d04b2a4c61911) Author: Benjamin Otte <otte@gnome.org> Date: Mon Feb 19 10:46:12 2007 +0100 make sure we really interrupt when breakpoints are set we're not having a special breakpoint at index 0 anymore, so don't index from 1 diff --git a/libswfdec/swfdec_debugger.c b/libswfdec/swfdec_debugger.c index 9a255b8..7f3546d 100644 --- a/libswfdec/swfdec_debugger.c +++ b/libswfdec/swfdec_debugger.c @@ -253,7 +253,7 @@ swfdec_debugger_update_interrupting (Swf guint i; gboolean should_interrupt = debugger->stepping; - for (i = 1; i < debugger->breakpoints->len && !should_interrupt; i++) { + for (i = 0; i < debugger->breakpoints->len && !should_interrupt; i++) { Breakpoint *br = &g_array_index (debugger->breakpoints, Breakpoint, i); if (br->script) { @@ -280,8 +280,9 @@ swfdec_debugger_set_breakpoint (SwfdecDe g_return_val_if_fail (script != NULL, 0); g_return_val_if_fail (line < script->n_commands, 0); - if (debugger->breakpoints == NULL) + if (debugger->breakpoints == NULL) { debugger->breakpoints = g_array_new (FALSE, FALSE, sizeof (Breakpoint)); + } if (script->commands[line].breakpoint != 0) return script->commands[line].breakpoint; diff-tree 23429b410bd475e0bc85db66160d04b2a4c61911 (from c13c11c4f1bb89da4ff0ab669868a896859b6d51) Author: Benjamin Otte <otte@gnome.org> Date: Mon Feb 19 10:44:58 2007 +0100 set buffer to NULL if not used, so we don't unref it later diff --git a/libswfdec/swfdec_tag.c b/libswfdec/swfdec_tag.c index 97a1e4d..9fd2491 100644 --- a/libswfdec/swfdec_tag.c +++ b/libswfdec/swfdec_tag.c @@ -225,6 +225,7 @@ tag_func_define_sprite (SwfdecSwfDecoder swfdec_swf_decoder_get_tag_name (tag), tag_len); if (tag_len == 0) { + buffer = NULL; swfdec_bits_init_data (&s->b, NULL, 0); } else { buffer = swfdec_bits_get_buffer (&parse, tag_len); diff-tree c13c11c4f1bb89da4ff0ab669868a896859b6d51 (from fe60df1a5559878b417a19a4c25355b6b996c56c) Author: Benjamin Otte <otte@gnome.org> Date: Mon Feb 19 09:33:14 2007 +0100 test that calling an undefined function does not abort execution diff --git a/test/trace/Makefile.am b/test/trace/Makefile.am index 294ae51..73bded0 100644 --- a/test/trace/Makefile.am +++ b/test/trace/Makefile.am @@ -48,6 +48,8 @@ EXTRA_DIST = \ function1.swf.trace \ function2.swf \ function2.swf.trace \ + function-undefined.swf \ + function-undefined.swf.trace \ goto1.swf \ goto1.swf.trace \ goto2.swf \ diff --git a/test/trace/function-undefined.swf b/test/trace/function-undefined.swf new file mode 100755 index 0000000..11484ca Binary files /dev/null and b/test/trace/function-undefined.swf differ diff --git a/test/trace/function-undefined.swf.trace b/test/trace/function-undefined.swf.trace new file mode 100755 index 0000000..742b9e5 --- /dev/null +++ b/test/trace/function-undefined.swf.trace @@ -0,0 +1,2 @@ +Test that calling undefined functions doesn't abort +didn't abort diff-tree fe60df1a5559878b417a19a4c25355b6b996c56c (from 68420cdc4618b5cb27669920bdef80f63f75f4e8) Author: Benjamin Otte <otte@gnome.org> Date: Mon Feb 19 08:16:40 2007 +0100 warn if a function does not exist, so it's easy to see what to implement diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c index 6972c81..d923039 100644 --- a/libswfdec/swfdec_script.c +++ b/libswfdec/swfdec_script.c @@ -639,6 +639,10 @@ swfdec_action_call_function (JSContext * return JS_FALSE; if (!JS_GetProperty (cx, obj, s, &fun)) return JS_FALSE; + if (!JSVAL_IS_OBJECT (fun)) { + SWFDEC_WARNING ("%s:%s is not a function", + JS_GetClass (obj)->name, s); + } fp->sp[-1] = fun; fp->sp[-2] = OBJECT_TO_JSVAL (obj); swfdec_action_call (cx, n_args, 0); diff-tree 68420cdc4618b5cb27669920bdef80f63f75f4e8 (from 52e6b97641109e79877c007d6da16f7e5d5271b1) Author: Benjamin Otte <otte@gnome.org> Date: Sat Feb 17 22:06:14 2007 +0100 only update the script if the script really changed big performance boost diff --git a/player/swfdec_debug_script.c b/player/swfdec_debug_script.c index 83e61c9..ccf6a3b 100644 --- a/player/swfdec_debug_script.c +++ b/player/swfdec_debug_script.c @@ -205,6 +205,8 @@ swfdec_debug_script_set_script (SwfdecDe if (debug->debugger == NULL) return; + if (debug->script == dscript) + return; debug->script = dscript; if (dscript) { swfdec_debug_script_set_model (debug); diff-tree 52e6b97641109e79877c007d6da16f7e5d5271b1 (from 7bd0f8a278aeb516f76ecdfb6297debd6fb736ab) Author: Benjamin Otte <otte@gnome.org> Date: Sat Feb 17 20:19:24 2007 +0100 check the parent of root really is undefined diff --git a/test/trace/Makefile.am b/test/trace/Makefile.am index f1755ee..294ae51 100644 --- a/test/trace/Makefile.am +++ b/test/trace/Makefile.am @@ -88,6 +88,8 @@ EXTRA_DIST = \ object-math-7.swf.trace \ order.swf \ order.swf.trace \ + parent-root.swf \ + parent-root.swf.trace \ rotation-5.swf \ rotation-5.swf.trace \ scope.swf \ diff --git a/test/trace/parent-root.swf b/test/trace/parent-root.swf new file mode 100755 index 0000000..a8eb741 Binary files /dev/null and b/test/trace/parent-root.swf differ diff --git a/test/trace/parent-root.swf.trace b/test/trace/parent-root.swf.trace new file mode 100755 index 0000000..4625226 --- /dev/null +++ b/test/trace/parent-root.swf.trace @@ -0,0 +1,2 @@ +The parent of root is: +undefined diff-tree 7bd0f8a278aeb516f76ecdfb6297debd6fb736ab (from 4600fb2de56a5b49aa2c4cf8d3d67d2811f8f46a) Author: Benjamin Otte <otte@gnome.org> Date: Sat Feb 17 20:18:53 2007 +0100 the parent of root is undefined diff --git a/libswfdec/swfdec_js_movie.c b/libswfdec/swfdec_js_movie.c index dde352d..5b730b3 100644 --- a/libswfdec/swfdec_js_movie.c +++ b/libswfdec/swfdec_js_movie.c @@ -979,14 +979,16 @@ mc_parent (JSContext *cx, JSObject *obj, g_assert (movie); /* FIXME: what do we do if we're the root movie? */ - if (movie->parent) + if (movie->parent) { movie = movie->parent; - jsobj = swfdec_scriptable_get_object (SWFDEC_SCRIPTABLE (movie)); - if (jsobj == NULL) - return JS_FALSE; - - *vp = OBJECT_TO_JSVAL (jsobj); + jsobj = swfdec_scriptable_get_object (SWFDEC_SCRIPTABLE (movie)); + if (jsobj == NULL) + return JS_FALSE; + + *vp = OBJECT_TO_JSVAL (jsobj); + } + /* else return JSVAL_VOID */ return JS_TRUE; } diff-tree 4600fb2de56a5b49aa2c4cf8d3d67d2811f8f46a (from abee9a29d76d305e67af6632dedc3b66c4e6827c) Author: Benjamin Otte <otte@gnome.org> Date: Sat Feb 17 19:53:40 2007 +0100 make all scripts have a call object This is required to be able to handle DefineLocal. It will definitely break more functions than I've fixed here, so if you find one that still assumes fp->scopeChain is the movie object, change it to use fp->thisp. Now all scripts have their own function, and they can access it via script->fun. If the function gets GC'ed, it'll unset it again. diff --git a/libswfdec/js/jsfun.c b/libswfdec/js/jsfun.c index a085673..a6ae7fc 100644 --- a/libswfdec/js/jsfun.c +++ b/libswfdec/js/jsfun.c @@ -1042,6 +1042,9 @@ fun_convert(JSContext *cx, JSObject *obj } } +struct _SwfdecScript { + JSFunction * fun; +}; extern void swfdec_script_unref (void *script); static void fun_finalize(JSContext *cx, JSObject *obj) @@ -1059,8 +1062,10 @@ fun_finalize(JSContext *cx, JSObject *ob return; if (fun->script) js_DestroyScript(cx, fun->script); - if (fun->swf) + if (fun->swf) { swfdec_script_unref (fun->swf); + ((struct _SwfdecScript *) fun->swf)->fun = NULL; + } JS_free(cx, fun); } diff --git a/libswfdec/swfdec_js.c b/libswfdec/swfdec_js.c index 4c14100..481ec48 100644 --- a/libswfdec/swfdec_js.c +++ b/libswfdec/swfdec_js.c @@ -334,7 +334,7 @@ swfdec_js_eval_set_property (JSContext * if (obj == NULL) { if (cx->fp == NULL || cx->fp->scopeChain == NULL) return JS_FALSE; - obj = cx->fp->scopeChain; + obj = JS_GetParent (cx, cx->fp->scopeChain); } return OBJ_SET_PROPERTY (cx, obj, (jsid) atom, ret); } @@ -383,8 +383,8 @@ swfdec_js_eval_internal (JSContext *cx, if (obj == NULL) { if (cx->fp == NULL) goto out; - g_assert (cx->fp->scopeChain); - cur = OBJECT_TO_JSVAL (OBJ_THIS_OBJECT (cx, cx->fp->scopeChain)); + g_assert (cx->fp->thisp); + cur = OBJECT_TO_JSVAL (cx->fp->thisp); } finish: diff --git a/libswfdec/swfdec_js_movie.c b/libswfdec/swfdec_js_movie.c index 10fde07..dde352d 100644 --- a/libswfdec/swfdec_js_movie.c +++ b/libswfdec/swfdec_js_movie.c @@ -941,6 +941,35 @@ mc_rotation_set (JSContext *cx, JSObject } static JSBool +mc_xmouse_get (JSContext *cx, JSObject *obj, jsval id, jsval *vp) +{ + double x, y; + SwfdecMovie *movie; + + movie = JS_GetPrivate (cx, obj); + g_assert (movie); + + swfdec_movie_get_mouse (movie, &x, &y); + x = rint (x * SWFDEC_TWIPS_SCALE_FACTOR) / SWFDEC_TWIPS_SCALE_FACTOR; + return JS_NewNumberValue (cx, x, vp); +} + +static JSBool +mc_ymouse_get (JSContext *cx, JSObject *obj, jsval id, jsval *vp) +{ + double x, y; + SwfdecMovie *movie; + + movie = JS_GetPrivate (cx, obj); + g_assert (movie); + + swfdec_movie_get_mouse (movie, &x, &y); + y = rint (y * SWFDEC_TWIPS_SCALE_FACTOR) / SWFDEC_TWIPS_SCALE_FACTOR; + return JS_NewNumberValue (cx, y, vp); +} + +/* FIXME: what do we do if we're the root movie? */ +static JSBool mc_parent (JSContext *cx, JSObject *obj, jsval id, jsval *vp) { SwfdecMovie *movie; @@ -1040,10 +1069,10 @@ static JSPropertySpec movieclip_props[] {"_focusrect", -1, MC_PROP_ATTRS, not_reached, not_reached }, {"_soundbuftime", -1, MC_PROP_ATTRS, not_reached, not_reached }, {"_quality", -1, MC_PROP_ATTRS, not_reached, not_reached }, - {"_xmouse", -1, MC_PROP_ATTRS, not_reached, not_reached }, - {"_ymouse", -1, MC_PROP_ATTRS, not_reached, not_reached }, - {"_parent", -1, MC_PROP_ATTRS | JSPROP_READONLY, mc_parent, NULL}, - {"_root", -1, MC_PROP_ATTRS | JSPROP_READONLY, mc_root, NULL}, + {"_xmouse", -1, MC_PROP_ATTRS | JSPROP_READONLY, mc_xmouse_get, NULL }, + {"_ymouse", -1, MC_PROP_ATTRS | JSPROP_READONLY, mc_ymouse_get, NULL }, + {"_parent", -1, MC_PROP_ATTRS | JSPROP_READONLY, mc_parent, NULL }, + {"_root", -1, MC_PROP_ATTRS | JSPROP_READONLY, mc_root, NULL }, {NULL} }; diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c index 1439882..6972c81 100644 --- a/libswfdec/swfdec_script.c +++ b/libswfdec/swfdec_script.c @@ -137,8 +137,7 @@ swfdec_action_has_register (JSContext *c static SwfdecMovie * swfdec_action_get_target (JSContext *cx) { - JSObject *object = cx->fp->scopeChain; - object = OBJ_THIS_OBJECT (cx, object); + JSObject *object = cx->fp->thisp; return swfdec_scriptable_from_jsval (cx, OBJECT_TO_JSVAL (object), SWFDEC_TYPE_MOVIE); } @@ -1638,10 +1637,7 @@ swfdec_action_define_local (JSContext *c { const char *name; - if (cx->fp->callobj == NULL) { - SWFDEC_ERROR ("FIXME: no local scope"); - return JS_FALSE; - } + g_assert (cx->fp->callobj != NULL); name = swfdec_js_to_string (cx, cx->fp->sp[-2]); if (name == NULL) return JS_FALSE; @@ -1657,10 +1653,7 @@ swfdec_action_define_local2 (JSContext * const char *name; jsval val = JSVAL_VOID; - if (cx->fp->callobj == NULL) { - SWFDEC_ERROR ("FIXME: no local scope"); - return JS_FALSE; - } + g_assert (cx->fp->callobj != NULL); name = swfdec_js_to_string (cx, cx->fp->sp[-1]); if (name == NULL) return JS_FALSE; @@ -2549,6 +2542,22 @@ internal_error: goto no_catch; } +static JSFunction * +swfdec_script_ensure_function (SwfdecScript *script, SwfdecScriptable *scriptable) +{ + JSContext *cx = scriptable->jscx; + JSObject *parent; + + if (script->fun) + return script->fun; + parent = swfdec_scriptable_get_object (scriptable); + script->fun = JS_NewFunction (cx, NULL, 0, JSFUN_LAMBDA, parent, NULL); + script->fun->swf = script; + script->fun->nvars = 4; + swfdec_script_ref (script); + return script->fun; +} + jsval swfdec_script_execute (SwfdecScript *script, SwfdecScriptable *scriptable) { @@ -2570,7 +2579,7 @@ swfdec_script_execute (SwfdecScript *scr frame.callobj = frame.argsobj = NULL; frame.script = NULL; frame.varobj = obj; - frame.fun = NULL; + frame.fun = swfdec_script_ensure_function (script, scriptable); frame.swf = script; frame.constant_pool = NULL; frame.thisp = obj; @@ -2596,13 +2605,15 @@ swfdec_script_execute (SwfdecScript *scr return JS_FALSE; } frame.vars[0] = frame.vars[1] = frame.vars[2] = frame.vars[3] = JSVAL_VOID; + /* create a call object */ + if (!js_GetCallObject(cx, &frame, obj)) + return JS_FALSE; if (oldfp) { g_assert (!oldfp->dormantNext); oldfp->dormantNext = cx->dormantFrameChain; cx->dormantFrameChain = oldfp; } - cx->fp = &frame; /* diff --git a/libswfdec/swfdec_script.h b/libswfdec/swfdec_script.h index 82d2169..8af5755 100644 --- a/libswfdec/swfdec_script.h +++ b/libswfdec/swfdec_script.h @@ -46,6 +46,8 @@ typedef gboolean (* SwfdecScriptForeachF /* FIXME: May want to typedef to SwfdecBuffer directly */ struct _SwfdecScript { + /* must be first arg */ + JSFunction * fun; /* function script belongs to or NULL */ SwfdecBuffer * buffer; /* buffer holding the script */ unsigned int refcount; /* reference count */ char * name; /* name identifying this script */ diff-tree abee9a29d76d305e67af6632dedc3b66c4e6827c (from 20b8eddca6677d1c69f541d058fce59031487450) Author: Benjamin Otte <otte@gnome.org> Date: Sat Feb 17 19:39:16 2007 +0100 document swfdec_movie_get_mouse diff --git a/libswfdec/swfdec_movie.c b/libswfdec/swfdec_movie.c index 3ab9c88..cbb787c 100644 --- a/libswfdec/swfdec_movie.c +++ b/libswfdec/swfdec_movie.c @@ -401,6 +401,14 @@ swfdec_movie_global_to_local (SwfdecMovi cairo_matrix_transform_point (&movie->inverse_matrix, x, y); } +/** + * swfdec_movie_get_mouse: + * @movie: a #SwfdecMovie + * @x: pointer to hold result of X coordinate + * @y: pointer to hold result of y coordinate + * + * Gets the mouse coordinates in the coordinate space of @movie. + **/ void swfdec_movie_get_mouse (SwfdecMovie *movie, double *x, double *y) {
Maybe Matching Threads
- 3 commits - libswfdec/swfdec_js.c libswfdec/swfdec_js_movie.c 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
- Branch 'interpreter' - 28 commits - configure.ac libswfdec/js libswfdec/swfdec_buffer.c libswfdec/swfdec_edittext_movie.c libswfdec/swfdec_js.c libswfdec/swfdec_js_global.c libswfdec/swfdec_js.h libswfdec/swfdec_js_movie.c libswfdec/swfdec_player.c
- 17 commits - libswfdec/js libswfdec/swfdec_js.c libswfdec/swfdec_js_global.c libswfdec/swfdec_js.h libswfdec/swfdec_js_movie.c libswfdec/swfdec_movie.c libswfdec/swfdec_player.c libswfdec/swfdec_player_internal.h libswfdec/swfdec_root_movie.c
- Branch 'interpreter' - 9 commits - libswfdec/js libswfdec/Makefile.am libswfdec/swfdec_debugger.c libswfdec/swfdec_debugger.h libswfdec/swfdec_edittext_movie.c libswfdec/swfdec_event.c libswfdec/swfdec_js.c libswfdec/swfdec_js_global.c