2 // Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012
3 // Free Software Foundation, Inc.
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.
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.
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"
41 class SWFStream
; // for read signature
42 class ClasstHierarchy
;
47 /// ABC-only resources for parsing and execution.
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.
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
) {
115 void set_target(Method
*m
) {
120 bool finalize(AbcBlock
* block
)
123 return finalize(block
, _classTarget
, _static
);
125 return finalize_mbody(block
, _methodTarget
);
130 friend class AbcBlock
;
134 std::uint32_t _slotID
;
135 std::uint32_t _typeIndex
;
136 std::uint32_t _classInfoIndex
;
140 string_table::key _globalName
;
142 Namespace
* _namespace
;
146 abc::Class
* _classTarget
;
147 Method
* _methodTarget
;
152 /// Output stream operator for abc::Trait::Kind
153 std::ostream
& operator<<(std::ostream
& o
, const Trait::Kind k
);
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.
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.
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.
212 enum NamespaceConstant
217 PACKAGE_INTERNAL_NS
= 0x17,
220 STATIC_PROTECTED_NS
= 0x1A
226 METHOD_ACTIVATION
= 0x02,
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
248 POOL_UINTEGER
= 0x04,
250 POOL_NAMESPACE
= 0x08,
256 typedef std::vector
<Namespace
*> NamespaceSet
;
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 {
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
);
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
);
310 Namespace
* namespacePoolAt(size_t i
) const {
311 checkBounds(i
, _namespacePool
);
312 return _namespacePool
[i
];
315 void prepare(Machine
* mach
);
319 friend class abc::Trait
;
321 bool pool_value(std::uint32_t index
, PoolConstant type
, as_value
&v
);
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();
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
;
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
);