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