Drop the bool operator for ObjectURI, to avoid getting the kind of side-effect that...
[gnash.git] / libcore / Function.cpp
blob43fa97e469e7d06872917d521277fcc57179ff41
1 //
2 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Free Software
3 // Foundation, Inc
4 //
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.
9 //
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.
14 //
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 "log.h"
20 #include "Function.h"
21 #include "fn_call.h"
22 #include "action_buffer.h"
23 #include "ActionExec.h"
24 #include "VM.h"
25 #include "NativeFunction.h"
26 #include "Global_as.h"
27 #include "namedStrings.h"
28 #include "CallStack.h"
29 #include "DisplayObject.h"
31 namespace gnash {
33 Function::Function(const action_buffer& ab, as_environment& env,
34 size_t start, const ScopeStack& scopeStack)
36 UserFunction(getGlobal(env)),
37 _env(env),
38 _action_buffer(ab),
39 _scopeStack(scopeStack),
40 _startPC(start),
41 _length(0)
43 assert( _startPC < _action_buffer.size() );
46 TargetGuard::TargetGuard(as_environment& e, DisplayObject* ch,
47 DisplayObject* och)
49 env(e),
50 from(env.get_target()),
51 from_orig(env.get_original_target())
53 env.set_target(ch);
54 env.set_original_target(och);
58 TargetGuard::~TargetGuard()
60 env.set_target(from);
61 env.set_original_target(from_orig);
64 // Dispatch.
65 as_value
66 Function::call(const fn_call& fn)
68 // Extract caller before pushing ourself on the call stack
69 VM& vm = getVM(fn);
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);
83 if (swfversion < 6) {
84 // In SWF5, when 'this' is a DisplayObject it becomes
85 // the target for this function call.
86 // See actionscript.all/setProperty.as
87 //
88 if (fn.this_ptr) {
89 DisplayObject* ch = get<DisplayObject>(fn.this_ptr);
90 if (ch) {
91 target = ch;
92 orig_target = ch;
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);
112 if (i < fn.nargs) {
113 setLocal(cf, _args[i].name, fn.arg(i));
115 else {
116 // Still declare named arguments, even if
117 // they are not passed from caller
118 // See bug #22203
119 declareLocal(cf, _args[i].name);
123 // Add 'this'
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);
134 // Add 'arguments'
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)
143 try {
144 as_value result;
145 ActionExec exec(*this, _env, &result, fn.this_ptr);
146 exec();
147 return result;
149 catch (ActionLimitException& ale) {
150 throw;
154 void
155 Function::setLength(size_t len)
157 assert(_startPC + len <= _action_buffer.size());
158 _length = len;
161 void
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();
177 as_object*
178 getArguments(Function& callee, as_object& args, const fn_call& fn,
179 as_object* caller)
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);
188 return &args;
192 } // end of gnash namespace