add a test for just-fixed crasher
[swfdec.git] / swfdec / swfdec_player_as.c
blob2455156b30770a88bd0ef102a4ce1ce9ae62e5a8
1 /* Swfdec
2 * Copyright (C) 2006-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.
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 /* NB: include this first, it redefines SWFDEC_AS_NATIVE */
25 #include "swfdec_asnative.h"
27 #include "swfdec_player_internal.h"
28 #include "swfdec_as_function.h"
29 #include "swfdec_as_internal.h"
30 #include "swfdec_as_native_function.h"
31 #include "swfdec_as_object.h"
32 #include "swfdec_as_strings.h"
33 #include "swfdec_debug.h"
34 #include "swfdec_internal.h"
35 #include "swfdec_interval.h"
36 #include "swfdec_as_frame_internal.h"
38 /*** INTERVALS ***/
40 static void
41 swfdec_player_do_set_interval (gboolean repeat, SwfdecAsContext *cx, guint argc,
42 SwfdecAsValue *argv, SwfdecAsValue *rval)
44 SwfdecPlayer *player = SWFDEC_PLAYER (cx);
45 SwfdecAsObject *object;
46 guint id, msecs;
47 #define MIN_INTERVAL_TIME 10
49 if (argc < 2) {
50 SWFDEC_WARNING ("setInterval needs at least 2 arguments");
51 return;
54 if (!SWFDEC_AS_VALUE_IS_OBJECT (&argv[0])) {
55 SWFDEC_WARNING ("first argument to setInterval is not an object");
56 return;
58 object = SWFDEC_AS_VALUE_GET_OBJECT (&argv[0]);
59 if (SWFDEC_IS_AS_FUNCTION (object)) {
60 msecs = swfdec_as_value_to_integer (cx, &argv[1]);
61 if (msecs < MIN_INTERVAL_TIME) {
62 SWFDEC_INFO ("interval duration is %u, making it %u msecs", msecs, MIN_INTERVAL_TIME);
63 msecs = MIN_INTERVAL_TIME;
65 id = swfdec_interval_new_function (player, msecs, repeat,
66 SWFDEC_AS_FUNCTION (object), argc - 2, &argv[2]);
67 } else {
68 const char *name;
69 if (argc < 3) {
70 SWFDEC_WARNING ("setInterval needs 3 arguments when not called with function");
71 return;
73 name = swfdec_as_value_to_string (cx, &argv[1]);
74 msecs = swfdec_as_value_to_integer (cx, &argv[2]);
75 if (msecs < MIN_INTERVAL_TIME) {
76 SWFDEC_INFO ("interval duration is %u, making it %u msecs", msecs, MIN_INTERVAL_TIME);
77 msecs = MIN_INTERVAL_TIME;
79 id = swfdec_interval_new_object (player, msecs, repeat, object, name, argc - 3, &argv[3]);
81 SWFDEC_AS_VALUE_SET_INT (rval, id);
84 SWFDEC_AS_NATIVE (2, 0, swfdec_player_ASnew)
85 void
86 swfdec_player_ASnew (SwfdecAsContext *cx, SwfdecAsObject *obj,
87 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
89 g_return_if_fail (cx->frame->next != NULL);
91 SWFDEC_AS_VALUE_SET_BOOLEAN (rval, cx->frame->next->construct);
94 SWFDEC_AS_NATIVE (250, 0, swfdec_player_setInterval)
95 void
96 swfdec_player_setInterval (SwfdecAsContext *cx, SwfdecAsObject *obj,
97 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
99 swfdec_player_do_set_interval (TRUE, cx, argc, argv, rval);
102 SWFDEC_AS_NATIVE (250, 2, swfdec_player_setTimeout)
103 void
104 swfdec_player_setTimeout (SwfdecAsContext *cx, SwfdecAsObject *obj,
105 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
107 swfdec_player_do_set_interval (FALSE, cx, argc, argv, rval);
110 SWFDEC_AS_NATIVE (250, 1, swfdec_player_clearInterval)
111 void
112 swfdec_player_clearInterval (SwfdecAsContext *cx, SwfdecAsObject *object,
113 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
115 SwfdecPlayer *player = SWFDEC_PLAYER (cx);
116 guint id;
118 SWFDEC_AS_CHECK (0, NULL, "i", &id);
120 swfdec_interval_remove (player, id);
123 /*** VARIOUS ***/
125 SWFDEC_AS_NATIVE (100, 4, swfdec_player_trace)
126 void
127 swfdec_player_trace (SwfdecAsContext *cx, SwfdecAsObject *obj,
128 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
130 SWFDEC_FIXME ("Is _global.trace supposed to do something?");
133 SWFDEC_AS_NATIVE (9, 0, swfdec_player_updateAfterEvent)
134 void
135 swfdec_player_updateAfterEvent (SwfdecAsContext *cx, SwfdecAsObject *obj,
136 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
138 SWFDEC_STUB ("updateAfterEvent");
141 SWFDEC_AS_NATIVE (1021, 1, swfdec_player_showRedrawRegions)
142 void
143 swfdec_player_showRedrawRegions (SwfdecAsContext *cx, SwfdecAsObject *obj,
144 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
146 SWFDEC_STUB ("showRedrawRegions");
149 static void
150 swfdec_player_enableDebugConsole (SwfdecAsContext *cx, SwfdecAsObject *obj,
151 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
153 SWFDEC_STUB ("enableDebugConsole");
156 static void
157 swfdec_player_do_nothing (SwfdecAsContext *cx, SwfdecAsObject *object,
158 guint argc, SwfdecAsValue *argv, SwfdecAsValue *retval)
162 static SwfdecAsFunction *
163 swfdec_get_asnative (SwfdecAsContext *cx, guint x, guint y)
165 gboolean x_exists;
166 guint i;
168 x_exists = FALSE;
169 for (i = 0; native_funcs[i].func != NULL; i++) {
170 if (native_funcs[i].x == x)
171 x_exists = TRUE;
172 if (native_funcs[i].x == x && native_funcs[i].y == y) {
173 SwfdecAsFunction *fun = swfdec_as_native_function_new (cx, native_funcs[i].name,
174 native_funcs[i].func, NULL);
175 if (native_funcs[i].get_type) {
176 swfdec_as_native_function_set_construct_type (SWFDEC_AS_NATIVE_FUNCTION (fun),
177 native_funcs[i].get_type ());
179 return fun;
182 SWFDEC_WARNING ("no ASnative (%u, %u)", x, y);
183 if (x_exists) {
184 SwfdecAsFunction *func;
185 char *name = g_strdup_printf ("ASnative (%u, %u)", x, y);
186 func = swfdec_as_native_function_new (cx, name, swfdec_player_do_nothing,
187 NULL);
188 g_free (name);
189 return func;
190 } else {
191 return NULL;
195 // same as ASnative, but also sets prototype
196 static void
197 swfdec_player_ASconstructor (SwfdecAsContext *cx, SwfdecAsObject *object,
198 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
200 SwfdecAsValue val;
201 SwfdecAsObject *proto;
202 SwfdecAsFunction *func;
203 guint x, y;
205 SWFDEC_AS_CHECK (0, NULL, "ii", &x, &y);
207 func = swfdec_get_asnative (cx, x, y);
208 if (func) {
209 proto = swfdec_as_object_new (cx);
211 SWFDEC_AS_VALUE_SET_OBJECT (&val, proto);
212 swfdec_as_object_set_variable_and_flags (SWFDEC_AS_OBJECT (func),
213 SWFDEC_AS_STR_prototype, &val,
214 SWFDEC_AS_VARIABLE_HIDDEN | SWFDEC_AS_VARIABLE_PERMANENT);
216 SWFDEC_AS_VALUE_SET_OBJECT (&val, SWFDEC_AS_OBJECT (func));
217 swfdec_as_object_set_variable_and_flags (proto, SWFDEC_AS_STR_constructor,
218 &val, SWFDEC_AS_VARIABLE_HIDDEN | SWFDEC_AS_VARIABLE_PERMANENT);
220 SWFDEC_AS_VALUE_SET_OBJECT (rval, SWFDEC_AS_OBJECT (func));
224 static void
225 swfdec_player_ASnative (SwfdecAsContext *cx, SwfdecAsObject *object,
226 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
228 SwfdecAsFunction *func;
229 guint x, y;
231 SWFDEC_AS_CHECK (0, NULL, "ii", &x, &y);
233 func = swfdec_get_asnative (cx, x, y);
234 if (func) {
235 SWFDEC_AS_VALUE_SET_OBJECT (rval, SWFDEC_AS_OBJECT (func));
239 SWFDEC_AS_NATIVE (4, 0, ASSetNative)
240 void
241 ASSetNative (SwfdecAsContext *cx, SwfdecAsObject *object,
242 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
244 SwfdecAsFunction *function;
245 SwfdecAsObject *target;
246 SwfdecAsValue val;
247 SwfdecAsVariableFlag flags;
248 const char *s;
249 char **names;
250 guint i, x, y;
252 SWFDEC_AS_CHECK (0, NULL, "ois", &target, &x, &s);
254 if (argc > 3)
255 y = swfdec_as_value_to_integer (cx, &argv[3]);
256 else
257 y = 0;
258 names = g_strsplit (s, ",", -1);
259 for (i = 0; names[i]; i++) {
260 s = names[i];
261 flags = 0;
262 if (s[0] == '6') {
263 flags |= SWFDEC_AS_VARIABLE_VERSION_6_UP;
264 s++;
265 } else if (s[0] == '7') {
266 flags |= SWFDEC_AS_VARIABLE_VERSION_7_UP;
267 s++;
268 } else if (s[0] == '8') {
269 flags |= SWFDEC_AS_VARIABLE_VERSION_8_UP;
270 s++;
271 } else if (s[0] == '9') {
272 flags |= SWFDEC_AS_VARIABLE_VERSION_9_UP;
273 s++;
275 function = swfdec_get_asnative (cx, x, y);
276 if (function == NULL)
277 break;
278 SWFDEC_AS_VALUE_SET_OBJECT (&val, SWFDEC_AS_OBJECT (function));
279 swfdec_as_object_set_variable_and_flags (target,
280 swfdec_as_context_get_string (cx, s), &val, flags);
281 y++;
283 g_strfreev (names);
286 SWFDEC_AS_NATIVE (4, 1, ASSetNativeAccessor)
287 void
288 ASSetNativeAccessor (SwfdecAsContext *cx, SwfdecAsObject *object,
289 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
291 SwfdecAsFunction *get, *set;
292 SwfdecAsObject *target;
293 SwfdecAsVariableFlag flags;
294 const char *s;
295 char **names;
296 guint i, x, y = 0;
298 SWFDEC_AS_CHECK (0, NULL, "ois|i", &target, &x, &s, &y);
300 names = g_strsplit (s, ",", -1);
301 for (i = 0; names[i]; i++) {
302 s = names[i];
303 flags = 0;
304 if (s[0] == '6') {
305 flags |= SWFDEC_AS_VARIABLE_VERSION_6_UP;
306 s++;
307 } else if (s[0] == '7') {
308 flags |= SWFDEC_AS_VARIABLE_VERSION_7_UP;
309 s++;
310 } else if (s[0] == '8') {
311 flags |= SWFDEC_AS_VARIABLE_VERSION_8_UP;
312 s++;
313 } else if (s[0] == '9') {
314 flags |= SWFDEC_AS_VARIABLE_VERSION_9_UP;
315 s++;
317 get = swfdec_get_asnative (cx, x, y++);
318 set = swfdec_get_asnative (cx, x, y++);
319 if (get == NULL) {
320 SWFDEC_ERROR ("no getter for %s", s);
321 break;
323 swfdec_as_object_add_variable (target, swfdec_as_context_get_string (cx, s),
324 get, set, flags);
326 g_strfreev (names);
329 SWFDEC_AS_NATIVE (101, 8, swfdec_player_object_registerClass)
330 void
331 swfdec_player_object_registerClass (SwfdecAsContext *cx, SwfdecAsObject *object,
332 guint argc, SwfdecAsValue *argv, SwfdecAsValue *rval)
334 const char *name;
336 SWFDEC_AS_CHECK (0, NULL, "s", &name);
338 if (argc < 2 || !SWFDEC_AS_VALUE_IS_OBJECT (&argv[1])) {
339 SWFDEC_AS_VALUE_SET_BOOLEAN (rval, FALSE);
340 return;
343 swfdec_player_set_export_class (SWFDEC_PLAYER (cx), name,
344 SWFDEC_AS_VALUE_GET_OBJECT (&argv[1]));
345 SWFDEC_AS_VALUE_SET_BOOLEAN (rval, TRUE);
348 /* This is ran at the beginning of swfdec_as_context_startup.
349 * Yes, this is a hack */
350 void
351 swfdec_player_preinit_global (SwfdecAsContext *context)
353 /* init these two before swfdec_as_context_startup, so they won't get
354 * __proto__ and constructor properties */
355 swfdec_as_object_add_function (context->global, SWFDEC_AS_STR_ASnative,
356 swfdec_player_ASnative);
357 swfdec_as_object_add_function (context->global, SWFDEC_AS_STR_ASconstructor,
358 swfdec_player_ASconstructor);
359 // FIXME: is this only the debug player?
360 swfdec_as_object_add_function (context->global,
361 SWFDEC_AS_STR_enableDebugConsole, swfdec_player_enableDebugConsole);