2 * Copyright (C) 2007 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_function.h"
25 #include "swfdec_as_context.h"
26 #include "swfdec_as_internal.h"
27 #include "swfdec_as_native_function.h"
28 #include "swfdec_as_strings.h"
29 #include "swfdec_debug.h"
31 G_DEFINE_ABSTRACT_TYPE (SwfdecAsFunction
, swfdec_as_function
, SWFDEC_TYPE_AS_OBJECT
)
34 * SECTION:SwfdecAsFunction
35 * @title: SwfdecAsFunction
36 * @short_description: script objects that can be executed
38 * Functions is the basic object for executing code in the Swfdec script engine.
39 * There is multiple different variants of functions, such as script-created
40 * ones and native functions.
42 * If you want to create your own functions, you should create native functions.
43 * The easiest way to do this is with swfdec_as_object_add_function() or
44 * swfdec_as_native_function_new().
46 * In Actionscript, every function can be used as a constructor. If you want to
47 * make a native function be used as a constructor for your own #SwfdecAsObject
48 * subclass, have a look at swfdec_as_native_function_set_construct_type().
54 * This is the base executable object in Swfdec. It is an abstract object. If
55 * you want to create functions yourself, use #SwfdecAsNativeFunction.
59 swfdec_as_function_class_init (SwfdecAsFunctionClass
*klass
)
64 swfdec_as_function_init (SwfdecAsFunction
*function
)
69 * swfdec_as_function_set_constructor:
70 * @fun: a #SwfdecAsFunction
72 * Sets the constructor and prototype of @fun. This is a shortcut for calling
73 * swfdec_as_object_set_constructor() with the right arguments.
76 swfdec_as_function_set_constructor (SwfdecAsFunction
*fun
)
78 SwfdecAsContext
*context
;
79 SwfdecAsObject
*object
;
82 g_return_if_fail (SWFDEC_IS_AS_FUNCTION (fun
));
84 object
= SWFDEC_AS_OBJECT (fun
);
85 context
= swfdec_gc_object_get_context (fun
);
86 if (context
->Function
== NULL
)
89 SWFDEC_AS_VALUE_SET_OBJECT (&val
, context
->Function
);
90 swfdec_as_object_set_variable_and_flags (object
, SWFDEC_AS_STR_constructor
,
91 &val
, SWFDEC_AS_VARIABLE_HIDDEN
| SWFDEC_AS_VARIABLE_PERMANENT
);
93 SWFDEC_AS_VALUE_SET_OBJECT (&val
, context
->Function_prototype
);
94 swfdec_as_object_set_variable_and_flags (object
, SWFDEC_AS_STR___proto__
,
95 &val
, SWFDEC_AS_VARIABLE_HIDDEN
| SWFDEC_AS_VARIABLE_PERMANENT
|
96 SWFDEC_AS_VARIABLE_VERSION_6_UP
);
100 * swfdec_as_function_call:
101 * @function: the #SwfdecAsFunction to call
102 * @thisp: this argument to use for the call or %NULL for none
103 * @n_args: number of arguments to pass to the function
104 * @args: the arguments to pass or %NULL to read the last @n_args stack elements.
105 * @return_value: pointer for return value or %NULL to push the return value to
108 * Calls the given function. This is a macro that resolves to
109 * swfdec_as_function_call_full().
112 * swfdec_as_function_call_full:
113 * @function: the #SwfdecAsFunction to call
114 * @thisp: this argument to use for the call or %NULL for none
115 * @construct: call this function as a constructor. This is only relevant for
117 * @super_reference: The object to be referenced by the super object in this
118 * function call or %NULL to use the default.
119 * @n_args: number of arguments to pass to the function
120 * @args: the arguments to pass or %NULL to read the last @n_args stack elements.
121 * @return_value: pointer for return value or %NULL to push the return value to
124 * Calls the given function.
127 swfdec_as_function_call_full (SwfdecAsFunction
*function
, SwfdecAsObject
*thisp
,
128 gboolean construct
, SwfdecAsObject
*super_reference
, guint n_args
,
129 const SwfdecAsValue
*args
, SwfdecAsValue
*return_value
)
131 SwfdecAsFunctionClass
*klass
;
133 g_return_if_fail (SWFDEC_IS_AS_FUNCTION (function
));
134 g_return_if_fail (thisp
== NULL
|| SWFDEC_IS_AS_OBJECT (thisp
));
135 g_return_if_fail (super_reference
== NULL
|| SWFDEC_IS_AS_OBJECT (super_reference
));
137 klass
= SWFDEC_AS_FUNCTION_GET_CLASS (function
);
138 klass
->call (function
, thisp
, construct
, super_reference
, n_args
, args
, return_value
);
143 SWFDEC_AS_NATIVE (101, 10, swfdec_as_function_do_call
)
145 swfdec_as_function_do_call (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
146 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
148 SwfdecAsFunction
*fun
;
149 SwfdecAsObject
*thisp
= NULL
;
151 SWFDEC_AS_CHECK (SWFDEC_TYPE_AS_FUNCTION
, &fun
, "|O", &thisp
);
154 thisp
= swfdec_as_object_new_empty (cx
);
160 swfdec_as_function_call (fun
, thisp
, argc
, argv
, ret
);
163 SWFDEC_AS_NATIVE (101, 11, swfdec_as_function_apply
)
165 swfdec_as_function_apply (SwfdecAsContext
*cx
, SwfdecAsObject
*object
,
166 guint argc
, SwfdecAsValue
*argv
, SwfdecAsValue
*ret
)
168 SwfdecAsValue
*argv_pass
= NULL
;
170 SwfdecAsFunction
*fun
;
171 SwfdecAsObject
*thisp
= NULL
;
173 SWFDEC_AS_CHECK (SWFDEC_TYPE_AS_FUNCTION
, &fun
, "|O", &thisp
);
176 thisp
= swfdec_as_object_new_empty (cx
);
178 if (argc
> 1 && SWFDEC_AS_VALUE_IS_OBJECT (&argv
[1])) {
180 SwfdecAsObject
*array
;
183 array
= SWFDEC_AS_VALUE_GET_OBJECT (&argv
[1]);
185 swfdec_as_object_get_variable (array
, SWFDEC_AS_STR_length
, &val
);
186 length
= swfdec_as_value_to_integer (cx
, &val
);
189 /* FIXME: find a smarter way to do this, like providing argv not as an array */
190 if (!swfdec_as_context_try_use_mem (cx
, sizeof (SwfdecAsValue
) * length
)) {
191 swfdec_as_context_abort (cx
, "too many arguments to Function.apply");
194 argv_pass
= g_malloc (sizeof (SwfdecAsValue
) * length
);
196 for (i
= 0; i
< length
; i
++) {
197 swfdec_as_object_get_variable (array
,
198 swfdec_as_integer_to_string (cx
, i
), &argv_pass
[i
]);
205 swfdec_as_function_call (fun
, thisp
, length
, argv_pass
, ret
);
208 swfdec_as_context_unuse_mem (cx
, sizeof (SwfdecAsValue
) * length
);
214 swfdec_as_function_init_context (SwfdecAsContext
*context
)
216 SwfdecAsObject
*function
, *proto
;
219 g_return_if_fail (SWFDEC_IS_AS_CONTEXT (context
));
221 function
= SWFDEC_AS_OBJECT (swfdec_as_object_add_function (context
->global
,
222 SWFDEC_AS_STR_Function
, NULL
));
223 swfdec_as_object_set_variable_flags (context
->global
, SWFDEC_AS_STR_Function
, SWFDEC_AS_VARIABLE_VERSION_6_UP
);
224 context
->Function
= function
;
225 SWFDEC_AS_VALUE_SET_OBJECT (&val
, function
);
226 swfdec_as_object_set_variable_and_flags (function
, SWFDEC_AS_STR_constructor
,
227 &val
, SWFDEC_AS_VARIABLE_HIDDEN
| SWFDEC_AS_VARIABLE_PERMANENT
);
228 proto
= swfdec_as_object_new_empty (context
);
229 context
->Function_prototype
= proto
;
230 SWFDEC_AS_VALUE_SET_OBJECT (&val
, proto
);
231 swfdec_as_object_set_variable_and_flags (function
, SWFDEC_AS_STR_prototype
,
232 &val
, SWFDEC_AS_VARIABLE_HIDDEN
| SWFDEC_AS_VARIABLE_PERMANENT
);
233 swfdec_as_object_set_variable_and_flags (function
, SWFDEC_AS_STR___proto__
,
234 &val
, SWFDEC_AS_VARIABLE_HIDDEN
| SWFDEC_AS_VARIABLE_PERMANENT
|
235 SWFDEC_AS_VARIABLE_VERSION_6_UP
);
236 SWFDEC_AS_VALUE_SET_OBJECT (&val
, function
);
237 swfdec_as_object_set_variable_and_flags (proto
, SWFDEC_AS_STR_constructor
,
238 &val
, SWFDEC_AS_VARIABLE_HIDDEN
| SWFDEC_AS_VARIABLE_PERMANENT
);