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
22 #include "action_buffer.h"
23 #include "ActionExec.h"
25 #include "NativeFunction.h"
26 #include "Global_as.h"
27 #include "namedStrings.h"
28 #include "CallStack.h"
29 #include "DisplayObject.h"
33 Function::Function(const action_buffer
& ab
, as_environment
& env
,
34 size_t start
, const ScopeStack
& scopeStack
)
36 UserFunction(getGlobal(env
)),
39 _scopeStack(scopeStack
),
43 assert( _startPC
< _action_buffer
.size() );
46 TargetGuard::TargetGuard(as_environment
& e
, DisplayObject
* ch
,
50 from(env
.get_target()),
51 from_orig(env
.get_original_target())
54 env
.set_original_target(och
);
58 TargetGuard::~TargetGuard()
61 env
.set_original_target(from_orig
);
66 Function::call(const fn_call
& fn
)
68 // Extract caller before pushing ourself on the call stack
71 as_object
* caller
= vm
.calling() ? &vm
.currentCall().function() : 0;
73 // Set up local stack frame, for parameters and locals.
74 FrameGuard
guard(getVM(fn
), *this);
75 CallFrame
& cf
= guard
.callFrame();
77 DisplayObject
* target
= _env
.get_target();
78 DisplayObject
* orig_target
= _env
.get_original_target();
80 // Some features are version-dependant.
81 const int swfversion
= getSWFVersion(fn
);
84 // In SWF5, when 'this' is a DisplayObject it becomes
85 // the target for this function call.
86 // See actionscript.all/setProperty.as
89 DisplayObject
* ch
= get
<DisplayObject
>(fn
.this_ptr
);
97 /// This is only needed for SWF5 (temp switch of target)
98 /// We do always and base 'target' value on SWF version.
99 /// TODO: simplify code by maybe using a custom as_environment
100 /// instead, so to get an "original" target being
101 /// the one set now (rather then the really original one)
102 /// TODO: test scope when calling functions defined in another timeline
103 /// (target, in particular).
104 TargetGuard
targetGuard(_env
, target
, orig_target
);
106 // Conventional function.
108 // Push the arguments onto the local frame.
109 for (size_t i
=0, n
=_args
.size(); i
<n
; ++i
)
111 assert(_args
[i
].reg
== 0);
113 setLocal(cf
, _args
[i
].name
, fn
.arg(i
));
116 // Still declare named arguments, even if
117 // they are not passed from caller
119 declareLocal(cf
, _args
[i
].name
);
124 setLocal(cf
, NSV::PROP_THIS
, fn
.this_ptr
? fn
.this_ptr
: as_value());
126 as_object
* super
= fn
.super
? fn
.super
:
127 fn
.this_ptr
? fn
.this_ptr
->get_super() : 0;
129 // Add 'super' (SWF6+ only)
130 if (super
&& swfversion
> 5) {
131 setLocal(cf
, NSV::PROP_SUPER
, super
);
135 as_object
* args
= getGlobal(fn
).createArray();
137 // Put 'arguments' in a local var.
138 setLocal(cf
, NSV::PROP_ARGUMENTS
, getArguments(*this, *args
, fn
, caller
));
140 // Execute the actions.
141 // Do this in a try block to proper drop the pushed call frame
142 // in case of problems (most interesting action limits)
145 ActionExec
exec(*this, _env
, &result
, fn
.this_ptr
);
149 catch (ActionLimitException
& ale
) {
155 Function::setLength(size_t len
)
157 assert(_startPC
+ len
<= _action_buffer
.size());
162 Function::markReachableResources() const
164 // Mark scope stack objects
165 for (ScopeStack::const_iterator i
= _scopeStack
.begin(),
166 e
= _scopeStack
.end(); i
!= e
; ++i
)
168 (*i
)->setReachable();
171 _env
.markReachableResources();
173 // Invoke parent class marker
174 markAsObjectReachable();
178 getArguments(Function
& callee
, as_object
& args
, const fn_call
& fn
,
182 for (size_t i
= 0; i
< fn
.nargs
; ++i
) {
183 callMethod(&args
, NSV::PROP_PUSH
, fn
.arg(i
));
186 args
.init_member(NSV::PROP_CALLEE
, &callee
);
187 args
.init_member(NSV::PROP_CALLER
, caller
);
192 } // end of gnash namespace