1 //
2 //   Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
3 //   Free Software 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
18 //
19 
20 #ifndef GNASH_GLOBAL_H
21 #define GNASH_GLOBAL_H
22 
23 #include <string>
24 #include <memory>
25 
26 #include "as_object.h"
27 #include "fn_call.h"
28 #include "log.h"
29 #include "ClassHierarchy.h"
30 #include "dsodefs.h" // for DSOTEXPORT
31 
32 // Forward declarations
33 namespace gnash {
34     class as_value;
35     class VM;
36     class Extension;
37 }
38 
39 namespace gnash {
40 
41 /// The Global object ultimately contains all objects in an ActionScript run
42 //
43 /// An ActionScript run is a single version (AS1/2 or AS3) and includes all
44 /// resources parsed from the SWF, created dynamically, loaded, or imported
45 /// that are available to ActionScript code.
46 //
47 /// Each VM (VM for AS1/2, Machine for AS3) has different resources in its
48 /// Global object. The two objects should be entirely separate.
49 class Global_as : public as_object
50 {
51 public:
52 
53     typedef as_value(*ASFunction)(const fn_call& fn);
54     typedef void(*Properties)(as_object&);
55 
56 	explicit Global_as(VM& vm);
57 	virtual ~Global_as();
58 
59     void registerClasses();
60 
61     as_object* createArray();
62 
getVM()63     VM& getVM() const {
64         return vm();
65     }
66 
67     /// Create an ActionScript function
68     as_function* createFunction(Global_as::ASFunction function);
69 
70     /// Create an ActionScript class
71     //
72     /// An AS2 class is generally a function (the constructor) with a
73     /// prototype.
74     as_object* createClass(Global_as::ASFunction ctor,
75             as_object* prototype);
76 
77     void makeObject(as_object& o) const;
78 
79 protected:
80 
81     virtual void markReachableResources() const;
82 
83 private:
84 
85     void loadExtensions();
86     std::unique_ptr<Extension> _et;
87 
88     ClassHierarchy _classes;
89 
90     as_object* _objectProto;
91 
92 };
93 
94 DSOTEXPORT as_object* createObject(const Global_as& gl);
95 
96 
97 /// Register a built-in object
98 //
99 /// This is used for simple objects that are part of the player API.
100 //
101 /// In the reference player these objects are always constructed in
102 /// ActionScript, though their functions may be native.
103 //
104 /// They include (AS2) Mouse, Selection and Stage, and (AS3) all constant
105 /// enumeration objects.
106 //
107 /// @param p        a pointer to a function that will attach properties to the
108 ///                 object
109 /// @param where    the object to which the created object will be attached
110 /// @param uri      an ObjectURI describing the name and namespace of the
111 ///                 created object.
112 /// @return         the built-in object with properties attached.
113 inline as_object*
registerBuiltinObject(as_object & where,Global_as::Properties p,const ObjectURI & uri)114 registerBuiltinObject(as_object& where, Global_as::Properties p,
115         const ObjectURI& uri)
116 {
117     Global_as& gl = getGlobal(where);
118     as_object* obj = createObject(gl);
119     if (p) p(*obj);
120 
121     where.init_member(uri, obj, as_object::DefaultFlags);
122 
123     return obj;
124 }
125 
126 /// Register a built-in class
127 //
128 /// This is used for classes that are part of the player API.
129 //
130 /// In the reference player these classes are always constructed in
131 /// ActionScript, though their functions may be native, and the constructor
132 /// may also call native functions.
133 //
134 /// @param c        a pointer to a function that will attach properties to the
135 ///                 class itself. These are known as static properties.
136 /// @param p        a pointer to a function that will attach properties to the
137 ///                 class prototype. These are instance properties.
138 /// @param ctor     the constructor function for the new class.
139 /// @param where    the object to which the created object will be attached
140 /// @param uri      an ObjectURI describing the name and namespace of the
141 ///                 created object.
142 /// @return         the built-in class with prototype and properties attached.
143 inline as_object*
registerBuiltinClass(as_object & where,Global_as::ASFunction ctor,Global_as::Properties p,Global_as::Properties c,const ObjectURI & uri)144 registerBuiltinClass(as_object& where, Global_as::ASFunction ctor,
145         Global_as::Properties p, Global_as::Properties c, const ObjectURI& uri)
146 {
147     Global_as& gl = getGlobal(where);
148     as_object* proto = createObject(gl);
149     as_object* cl = gl.createClass(ctor, proto);
150 
151     // Attach class properties to class
152     if (c) c(*cl);
153 
154     // Attach prototype properties to prototype
155     if (p) p(*proto);
156 
157     // Register class with specified object.
158     where.init_member(uri, cl, as_object::DefaultFlags);
159     return cl;
160 }
161 
162 /// Call an as_value on an as_object.
163 //
164 /// The call will fail harmlessly if the as_value is not callable.
165 inline DSOEXPORT as_value
166 invoke(const as_value& method, const as_environment& env, as_object* this_ptr,
167         fn_call::Args& args, as_object* super = nullptr,
168         const movie_definition* callerDef = nullptr)
169 {
170 
171 	as_value val;
172 	fn_call call(this_ptr, env, args);
173 	call.super = super;
174     call.callerDef = callerDef;
175 
176 	try {
177 		if (as_object* func = toObject(method, getVM(env))) {
178             // Call function.
179 		    val = func->call(call);
180 		}
181 		else {
182             IF_VERBOSE_ASCODING_ERRORS(
183                 log_aserror("Attempt to call a value which is not "
184                     "a function (%s)", method);
185             );
186             return val;
187 		}
188 	}
catch(ActionTypeError & e)189 	catch (ActionTypeError& e) {
190 		assert(val.is_undefined());
191 		IF_VERBOSE_ASCODING_ERRORS(
192             log_aserror("%s", e.what());
193 		);
194 	}
195 	return val;
196 }
197 
198 /// Call a member function of this object in an AS-compatible way
199 //
200 /// This is a variadic function to cope with a varying number of arguments. Its
201 /// signature is as follows:
202 //
203 /// as_value callMethod(as_object* obj, const ObjectURI& uri,
204 ///     const as_value& arg1, ..., const as_value& argN);
205 //
206 /// If the member function exists and is a function, invoke() is called on
207 /// the member with the object as the this pointer.
208 //
209 /// @param obj          The object to call the method on. This may be null, in
210 ///                     which case the call is a no-op. This is because calling
211 ///                     methods on null or non-objects in AS is harmless.
212 /// @param name         The name of the method.
213 ///
214 /// @param arg0..argN   The arguments to pass
215 ///
216 /// @return             The return value of the call (possibly undefined).
217 
218 inline as_value
callMethod(fn_call::Args & args,as_object * obj,const ObjectURI & uri)219 callMethod(fn_call::Args& args, as_object* obj, const ObjectURI& uri)
220 {
221     if (!obj) return as_value();
222     as_value func;
223     if (!obj->get_member(uri, &func)) return as_value();
224 
225     return invoke(func, as_environment(getVM(*obj)), obj, args);
226 }
227 
228 template <typename Param, typename... Params>
229 inline as_value
callMethod(fn_call::Args & args,as_object * obj,const ObjectURI & uri,Param param,Params...params)230 callMethod(fn_call::Args& args, as_object* obj, const ObjectURI& uri, Param param, Params... params)
231 {
232     args += param;
233     return callMethod(args, obj, uri, params...);
234 }
235 
236 
237 template <typename... Params>
238 inline as_value
callMethod(as_object * obj,const ObjectURI & uri,Params...params)239 callMethod(as_object* obj, const ObjectURI& uri, Params... params)
240 {
241     fn_call::Args args;
242     return callMethod(args, obj, uri, params...);
243 }
244 
245 /// Convenience function for finding a class constructor.
246 //
247 /// Only currently useful in AS2.
248 inline as_function*
getClassConstructor(const fn_call & fn,const std::string & s)249 getClassConstructor(const fn_call& fn, const std::string& s)
250 {
251     const as_value ctor(findObject(fn.env(), s));
252     return ctor.to_function();
253 }
254 
255 inline as_value
emptyFunction(const fn_call &)256 emptyFunction(const fn_call&)
257 {
258     return as_value();
259 }
260 
261 } // namespace gnash
262 
263 #endif
264