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