update copyright date
[gnash.git] / libcore / asobj / Function_as.cpp
blobd6e492e76bcdd9168b1f501c75396e1cf26a937d
1 // Function_as.cpp: ActionScript "Function" class, for Gnash.
2 //
3 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010,
4 // 2011 Free Software Foundation, Inc
5 //
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 3 of the License, or
9 // (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 #include "Function_as.h"
23 #include "as_object.h"
24 #include "Global_as.h"
25 #include "as_value.h"
26 #include "Array_as.h"
27 #include "NativeFunction.h"
28 #include "fn_call.h"
29 #include "VM.h"
30 #include "log.h"
31 #include "namedStrings.h"
33 namespace gnash {
35 // Forward declarations
36 namespace {
37 as_value function_apply(const fn_call& fn);
38 as_value function_call(const fn_call& fn);
39 as_value function_ctor(const fn_call& fn);
42 namespace {
44 /// Utility struct for pushing args to an array.
45 class PushFunctionArgs
47 public:
48 PushFunctionArgs(fn_call& fn) : _fn(fn) {}
49 void operator()(const as_value& val) {
50 _fn.pushArg(val);
52 private:
53 fn_call& _fn;
58 void
59 registerFunctionNative(as_object& global)
61 VM& vm = getVM(global);
62 vm.registerNative(function_call, 101, 10);
63 vm.registerNative(function_apply, 101, 11);
66 void
67 function_class_init(as_object& where, const ObjectURI& uri)
69 Global_as& gl = getGlobal(where);
71 NativeFunction* func = new NativeFunction(gl, function_ctor);
72 as_object* proto = createObject(gl);
74 func->init_member(NSV::PROP_PROTOTYPE, proto);
75 func->init_member(NSV::PROP_CONSTRUCTOR, func);
76 proto->init_member(NSV::PROP_CONSTRUCTOR, func);
78 // Register _global.Function, only visible for SWF6 up
79 const int swf6flags = as_object::DefaultFlags | PropFlags::onlySWF6Up;
80 func->init_member(NSV::PROP_uuPROTOuu, proto, swf6flags);
81 where.init_member(uri, func, swf6flags);
83 VM& vm = getVM(where);
85 // Note: these are the first functions created, and they need the
86 // Function class to be registered.
87 proto->init_member("call", vm.getNative(101, 10), swf6flags);
88 proto->init_member("apply", vm.getNative(101, 11), swf6flags);
91 namespace {
93 as_value
94 function_ctor(const fn_call& /*fn*/)
96 return as_value();
99 as_value
100 function_apply(const fn_call& fn)
103 as_object* function_obj = ensure<ValidThis>(fn);
105 // Copy new function call from old one, we'll modify
106 // the copy only if needed
107 fn_call new_fn_call(fn);
108 new_fn_call.resetArgs();
110 if (!fn.nargs) {
111 IF_VERBOSE_ASCODING_ERRORS(
112 log_aserror (_("Function.apply() called with no args"));
114 new_fn_call.this_ptr = new as_object(getGlobal(fn));
116 else {
117 // Get the object to use as 'this' reference
118 as_object* obj = toObject(fn.arg(0), getVM(fn));
120 if (!obj) obj = new as_object(getGlobal(fn));
122 new_fn_call.this_ptr = obj;
124 // Note: do not override fn_call::super by creating a super
125 // object, as it may not be needed. Doing so can have a very
126 // detrimental effect on memory usage!
127 // Normal supers will be created when needed in the function
128 // call.
129 new_fn_call.super = 0;
131 // Check for second argument ('arguments' array)
132 if (fn.nargs > 1) {
134 IF_VERBOSE_ASCODING_ERRORS(
135 if (fn.nargs > 2) {
136 log_aserror(_("Function.apply() got %d args, expected at "
137 "most 2 -- discarding the ones in excess"), fn.nargs);
141 as_object* arg1 = toObject(fn.arg(1), getVM(fn));
143 if (arg1) {
144 PushFunctionArgs pa(new_fn_call);
145 foreachArray(*arg1, pa);
150 // Call the function
151 return function_obj->call(new_fn_call);
154 as_value
155 function_call(const fn_call& fn)
157 as_object* function_obj = ensure<ValidThis>(fn);
159 // Copy new function call from old one, we'll modify
160 // the copy only if needed
161 fn_call new_fn_call(fn);
163 as_object* tp;
165 if (!fn.nargs || fn.arg(0).is_undefined() || fn.arg(0).is_null()) {
166 tp = new as_object(getGlobal(fn));
168 else tp = toObject(fn.arg(0), getVM(fn));
170 new_fn_call.this_ptr = tp;
171 new_fn_call.super = 0;
172 if (fn.nargs) new_fn_call.drop_bottom();
174 // Call the function
175 return function_obj->call(new_fn_call);
179 } // anonymous namespace
180 } // gnash namespace