move dereferencing out of SwfdecAsValue macros
[swfdec.git] / swfdec / swfdec_as_script_function.c
blob49811c0ab97033c4cea62530c2ff6bd2109c0d4d
1 /* Swfdec
2 * Copyright (C) 2007-2008 Benjamin Otte <otte@gnome.org>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301 USA
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
24 #include "swfdec_as_script_function.h"
25 #include "swfdec_as_context.h"
26 #include "swfdec_as_frame_internal.h"
27 #include "swfdec_as_internal.h"
28 #include "swfdec_as_stack.h"
29 #include "swfdec_as_strings.h"
30 #include "swfdec_as_super.h"
31 #include "swfdec_debug.h"
33 G_DEFINE_TYPE (SwfdecAsScriptFunction, swfdec_as_script_function, SWFDEC_TYPE_AS_FUNCTION)
35 static void
36 swfdec_as_script_function_call (SwfdecAsFunction *function, SwfdecAsObject *thisp,
37 gboolean construct, SwfdecAsObject *super_reference, guint n_args,
38 const SwfdecAsValue *args, SwfdecAsValue *return_value)
40 SwfdecAsScriptFunction *script = SWFDEC_AS_SCRIPT_FUNCTION (function);
41 SwfdecAsContext *context;
42 SwfdecSandbox *old_sandbox = NULL;
43 SwfdecAsFrame frame = { NULL, };
45 /* just to be sure... */
46 if (return_value)
47 SWFDEC_AS_VALUE_SET_UNDEFINED (return_value);
49 context = swfdec_gc_object_get_context (function);
50 /* do security checks */
51 if (script->sandbox != NULL &&
52 script->sandbox != (old_sandbox = swfdec_sandbox_get (SWFDEC_PLAYER (context)))) {
53 if (!swfdec_sandbox_allow (script->sandbox, old_sandbox))
54 return;
55 swfdec_sandbox_unuse (old_sandbox);
56 swfdec_sandbox_use (script->sandbox);
59 swfdec_as_frame_init (&frame, swfdec_gc_object_get_context (function), script->script);
60 frame.scope_chain = g_slist_concat (frame.scope_chain, g_slist_copy (script->scope_chain));
61 frame.function = function;
62 if (script->target) {
63 frame.target = script->target;
64 frame.original_target = script->target;
66 /* second check especially for super object */
67 if (thisp != NULL && SWFDEC_AS_VALUE_IS_UNDEFINED (*&frame.thisp)) {
68 swfdec_as_frame_set_this (&frame, swfdec_as_object_resolve (thisp));
70 frame.argc = n_args;
71 frame.argv = args;
72 frame.return_value = return_value;
73 frame.construct = construct;
74 if (super_reference == NULL) {
75 /* don't create a super object */
76 } else if (thisp != NULL) {
77 swfdec_as_super_new (&frame, thisp, super_reference);
78 } else {
79 // FIXME: Does the super object really reference the function when thisp is NULL?
80 swfdec_as_super_new (&frame,
81 swfdec_as_relay_get_as_object (SWFDEC_AS_RELAY (function)), super_reference);
83 swfdec_as_frame_preload (context, &frame);
84 swfdec_as_context_run (context);
86 if (old_sandbox) {
87 swfdec_sandbox_unuse (script->sandbox);
88 swfdec_sandbox_use (old_sandbox);
92 static void
93 swfdec_as_script_function_dispose (GObject *object)
95 SwfdecAsScriptFunction *script = SWFDEC_AS_SCRIPT_FUNCTION (object);
97 if (script->script) {
98 swfdec_script_unref (script->script);
99 script->script = NULL;
101 g_slist_free (script->scope_chain);
102 script->scope_chain = NULL;
104 G_OBJECT_CLASS (swfdec_as_script_function_parent_class)->dispose (object);
107 static void
108 swfdec_as_script_function_mark (SwfdecGcObject *object)
110 SwfdecAsScriptFunction *script = SWFDEC_AS_SCRIPT_FUNCTION (object);
112 g_slist_foreach (script->scope_chain, (GFunc) swfdec_as_object_mark, NULL);
113 if (script->sandbox)
114 swfdec_gc_object_mark (script->sandbox);
116 SWFDEC_GC_OBJECT_CLASS (swfdec_as_script_function_parent_class)->mark (object);
119 static void
120 swfdec_as_script_function_class_init (SwfdecAsScriptFunctionClass *klass)
122 GObjectClass *object_class = G_OBJECT_CLASS (klass);
123 SwfdecGcObjectClass *gc_class = SWFDEC_GC_OBJECT_CLASS (klass);
124 SwfdecAsFunctionClass *function_class = SWFDEC_AS_FUNCTION_CLASS (klass);
126 object_class->dispose = swfdec_as_script_function_dispose;
128 gc_class->mark = swfdec_as_script_function_mark;
130 function_class->call = swfdec_as_script_function_call;
133 static void
134 swfdec_as_script_function_init (SwfdecAsScriptFunction *script_function)
138 SwfdecAsFunction *
139 swfdec_as_script_function_new (SwfdecAsContext *context, SwfdecMovie *target,
140 const GSList *scope_chain, SwfdecScript *script)
142 SwfdecAsValue val, *tmp;
143 SwfdecAsScriptFunction *fun;
144 SwfdecAsObject *proto, *object;
146 g_return_val_if_fail (SWFDEC_IS_AS_CONTEXT (context), NULL);
147 g_return_val_if_fail (target == NULL || SWFDEC_IS_MOVIE (target), NULL);
148 g_return_val_if_fail (script != NULL, NULL);
150 fun = g_object_new (SWFDEC_TYPE_AS_SCRIPT_FUNCTION, "context", context, NULL);
151 fun->scope_chain = g_slist_copy ((GSList *) scope_chain);
152 fun->script = script;
153 fun->target = target;
155 /* if context is a flash player, copy current sandbox for security checking.
156 * FIXME: export this somehow? */
157 if (SWFDEC_IS_PLAYER (context))
158 fun->sandbox = swfdec_sandbox_get (SWFDEC_PLAYER (context));
160 object = swfdec_as_object_new_empty (context);
161 swfdec_as_object_set_relay (object, SWFDEC_AS_RELAY (fun));
162 swfdec_as_object_set_constructor_by_name (object, SWFDEC_AS_STR_Function, NULL);
163 swfdec_as_object_set_variable_flags (object, SWFDEC_AS_STR___proto__,
164 SWFDEC_AS_VARIABLE_VERSION_6_UP);
166 /* set prototype */
167 proto = swfdec_as_object_new_empty (context);
168 SWFDEC_AS_VALUE_SET_OBJECT (&val, proto);
169 swfdec_as_object_set_variable_and_flags (object, SWFDEC_AS_STR_prototype,
170 &val, SWFDEC_AS_VARIABLE_HIDDEN | SWFDEC_AS_VARIABLE_PERMANENT);
172 SWFDEC_AS_VALUE_SET_OBJECT (&val, object);
173 swfdec_as_object_set_variable_and_flags (proto, SWFDEC_AS_STR_constructor,
174 &val, SWFDEC_AS_VARIABLE_HIDDEN | SWFDEC_AS_VARIABLE_PERMANENT);
175 tmp = swfdec_as_object_peek_variable (context->global, SWFDEC_AS_STR_Object);
176 if (tmp && SWFDEC_AS_VALUE_IS_OBJECT (*tmp)) {
177 tmp = swfdec_as_object_peek_variable (SWFDEC_AS_VALUE_GET_OBJECT (*tmp),
178 SWFDEC_AS_STR_prototype);
179 if (tmp) {
180 swfdec_as_object_set_variable_and_flags (proto, SWFDEC_AS_STR___proto__,
181 tmp, SWFDEC_AS_VARIABLE_HIDDEN | SWFDEC_AS_VARIABLE_PERMANENT);
185 return SWFDEC_AS_FUNCTION (fun);