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
26 #include "swfdec_as_super.h"
27 #include "swfdec_as_context.h"
28 #include "swfdec_as_frame_internal.h"
29 #include "swfdec_as_function.h"
30 #include "swfdec_as_internal.h"
31 #include "swfdec_as_strings.h"
32 #include "swfdec_debug.h"
33 #include "swfdec_movie.h"
35 G_DEFINE_TYPE (SwfdecAsSuper
, swfdec_as_super
, SWFDEC_TYPE_AS_FUNCTION
)
38 swfdec_as_super_call (SwfdecAsFunction
*function
, SwfdecAsObject
*thisp
,
39 gboolean construct
, SwfdecAsObject
*super_reference
, guint n_args
,
40 const SwfdecAsValue
*args
, SwfdecAsValue
*return_value
)
42 SwfdecAsSuper
*super
= SWFDEC_AS_SUPER (function
);
43 SwfdecAsFunction
*fun
;
46 if (super
->object
== NULL
) {
47 SWFDEC_WARNING ("super () called without an object.");
51 swfdec_as_object_get_variable (super
->object
, SWFDEC_AS_STR___constructor__
, &val
);
52 if (!SWFDEC_AS_VALUE_IS_OBJECT (&val
) ||
53 !SWFDEC_IS_AS_FUNCTION (fun
= (SwfdecAsFunction
*) SWFDEC_AS_VALUE_GET_OBJECT (&val
)))
57 SWFDEC_FIXME ("What happens with \"new super()\"?");
59 swfdec_as_function_call_full (fun
, super
->thisp
, construct
||
60 swfdec_as_context_is_constructing (swfdec_gc_object_get_context (super
)),
61 super
->object
->prototype
, n_args
, args
, return_value
);
65 swfdec_as_super_get (SwfdecAsObject
*object
, SwfdecAsObject
*orig
,
66 const char *variable
, SwfdecAsValue
*val
, guint
*flags
)
68 SwfdecAsSuper
*super
= SWFDEC_AS_SUPER (object
);
69 SwfdecAsObjectClass
*klass
;
73 if (super
->object
== NULL
) {
74 SWFDEC_WARNING ("super.%s () called without an object.", variable
);
77 cur
= super
->object
->prototype
;
78 for (i
= 0; i
<= SWFDEC_AS_OBJECT_PROTOTYPE_RECURSION_LIMIT
&& cur
!= NULL
; i
++) {
79 klass
= SWFDEC_AS_OBJECT_GET_CLASS (cur
);
80 /* FIXME: is the orig pointer correct? */
81 if (klass
->get (cur
, super
->object
, variable
, val
, flags
))
83 /* FIXME: need get_prototype_internal here? */
84 cur
= swfdec_as_object_get_prototype (cur
);
86 if (i
> SWFDEC_AS_OBJECT_PROTOTYPE_RECURSION_LIMIT
) {
87 swfdec_as_context_abort (swfdec_gc_object_get_context (object
),
88 "Prototype recursion limit exceeded");
90 SWFDEC_AS_VALUE_SET_UNDEFINED (val
);
96 swfdec_as_super_set (SwfdecAsObject
*object
, const char *variable
, const SwfdecAsValue
*val
, guint flags
)
98 /* This seems to be ignored completely */
102 swfdec_as_super_set_flags (SwfdecAsObject
*object
, const char *variable
, guint flags
, guint mask
)
104 /* if we have no variables, we also can't set its flags... */
107 static SwfdecAsDeleteReturn
108 swfdec_as_super_delete (SwfdecAsObject
*object
, const char *variable
)
110 /* if we have no variables... */
111 return SWFDEC_AS_DELETE_NOT_FOUND
;
114 static SwfdecAsObject
*
115 swfdec_as_super_resolve (SwfdecAsObject
*object
)
117 SwfdecAsSuper
*super
= SWFDEC_AS_SUPER (object
);
123 swfdec_as_super_class_init (SwfdecAsSuperClass
*klass
)
125 SwfdecAsObjectClass
*asobject_class
= SWFDEC_AS_OBJECT_CLASS (klass
);
126 SwfdecAsFunctionClass
*function_class
= SWFDEC_AS_FUNCTION_CLASS (klass
);
128 asobject_class
->get
= swfdec_as_super_get
;
129 asobject_class
->set
= swfdec_as_super_set
;
130 asobject_class
->set_flags
= swfdec_as_super_set_flags
;
131 asobject_class
->del
= swfdec_as_super_delete
;
132 asobject_class
->resolve
= swfdec_as_super_resolve
;
134 function_class
->call
= swfdec_as_super_call
;
138 swfdec_as_super_init (SwfdecAsSuper
*super
)
143 swfdec_as_super_new (SwfdecAsFrame
*frame
, SwfdecAsObject
*thisp
, SwfdecAsObject
*ref
)
145 SwfdecAsContext
*context
;
146 SwfdecAsSuper
*super
;
148 g_return_if_fail (frame
!= NULL
);
149 g_return_if_fail (SWFDEC_IS_AS_OBJECT (thisp
));
150 g_return_if_fail (ref
== NULL
|| SWFDEC_IS_AS_OBJECT (ref
));
152 if (frame
->super
!= NULL
)
154 context
= swfdec_gc_object_get_context (thisp
);
155 if (context
->version
<= 5)
158 super
= g_object_new (SWFDEC_TYPE_AS_SUPER
, "context", context
, NULL
);
159 frame
->super
= SWFDEC_AS_OBJECT (super
);
160 super
->thisp
= swfdec_as_object_resolve (thisp
);
161 if (context
->version
<= 5) {
162 super
->object
= NULL
;
169 swfdec_as_super_resolve_property (SwfdecAsSuper
*super
, const char *name
)
172 SwfdecAsContext
*context
;
174 g_return_val_if_fail (SWFDEC_IS_AS_SUPER (super
), NULL
);
176 if (super
->object
== NULL
)
178 ref
= super
->object
->prototype
;
181 context
= swfdec_gc_object_get_context (super
);
182 if (name
&& context
->version
> 6) {
183 /* skip prototypes to find the next one that has this function defined */
185 if (swfdec_as_object_get_variable_and_flags (ref
,
186 name
, NULL
, NULL
, &res
) && ref
!= res
) {
187 while (ref
->prototype
!= res
) {
188 ref
= ref
->prototype
;