[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
Benjamin Otte
company at kemper.freedesktop.org
Mon Feb 19 11:35:48 PST 2007
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 at 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 at 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 at 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 at gnome.org>
+ * Copyright (C) 2006-2007 Benjamin Otte <otte at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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)
{
More information about the Swfdec
mailing list