1 //
2 //   Copyright (C) 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_EXECUTABLECODE_H
21 #define GNASH_EXECUTABLECODE_H
22 
23 #include <vector>
24 #include <boost/noncopyable.hpp>
25 
26 #include "ActionExec.h"
27 #include "Global_as.h"
28 #include "fn_call.h"
29 #include "ConstantPool.h"
30 
31 namespace gnash {
32 
33 /// Any executable code
34 class ExecutableCode : boost::noncopyable
35 {
36 public:
37 
ExecutableCode(DisplayObject * t)38     ExecutableCode(DisplayObject* t) : _target(t) {}
39 
40     virtual void execute() = 0;
41 
~ExecutableCode()42     virtual ~ExecutableCode() {}
43 
setReachable()44     virtual void setReachable() const {}
45 
46     /// Mark reachable resources (for the GC)
markReachableResources()47     void markReachableResources() const {
48         setReachable();
49         if (_target) _target->setReachable();
50     }
51 
target()52     DisplayObject* target() const {
53         return _target;
54     }
55 
56 private:
57 
58     DisplayObject* _target;
59 };
60 
61 /// Global code (out of any function)
62 class GlobalCode : public ExecutableCode
63 {
64 public:
65 
GlobalCode(const action_buffer & nBuffer,DisplayObject * nTarget)66     GlobalCode(const action_buffer& nBuffer, DisplayObject* nTarget)
67         :
68         ExecutableCode(nTarget),
69         buffer(nBuffer)
70     {}
71 
execute()72     virtual void execute() {
73         if (!target()->unloaded()) {
74             ActionExec exec(buffer, target()->get_environment());
75             exec();
76         }
77     }
78 
79 private:
80     const action_buffer& buffer;
81 };
82 
83 /// Event code
84 class EventCode : public ExecutableCode
85 {
86 public:
87 
88     typedef std::vector<const action_buffer*> BufferList;
89 
EventCode(DisplayObject * nTarget)90     EventCode(DisplayObject* nTarget)
91         :
92         ExecutableCode(nTarget)
93     {}
94 
EventCode(DisplayObject * nTarget,BufferList buffers)95     EventCode(DisplayObject* nTarget, BufferList buffers)
96         :
97         ExecutableCode(nTarget),
98         _buffers(std::move(buffers))
99     {}
100 
101     /// Add an action buffer to this event handler
102     //
103     /// @param buffer
104     /// An action buffer to execute. Externally owned
105     /// and not copied, so make sure it's kept
106     /// alive for the whole EventCode lifetime.
107     ///
addAction(const action_buffer & buffer)108     void addAction(const action_buffer& buffer) {
109         // don't push actions for destroyed DisplayObjects,
110         // our opcode guard is bogus at the moment.
111         if (!target()->isDestroyed()) {
112             _buffers.push_back(&buffer);
113         }
114     }
115 
execute()116     virtual void execute() {
117         for (const action_buffer* buffer : _buffers) {
118 
119             // onClipEvents code are guarded by isDestroyed(),
120             // still might be also guarded by unloaded()
121             if (target()->isDestroyed()) break;
122 
123             PoolGuard guard(getVM(target()->get_environment()), nullptr);
124             ActionExec exec(*buffer, target()->get_environment(), false);
125             exec();
126         }
127     }
128 
129 private:
130     BufferList _buffers;
131 };
132 
133 /// This class is used to queue a function call action
134 //
135 /// Exact use is to queue onLoadInit, which should be invoked
136 /// after actions of in first frame of a loaded movie are executed.
137 /// Since those actions are queued the only way to execute something
138 /// after them is to queue the function call as well.
139 ///
140 /// The class might be made more general and accessible outside
141 /// of the MovieClipLoader class. For now it only works for
142 /// calling a function with a two argument.
143 ///
144 class DelayedFunctionCall : public ExecutableCode
145 {
146 public:
147 
DelayedFunctionCall(DisplayObject * target,as_object * obj,ObjectURI name,as_value arg1,as_value arg2)148     DelayedFunctionCall(DisplayObject* target,
149             as_object* obj, ObjectURI name,
150             as_value arg1, as_value arg2)
151         :
152         ExecutableCode(target),
153         _obj(obj),
154         _name(std::move(name)),
155         _arg1(std::move(arg1)),
156         _arg2(std::move(arg2))
157     {}
158 
execute()159     virtual void execute() {
160         callMethod(_obj, _name, _arg1, _arg2);
161     }
162 
163     /// Mark reachable resources (for the GC)
setReachable()164     virtual void setReachable() const {
165         _obj->setReachable();
166         _arg1.setReachable();
167         _arg2.setReachable();
168     }
169 
170 private:
171     as_object* _obj;
172     ObjectURI _name;
173     as_value _arg1, _arg2;
174 };
175 
176 
177 
178 } // namespace gnash
179 
180 #endif // GNASH_EXECUTABLECODE_H
181