Benjamin Otte
2007-Jan-26 12:36 UTC
[Swfdec] 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 libswfdec/swfdec_js.h libswfdec/swfdec_root_movie.c libswfdec/swfdec_script.c libswfdec/swfdec_script.h libswfdec/swfdec_tag.c player/swfdebug.c player/swfdec_debug_scripts.c player/swfdec_player_manager.c test/swfedit_token.c
libswfdec/Makefile.am | 2 libswfdec/js/jsatom.c | 6 - libswfdec/js/jsatom.h | 1 libswfdec/swfdec_debugger.c | 116 +++++++++++++++++++++++--------------- libswfdec/swfdec_debugger.h | 16 +---- libswfdec/swfdec_edittext_movie.c | 4 - libswfdec/swfdec_event.c | 2 libswfdec/swfdec_js.c | 69 ++++++++++------------ libswfdec/swfdec_js.h | 6 - libswfdec/swfdec_js_global.c | 2 libswfdec/swfdec_root_movie.c | 8 ++ libswfdec/swfdec_script.c | 88 ++++++++++++++++++++++++---- libswfdec/swfdec_script.h | 12 +++ libswfdec/swfdec_tag.c | 2 player/swfdebug.c | 4 - player/swfdec_debug_scripts.c | 2 player/swfdec_player_manager.c | 8 +- test/swfedit_token.c | 1 18 files changed, 225 insertions(+), 124 deletions(-) New commits: diff-tree 6f0034ba32dd13577f1f2fb050734a7c55b4fdec (from db8da8e1714ce0839759c2fd0e65fbd6debf51fa) Author: Benjamin Otte <otte@gnome.org> Date: Fri Jan 26 21:32:40 2007 +0100 use NULL in _eval of SetVariable and GetVariable to walk the scope chain diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c index a3bb563..7848e14 100644 --- a/libswfdec/swfdec_script.c +++ b/libswfdec/swfdec_script.c @@ -316,7 +316,7 @@ swfdec_action_get_variable (JSContext *c s = swfdec_js_to_string (cx, cx->fp->sp[-1]); if (s == NULL) return JS_FALSE; - cx->fp->sp[-1] = swfdec_js_eval (cx, cx->fp->scopeChain, s); + cx->fp->sp[-1] = swfdec_js_eval (cx, NULL, s); return JS_TRUE; } @@ -329,7 +329,7 @@ swfdec_action_set_variable (JSContext *c if (s == NULL) return JS_FALSE; - swfdec_js_eval_set (cx, cx->fp->scopeChain, s, cx->fp->sp[-1]); + swfdec_js_eval_set (cx, NULL, s, cx->fp->sp[-1]); cx->fp->sp -= 2; return JS_TRUE; } diff-tree db8da8e1714ce0839759c2fd0e65fbd6debf51fa (from 2321fe755e190939f34b1d27b306a5270f17f43c) Author: Benjamin Otte <otte@gnome.org> Date: Fri Jan 26 21:32:04 2007 +0100 more fixes for swfdec_eval when parsing the scope chain diff --git a/libswfdec/swfdec_js.c b/libswfdec/swfdec_js.c index 84a1113..68e89ff 100644 --- a/libswfdec/swfdec_js.c +++ b/libswfdec/swfdec_js.c @@ -318,8 +318,6 @@ swfdec_js_eval_get_property (JSContext * return JS_FALSE; if (!prop) return JS_FALSE; - if (pobj) - obj = pobj; return OBJ_GET_PROPERTY (cx, obj, (jsid) prop->id, ret); } } @@ -345,7 +343,7 @@ static gboolean swfdec_js_eval_internal (JSContext *cx, JSObject *obj, const char *str, jsval *val, gboolean set) { - jsval cur; + jsval cur = JSVAL_NULL; char *work = NULL; SWFDEC_LOG ("eval called with \"%s\" on %p", str, obj); @@ -361,12 +359,10 @@ swfdec_js_eval_internal (JSContext *cx, goto out; obj = cx->fp->thisp; } - cur = OBJECT_TO_JSVAL (obj); while (str != NULL && *str != '\0') { char *dot = strchr (str, '.'); if (!JSVAL_IS_OBJECT (cur)) goto out; - obj = JSVAL_TO_OBJECT (cur); if (dot) { if (!swfdec_js_eval_get_property (cx, obj, str, dot - str, &cur)) goto out; @@ -381,6 +377,7 @@ swfdec_js_eval_internal (JSContext *cx, } str = NULL; } + obj = JSVAL_TO_OBJECT (cur); } if (obj == NULL) { if (cx->fp == NULL) diff-tree 2321fe755e190939f34b1d27b306a5270f17f43c (from 5fbaf958eeb90c6052933d2df118dc77fe18b15d) Author: Benjamin Otte <otte@gnome.org> Date: Fri Jan 26 18:17:39 2007 +0100 avoid strdup in js_eval diff --git a/libswfdec/swfdec_js.c b/libswfdec/swfdec_js.c index 9c01869..84a1113 100644 --- a/libswfdec/swfdec_js.c +++ b/libswfdec/swfdec_js.c @@ -300,13 +300,13 @@ fail: static JSBool swfdec_js_eval_get_property (JSContext *cx, JSObject *obj, - const char *name, jsval *ret) + const char *name, guint name_len, jsval *ret) { JSAtom *atom; JSObject *pobj; JSProperty *prop; - atom = js_Atomize (cx, name, strlen(name), 0); + atom = js_Atomize (cx, name, name_len, 0); if (!atom) return JS_FALSE; if (obj) { @@ -326,11 +326,11 @@ swfdec_js_eval_get_property (JSContext * static JSBool swfdec_js_eval_set_property (JSContext *cx, JSObject *obj, - const char *name, jsval *ret) + const char *name, guint name_len, jsval *ret) { JSAtom *atom; - atom = js_Atomize (cx, name, strlen(name), 0); + atom = js_Atomize (cx, name, name_len, 0); if (!atom) return JS_FALSE; if (obj == NULL) { @@ -368,17 +368,15 @@ swfdec_js_eval_internal (JSContext *cx, goto out; obj = JSVAL_TO_OBJECT (cur); if (dot) { - char *name = g_strndup (str, dot - str); - if (!swfdec_js_eval_get_property (cx, obj, name, &cur)) + if (!swfdec_js_eval_get_property (cx, obj, str, dot - str, &cur)) goto out; - g_free (name); str = dot + 1; } else { if (set) { - if (!swfdec_js_eval_set_property (cx, obj, str, val)) + if (!swfdec_js_eval_set_property (cx, obj, str, strlen (str), val)) goto out; } else { - if (!swfdec_js_eval_get_property (cx, obj, str, &cur)) + if (!swfdec_js_eval_get_property (cx, obj, str, strlen (str), &cur)) goto out; } str = NULL; diff-tree 5fbaf958eeb90c6052933d2df118dc77fe18b15d (from 6e0acc92fadc5b3ae1eaab51f3e16f3f96830e7a) Author: Benjamin Otte <otte@gnome.org> Date: Fri Jan 26 18:15:16 2007 +0100 fix _eval to work with the empty string This is a regression fix diff --git a/libswfdec/swfdec_js.c b/libswfdec/swfdec_js.c index 7111833..9c01869 100644 --- a/libswfdec/swfdec_js.c +++ b/libswfdec/swfdec_js.c @@ -384,6 +384,12 @@ swfdec_js_eval_internal (JSContext *cx, str = NULL; } } + if (obj == NULL) { + if (cx->fp == NULL) + goto out; + g_assert (cx->fp->scopeChain); + cur = OBJECT_TO_JSVAL (cx->fp->scopeChain); + } g_free (work); *val = cur; diff-tree 6e0acc92fadc5b3ae1eaab51f3e16f3f96830e7a (from ea89d7b542169e7173d93938041a16515b93c896) Author: Benjamin Otte <otte@gnome.org> Date: Fri Jan 26 18:12:00 2007 +0100 set property on the right object diff --git a/libswfdec/swfdec_js.c b/libswfdec/swfdec_js.c index 524707c..7111833 100644 --- a/libswfdec/swfdec_js.c +++ b/libswfdec/swfdec_js.c @@ -329,25 +329,16 @@ swfdec_js_eval_set_property (JSContext * const char *name, jsval *ret) { JSAtom *atom; - JSObject *pobj; - JSProperty *prop; atom = js_Atomize (cx, name, strlen(name), 0); if (!atom) return JS_FALSE; - if (obj) { - return OBJ_SET_PROPERTY (cx, obj, (jsid) atom, ret); - } else { + if (obj == NULL) { if (cx->fp == NULL || cx->fp->scopeChain == NULL) return JS_FALSE; - if (!js_FindProperty (cx, (jsid) atom, &obj, &pobj, &prop)) - return JS_FALSE; - if (!prop) - return JS_FALSE; - if (pobj) - obj = pobj; - return OBJ_SET_PROPERTY (cx, obj, (jsid) prop->id, ret); + obj = cx->fp->scopeChain; } + return OBJ_SET_PROPERTY (cx, obj, (jsid) atom, ret); } static gboolean diff-tree ea89d7b542169e7173d93938041a16515b93c896 (from 52828a39c261a28bf65734800692391b4f76b7c8) Author: Benjamin Otte <otte@gnome.org> Date: Fri Jan 26 18:06:33 2007 +0100 makee debugging work again I don't like the debugging implementation in SpiderMonkey at all, since it's too intrusive, but oh well... diff --git a/libswfdec/Makefile.am b/libswfdec/Makefile.am index 7233f02..0216266 100644 --- a/libswfdec/Makefile.am +++ b/libswfdec/Makefile.am @@ -15,7 +15,6 @@ lib_LTLIBRARIES = libswfdec-@SWFDEC_MAJO js_cflags = -I$(srcdir)/js/ -I./js -DXP_UNIX -DDEBUG -# swfdec_debugger.c libswfdec_@SWFDEC_MAJORMINOR@_la_SOURCES = \ swfdec_audio.c \ swfdec_audio_event.c \ @@ -34,6 +33,7 @@ libswfdec_@SWFDEC_MAJORMINOR@_la_SOURCES swfdec_codec_screen.c \ swfdec_color.c \ swfdec_debug.c \ + swfdec_debugger.c \ swfdec_decoder.c \ swfdec_edittext.c \ swfdec_edittext_movie.c \ diff --git a/libswfdec/swfdec_debugger.c b/libswfdec/swfdec_debugger.c index 6123389..9a255b8 100644 --- a/libswfdec/swfdec_debugger.c +++ b/libswfdec/swfdec_debugger.c @@ -28,20 +28,36 @@ #include "swfdec_movie.h" #include "swfdec_player_internal.h" #include "js/jsdbgapi.h" +#include "js/jsinterp.h" /* for frame->swf */ /*** SwfdecDebuggerScript ***/ +static gboolean +swfdec_debugger_add_command (gconstpointer bytecode, guint action, + const guint8 *data, guint len, gpointer arrayp) +{ + SwfdecDebuggerCommand command; + + command.code = bytecode; + command.breakpoint = 0; + command.description = swfdec_script_print_action (action, data, len); + g_array_append_val (arrayp, command); + return TRUE; +} + static SwfdecDebuggerScript * -swfdec_debugger_script_new (JSScript *script, const char *name, - SwfdecDebuggerCommand *commands, guint n_commands) +swfdec_debugger_script_new (SwfdecScript *script) { + GArray *array; SwfdecDebuggerScript *ret; ret = g_new0 (SwfdecDebuggerScript, 1); ret->script = script; - ret->name = g_strdup (name); - ret->commands = commands; - ret->n_commands = n_commands; + swfdec_script_ref (script); + array = g_array_new (TRUE, FALSE, sizeof (SwfdecDebuggerCommand)); + swfdec_script_foreach (script, swfdec_debugger_add_command, array); + ret->n_commands = array->len; + ret->commands = (SwfdecDebuggerCommand *) g_array_free (array, FALSE); return ret; } @@ -49,7 +65,13 @@ swfdec_debugger_script_new (JSScript *sc static void swfdec_debugger_script_free (SwfdecDebuggerScript *script) { + guint i; + g_assert (script); + swfdec_script_unref (script->script); + for (i = 0; i < script->n_commands; i++) { + g_free (script->commands[i].description); + } g_free (script->commands); g_free (script); } @@ -131,17 +153,16 @@ swfdec_debugger_new (void) } void -swfdec_debugger_add_script (SwfdecDebugger *debugger, JSScript *jscript, const char *name, - SwfdecDebuggerCommand *commands, guint n_commands) +swfdec_debugger_add_script (SwfdecDebugger *debugger, SwfdecScript *script) { - SwfdecDebuggerScript *dscript = swfdec_debugger_script_new (jscript, name, commands, n_commands); + SwfdecDebuggerScript *dscript = swfdec_debugger_script_new (script); - g_hash_table_insert (debugger->scripts, jscript, dscript); + g_hash_table_insert (debugger->scripts, script, dscript); g_signal_emit (debugger, signals[SCRIPT_ADDED], 0, dscript); } SwfdecDebuggerScript * -swfdec_debugger_get_script (SwfdecDebugger *debugger, JSScript *script) +swfdec_debugger_get_script (SwfdecDebugger *debugger, SwfdecScript *script) { SwfdecDebuggerScript *dscript = g_hash_table_lookup (debugger->scripts, script); @@ -149,7 +170,7 @@ swfdec_debugger_get_script (SwfdecDebugg } void -swfdec_debugger_remove_script (SwfdecDebugger *debugger, JSScript *script) +swfdec_debugger_remove_script (SwfdecDebugger *debugger, SwfdecScript *script) { SwfdecDebuggerScript *dscript = g_hash_table_lookup (debugger->scripts, script); @@ -211,15 +232,43 @@ swfdec_debugger_do_breakpoint (SwfdecDeb } static JSTrapStatus -swfdec_debugger_handle_breakpoint (JSContext *cx, JSScript *script, jsbytecode *pc, - jsval *rval, void *closure) +swfdec_debugger_interrupt_cb (JSContext *cx, JSScript *script, + jsbytecode *pc, jsval *rval, void *debugger) { - SwfdecDebugger *debugger = JS_GetContextPrivate (cx); - - swfdec_debugger_do_breakpoint (debugger, GPOINTER_TO_UINT (closure)); + SwfdecDebuggerScript *dscript; + guint line; + if (!swfdec_debugger_get_current (debugger, &dscript, &line)) + return JSTRAP_CONTINUE; + if (dscript->commands[line].breakpoint) { + swfdec_debugger_do_breakpoint (debugger, dscript->commands[line].breakpoint); + } else if (SWFDEC_DEBUGGER (debugger)->stepping) { + swfdec_debugger_do_breakpoint (debugger, 0); + } return JSTRAP_CONTINUE; } +static void +swfdec_debugger_update_interrupting (SwfdecDebugger *debugger) +{ + guint i; + gboolean should_interrupt = debugger->stepping; + + for (i = 1; i < debugger->breakpoints->len && !should_interrupt; i++) { + Breakpoint *br = &g_array_index (debugger->breakpoints, Breakpoint, i); + + if (br->script) { + should_interrupt = TRUE; + break; + } + } + if (should_interrupt) { + JS_SetInterrupt (JS_GetRuntime (SWFDEC_PLAYER (debugger)->jscx), + swfdec_debugger_interrupt_cb, debugger); + } else { + JS_ClearInterrupt (JS_GetRuntime (SWFDEC_PLAYER (debugger)->jscx), NULL, NULL); + } +} + guint swfdec_debugger_set_breakpoint (SwfdecDebugger *debugger, SwfdecDebuggerScript *script, guint line) @@ -242,10 +291,6 @@ swfdec_debugger_set_breakpoint (SwfdecDe break; br = NULL; } - if (!JS_SetTrap (SWFDEC_PLAYER (debugger)->jscx, script->script, - script->commands[line].code, swfdec_debugger_handle_breakpoint, - GUINT_TO_POINTER (i + 1))) - return 0; if (br == NULL) { g_array_set_size (debugger->breakpoints, debugger->breakpoints->len + 1); @@ -255,6 +300,7 @@ swfdec_debugger_set_breakpoint (SwfdecDe br->script = script; br->line = line; script->commands[line].breakpoint = i + 1; + swfdec_debugger_update_interrupting (debugger); g_signal_emit (debugger, signals[BREAKPOINT_ADDED], 0, i + 1); return i + 1; } @@ -275,16 +321,15 @@ swfdec_debugger_unset_breakpoint (Swfdec if (br->script == NULL) return; - JS_ClearTrap (SWFDEC_PLAYER (debugger)->jscx, br->script->script, - br->script->commands[br->line].code, NULL, NULL); g_signal_emit (debugger, signals[BREAKPOINT_REMOVED], 0, id); br->script->commands[br->line].breakpoint = 0; br->script = NULL; + swfdec_debugger_update_interrupting (debugger); } static gboolean -swfdec_debugger_get_from_js (SwfdecDebugger *debugger, JSScript *script, jsbytecode *pc, - SwfdecDebuggerScript **script_out, guint *line_out) +swfdec_debugger_get_from_js (SwfdecDebugger *debugger, SwfdecScript *script, + jsbytecode *pc, SwfdecDebuggerScript **script_out, guint *line_out) { guint line; SwfdecDebuggerScript *dscript = swfdec_debugger_get_script (debugger, script); @@ -292,7 +337,7 @@ swfdec_debugger_get_from_js (SwfdecDebug if (dscript == NULL) return FALSE; for (line = 0; line < dscript->n_commands; line++) { - if (pc == (jsbytecode *) dscript->commands[line].code) { + if (pc == dscript->commands[line].code) { if (script_out) *script_out = dscript; if (line_out) @@ -311,16 +356,16 @@ swfdec_debugger_get_current (SwfdecDebug { JSStackFrame *frame = NULL; JSContext *cx; - JSScript *script; jsbytecode *pc; cx = SWFDEC_PLAYER (debugger)->jscx; JS_FrameIterator (cx, &frame); if (frame == NULL) return FALSE; - script = JS_GetFrameScript (cx, frame); + if (frame->swf == NULL) + return FALSE; pc = JS_GetFramePC (cx, frame); - return swfdec_debugger_get_from_js (debugger, script, pc, dscript, line); + return swfdec_debugger_get_from_js (debugger, frame->swf, pc, dscript, line); } gboolean @@ -358,15 +403,6 @@ swfdec_debugger_get_n_breakpoints (Swfde return debugger->breakpoints->len; } -static JSTrapStatus -swfdec_debugger_interrupt_cb (JSContext *cx, JSScript *script, - jsbytecode *pc, jsval *rval, void *debugger) -{ - if (swfdec_debugger_get_current (debugger, NULL, NULL)) - swfdec_debugger_do_breakpoint (debugger, 0); - return JSTRAP_CONTINUE; -} - void swfdec_debugger_set_stepping (SwfdecDebugger *debugger, gboolean stepping) { @@ -375,12 +411,6 @@ swfdec_debugger_set_stepping (SwfdecDebu if (debugger->stepping == stepping) return; debugger->stepping = stepping; - if (stepping) { - JS_SetInterrupt (JS_GetRuntime (SWFDEC_PLAYER (debugger)->jscx), - swfdec_debugger_interrupt_cb, debugger); - } else { - JS_ClearInterrupt (JS_GetRuntime (SWFDEC_PLAYER (debugger)->jscx), NULL, NULL); - } } gboolean diff --git a/libswfdec/swfdec_debugger.h b/libswfdec/swfdec_debugger.h index bd54f9f..7c87604 100644 --- a/libswfdec/swfdec_debugger.h +++ b/libswfdec/swfdec_debugger.h @@ -23,8 +23,8 @@ #include <glib-object.h> #include <libswfdec/swfdec.h> #include <libswfdec/swfdec_player_internal.h> +#include <libswfdec/swfdec_script.h> #include <libswfdec/swfdec_types.h> -#include <libswfdec/js/jsapi.h> G_BEGIN_DECLS @@ -41,14 +41,13 @@ typedef struct _SwfdecDebuggerCommand Sw #define SWFDEC_DEBUGGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFDEC_TYPE_DEBUGGER, SwfdecDebuggerClass)) struct _SwfdecDebuggerCommand { - gpointer code; /* pointer to start bytecode in JScript */ + gconstpointer code; /* pointer to start bytecode in SwfdecScript */ guint breakpoint; /* id of breakpoint pointing here */ char * description; /* string describing the action */ }; struct _SwfdecDebuggerScript { - JSScript * script; /* the script */ - char * name; /* descriptive name of script */ + SwfdecScript * script; /* the script */ SwfdecDebuggerCommand *commands; /* commands executed in the script (NULL-terminated) */ guint n_commands; /* number of commands */ }; @@ -88,14 +87,11 @@ void swfdec_debugger_set_stepping (Swf gboolean swfdec_debugger_get_stepping (SwfdecDebugger * debugger); void swfdec_debugger_add_script (SwfdecDebugger * debugger, - JSScript * script, - const char * name, - SwfdecDebuggerCommand *commands, - guint n_commands); + SwfdecScript * script); SwfdecDebuggerScript * swfdec_debugger_get_script (SwfdecDebugger * debugger, - JSScript * script); + SwfdecScript * script); void swfdec_debugger_remove_script (SwfdecDebugger * debugger, - JSScript * script); + SwfdecScript * script); void swfdec_debugger_foreach_script (SwfdecDebugger * debugger, GFunc func, gpointer data); diff --git a/libswfdec/swfdec_event.c b/libswfdec/swfdec_event.c index 7ed820b..d988ad3 100644 --- a/libswfdec/swfdec_event.c +++ b/libswfdec/swfdec_event.c @@ -146,7 +146,7 @@ swfdec_event_list_parse (SwfdecEventList event.key = key; name = g_strconcat (description, ".", swfdec_event_list_condition_name (conditions), NULL); - event.script = swfdec_script_new (bits, name, version); + event.script = swfdec_script_new_for_player (list->player, bits, name, version); g_free (name); if (event.script) g_array_append_val (list->events, event); diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c index e5c205f..a3bb563 100644 --- a/libswfdec/swfdec_script.c +++ b/libswfdec/swfdec_script.c @@ -23,6 +23,7 @@ #include "swfdec_script.h" #include "swfdec_debug.h" +#include "swfdec_debugger.h" #include "swfdec_scriptable.h" #include "js/jscntxt.h" #include "js/jsinterp.h" @@ -1105,13 +1106,14 @@ swfdec_script_print_action (guint action } } -typedef gboolean (* SwfdecScriptForeachFunc) (guint action, const guint8 *data, guint len, gpointer user_data); static gboolean -swfdec_script_foreach (SwfdecBits *bits, SwfdecScriptForeachFunc func, gpointer user_data) +swfdec_script_foreach_internal (SwfdecBits *bits, SwfdecScriptForeachFunc func, gpointer user_data) { guint action, len; const guint8 *data; + gconstpointer bytecode; + bytecode = bits->ptr; while ((action = swfdec_bits_get_u8 (bits))) { if (action & 0x80) { len = swfdec_bits_get_u16 (bits); @@ -1124,16 +1126,29 @@ swfdec_script_foreach (SwfdecBits *bits, SWFDEC_ERROR ("script too short"); return FALSE; } - if (!func (action, data, len, user_data)) + if (!func (bytecode, action, data, len, user_data)) return FALSE; + bytecode = bits->ptr; } return TRUE; } /*** PUBLIC API ***/ +gboolean +swfdec_script_foreach (SwfdecScript *script, SwfdecScriptForeachFunc func, gpointer user_data) +{ + SwfdecBits bits; + + g_return_val_if_fail (script != NULL, FALSE); + g_return_val_if_fail (func != NULL, FALSE); + + swfdec_bits_init (&bits, script->buffer); + return swfdec_script_foreach_internal (&bits, func, user_data); +} + static gboolean -validate_action (guint action, const guint8 *data, guint len, gpointer scriptp) +validate_action (gconstpointer bytecode, guint action, const guint8 *data, guint len, gpointer scriptp) { SwfdecScript *script = scriptp; int version = EXTRACT_VERSION (script->version); @@ -1158,12 +1173,30 @@ validate_action (guint action, const gui } SwfdecScript * +swfdec_script_new_for_player (SwfdecPlayer *player, SwfdecBits *bits, + const char *name, unsigned int version) +{ + SwfdecScript *script; + + g_return_val_if_fail (SWFDEC_IS_PLAYER (player), NULL); + g_return_val_if_fail (bits != NULL, NULL); + + script = swfdec_script_new (bits, name, version); + if (SWFDEC_IS_DEBUGGER (player) && script) { + swfdec_debugger_add_script (SWFDEC_DEBUGGER (player), script); + script->debugger = player; + } + return script; +} + +SwfdecScript * swfdec_script_new (SwfdecBits *bits, const char *name, unsigned int version) { SwfdecScript *script; const guchar *start; g_return_val_if_fail (bits != NULL, NULL); + if (version < MINSCRIPTVERSION) { SWFDEC_ERROR ("swfdec version %u doesn't support scripts", version); return NULL; @@ -1176,7 +1209,7 @@ swfdec_script_new (SwfdecBits *bits, con script->name = g_strdup (name ? name : "Unnamed script"); script->version = version; - if (!swfdec_script_foreach (bits, validate_action, script)) { + if (!swfdec_script_foreach_internal (bits, validate_action, script)) { /* assign a random buffer here so we have something to unref */ script->buffer = bits->buffer; swfdec_buffer_ref (script->buffer); @@ -1203,6 +1236,11 @@ swfdec_script_unref (SwfdecScript *scrip g_return_if_fail (script->refcount > 0); script->refcount--; + if (script->refcount == 1 && script->debugger) { + script->debugger = NULL; + swfdec_debugger_remove_script (script->debugger, script); + return; + } if (script->refcount > 0) return; @@ -1266,13 +1304,37 @@ swfdec_script_interpret (SwfdecScript *s goto out; } - /* only valid return value */ while (TRUE) { /* check pc */ if (pc < startpc || pc >= endpc) { SWFDEC_ERROR ("pc %p not in valid range [%p, %p] anymore", pc, startpc, endpc); goto internal_error; } + + /* run interrupt handler */ + if (cx->runtime->interruptHandler) { + jsval tmp; + switch (cx->runtime->interruptHandler (cx, NULL, pc, &tmp, + cx->runtime->interruptHandlerData)) { + case JSTRAP_ERROR: + ok = JS_FALSE; + goto out; + case JSTRAP_CONTINUE: + break; + case JSTRAP_RETURN: + fp->rval = tmp; + goto out; + case JSTRAP_THROW: + cx->throwing = JS_TRUE; + cx->exception = tmp; + ok = JS_FALSE; + goto out; + default: + g_assert_not_reached (); + break; + } + } + /* decode next action */ action = *pc; spec = actions + action; @@ -1433,3 +1495,4 @@ swfdec_script_execute (SwfdecScript *scr return ok ? frame.rval : JSVAL_VOID; } + diff --git a/libswfdec/swfdec_script.h b/libswfdec/swfdec_script.h index d8688c3..1cea4a7 100644 --- a/libswfdec/swfdec_script.h +++ b/libswfdec/swfdec_script.h @@ -29,17 +29,25 @@ G_BEGIN_DECLS //typedef struct _SwfdecScript SwfdecScript; +typedef gboolean (* SwfdecScriptForeachFunc) (gconstpointer bytecode, guint action, + const guint8 *data, guint len, gpointer user_data); + /* FIXME: May want to typedef to SwfdecBuffer directly */ struct _SwfdecScript { SwfdecBuffer * buffer; /* buffer holding the script */ unsigned int refcount; /* reference count */ char * name; /* name identifying this script */ unsigned int version; /* version of the script */ + gpointer debugger; /* debugger owning us or NULL */ }; SwfdecScript * swfdec_script_new (SwfdecBits * bits, const char * name, unsigned int version); +SwfdecScript * swfdec_script_new_for_player (SwfdecPlayer * player, + SwfdecBits * bits, + const char * name, + unsigned int version); void swfdec_script_ref (SwfdecScript * script); void swfdec_script_unref (SwfdecScript * script); @@ -49,9 +57,13 @@ JSBool swfdec_script_interpret (Swfdec jsval swfdec_script_execute (SwfdecScript * script, SwfdecScriptable * scriptable); +gboolean swfdec_script_foreach (SwfdecScript * script, + SwfdecScriptForeachFunc func, + gpointer user_data); char * swfdec_script_print_action (guint action, const guint8 * data, guint len); + G_END_DECLS #endif diff --git a/libswfdec/swfdec_tag.c b/libswfdec/swfdec_tag.c index 3896101..e7c8aa8 100644 --- a/libswfdec/swfdec_tag.c +++ b/libswfdec/swfdec_tag.c @@ -297,7 +297,7 @@ tag_func_do_action (SwfdecSwfDecoder * s name = g_strdup_printf ("Sprite%u.Frame%u", SWFDEC_CHARACTER (s->parse_sprite)->id, s->parse_sprite->parse_frame); - script = swfdec_script_new (&s->b, name, s->version); + script = swfdec_script_new_for_player (SWFDEC_DECODER (s)->player, &s->b, name, s->version); g_free (name); if (script) swfdec_sprite_add_action (s->parse_sprite, s->parse_sprite->parse_frame, diff --git a/player/swfdec_debug_scripts.c b/player/swfdec_debug_scripts.c index 89bebce..3877da8 100644 --- a/player/swfdec_debug_scripts.c +++ b/player/swfdec_debug_scripts.c @@ -40,7 +40,7 @@ add_row (gpointer scriptp, gpointer stor gtk_list_store_append (store, &iter); gtk_list_store_set (store, &iter, COLUMN_SCRIPT, script, - COLUMN_NAME, script->name, -1); + COLUMN_NAME, script->script->name, -1); } static void diff --git a/player/swfdec_player_manager.c b/player/swfdec_player_manager.c index d51e49b..82d55ed 100644 --- a/player/swfdec_player_manager.c +++ b/player/swfdec_player_manager.c @@ -137,7 +137,7 @@ swfdec_player_manager_class_init (Swfdec signals[MESSAGE] = g_signal_new ("message", G_TYPE_FROM_CLASS (g_class), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__UINT_POINTER, /* FIXME */ - G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_STRING); + G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_POINTER); } static void @@ -458,7 +458,7 @@ command_break (SwfdecPlayerManager *mana guint id = swfdec_debugger_set_breakpoint (SWFDEC_DEBUGGER (manager->player), manager->interrupt_script, line); swfdec_player_manager_output (manager, "%u: %s line %u: %s", - id, manager->interrupt_script->name, line, + id, manager->interrupt_script->script->name, line, manager->interrupt_script->commands[line].description); } else { swfdec_player_manager_error (manager, @@ -494,7 +494,7 @@ command_breakpoints (SwfdecPlayerManager for (i = 1; i <= n; i++) { if (swfdec_debugger_get_breakpoint (debugger, i, &script, &line)) { swfdec_player_manager_output (manager, "%u: %s line %u: %s", - i, script->name, line, script->commands[line].description); + i, script->script->name, line, script->commands[line].description); } } } @@ -552,7 +552,7 @@ do_find (gpointer scriptp, gpointer data for (i = 0; i < script->n_commands; i++) { if (strstr (script->commands[i].description, data->string)) { swfdec_player_manager_output (data->manager, "%s %u: %s", - script->name, i, script->commands[i].description); + script->script->name, i, script->commands[i].description); } } } diff-tree 52828a39c261a28bf65734800692391b4f76b7c8 (from b8b6df20af7044cda18cfde12662492f2903ecb0) Author: Benjamin Otte <otte@gnome.org> Date: Fri Jan 26 18:05:39 2007 +0100 use automatic hscrollbars, too diff --git a/player/swfdebug.c b/player/swfdebug.c index 2f041f1..490814e 100644 --- a/player/swfdebug.c +++ b/player/swfdebug.c @@ -214,7 +214,7 @@ view_swf (SwfdecPlayer *player, double s scroll = gtk_scrolled_window_new (NULL, NULL); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll), - GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_box_pack_start (GTK_BOX (vbox), scroll, TRUE, TRUE, 0); scripts = swfdec_debug_scripts_new (SWFDEC_DEBUGGER (player)); gtk_container_add (GTK_CONTAINER (scroll), scripts); @@ -251,7 +251,7 @@ view_swf (SwfdecPlayer *player, double s scroll = gtk_scrolled_window_new (NULL, NULL); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll), - GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_box_pack_start (GTK_BOX (hbox), scroll, TRUE, TRUE, 0); widget = swfdec_debug_script_new (SWFDEC_DEBUGGER (player)); gtk_container_add (GTK_CONTAINER (scroll), widget); diff-tree b8b6df20af7044cda18cfde12662492f2903ecb0 (from fc10e6599a2821de28900eb4f570654e4fe1958a) Author: Benjamin Otte <otte@gnome.org> Date: Fri Jan 26 10:03:05 2007 +0100 rework case sensitivity once again - this time making it global and set only on startup I really should do a testsuite with embedding movies and testing their case sensitivity so I know what the official Flash player does diff --git a/libswfdec/js/jsatom.c b/libswfdec/js/jsatom.c index c4c85b7..f0816b2 100644 --- a/libswfdec/js/jsatom.c +++ b/libswfdec/js/jsatom.c @@ -673,10 +673,10 @@ out: JSAtom * js_AtomizeString(JSContext *cx, JSString *str, uintN flags) { - if (flags & ATOM_NOCASE) - return js_AtomizeStringWithCompare (cx, str, flags, js_compare_atom_keys_no_case); - else + if (cx->caseSensitive) return js_AtomizeStringWithCompare (cx, str, flags, js_compare_atom_keys); + else + return js_AtomizeStringWithCompare (cx, str, flags, js_compare_atom_keys_no_case); } JS_FRIEND_API(JSAtom *) diff --git a/libswfdec/js/jsatom.h b/libswfdec/js/jsatom.h index d9d2025..6f486c3 100644 --- a/libswfdec/js/jsatom.h +++ b/libswfdec/js/jsatom.h @@ -58,7 +58,6 @@ JS_BEGIN_EXTERN_C #define ATOM_PINNED 0x01 /* atom is pinned against GC */ #define ATOM_INTERNED 0x02 /* pinned variant for JS_Intern* API */ #define ATOM_MARK 0x04 /* atom is reachable via GC */ -#define ATOM_NOCASE 0x20 /* treat atom case-insensitive */ #define ATOM_NOCOPY 0x40 /* don't copy atom string bytes */ #define ATOM_TMPSTR 0x80 /* internal, to avoid extra string */ diff --git a/libswfdec/swfdec_edittext_movie.c b/libswfdec/swfdec_edittext_movie.c index e3d2119..421f6bc 100644 --- a/libswfdec/swfdec_edittext_movie.c +++ b/libswfdec/swfdec_edittext_movie.c @@ -80,7 +80,7 @@ swfdec_edit_text_movie_iterate (SwfdecMo jsobj = swfdec_scriptable_get_object (parent); if (jsobj == NULL) return; - val = swfdec_js_eval (parent->jscx, jsobj, text->text->variable, FALSE); + val = swfdec_js_eval (parent->jscx, jsobj, text->text->variable); if (JSVAL_IS_VOID (val)) return; @@ -110,7 +110,7 @@ swfdec_edit_text_movie_init_movie (Swfde if (jsobj == NULL) return; if (text->text->variable_prefix) { - val = swfdec_js_eval (parent->jscx, jsobj, text->text->variable_prefix, FALSE); + val = swfdec_js_eval (parent->jscx, jsobj, text->text->variable_prefix); if (!JSVAL_IS_OBJECT (val)) return; jsobj = JSVAL_TO_OBJECT (val); diff --git a/libswfdec/swfdec_js.c b/libswfdec/swfdec_js.c index 1601b4b..524707c 100644 --- a/libswfdec/swfdec_js.c +++ b/libswfdec/swfdec_js.c @@ -300,18 +300,20 @@ fail: static JSBool swfdec_js_eval_get_property (JSContext *cx, JSObject *obj, - const char *name, gboolean initial, gboolean ignore_case, jsval *ret) + const char *name, jsval *ret) { JSAtom *atom; JSObject *pobj; JSProperty *prop; - atom = js_Atomize (cx, name, strlen(name), ignore_case ? ATOM_NOCASE : 0); + atom = js_Atomize (cx, name, strlen(name), 0); if (!atom) return JS_FALSE; - if (initial) { + if (obj) { return OBJ_GET_PROPERTY (cx, obj, (jsid) atom, ret); } else { + if (cx->fp == NULL || cx->fp->scopeChain == NULL) + return JS_FALSE; if (!js_FindProperty (cx, (jsid) atom, &obj, &pobj, &prop)) return JS_FALSE; if (!prop) @@ -324,18 +326,20 @@ swfdec_js_eval_get_property (JSContext * static JSBool swfdec_js_eval_set_property (JSContext *cx, JSObject *obj, - const char *name, gboolean initial, gboolean ignore_case, jsval *ret) + const char *name, jsval *ret) { JSAtom *atom; JSObject *pobj; JSProperty *prop; - atom = js_Atomize (cx, name, strlen(name), ignore_case ? ATOM_NOCASE : 0); + atom = js_Atomize (cx, name, strlen(name), 0); if (!atom) return JS_FALSE; - if (initial) { + if (obj) { return OBJ_SET_PROPERTY (cx, obj, (jsid) atom, ret); } else { + if (cx->fp == NULL || cx->fp->scopeChain == NULL) + return JS_FALSE; if (!js_FindProperty (cx, (jsid) atom, &obj, &pobj, &prop)) return JS_FALSE; if (!prop) @@ -348,23 +352,25 @@ swfdec_js_eval_set_property (JSContext * static gboolean swfdec_js_eval_internal (JSContext *cx, JSObject *obj, const char *str, - gboolean ignore_case, jsval *val, gboolean set) + jsval *val, gboolean set) { jsval cur; char *work = NULL; - gboolean initial = TRUE; SWFDEC_LOG ("eval called with \"%s\" on %p", str, obj); if (strchr (str, '/')) { work = swfdec_js_slash_to_dot (str); str = work; } - cur = OBJECT_TO_JSVAL (obj); if (g_str_has_prefix (str, "this")) { str += 4; if (*str == '.') str++; + if (cx->fp == NULL) + goto out; + obj = cx->fp->thisp; } + cur = OBJECT_TO_JSVAL (obj); while (str != NULL && *str != '\0') { char *dot = strchr (str, '.'); if (!JSVAL_IS_OBJECT (cur)) @@ -372,21 +378,20 @@ swfdec_js_eval_internal (JSContext *cx, obj = JSVAL_TO_OBJECT (cur); if (dot) { char *name = g_strndup (str, dot - str); - if (!swfdec_js_eval_get_property (cx, obj, name, initial, ignore_case, &cur)) + if (!swfdec_js_eval_get_property (cx, obj, name, &cur)) goto out; g_free (name); str = dot + 1; } else { if (set) { - if (!swfdec_js_eval_set_property (cx, obj, str, initial, ignore_case, val)) + if (!swfdec_js_eval_set_property (cx, obj, str, val)) goto out; } else { - if (!swfdec_js_eval_get_property (cx, obj, str, initial, ignore_case, &cur)) + if (!swfdec_js_eval_get_property (cx, obj, str, &cur)) goto out; } str = NULL; } - initial = FALSE; } g_free (work); @@ -403,7 +408,6 @@ out: * @cx: a #JSContext * @obj: #JSObject to use as a source for evaluating * @str: The string to evaluate - * @ignore_case: TRUE for case insensitive evaluation * * This function works like the Actionscript eval function used on @obj. * It handles both slash-style and dot-style notation. @@ -411,23 +415,24 @@ out: * Returns: the value or JSVAL_VOID if no value was found. **/ jsval -swfdec_js_eval (JSContext *cx, JSObject *obj, const char *str, - gboolean ignore_case) +swfdec_js_eval (JSContext *cx, JSObject *obj, const char *str) { jsval ret; g_return_val_if_fail (cx != NULL, JSVAL_VOID); - g_return_val_if_fail (obj != NULL, JSVAL_VOID); g_return_val_if_fail (str != NULL, JSVAL_VOID); - if (!swfdec_js_eval_internal (cx, obj, str, ignore_case, &ret, FALSE)) + if (!swfdec_js_eval_internal (cx, obj, str, &ret, FALSE)) ret = JSVAL_VOID; return ret; } void swfdec_js_eval_set (JSContext *cx, JSObject *obj, const char *str, - jsval val, gboolean ignore_case) + jsval val) { - swfdec_js_eval_internal (cx, obj, str, ignore_case, &val, TRUE); + g_return_if_fail (cx != NULL); + g_return_if_fail (str != NULL); + + swfdec_js_eval_internal (cx, obj, str, &val, TRUE); } diff --git a/libswfdec/swfdec_js.h b/libswfdec/swfdec_js.h index ea49a72..5e58152 100644 --- a/libswfdec/swfdec_js.h +++ b/libswfdec/swfdec_js.h @@ -49,13 +49,11 @@ void swfdec_js_movie_remove_property (S char * swfdec_js_slash_to_dot (const char * slash_str); jsval swfdec_js_eval (JSContext * cx, JSObject * obj, - const char * str, - gboolean ignore_case); + const char * str); void swfdec_js_eval_set (JSContext * cx, JSObject * obj, const char * str, - jsval val, - gboolean ignore_case); + jsval val); /* support functions */ const char * swfdec_js_to_string (JSContext * cx, diff --git a/libswfdec/swfdec_js_global.c b/libswfdec/swfdec_js_global.c index 27522c1..328d74d 100644 --- a/libswfdec/swfdec_js_global.c +++ b/libswfdec/swfdec_js_global.c @@ -33,7 +33,7 @@ swfdec_js_global_eval (JSContext *cx, JS const char *bytes = swfdec_js_to_string (cx, argv[0]); if (bytes == NULL) return JS_FALSE; - *rval = swfdec_js_eval (cx, obj, bytes, FALSE); + *rval = swfdec_js_eval (cx, obj, bytes); } else { *rval = argv[0]; } diff --git a/libswfdec/swfdec_root_movie.c b/libswfdec/swfdec_root_movie.c index 440f9d4..9121560 100644 --- a/libswfdec/swfdec_root_movie.c +++ b/libswfdec/swfdec_root_movie.c @@ -32,6 +32,7 @@ #include "swfdec_loadertarget.h" #include "swfdec_player_internal.h" #include "swfdec_swf_decoder.h" +#include "js/jsapi.h" static void swfdec_root_movie_loader_target_init (SwfdecLoaderTargetInterface *iface); @@ -67,6 +68,13 @@ swfdec_root_movie_loader_target_do_init swfdec_player_initialize (movie->player, movie->decoder->rate, movie->decoder->width, movie->decoder->height); + if (SWFDEC_IS_SWF_DECODER (movie->decoder) && + movie->player->roots->next == 0) { + /* if we're the only child */ + /* FIXME: check case sensitivity wrt embedding movies of different version */ + JS_SetContextCaseSensitive (movie->player->jscx, + SWFDEC_SWF_DECODER (movie->decoder)->version > 6); + } if (SWFDEC_IS_FLV_DECODER (movie->decoder)) { swfdec_flv_decoder_add_movie (SWFDEC_FLV_DECODER (movie->decoder), SWFDEC_MOVIE (movie)); diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c index 32af30e..e5c205f 100644 --- a/libswfdec/swfdec_script.c +++ b/libswfdec/swfdec_script.c @@ -315,8 +315,7 @@ swfdec_action_get_variable (JSContext *c s = swfdec_js_to_string (cx, cx->fp->sp[-1]); if (s == NULL) return JS_FALSE; - cx->fp->sp[-1] = swfdec_js_eval (cx, cx->fp->scopeChain, s, - ((SwfdecScript *) cx->fp->swf)->version < 7); + cx->fp->sp[-1] = swfdec_js_eval (cx, cx->fp->scopeChain, s); return JS_TRUE; } @@ -329,8 +328,7 @@ swfdec_action_set_variable (JSContext *c if (s == NULL) return JS_FALSE; - swfdec_js_eval_set (cx, cx->fp->scopeChain, s, cx->fp->sp[-1], - ((SwfdecScript *) cx->fp->swf)->version < 7); + swfdec_js_eval_set (cx, cx->fp->scopeChain, s, cx->fp->sp[-1]); cx->fp->sp -= 2; return JS_TRUE; } @@ -441,8 +439,7 @@ swfdec_eval_jsval (JSContext *cx, JSObje const char *bytes = swfdec_js_to_string (cx, *val); if (bytes == NULL) return JS_FALSE; - *val = swfdec_js_eval (cx, obj, bytes, - ((SwfdecScript *) cx->fp->swf)->version < 7); + *val = swfdec_js_eval (cx, obj, bytes); } else { *val = OBJECT_TO_JSVAL (obj); } @@ -458,7 +455,7 @@ swfdec_action_get_property (JSContext *c guint32 id; val = cx->fp->sp[-2]; - if (!swfdec_eval_jsval (cx, cx->fp->scopeChain, &val)) + if (!swfdec_eval_jsval (cx, NULL, &val)) return JS_FALSE; movie = swfdec_scriptable_from_jsval (cx, val, SWFDEC_TYPE_MOVIE); val = JSVAL_VOID; @@ -493,7 +490,7 @@ swfdec_action_set_property (JSContext *c guint32 id; val = cx->fp->sp[-3]; - if (!swfdec_eval_jsval (cx, cx->fp->scopeChain, &val)) + if (!swfdec_eval_jsval (cx, NULL, &val)) return JS_FALSE; movie = swfdec_scriptable_from_jsval (cx, val, SWFDEC_TYPE_MOVIE); if (movie == NULL) { diff-tree fc10e6599a2821de28900eb4f570654e4fe1958a (from 4db4a99c916781cbceb31ca171c242867d4047cd) Author: Benjamin Otte <otte@gnome.org> Date: Thu Jan 25 16:29:56 2007 +0100 That line must've been accidentally removed somewhere diff --git a/test/swfedit_token.c b/test/swfedit_token.c index 3327b81..8c8b075 100644 --- a/test/swfedit_token.c +++ b/test/swfedit_token.c @@ -112,6 +112,7 @@ swfedit_from_string_unsigned (const char return FALSE; if (u > max) return FALSE; + *result = GUINT_TO_POINTER (u); return TRUE; }
Maybe Matching Threads
- 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' - 8 commits - libswfdec/swfdec_bits.c libswfdec/swfdec_bits.h libswfdec/swfdec_js.c libswfdec/swfdec_js.h libswfdec/swfdec_script.c test/swfdec_out.c test/swfdec_out.h test/swfedit_tag.c test/swfedit_token.c test/swfedit_token.h
- Branch 'as' - 17 commits - configure.ac doc/Makefile.am doc/swfdec-docs.sgml doc/swfdec-sections.txt doc/swfdec.types libswfdec-gtk/Makefile.am libswfdec-gtk/swfdec-gtk.h libswfdec-gtk/swfdec_gtk_loader.c libswfdec-gtk/swfdec_gtk_loader.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
- 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