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.
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
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
)
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... */
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
))
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
;
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
));
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
);
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
);
87 swfdec_sandbox_unuse (script
->sandbox
);
88 swfdec_sandbox_use (old_sandbox
);
93 swfdec_as_script_function_dispose (GObject
*object
)
95 SwfdecAsScriptFunction
*script
= SWFDEC_AS_SCRIPT_FUNCTION (object
);
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
);
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
);
114 swfdec_gc_object_mark (script
->sandbox
);
116 SWFDEC_GC_OBJECT_CLASS (swfdec_as_script_function_parent_class
)->mark (object
);
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
;
134 swfdec_as_script_function_init (SwfdecAsScriptFunction
*script_function
)
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
);
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
);
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
);