1 // Function_as.cpp: ActionScript "Function" class, for Gnash.
3 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010,
4 // 2011 Free Software Foundation, Inc
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"
27 #include "NativeFunction.h"
31 #include "namedStrings.h"
35 // Forward declarations
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
);
44 /// Utility struct for pushing args to an array.
45 class PushFunctionArgs
48 PushFunctionArgs(fn_call
& fn
) : _fn(fn
) {}
49 void operator()(const as_value
& val
) {
59 registerFunctionNative(as_object
& global
)
61 VM
& vm
= getVM(global
);
62 vm
.registerNative(function_call
, 101, 10);
63 vm
.registerNative(function_apply
, 101, 11);
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
);
94 function_ctor(const fn_call
& /*fn*/)
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();
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
));
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
129 new_fn_call
.super
= 0;
131 // Check for second argument ('arguments' array)
134 IF_VERBOSE_ASCODING_ERRORS(
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
));
144 PushFunctionArgs
pa(new_fn_call
);
145 foreachArray(*arg1
, pa
);
151 return function_obj
->call(new_fn_call
);
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
);
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();
175 return function_obj
->call(new_fn_call
);
179 } // anonymous namespace