2 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Free Software
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 3 of the License, or
8 // (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 #include "Function2.h"
23 #include "action_buffer.h"
24 #include "ActionExec.h"
26 #include "NativeFunction.h"
27 #include "Global_as.h"
28 #include "namedStrings.h"
29 #include "CallStack.h"
30 #include "MovieClip.h"
31 #include "DisplayObject.h"
35 Function2::Function2(const action_buffer
& ab
, as_environment
& env
,
36 size_t start
, const ScopeStack
& scopeStack
)
38 Function(ab
, env
, start
, scopeStack
),
46 Function2::call(const fn_call
& fn
)
48 // Extract caller before pushing ourself on the call stack
51 as_object
* caller
= vm
.calling() ? &vm
.currentCall().function() : 0;
53 // Set up local stack frame, for parameters and locals.
54 FrameGuard
guard(getVM(fn
), *this);
55 CallFrame
& cf
= guard
.callFrame();
57 DisplayObject
* target
= _env
.get_target();
58 DisplayObject
* orig_target
= _env
.get_original_target();
60 // Some features are version-dependant.
61 const int swfversion
= getSWFVersion(fn
);
64 // In SWF5, when 'this' is a DisplayObject it becomes
65 // the target for this function call.
66 // See actionscript.all/setProperty.as
69 DisplayObject
* ch
= get
<DisplayObject
>(fn
.this_ptr
);
77 /// This is only needed for SWF5 (temp switch of target)
78 /// We do always and base 'target' value on SWF version.
79 /// TODO: simplify code by maybe using a custom as_environment
80 /// instead, so to get an "original" target being
81 /// the one set now (rather then the really original one)
82 /// TODO: test scope when calling functions defined in another timeline
83 /// (target, in particular).
84 TargetGuard
targetGuard(_env
, target
, orig_target
);
86 // function2: most args go in registers; any others get pushed.
88 // Handle the implicit args.
89 // @@ why start at 1 ? Note that starting at 0 makes
90 // intro.swf movie fail to play correctly.
91 size_t current_reg(1);
93 // This is us. TODO: why do we have to query the VM to get
94 // what are effectively our own resources?
96 // If this is not suppressed it is either placed in a register
97 // or set as a local variable, but not both.
98 if (!(_function2Flags
& SUPPRESS_THIS
)) {
99 if (_function2Flags
& PRELOAD_THIS
) {
100 // preload 'this' into a register.
101 // TODO: check whether it should be undefined or null
102 // if this_ptr is null.
103 cf
.setLocalRegister(current_reg
, fn
.this_ptr
);
107 // Put 'this' in a local var.
108 setLocal(cf
, NSV::PROP_THIS
,
109 fn
.this_ptr
? fn
.this_ptr
: as_value());
113 // This works slightly differently from 'super' and 'this'. The
114 // arguments are only ever either placed in the register or a
115 // local variable, but if both preload and suppress arguments flags
116 // are set, an empty array is still placed to the register.
117 // This seems like a bug in the reference player.
118 if (!(_function2Flags
& SUPPRESS_ARGUMENTS
) ||
119 (_function2Flags
& PRELOAD_ARGUMENTS
)) {
121 as_object
* args
= getGlobal(fn
).createArray();
123 if (!(_function2Flags
& SUPPRESS_ARGUMENTS
)) {
124 getArguments(*this, *args
, fn
, caller
);
127 if (_function2Flags
& PRELOAD_ARGUMENTS
) {
128 // preload 'arguments' into a register.
129 cf
.setLocalRegister(current_reg
, args
);
133 // Put 'arguments' in a local var.
134 setLocal(cf
, NSV::PROP_ARGUMENTS
, args
);
139 // If super is not suppressed it is either placed in a register
140 // or set as a local variable, but not both.
141 if (swfversion
> 5 && !(_function2Flags
& SUPPRESS_SUPER
)) {
143 // Put 'super' in a register (SWF6+ only).
144 // TOCHECK: should we still set it if not available ?
145 as_object
* super
= fn
.super
? fn
.super
:
146 fn
.this_ptr
? fn
.this_ptr
->get_super() : 0;
148 if (super
&& (_function2Flags
& PRELOAD_SUPER
)) {
149 cf
.setLocalRegister(current_reg
, super
);
153 setLocal(cf
, NSV::PROP_SUPER
, super
);
157 if (_function2Flags
& PRELOAD_ROOT
) {
158 // Put '_root' (if any) in a register.
159 DisplayObject
* tgtch
= _env
.get_target();
161 // NOTE: _lockroot will be handled by getAsRoot()
162 as_object
* r
= getObject(tgtch
->getAsRoot());
163 cf
.setLocalRegister(current_reg
, r
);
168 if (_function2Flags
& PRELOAD_PARENT
) {
169 DisplayObject
* tgtch
= _env
.get_target();
171 as_object
* p
= getObject(tgtch
->parent());
172 cf
.setLocalRegister(current_reg
, p
);
177 if (_function2Flags
& PRELOAD_GLOBAL
) {
178 // Put '_global' in a register.
179 as_object
* global
= vm
.getGlobal();
180 cf
.setLocalRegister(current_reg
, global
);
184 // Handle the explicit args.
185 // This must be done after implicit ones,
186 // as the explicit override the implicits:
187 // see swfdec/definefunction2-override
188 for (size_t i
= 0, n
= _args
.size(); i
< n
; ++i
) {
189 // not a register, declare as local
192 // Conventional arg passing: create a local var.
193 setLocal(cf
, _args
[i
].name
, fn
.arg(i
));
196 // Still declare named arguments, even if
197 // they are not passed from caller
199 declareLocal(cf
, _args
[i
].name
);
204 // Pass argument into a register.
205 const int reg
= _args
[i
].reg
;
206 cf
.setLocalRegister(reg
, fn
.arg(i
));
208 // If no argument was passed, no need to setup a register
213 // Execute the actions.
214 // Do this in a try block to proper drop the pushed call frame
215 // in case of problems (most interesting action limits)
218 ActionExec
exec(*this, _env
, &result
, fn
.this_ptr
);
222 catch (ActionLimitException
& ale
) {
227 } // end of gnash namespace