Make automated FSCommand invocation tests show player-side output.
[gnash.git] / libcore / abc / AbcBlock.h
blob2a25d0a9b65f7d69da438928208acc9361b76de7
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
19 // The AS3 abc block format reader.
22 #ifndef GNASH_ABC_BLOCK_H
23 #define GNASH_ABC_BLOCK_H
25 #include "string_table.h"
26 #include "MultiName.h"
27 #include "Namespace.h"
28 #include "as_value.h"
30 #include <vector>
31 #include <string>
32 #include <stdexcept>
34 namespace gnash {
35 namespace abc {
36 class AbcBlock;
37 class Machine;
38 class Class;
39 class Method;
41 class SWFStream; // for read signature
42 class ClasstHierarchy;
45 namespace gnash {
47 /// ABC-only resources for parsing and execution.
48 namespace abc {
50 /// Class describing a static property
52 /// Traits are non-dynamic properties. That is, they are not deletable or
53 /// modifiable in certain ways through ActionScript. They exist for reasons
54 /// of performance. A property lookup on an object always checks the Traits
55 /// before dynamic properties.
57 /// Traits can belong to Methods, Classes, and Scripts. Classes have both
58 /// instance and Class traits.
60 /// TODO: Traits currently need finalization. This performs two tasks. At least
61 /// one, and possibly both, are wrong:
62 /// 1. Trait definitions contain references to AbcBlock definitions. Currently
63 /// these references are resolved during finalization. It may be possible
64 /// to do this during parsing.
65 /// 2. Traits should be made available to ActionScript. Currently this is done
66 /// by attaching them to an object. This is plain wrong and doesn't even
67 /// work in many cases.
69 /// TODO: As Traits are stored in the correct Class, Method etc, they do not
70 /// need to store a target.
71 class Trait
73 public:
75 enum Kind
77 KIND_SLOT = 0,
78 KIND_CONST = 6,
79 KIND_METHOD = 1,
80 KIND_GETTER = 2,
81 KIND_SETTER = 3,
82 KIND_CLASS = 4,
83 KIND_FUNCTION = 5
86 Trait()
88 _hasValue(false),
89 _kind(KIND_SLOT),
90 _slotID(0),
91 _typeIndex(0),
92 _classInfoIndex(0),
93 _value(),
94 _name(0),
95 _globalName(),
96 _namespace(0),
97 _method(0),
98 _valueSet(false),
99 _classTarget(0),
100 _methodTarget(0),
101 _static(false)
104 bool read(SWFStream* in, AbcBlock *block);
106 bool finalize(AbcBlock* block, abc::Class* cl, bool do_static);
108 bool finalize_mbody(AbcBlock* block, Method* m);
110 void set_target(abc::Class* cl, bool do_static) {
111 _classTarget = cl;
112 _static = do_static;
115 void set_target(Method *m) {
116 _classTarget = 0;
117 _methodTarget = m;
120 bool finalize(AbcBlock* block)
122 if (_classTarget) {
123 return finalize(block, _classTarget, _static);
125 return finalize_mbody(block, _methodTarget);
128 private:
130 friend class AbcBlock;
132 bool _hasValue;
133 Kind _kind;
134 std::uint32_t _slotID;
135 std::uint32_t _typeIndex;
136 std::uint32_t _classInfoIndex;
137 as_value _value;
139 URI _name;
140 string_table::key _globalName;
142 Namespace* _namespace;
143 Method* _method;
144 bool _valueSet;
146 abc::Class* _classTarget;
147 Method* _methodTarget;
148 bool _static;
152 /// Output stream operator for abc::Trait::Kind
153 std::ostream& operator<<(std::ostream& o, const Trait::Kind k);
155 namespace {
157 template<typename T>
158 inline void checkBounds(size_t i, const T& container)
160 if (i >= container.size()) {
161 throw std::range_error("Attempt to access pool out of range");
168 /// The ActionScript bytecode of a single ABC tag in a SWF.
170 /// ABC blocks have their own "names" for all resources. In Gnash, these are
171 /// a string table index. They are different from global names. These are used
172 /// to locate resources inside the ABC block.
174 /// ABC blocks have a set of "namespace" resources. Some namespaces are
175 /// private. We make these into anonymous namespaces.
177 /// We assume all non-private namespaces are public. Some are "package"
178 /// namespaces; these seem to coincide with the built-in packages or 0,
179 /// the global namespace.
180 ///
181 /// We always search for these public namespaces by global URI in our
182 /// ClassHierarchy. If we use ABC names, "flash.text" will not find the built-in
183 /// flash.text namespace. Using the global name means that we 'import' the
184 /// built-in namespace into our own resources.
186 /// Instances / Scriptes
188 /// Likewise, classes are always given a global name, not an ABC name. This is
189 /// because they become globally available, including (we assume) to other ABC
190 /// blocks, so using an ABC name means they cannot be located externally.
191 /// Even if ABC block resources should not be available to other blocks (which
192 /// seems unlikely), using an ABC name for classes risks name conflicts with
193 /// the built-in classes already in a namespace: ABC names and global names
194 /// can have the same index even when the names are different.
196 /// Class lookup
198 /// This is particularly important for locateClass (called by instantiateScript
199 /// from SymbolScript tag execution). The SymbolScript tag identifies a class
200 /// using a global name, which may be qualified with a namespace. If it is
201 /// not qualified, we look in the global namespace 0.
203 /// When we call locateClass, we use global names, not ABC names, because
204 /// classes are identified by global names (see above). However, we
205 /// still look only in the ABC block's namespaces. The block's first namespace
206 /// is always the global namespace; other package namespaces are imported
207 /// according to the block's namespace constants.
208 class AbcBlock
210 public:
212 enum NamespaceConstant
214 PRIVATE_NS = 0x05,
215 CONSTANT_NS = 0x08,
216 PACKAGE_NS = 0x16,
217 PACKAGE_INTERNAL_NS = 0x17,
218 PROTECTED_NS = 0x18,
219 EXPLICIT_NS = 0x19,
220 STATIC_PROTECTED_NS = 0x1A
223 enum MethodConstant
225 METHOD_ARGS = 0x01,
226 METHOD_ACTIVATION = 0x02,
227 METHOD_MORE = 0x04,
228 METHOD_OPTIONAL_ARGS = 0x08,
229 METHOD_IGNORE = 0x10,
230 METHOD_NATIVE = 0x20,
231 METHOD_DEFAULT_NS = 0x40,
232 METHOD_ARG_NAMES = 0x80
235 enum InstanceConstant
237 INSTANCE_SEALED = 0x01,
238 INSTANCE_FINAL = 0x02,
239 INSTANCE_INTERFACE = 0x04,
240 INSTANCE_DYNAMIC = 0x00,
241 INSTANCE_PROTECTED_NS = 0x08
244 enum PoolConstant
246 POOL_STRING = 0x01,
247 POOL_INTEGER = 0x03,
248 POOL_UINTEGER = 0x04,
249 POOL_DOUBLE = 0x06,
250 POOL_NAMESPACE = 0x08,
251 POOL_FALSE = 0x0A,
252 POOL_TRUE = 0x0B,
253 POOL_NULL = 0x0C
256 typedef std::vector<Namespace*> NamespaceSet;
258 AbcBlock();
260 abc::Class* locateClass(MultiName &m);
262 abc::Class* locateClass(const std::string& className);
264 bool read(SWFStream& in);
266 void update_global_name(unsigned int multiname_index);
268 /// Scripts can contain several classes.
270 /// TODO: why on earth are Scripts implemented using Classes?
271 const std::vector<abc::Class*>& scripts() const {
272 return _scripts;
275 std::uint32_t uIntegerPoolAt(size_t i) const {
276 checkBounds(i, _uIntegerPool);
277 return _uIntegerPool[i];
280 const std::string& stringPoolAt(size_t i) const {
281 checkBounds(i, _stringPool);
282 return _stringPool[i];
285 std::int32_t integerPoolAt(size_t i) const {
286 checkBounds(i, _integerPool);
287 return _integerPool[i];
290 double doublePoolAt(size_t i) const {
291 checkBounds(i, _doublePool);
292 return _doublePool[i];
295 Method* methodPoolAt(size_t i) const {
296 checkBounds(i, _methods);
297 return _methods[i];
300 MultiName multinamePoolAt(size_t i) const {
301 checkBounds(i, _multinamePool);
302 return _multinamePool[i];
305 abc::Class* classPoolAt(size_t i) const {
306 checkBounds(i, _classes);
307 return _classes[i];
310 Namespace* namespacePoolAt(size_t i) const {
311 checkBounds(i, _namespacePool);
312 return _namespacePool[i];
315 void prepare(Machine* mach);
317 private:
319 friend class abc::Trait;
321 bool pool_value(std::uint32_t index, PoolConstant type, as_value &v);
323 bool read_version();
324 bool read_integer_constants();
325 bool read_unsigned_integer_constants();
326 bool read_double_constants();
327 bool read_string_constants();
328 bool read_namespaces();
329 bool read_namespace_sets();
330 bool read_multinames();
331 bool read_method_infos();
332 bool skip_metadata();
333 bool read_instances();
334 bool read_classes();
335 bool read_scripts();
336 bool read_method_bodies();
338 void check_multiname_name(std::uint32_t name);
340 void check_multiname_namespace(std::uint32_t ns);
342 void check_multiname_namespaceset(std::uint32_t nsset);
344 void setMultinameNames(MultiName *n, abc::URI ABCName);
346 void setNamespaceURI(Namespace *ns, abc::URI ABCName);
348 std::vector<std::int32_t> _integerPool;
349 std::vector<std::uint32_t> _uIntegerPool;
350 std::vector<double> _doublePool;
351 std::vector<std::string> _stringPool;
352 std::vector<Namespace*> _namespacePool;
353 std::vector<NamespaceSet> _namespaceSetPool;
354 std::vector<Method*> _methods;
355 std::vector<MultiName> _multinamePool;
356 std::vector<Class*> _classes;
357 std::vector<Class*> _scripts;
359 string_table* _stringTable;
360 SWFStream* _stream; // Not stored beyond one read.
362 abc::Class *mTheObject;
363 ClassHierarchy *mCH;
365 std::uint32_t mVersion;
370 std::ostream& operator<<(std::ostream& o, AbcBlock::NamespaceConstant c);
371 std::ostream& operator<<(std::ostream& o, AbcBlock::MethodConstant c);
372 std::ostream& operator<<(std::ostream& o, AbcBlock::InstanceConstant c);
373 std::ostream& operator<<(std::ostream& o, AbcBlock::PoolConstant c);
375 } // namespace abc
376 } // namespace gnash
379 #endif