[Swfdec] 7 commits - libswfdec/swfdec_as_frame.c libswfdec/swfdec_as_function.c libswfdec/swfdec_as_internal.h libswfdec/swfdec_as_interpret.c libswfdec/swfdec_as_object.c libswfdec/swfdec_as_super.c libswfdec/swfdec_as_super.h
Benjamin Otte
company at kemper.freedesktop.org
Wed Nov 14 08:09:13 PST 2007
libswfdec/swfdec_as_frame.c | 3 -
libswfdec/swfdec_as_function.c | 66 ++++++++++++++++--------
libswfdec/swfdec_as_internal.h | 16 ++++-
libswfdec/swfdec_as_interpret.c | 60 +++++++++++-----------
libswfdec/swfdec_as_object.c | 10 ++-
libswfdec/swfdec_as_super.c | 109 +++++++++++++++++++++-------------------
libswfdec/swfdec_as_super.h | 10 ++-
7 files changed, 159 insertions(+), 115 deletions(-)
New commits:
commit 9df5ed45ad9076f38f69903016298dc87b661efe
Author: Benjamin Otte <otte at gnome.org>
Date: Wed Nov 14 17:03:15 2007 +0100
work instantiating of super objects once again
swfdec_as_super_new () now takes a this object and a reference object.
Usually, the reference will be this->prototype, but in special cases, this
is not true.
diff --git a/libswfdec/swfdec_as_function.c b/libswfdec/swfdec_as_function.c
index ef60c0b..c64df5e 100644
--- a/libswfdec/swfdec_as_function.c
+++ b/libswfdec/swfdec_as_function.c
@@ -164,10 +164,10 @@ swfdec_as_function_call (SwfdecAsFunction *function, SwfdecAsObject *thisp, guin
if (frame == NULL)
return;
if (thisp != NULL) {
- swfdec_as_super_new (frame, thisp, FALSE);
+ swfdec_as_super_new (frame, thisp, thisp->prototype);
} else {
SWFDEC_FIXME ("does the super object really reference the function when thisp is NULL?");
- swfdec_as_super_new (frame, SWFDEC_AS_OBJECT (function), FALSE);
+ swfdec_as_super_new (frame, SWFDEC_AS_OBJECT (function), SWFDEC_AS_OBJECT (function)->prototype);
}
swfdec_as_frame_preload (frame);
}
diff --git a/libswfdec/swfdec_as_interpret.c b/libswfdec/swfdec_as_interpret.c
index c911276..cb44953 100644
--- a/libswfdec/swfdec_as_interpret.c
+++ b/libswfdec/swfdec_as_interpret.c
@@ -876,6 +876,7 @@ swfdec_action_call_method (SwfdecAsContext *cx, guint action, const guint8 *data
SwfdecAsFrame *frame = cx->frame;
SwfdecAsValue *val;
SwfdecAsObject *obj;
+ SwfdecAsObject *pobj = NULL;
guint n_args;
const char *name;
@@ -892,7 +893,7 @@ swfdec_action_call_method (SwfdecAsContext *cx, guint action, const guint8 *data
name = "";
} else {
SWFDEC_AS_VALUE_SET_OBJECT (swfdec_as_stack_peek (cx, 3), obj);
- swfdec_as_object_get_variable (obj, name, swfdec_as_stack_peek (cx, 2));
+ swfdec_as_object_get_variable_and_flags (obj, name, swfdec_as_stack_peek (cx, 2), NULL, &pobj);
}
} else {
if (SWFDEC_AS_VALUE_IS_STRING (val))
@@ -908,8 +909,10 @@ swfdec_action_call_method (SwfdecAsContext *cx, guint action, const guint8 *data
/* setup super to point to the right prototype */
if (SWFDEC_IS_AS_SUPER (obj)) {
swfdec_as_super_new_chain (frame, SWFDEC_AS_SUPER (obj), name);
+ } else if (cx->version > 6) {
+ swfdec_as_super_new (frame, obj, pobj == obj ? obj->prototype : pobj);
} else {
- swfdec_as_super_new (frame, obj, FALSE);
+ swfdec_as_super_new (frame, obj, obj->prototype);
}
swfdec_as_frame_preload (frame);
} else {
diff --git a/libswfdec/swfdec_as_object.c b/libswfdec/swfdec_as_object.c
index 1127cef..9a723f4 100644
--- a/libswfdec/swfdec_as_object.c
+++ b/libswfdec/swfdec_as_object.c
@@ -1283,7 +1283,7 @@ swfdec_as_object_create (SwfdecAsFunction *fun, guint n_args,
frame = swfdec_as_function_call_no_preload (fun, new, n_args, args, return_value);
frame->construct = TRUE;
- swfdec_as_super_new (frame, new, TRUE);
+ swfdec_as_super_new (frame, new, new->prototype);
swfdec_as_frame_preload (frame);
}
diff --git a/libswfdec/swfdec_as_super.c b/libswfdec/swfdec_as_super.c
index 1a4df38..9e67b40 100644
--- a/libswfdec/swfdec_as_super.c
+++ b/libswfdec/swfdec_as_super.c
@@ -43,8 +43,6 @@ swfdec_as_super_call (SwfdecAsFunction *function)
SwfdecAsFunctionClass *klass;
SwfdecAsFrame *frame;
- //if (!super->callable)
- // return NULL;
if (super->object == NULL) {
SWFDEC_WARNING ("super () called without an object.");
return NULL;
@@ -146,13 +144,14 @@ swfdec_as_super_init (SwfdecAsSuper *super)
}
void
-swfdec_as_super_new (SwfdecAsFrame *frame, SwfdecAsObject *ref, gboolean callable)
+swfdec_as_super_new (SwfdecAsFrame *frame, SwfdecAsObject *thisp, SwfdecAsObject *ref)
{
SwfdecAsContext *context;
SwfdecAsSuper *super;
g_return_if_fail (SWFDEC_IS_AS_FRAME (frame));
- g_return_if_fail (SWFDEC_IS_AS_OBJECT (ref));
+ g_return_if_fail (SWFDEC_IS_AS_OBJECT (thisp));
+ g_return_if_fail (ref == NULL || SWFDEC_IS_AS_OBJECT (ref));
if (frame->super != NULL)
return;
@@ -165,12 +164,11 @@ swfdec_as_super_new (SwfdecAsFrame *frame, SwfdecAsObject *ref, gboolean callabl
super = g_object_new (SWFDEC_TYPE_AS_SUPER, NULL);
frame->super = SWFDEC_AS_OBJECT (super);
swfdec_as_object_add (SWFDEC_AS_OBJECT (super), context, sizeof (SwfdecAsSuper));
- super->thisp = ref;
- super->callable = callable;
+ super->thisp = thisp;
if (context->version <= 5) {
super->object = NULL;
} else {
- super->object = ref->prototype;
+ super->object = ref;
}
}
@@ -188,38 +186,32 @@ void
swfdec_as_super_new_chain (SwfdecAsFrame *frame, SwfdecAsSuper *super,
const char *function_name)
{
- SwfdecAsSuper *replace;
+ SwfdecAsObject *ref;
SwfdecAsContext *context;
+ g_return_if_fail (SWFDEC_IS_AS_FRAME (frame));
g_return_if_fail (SWFDEC_IS_AS_SUPER (super));
if (frame->super != NULL)
return;
-
- context = SWFDEC_AS_OBJECT (frame)->context;
- if (!swfdec_as_context_use_mem (context, sizeof (SwfdecAsSuper)))
+
+ if (super->object == NULL)
return;
- replace = g_object_new (SWFDEC_TYPE_AS_SUPER, NULL);
- frame->super = SWFDEC_AS_OBJECT (replace);
- swfdec_as_object_add (SWFDEC_AS_OBJECT (replace), context, sizeof (SwfdecAsSuper));
- if (super->object == NULL || super->object->prototype == NULL) {
- replace->object = NULL;
+ ref = super->object->prototype;
+ if (ref == NULL)
return;
- }
- replace->thisp = super->thisp;
- replace->object = super->object->prototype;
- replace->callable = super->callable;
+ context = SWFDEC_AS_OBJECT (frame)->context;
if (function_name && context->version > 6) {
/* skip prototypes to find the next one that has this function defined */
SwfdecAsObject *res;
- if (swfdec_as_object_get_variable_and_flags (replace->object,
- function_name, NULL, NULL, &res) &&
- replace->object != res) {
- while (replace->object->prototype != res) {
- replace->object = replace->object->prototype;
- g_return_if_fail (replace->object);
+ if (swfdec_as_object_get_variable_and_flags (ref,
+ function_name, NULL, NULL, &res) && ref != res) {
+ while (ref->prototype != res) {
+ ref = ref->prototype;
+ g_return_if_fail (ref);
}
}
}
+ swfdec_as_super_new (frame, super->thisp, ref);
}
diff --git a/libswfdec/swfdec_as_super.h b/libswfdec/swfdec_as_super.h
index 2eaa1d7..ad082e9 100644
--- a/libswfdec/swfdec_as_super.h
+++ b/libswfdec/swfdec_as_super.h
@@ -38,9 +38,8 @@ typedef struct _SwfdecAsSuperClass SwfdecAsSuperClass;
struct _SwfdecAsSuper {
SwfdecAsFunction function;
- gboolean callable; /* TRUE if this super object can be called */
SwfdecAsObject * thisp; /* object super was called on */
- SwfdecAsObject * object; /* current prototype we reference */
+ SwfdecAsObject * object; /* current prototype we reference or NULL if none */
};
struct _SwfdecAsSuperClass {
@@ -50,8 +49,8 @@ struct _SwfdecAsSuperClass {
GType swfdec_as_super_get_type (void);
void swfdec_as_super_new (SwfdecAsFrame * frame,
- SwfdecAsObject * ref,
- gboolean callable);
+ SwfdecAsObject * thisp,
+ SwfdecAsObject * ref);
void swfdec_as_super_new_chain (SwfdecAsFrame * frame,
SwfdecAsSuper * super,
const char * function_name);
commit 45d1aa5e5d55422409f47dd686a09d1e29f30099
Author: Benjamin Otte <otte at gnome.org>
Date: Wed Nov 14 16:43:59 2007 +0100
make creating chained super objects work
diff --git a/libswfdec/swfdec_as_super.c b/libswfdec/swfdec_as_super.c
index 20a4f02..1a4df38 100644
--- a/libswfdec/swfdec_as_super.c
+++ b/libswfdec/swfdec_as_super.c
@@ -27,6 +27,7 @@
#include "swfdec_as_context.h"
#include "swfdec_as_frame_internal.h"
#include "swfdec_as_function.h"
+#include "swfdec_as_internal.h"
#include "swfdec_as_strings.h"
#include "swfdec_debug.h"
#include "swfdec_movie.h"
@@ -42,6 +43,8 @@ swfdec_as_super_call (SwfdecAsFunction *function)
SwfdecAsFunctionClass *klass;
SwfdecAsFrame *frame;
+ //if (!super->callable)
+ // return NULL;
if (super->object == NULL) {
SWFDEC_WARNING ("super () called without an object.");
return NULL;
@@ -71,19 +74,28 @@ swfdec_as_super_get (SwfdecAsObject *object, SwfdecAsObject *orig,
const char *variable, SwfdecAsValue *val, guint *flags)
{
SwfdecAsSuper *super = SWFDEC_AS_SUPER (object);
+ SwfdecAsObjectClass *klass;
+ SwfdecAsObject *cur;
+ guint i;
if (super->object == NULL) {
SWFDEC_WARNING ("super.%s () called without an object.", variable);
return FALSE;
}
- if (super->object->prototype == NULL) {
- SWFDEC_WARNING ("super.%s () called without a prototype.", variable);
- return FALSE;
+ cur = super->object->prototype;
+ for (i = 0; i <= SWFDEC_AS_OBJECT_PROTOTYPE_RECURSION_LIMIT && cur != NULL; i++) {
+ klass = SWFDEC_AS_OBJECT_GET_CLASS (cur);
+ /* FIXME: is the orig pointer correct? */
+ if (klass->get (cur, super->object, variable, val, flags))
+ return TRUE;
+ /* FIXME: need get_prototype_internal here? */
+ cur = swfdec_as_object_get_prototype (cur);
}
- if (!swfdec_as_object_get_variable_and_flags (super->object->prototype, variable, val, NULL, NULL))
- return FALSE;
+ if (i > SWFDEC_AS_OBJECT_PROTOTYPE_RECURSION_LIMIT)
+ swfdec_as_context_abort (object->context, "Prototype recursion limit exceeded");
+ SWFDEC_AS_VALUE_SET_UNDEFINED (val);
*flags = 0;
- return TRUE;
+ return FALSE;
}
static void
@@ -166,13 +178,11 @@ swfdec_as_super_new (SwfdecAsFrame *frame, SwfdecAsObject *ref, gboolean callabl
* swfdec_as_super_new_chain:
* @frame: the frame that is called
* @super: the super object to chain from
- * @function_name: garbage-collected name of the function that was called on
- * @super or %NULL
+ * @chain_to: object to chain to. Must be in the prototype chain of @super. Or
+ * %NULL to just use the super object's prototype
*
- * This is an internal function used to replace the current frame's super object
- * with the next one starting from @super. (FIXME: nice explanation!) So when
- * super.foo () has been called, a new frame is constructed and after that this
- * function is called with @super and "foo" as @function_name.
+ * This function creates a super object relative to the given @super object. It
+ * is only needed when calling functions on the @super object.
**/
void
swfdec_as_super_new_chain (SwfdecAsFrame *frame, SwfdecAsSuper *super,
@@ -180,11 +190,12 @@ swfdec_as_super_new_chain (SwfdecAsFrame *frame, SwfdecAsSuper *super,
{
SwfdecAsSuper *replace;
SwfdecAsContext *context;
-
+
g_return_if_fail (SWFDEC_IS_AS_SUPER (super));
- /* should be the first call trying to set super */
- g_return_if_fail (frame->super == NULL);
+ if (frame->super != NULL)
+ return;
+
context = SWFDEC_AS_OBJECT (frame)->context;
if (!swfdec_as_context_use_mem (context, sizeof (SwfdecAsSuper)))
return;
@@ -202,10 +213,13 @@ swfdec_as_super_new_chain (SwfdecAsFrame *frame, SwfdecAsSuper *super,
/* skip prototypes to find the next one that has this function defined */
SwfdecAsObject *res;
if (swfdec_as_object_get_variable_and_flags (replace->object,
- function_name, NULL, NULL, &res) &&
- replace->object != res) {
- while (replace->object->prototype != res)
- replace->object = replace->object->prototype;
+ function_name, NULL, NULL, &res) &&
+ replace->object != res) {
+ while (replace->object->prototype != res) {
+ replace->object = replace->object->prototype;
+ g_return_if_fail (replace->object);
+ }
}
}
}
+
commit da82269a02a6e227cdb78be59da48d645c4f5b7a
Author: Benjamin Otte <otte at gnome.org>
Date: Wed Nov 14 16:43:49 2007 +0100
create a chained super object for function calls
diff --git a/libswfdec/swfdec_as_interpret.c b/libswfdec/swfdec_as_interpret.c
index 99a1410..c911276 100644
--- a/libswfdec/swfdec_as_interpret.c
+++ b/libswfdec/swfdec_as_interpret.c
@@ -877,7 +877,7 @@ swfdec_action_call_method (SwfdecAsContext *cx, guint action, const guint8 *data
SwfdecAsValue *val;
SwfdecAsObject *obj;
guint n_args;
- const char *name = NULL;
+ const char *name;
swfdec_as_stack_ensure_size (cx, 3);
obj = swfdec_as_value_to_object (cx, swfdec_as_stack_peek (cx, 2));
@@ -906,7 +906,11 @@ swfdec_action_call_method (SwfdecAsContext *cx, guint action, const guint8 *data
frame = swfdec_action_call (cx, n_args);
if (frame) {
/* setup super to point to the right prototype */
- swfdec_as_super_new (frame, obj, FALSE);
+ if (SWFDEC_IS_AS_SUPER (obj)) {
+ swfdec_as_super_new_chain (frame, SWFDEC_AS_SUPER (obj), name);
+ } else {
+ swfdec_as_super_new (frame, obj, FALSE);
+ }
swfdec_as_frame_preload (frame);
} else {
SWFDEC_WARNING ("no function named \"%s\" on object %s", name, obj ? G_OBJECT_TYPE_NAME(obj) : "unknown");
commit 24519c4a837757ff3cf5c0791b62c3731f3f0329
Author: Benjamin Otte <otte at gnome.org>
Date: Wed Nov 14 16:43:24 2007 +0100
export RECURSION_LIMIT definition
diff --git a/libswfdec/swfdec_as_internal.h b/libswfdec/swfdec_as_internal.h
index 68ff91b..13624c0 100644
--- a/libswfdec/swfdec_as_internal.h
+++ b/libswfdec/swfdec_as_internal.h
@@ -33,6 +33,7 @@ G_BEGIN_DECLS
#define SWFDEC_AS_CONSTRUCTOR(x, y, func, type) void func (SwfdecAsContext *cx, \
SwfdecAsObject *object, guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret);
+#define SWFDEC_AS_OBJECT_PROTOTYPE_RECURSION_LIMIT 256
void swfdec_as_function_set_constructor (SwfdecAsFunction * fun);
void swfdec_as_function_set_security (SwfdecAsFunction * fun,
diff --git a/libswfdec/swfdec_as_object.c b/libswfdec/swfdec_as_object.c
index 3835a59..1127cef 100644
--- a/libswfdec/swfdec_as_object.c
+++ b/libswfdec/swfdec_as_object.c
@@ -36,8 +36,6 @@
#include "swfdec_movie.h"
#include "swfdec_security_allow.h"
-#define SWFDEC_AS_OBJECT_PROTOTYPE_RECURSION_LIMIT 256
-
/**
* SECTION:SwfdecAsObject
* @title: SwfdecAsObject
commit f215db2740e23b51fc3ec46d562c8fb611f796b6
Author: Benjamin Otte <otte at gnome.org>
Date: Wed Nov 14 14:58:31 2007 +0100
rework super handling yet again
This doesn't work properly yet, but small(ish) commits are better than lots of
big ones.
diff --git a/libswfdec/swfdec_as_function.c b/libswfdec/swfdec_as_function.c
index fea1b3d..ef60c0b 100644
--- a/libswfdec/swfdec_as_function.c
+++ b/libswfdec/swfdec_as_function.c
@@ -118,14 +118,17 @@ swfdec_as_function_call_no_preload (SwfdecAsFunction *function,
klass = SWFDEC_AS_FUNCTION_GET_CLASS (function);
g_assert (klass->call);
frame = klass->call (function);
- /* FIXME: figure out what to do in these situations */
+ /* FIXME: figure out what to do in these situations?
+ * It's a problem when called inside swfdec_as_function_call () as the
+ * user of that function expects success, but super may fail here */
if (frame == NULL)
return NULL;
if (function->priv)
swfdec_as_frame_set_security (frame, function->priv);
/* second check especially for super object */
- if (thisp != NULL && frame->thisp == NULL)
+ if (thisp != NULL && frame->thisp == NULL) {
swfdec_as_frame_set_this (frame, swfdec_as_object_resolve (thisp));
+ }
frame->is_local = TRUE;
frame->argc = n_args;
frame->argv = args;
@@ -160,7 +163,12 @@ swfdec_as_function_call (SwfdecAsFunction *function, SwfdecAsObject *thisp, guin
frame = swfdec_as_function_call_no_preload (function, thisp, n_args, args, return_value);
if (frame == NULL)
return;
- frame->super = swfdec_as_super_new (frame);
+ if (thisp != NULL) {
+ swfdec_as_super_new (frame, thisp, FALSE);
+ } else {
+ SWFDEC_FIXME ("does the super object really reference the function when thisp is NULL?");
+ swfdec_as_super_new (frame, SWFDEC_AS_OBJECT (function), FALSE);
+ }
swfdec_as_frame_preload (frame);
}
diff --git a/libswfdec/swfdec_as_interpret.c b/libswfdec/swfdec_as_interpret.c
index 613f594..99a1410 100644
--- a/libswfdec/swfdec_as_interpret.c
+++ b/libswfdec/swfdec_as_interpret.c
@@ -26,6 +26,7 @@
#include "swfdec_as_context.h"
#include "swfdec_as_frame_internal.h"
#include "swfdec_as_function.h"
+#include "swfdec_as_internal.h"
#include "swfdec_as_script_function.h"
#include "swfdec_as_stack.h"
#include "swfdec_as_string.h"
@@ -801,9 +802,10 @@ swfdec_action_trace (SwfdecAsContext *cx, guint action, const guint8 *data, guin
/* stack looks like this: [ function, this, arg1, arg2, ... ] */
/* stack must be at least 2 elements big */
-static gboolean
+static SwfdecAsFrame *
swfdec_action_call (SwfdecAsContext *cx, guint n_args)
{
+ SwfdecAsFrame *frame;
SwfdecAsFunction *fun;
SwfdecAsObject *thisp;
@@ -821,12 +823,14 @@ swfdec_action_call (SwfdecAsContext *cx, guint n_args)
/* sanitize argument count */
if (n_args >= swfdec_as_stack_get_size (cx))
n_args = swfdec_as_stack_get_size (cx);
- swfdec_as_function_call (fun, thisp, n_args, NULL, NULL);
+ frame = swfdec_as_function_call_no_preload (fun, thisp, n_args, NULL, NULL);
+ if (frame == NULL)
+ return NULL;
if (SWFDEC_IS_AS_SUPER (fun)) {
SWFDEC_LOG ("replacing super object on frame");
- swfdec_as_super_replace (SWFDEC_AS_SUPER (fun), NULL);
+ swfdec_as_super_new_chain (frame, SWFDEC_AS_SUPER (fun), NULL);
}
- return TRUE;
+ return frame;
error:
n_args += 2;
@@ -834,7 +838,7 @@ error:
n_args = swfdec_as_stack_get_size (cx);
swfdec_as_stack_pop_n (cx, n_args);
SWFDEC_AS_VALUE_SET_UNDEFINED (swfdec_as_stack_push (cx));
- return FALSE;
+ return NULL;
}
static void
@@ -858,7 +862,10 @@ swfdec_action_call_function (SwfdecAsContext *cx, guint action, const guint8 *da
SWFDEC_AS_VALUE_SET_NULL (thisp);
SWFDEC_AS_VALUE_SET_UNDEFINED (fun);
}
- if (!swfdec_action_call (cx, n_args)) {
+ frame = swfdec_action_call (cx, n_args);
+ if (frame) {
+ swfdec_as_frame_preload (frame);
+ } else {
SWFDEC_WARNING ("no function named %s", name);
}
}
@@ -876,45 +883,33 @@ swfdec_action_call_method (SwfdecAsContext *cx, guint action, const guint8 *data
obj = swfdec_as_value_to_object (cx, swfdec_as_stack_peek (cx, 2));
n_args = swfdec_as_value_to_integer (cx, swfdec_as_stack_peek (cx, 3));
val = swfdec_as_stack_peek (cx, 1);
- /* FIXME: this is a hack for constructors calling super - is this correct? */
- if (SWFDEC_AS_VALUE_IS_UNDEFINED (val)) {
- SWFDEC_AS_VALUE_SET_STRING (val, SWFDEC_AS_STR_EMPTY);
- }
if (obj) {
- if (SWFDEC_AS_VALUE_IS_STRING (val) &&
- SWFDEC_AS_VALUE_GET_STRING (val) == SWFDEC_AS_STR_EMPTY) {
+ name = swfdec_as_value_to_string (cx, val);
+ if (SWFDEC_AS_VALUE_IS_UNDEFINED (val) ||
+ name == SWFDEC_AS_STR_EMPTY) {
SWFDEC_AS_VALUE_SET_UNDEFINED (swfdec_as_stack_peek (cx, 3));
SWFDEC_AS_VALUE_SET_OBJECT (swfdec_as_stack_peek (cx, 2), obj);
+ name = "";
} else {
SWFDEC_AS_VALUE_SET_OBJECT (swfdec_as_stack_peek (cx, 3), obj);
- name = swfdec_as_value_to_string (cx, val);
swfdec_as_object_get_variable (obj, name, swfdec_as_stack_peek (cx, 2));
}
} else {
if (SWFDEC_AS_VALUE_IS_STRING (val))
name = SWFDEC_AS_VALUE_GET_STRING (val);
+ else
+ name = "???";
SWFDEC_AS_VALUE_SET_NULL (swfdec_as_stack_peek (cx, 3));
SWFDEC_AS_VALUE_SET_UNDEFINED (swfdec_as_stack_peek (cx, 2));
}
swfdec_as_stack_pop (cx);
- if (swfdec_action_call (cx, n_args)) {
+ frame = swfdec_action_call (cx, n_args);
+ if (frame) {
/* setup super to point to the right prototype */
- frame = cx->frame;
- if (SWFDEC_IS_AS_SUPER (obj)) {
- swfdec_as_super_replace (SWFDEC_AS_SUPER (obj), name);
- } else if (frame->super) {
- SwfdecAsSuper *super = SWFDEC_AS_SUPER (frame->super);
- if (name &&
- cx->version > 6 &&
- swfdec_as_object_get_variable_and_flags (frame->thisp,
- name, NULL, NULL, &super->object) &&
- super->object == frame->thisp) {
- // FIXME: Do we need to check prototype_flags here?
- super->object = super->object->prototype;
- }
- }
+ swfdec_as_super_new (frame, obj, FALSE);
+ swfdec_as_frame_preload (frame);
} else {
- SWFDEC_WARNING ("no function named %s on object %s", name ? name : "unknown", obj ? G_OBJECT_TYPE_NAME(obj) : "unknown");
+ SWFDEC_WARNING ("no function named \"%s\" on object %s", name, obj ? G_OBJECT_TYPE_NAME(obj) : "unknown");
}
}
diff --git a/libswfdec/swfdec_as_object.c b/libswfdec/swfdec_as_object.c
index 5cc446c..3835a59 100644
--- a/libswfdec/swfdec_as_object.c
+++ b/libswfdec/swfdec_as_object.c
@@ -31,6 +31,7 @@
#include "swfdec_as_stack.h"
#include "swfdec_as_string.h"
#include "swfdec_as_strings.h"
+#include "swfdec_as_super.h"
#include "swfdec_debug.h"
#include "swfdec_movie.h"
#include "swfdec_security_allow.h"
@@ -1230,6 +1231,7 @@ swfdec_as_object_create (SwfdecAsFunction *fun, guint n_args,
SwfdecAsObject *new;
SwfdecAsContext *context;
SwfdecAsFunction *cur;
+ SwfdecAsFrame *frame;
guint size;
GType type = 0;
@@ -1281,8 +1283,10 @@ swfdec_as_object_create (SwfdecAsFunction *fun, guint n_args,
swfdec_as_object_set_variable_and_flags (new, SWFDEC_AS_STR___constructor__,
&val, SWFDEC_AS_VARIABLE_HIDDEN | SWFDEC_AS_VARIABLE_VERSION_6_UP);
- swfdec_as_function_call (fun, new, n_args, args, return_value);
- context->frame->construct = TRUE;
+ frame = swfdec_as_function_call_no_preload (fun, new, n_args, args, return_value);
+ frame->construct = TRUE;
+ swfdec_as_super_new (frame, new, TRUE);
+ swfdec_as_frame_preload (frame);
}
/**
diff --git a/libswfdec/swfdec_as_super.c b/libswfdec/swfdec_as_super.c
index 3a52c16..20a4f02 100644
--- a/libswfdec/swfdec_as_super.c
+++ b/libswfdec/swfdec_as_super.c
@@ -133,41 +133,39 @@ swfdec_as_super_init (SwfdecAsSuper *super)
{
}
-SwfdecAsObject *
-swfdec_as_super_new (SwfdecAsFrame *frame)
+void
+swfdec_as_super_new (SwfdecAsFrame *frame, SwfdecAsObject *ref, gboolean callable)
{
SwfdecAsContext *context;
SwfdecAsSuper *super;
- SwfdecAsObject *ret;
- g_return_val_if_fail (SWFDEC_IS_AS_FRAME (frame), NULL);
+ g_return_if_fail (SWFDEC_IS_AS_FRAME (frame));
+ g_return_if_fail (SWFDEC_IS_AS_OBJECT (ref));
- if (frame->thisp == NULL) {
- SWFDEC_FIXME ("found a case where this was NULL, test how super behaves here!");
- return NULL;
- }
-
+ if (frame->super != NULL)
+ return;
context = SWFDEC_AS_OBJECT (frame)->context;
- if (context->version <= 5 && !frame->construct)
- return NULL;
+ if (context->version <= 5)
+ return;
if (!swfdec_as_context_use_mem (context, sizeof (SwfdecAsSuper)))
- return NULL;
- ret = g_object_new (SWFDEC_TYPE_AS_SUPER, NULL);
- swfdec_as_object_add (ret, context, sizeof (SwfdecAsSuper));
- super = SWFDEC_AS_SUPER (ret);
- super->thisp = frame->thisp;
+ return;
+ super = g_object_new (SWFDEC_TYPE_AS_SUPER, NULL);
+ frame->super = SWFDEC_AS_OBJECT (super);
+ swfdec_as_object_add (SWFDEC_AS_OBJECT (super), context, sizeof (SwfdecAsSuper));
+ super->thisp = ref;
+ super->callable = callable;
if (context->version <= 5) {
super->object = NULL;
} else {
- super->object = frame->thisp->prototype;
+ super->object = ref->prototype;
}
- return ret;
}
/**
- * swfdec_as_super_replace:
- * @super: the super object to replace from
+ * swfdec_as_super_new_chain:
+ * @frame: the frame that is called
+ * @super: the super object to chain from
* @function_name: garbage-collected name of the function that was called on
* @super or %NULL
*
@@ -177,23 +175,31 @@ swfdec_as_super_new (SwfdecAsFrame *frame)
* function is called with @super and "foo" as @function_name.
**/
void
-swfdec_as_super_replace (SwfdecAsSuper *super, const char *function_name)
+swfdec_as_super_new_chain (SwfdecAsFrame *frame, SwfdecAsSuper *super,
+ const char *function_name)
{
SwfdecAsSuper *replace;
SwfdecAsContext *context;
g_return_if_fail (SWFDEC_IS_AS_SUPER (super));
+ /* should be the first call trying to set super */
+ g_return_if_fail (frame->super == NULL);
- context = SWFDEC_AS_OBJECT (super)->context;
- replace = SWFDEC_AS_SUPER (context->frame->super);
- if (replace == NULL)
+ context = SWFDEC_AS_OBJECT (frame)->context;
+ if (!swfdec_as_context_use_mem (context, sizeof (SwfdecAsSuper)))
return;
+ replace = g_object_new (SWFDEC_TYPE_AS_SUPER, NULL);
+ frame->super = SWFDEC_AS_OBJECT (replace);
+ swfdec_as_object_add (SWFDEC_AS_OBJECT (replace), context, sizeof (SwfdecAsSuper));
if (super->object == NULL || super->object->prototype == NULL) {
replace->object = NULL;
return;
}
+ replace->thisp = super->thisp;
replace->object = super->object->prototype;
+ replace->callable = super->callable;
if (function_name && context->version > 6) {
+ /* skip prototypes to find the next one that has this function defined */
SwfdecAsObject *res;
if (swfdec_as_object_get_variable_and_flags (replace->object,
function_name, NULL, NULL, &res) &&
diff --git a/libswfdec/swfdec_as_super.h b/libswfdec/swfdec_as_super.h
index de14152..2eaa1d7 100644
--- a/libswfdec/swfdec_as_super.h
+++ b/libswfdec/swfdec_as_super.h
@@ -38,6 +38,7 @@ typedef struct _SwfdecAsSuperClass SwfdecAsSuperClass;
struct _SwfdecAsSuper {
SwfdecAsFunction function;
+ gboolean callable; /* TRUE if this super object can be called */
SwfdecAsObject * thisp; /* object super was called on */
SwfdecAsObject * object; /* current prototype we reference */
};
@@ -48,9 +49,11 @@ struct _SwfdecAsSuperClass {
GType swfdec_as_super_get_type (void);
-SwfdecAsObject *swfdec_as_super_new (SwfdecAsFrame * frame);
-
-void swfdec_as_super_replace (SwfdecAsSuper * super,
+void swfdec_as_super_new (SwfdecAsFrame * frame,
+ SwfdecAsObject * ref,
+ gboolean callable);
+void swfdec_as_super_new_chain (SwfdecAsFrame * frame,
+ SwfdecAsSuper * super,
const char * function_name);
G_END_DECLS
commit c5b4397d7a2d1c915f55bc2c6864a79d11dcc199
Author: Benjamin Otte <otte at gnome.org>
Date: Tue Nov 13 23:50:31 2007 +0100
add swfdec_as_function_call_no_preload () to allow doing stuff before preloading
use this by swfdec_as_function_call () to create the super object. And don't
create the super object in swfdec_as_frame_preload () anymore. It seems existance
of a super object depends on how a function was called, so we need to make
creation non-automatic.
Currently, various tests will break.
diff --git a/libswfdec/swfdec_as_frame.c b/libswfdec/swfdec_as_frame.c
index e850d96..77f4c3a 100644
--- a/libswfdec/swfdec_as_frame.c
+++ b/libswfdec/swfdec_as_frame.c
@@ -699,9 +699,6 @@ swfdec_as_frame_preload (SwfdecAsFrame *frame)
/* silence gcc */
args = NULL;
}
- if ((script->flags & (SWFDEC_SCRIPT_PRELOAD_SUPER | SWFDEC_SCRIPT_SUPPRESS_SUPER)) != SWFDEC_SCRIPT_SUPPRESS_SUPER) {
- frame->super = swfdec_as_super_new (frame);
- }
/* set the default variables (unless suppressed */
if (!(script->flags & SWFDEC_SCRIPT_SUPPRESS_THIS)) {
diff --git a/libswfdec/swfdec_as_function.c b/libswfdec/swfdec_as_function.c
index 8d2f927..fea1b3d 100644
--- a/libswfdec/swfdec_as_function.c
+++ b/libswfdec/swfdec_as_function.c
@@ -26,6 +26,7 @@
#include "swfdec_as_frame_internal.h"
#include "swfdec_as_internal.h"
#include "swfdec_as_stack.h"
+#include "swfdec_as_super.h"
#include "swfdec_as_strings.h"
#include "swfdec_debug.h"
@@ -97,6 +98,41 @@ swfdec_as_function_set_constructor (SwfdecAsFunction *fun)
SWFDEC_AS_VARIABLE_VERSION_6_UP);
}
+SwfdecAsFrame *
+swfdec_as_function_call_no_preload (SwfdecAsFunction *function,
+ SwfdecAsObject *thisp, guint n_args, const SwfdecAsValue *args,
+ SwfdecAsValue *return_value)
+{
+ SwfdecAsContext *context;
+ SwfdecAsFrame *frame;
+ SwfdecAsFunctionClass *klass;
+
+ g_return_val_if_fail (SWFDEC_IS_AS_FUNCTION (function), NULL);
+ g_return_val_if_fail (thisp == NULL || SWFDEC_IS_AS_OBJECT (thisp), NULL);
+
+ context = SWFDEC_AS_OBJECT (function)->context;
+ /* just to be sure... */
+ if (return_value)
+ SWFDEC_AS_VALUE_SET_UNDEFINED (return_value);
+
+ klass = SWFDEC_AS_FUNCTION_GET_CLASS (function);
+ g_assert (klass->call);
+ frame = klass->call (function);
+ /* FIXME: figure out what to do in these situations */
+ if (frame == NULL)
+ return NULL;
+ if (function->priv)
+ swfdec_as_frame_set_security (frame, function->priv);
+ /* second check especially for super object */
+ if (thisp != NULL && frame->thisp == NULL)
+ swfdec_as_frame_set_this (frame, swfdec_as_object_resolve (thisp));
+ frame->is_local = TRUE;
+ frame->argc = n_args;
+ frame->argv = args;
+ frame->return_value = return_value;
+ return frame;
+}
+
/**
* swfdec_as_function_call:
* @function: the #SwfdecAsFunction to call
@@ -116,33 +152,15 @@ void
swfdec_as_function_call (SwfdecAsFunction *function, SwfdecAsObject *thisp, guint n_args,
const SwfdecAsValue *args, SwfdecAsValue *return_value)
{
- SwfdecAsContext *context;
SwfdecAsFrame *frame;
- SwfdecAsFunctionClass *klass;
g_return_if_fail (SWFDEC_IS_AS_FUNCTION (function));
g_return_if_fail (thisp == NULL || SWFDEC_IS_AS_OBJECT (thisp));
- context = SWFDEC_AS_OBJECT (function)->context;
- /* just to be sure... */
- if (return_value)
- SWFDEC_AS_VALUE_SET_UNDEFINED (return_value);
-
- klass = SWFDEC_AS_FUNCTION_GET_CLASS (function);
- g_assert (klass->call);
- frame = klass->call (function);
- /* FIXME: figure out what to do in these situations */
+ frame = swfdec_as_function_call_no_preload (function, thisp, n_args, args, return_value);
if (frame == NULL)
return;
- if (function->priv)
- swfdec_as_frame_set_security (frame, function->priv);
- /* second check especially for super object */
- if (thisp != NULL && frame->thisp == NULL)
- swfdec_as_frame_set_this (frame, swfdec_as_object_resolve (thisp));
- frame->is_local = TRUE;
- frame->argc = n_args;
- frame->argv = args;
- frame->return_value = return_value;
+ frame->super = swfdec_as_super_new (frame);
swfdec_as_frame_preload (frame);
}
diff --git a/libswfdec/swfdec_as_internal.h b/libswfdec/swfdec_as_internal.h
index 6dc088d..68ff91b 100644
--- a/libswfdec/swfdec_as_internal.h
+++ b/libswfdec/swfdec_as_internal.h
@@ -34,11 +34,16 @@ G_BEGIN_DECLS
SwfdecAsObject *object, guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret);
-void swfdec_as_function_set_constructor (SwfdecAsFunction * fun);
-void swfdec_as_function_set_security (SwfdecAsFunction * fun,
- SwfdecSecurity * sec);
-void swfdec_as_function_init_context (SwfdecAsContext * context,
- guint version);
+void swfdec_as_function_set_constructor (SwfdecAsFunction * fun);
+void swfdec_as_function_set_security (SwfdecAsFunction * fun,
+ SwfdecSecurity * sec);
+void swfdec_as_function_init_context (SwfdecAsContext * context,
+ guint version);
+SwfdecAsFrame * swfdec_as_function_call_no_preload (SwfdecAsFunction * function,
+ SwfdecAsObject * thisp,
+ guint n_args,
+ const SwfdecAsValue * args,
+ SwfdecAsValue * return_value);
/* swfdec_as_context.c */
gboolean swfdec_as_context_check_continue (SwfdecAsContext * context);
commit 0fcd2465a6e039c65d749a761d31f699811b4692
Author: Benjamin Otte <otte at gnome.org>
Date: Tue Nov 13 23:48:03 2007 +0100
movies _do_ get a super object
diff --git a/libswfdec/swfdec_as_super.c b/libswfdec/swfdec_as_super.c
index 8a94749..3a52c16 100644
--- a/libswfdec/swfdec_as_super.c
+++ b/libswfdec/swfdec_as_super.c
@@ -146,9 +146,6 @@ swfdec_as_super_new (SwfdecAsFrame *frame)
SWFDEC_FIXME ("found a case where this was NULL, test how super behaves here!");
return NULL;
}
- /* functions called on native objects don't get a super object?! */
- if (SWFDEC_IS_MOVIE (frame->thisp))
- return NULL;
context = SWFDEC_AS_OBJECT (frame)->context;
if (context->version <= 5 && !frame->construct)
More information about the Swfdec
mailing list