pyflashkit 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. pyflashkit-1.0.0/.github/workflows/ci.yml +35 -0
  2. pyflashkit-1.0.0/.github/workflows/release.yml +35 -0
  3. pyflashkit-1.0.0/.gitignore +10 -0
  4. pyflashkit-1.0.0/CONTRIBUTING.md +125 -0
  5. pyflashkit-1.0.0/LICENSE +21 -0
  6. pyflashkit-1.0.0/PKG-INFO +281 -0
  7. pyflashkit-1.0.0/README.md +260 -0
  8. pyflashkit-1.0.0/flashkit/__init__.py +54 -0
  9. pyflashkit-1.0.0/flashkit/abc/__init__.py +79 -0
  10. pyflashkit-1.0.0/flashkit/abc/builder.py +847 -0
  11. pyflashkit-1.0.0/flashkit/abc/constants.py +198 -0
  12. pyflashkit-1.0.0/flashkit/abc/disasm.py +364 -0
  13. pyflashkit-1.0.0/flashkit/abc/parser.py +434 -0
  14. pyflashkit-1.0.0/flashkit/abc/types.py +275 -0
  15. pyflashkit-1.0.0/flashkit/abc/writer.py +230 -0
  16. pyflashkit-1.0.0/flashkit/analysis/__init__.py +28 -0
  17. pyflashkit-1.0.0/flashkit/analysis/call_graph.py +317 -0
  18. pyflashkit-1.0.0/flashkit/analysis/inheritance.py +267 -0
  19. pyflashkit-1.0.0/flashkit/analysis/references.py +371 -0
  20. pyflashkit-1.0.0/flashkit/analysis/strings.py +299 -0
  21. pyflashkit-1.0.0/flashkit/cli/__init__.py +75 -0
  22. pyflashkit-1.0.0/flashkit/cli/_util.py +52 -0
  23. pyflashkit-1.0.0/flashkit/cli/build.py +36 -0
  24. pyflashkit-1.0.0/flashkit/cli/callees.py +30 -0
  25. pyflashkit-1.0.0/flashkit/cli/callers.py +30 -0
  26. pyflashkit-1.0.0/flashkit/cli/class_cmd.py +83 -0
  27. pyflashkit-1.0.0/flashkit/cli/classes.py +71 -0
  28. pyflashkit-1.0.0/flashkit/cli/disasm.py +77 -0
  29. pyflashkit-1.0.0/flashkit/cli/extract.py +36 -0
  30. pyflashkit-1.0.0/flashkit/cli/info.py +41 -0
  31. pyflashkit-1.0.0/flashkit/cli/packages.py +30 -0
  32. pyflashkit-1.0.0/flashkit/cli/refs.py +31 -0
  33. pyflashkit-1.0.0/flashkit/cli/strings.py +58 -0
  34. pyflashkit-1.0.0/flashkit/cli/tags.py +32 -0
  35. pyflashkit-1.0.0/flashkit/cli/tree.py +52 -0
  36. pyflashkit-1.0.0/flashkit/errors.py +33 -0
  37. pyflashkit-1.0.0/flashkit/info/__init__.py +31 -0
  38. pyflashkit-1.0.0/flashkit/info/class_info.py +176 -0
  39. pyflashkit-1.0.0/flashkit/info/member_info.py +275 -0
  40. pyflashkit-1.0.0/flashkit/info/package_info.py +60 -0
  41. pyflashkit-1.0.0/flashkit/search/__init__.py +16 -0
  42. pyflashkit-1.0.0/flashkit/search/search.py +456 -0
  43. pyflashkit-1.0.0/flashkit/swf/__init__.py +66 -0
  44. pyflashkit-1.0.0/flashkit/swf/builder.py +283 -0
  45. pyflashkit-1.0.0/flashkit/swf/parser.py +164 -0
  46. pyflashkit-1.0.0/flashkit/swf/tags.py +120 -0
  47. pyflashkit-1.0.0/flashkit/workspace/__init__.py +20 -0
  48. pyflashkit-1.0.0/flashkit/workspace/resource.py +189 -0
  49. pyflashkit-1.0.0/flashkit/workspace/workspace.py +232 -0
  50. pyflashkit-1.0.0/pyflashkit.egg-info/PKG-INFO +281 -0
  51. pyflashkit-1.0.0/pyflashkit.egg-info/SOURCES.txt +79 -0
  52. pyflashkit-1.0.0/pyflashkit.egg-info/dependency_links.txt +1 -0
  53. pyflashkit-1.0.0/pyflashkit.egg-info/entry_points.txt +2 -0
  54. pyflashkit-1.0.0/pyflashkit.egg-info/requires.txt +3 -0
  55. pyflashkit-1.0.0/pyflashkit.egg-info/top_level.txt +1 -0
  56. pyflashkit-1.0.0/pyproject.toml +31 -0
  57. pyflashkit-1.0.0/setup.cfg +4 -0
  58. pyflashkit-1.0.0/tests/__init__.py +0 -0
  59. pyflashkit-1.0.0/tests/abc/__init__.py +0 -0
  60. pyflashkit-1.0.0/tests/abc/test_builder.py +375 -0
  61. pyflashkit-1.0.0/tests/abc/test_disasm.py +136 -0
  62. pyflashkit-1.0.0/tests/abc/test_parser.py +149 -0
  63. pyflashkit-1.0.0/tests/abc/test_writer.py +118 -0
  64. pyflashkit-1.0.0/tests/analysis/__init__.py +0 -0
  65. pyflashkit-1.0.0/tests/analysis/test_call_graph.py +176 -0
  66. pyflashkit-1.0.0/tests/analysis/test_inheritance.py +193 -0
  67. pyflashkit-1.0.0/tests/analysis/test_references.py +177 -0
  68. pyflashkit-1.0.0/tests/analysis/test_strings.py +139 -0
  69. pyflashkit-1.0.0/tests/cli/__init__.py +0 -0
  70. pyflashkit-1.0.0/tests/cli/test_cli.py +251 -0
  71. pyflashkit-1.0.0/tests/conftest.py +289 -0
  72. pyflashkit-1.0.0/tests/info/__init__.py +0 -0
  73. pyflashkit-1.0.0/tests/info/test_class_info.py +165 -0
  74. pyflashkit-1.0.0/tests/search/__init__.py +0 -0
  75. pyflashkit-1.0.0/tests/search/test_search.py +227 -0
  76. pyflashkit-1.0.0/tests/swf/__init__.py +0 -0
  77. pyflashkit-1.0.0/tests/swf/test_builder.py +164 -0
  78. pyflashkit-1.0.0/tests/swf/test_parser.py +80 -0
  79. pyflashkit-1.0.0/tests/test_integration.py +323 -0
  80. pyflashkit-1.0.0/tests/workspace/__init__.py +0 -0
  81. pyflashkit-1.0.0/tests/workspace/test_workspace.py +206 -0
@@ -0,0 +1,35 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ paths-ignore:
7
+ - "*.md"
8
+ - "LICENSE"
9
+ - ".gitignore"
10
+ pull_request:
11
+ branches: [main]
12
+ paths-ignore:
13
+ - "*.md"
14
+ - "LICENSE"
15
+ - ".gitignore"
16
+
17
+ jobs:
18
+ test:
19
+ runs-on: ubuntu-latest
20
+ strategy:
21
+ matrix:
22
+ python-version: ["3.10", "3.11", "3.12"]
23
+
24
+ steps:
25
+ - uses: actions/checkout@v4
26
+
27
+ - uses: actions/setup-python@v5
28
+ with:
29
+ python-version: ${{ matrix.python-version }}
30
+
31
+ - name: Install
32
+ run: pip install -e ".[dev]"
33
+
34
+ - name: Run tests
35
+ run: python -m pytest -v
@@ -0,0 +1,35 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags: ["v*"]
6
+
7
+ permissions:
8
+ contents: write
9
+ id-token: write
10
+
11
+ jobs:
12
+ release:
13
+ runs-on: ubuntu-latest
14
+
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+
18
+ - uses: actions/setup-python@v5
19
+ with:
20
+ python-version: "3.12"
21
+
22
+ - name: Install build tools
23
+ run: pip install build
24
+
25
+ - name: Build package
26
+ run: python -m build
27
+
28
+ - name: Publish to PyPI
29
+ uses: pypa/gh-action-pypi-publish@release/v1
30
+
31
+ - name: Create GitHub Release
32
+ uses: softprops/action-gh-release@v2
33
+ with:
34
+ files: dist/*
35
+ generate_release_notes: true
@@ -0,0 +1,10 @@
1
+ __pycache__/
2
+ *.pyc
3
+ *.pyo
4
+ *.egg-info/
5
+ dist/
6
+ build/
7
+ .eggs/
8
+ .venv/
9
+ *.so
10
+ .pytest_cache/
@@ -0,0 +1,125 @@
1
+ # Contributing to flashkit
2
+
3
+ ## Setup
4
+
5
+ ```bash
6
+ git clone <repo-url>
7
+ cd flashkit
8
+ pip install -e ".[dev]"
9
+ ```
10
+
11
+ ## Running tests
12
+
13
+ ```bash
14
+ python -m pytest
15
+ python -m pytest -v # verbose
16
+ python -m pytest tests/cli/ # just CLI tests
17
+ python -m pytest -k "roundtrip" # filter by name
18
+ ```
19
+
20
+ ## Project layout
21
+
22
+ ```
23
+ flashkit/
24
+ cli/ CLI commands (one file per subcommand)
25
+ swf/ SWF container format
26
+ abc/ AVM2 bytecode parsing, writing, disassembly, builder
27
+ info/ Resolved class/field/method model
28
+ workspace/ File loading, resource management
29
+ analysis/ Inheritance, call graph, references, strings
30
+ search/ Unified query engine
31
+ errors.py Error hierarchy
32
+
33
+ tests/
34
+ abc/ ABC parser, writer, builder, disasm tests
35
+ swf/ SWF parser and builder tests
36
+ info/ ClassInfo resolution tests
37
+ workspace/ Workspace loading tests
38
+ analysis/ Analysis module tests
39
+ search/ Search engine tests
40
+ cli/ CLI integration tests
41
+ conftest.py Shared fixtures (build_abc_bytes, build_swf_bytes)
42
+ ```
43
+
44
+ ## Writing tests
45
+
46
+ All tests use programmatically built SWFs via `AbcBuilder` and `SwfBuilder` — no real `.swf` fixture files. This keeps the repo clean and tests fast.
47
+
48
+ ```python
49
+ from flashkit.abc.builder import AbcBuilder
50
+ from flashkit.abc.writer import serialize_abc
51
+ from flashkit.swf.builder import SwfBuilder
52
+
53
+ b = AbcBuilder()
54
+ b.simple_class("Player", package="com.game", fields=[("hp", "int")])
55
+ b.script()
56
+ abc_bytes = serialize_abc(b.build())
57
+
58
+ swf = SwfBuilder(version=40, width=800, height=600, fps=30)
59
+ swf.add_abc("TestCode", abc_bytes)
60
+ swf_bytes = swf.build()
61
+ ```
62
+
63
+ ## Adding a CLI command
64
+
65
+ 1. Create `flashkit/cli/mycommand.py`:
66
+
67
+ ```python
68
+ """``flashkit mycommand`` — description."""
69
+
70
+ from __future__ import annotations
71
+ import argparse
72
+ from ._util import load, bold
73
+
74
+ def register(sub: argparse._SubParsersAction) -> None:
75
+ p = sub.add_parser("mycommand", help="Short help text")
76
+ p.add_argument("file", help="SWF or SWZ file")
77
+ p.set_defaults(func=run)
78
+
79
+ def run(args: argparse.Namespace) -> None:
80
+ ws = load(args.file)
81
+ # ...
82
+ ```
83
+
84
+ 2. Import and register it in `flashkit/cli/__init__.py`:
85
+
86
+ ```python
87
+ from . import mycommand
88
+ mycommand.register(sub)
89
+ ```
90
+
91
+ 3. Add tests in `tests/cli/test_cli.py`.
92
+
93
+ ## Pull requests
94
+
95
+ 1. Fork the repo and create a branch from `main`.
96
+ 2. If you added code, add tests. Run `python -m pytest` and make sure everything passes.
97
+ 3. Keep PRs focused — one feature or fix per PR.
98
+ 4. Use conventional commit messages for the PR title (`feat: add xyz`, `fix: handle edge case`).
99
+ 5. Describe **what** changed and **why** in the PR body. If it's a fix, link the issue.
100
+ 6. Make sure there are no type errors or lint warnings in the code you changed.
101
+
102
+ ## Conventions
103
+
104
+ - **Zero dependencies.** Standard library only. No Click, no Rich, no Typer.
105
+ - **Round-trip fidelity.** `serialize(parse(data)) == data` must hold for unmodified ABC.
106
+ - **Conventional commits.** `feat:`, `fix:`, `test:`, `docs:`, `chore:`.
107
+ - **Type hints everywhere.** All public functions and methods must have type annotations.
108
+ - **No fixture files.** Tests build SWFs programmatically via `AbcBuilder` / `SwfBuilder`.
109
+ - **One command per file.** CLI commands live in `flashkit/cli/`, one module each.
110
+ - **Errors over silent failures.** Raise specific `FlashkitError` subclasses, never return `None` to signal failure in parsing code.
111
+
112
+ ## Error handling
113
+
114
+ All public errors inherit from `FlashkitError`:
115
+
116
+ ```
117
+ FlashkitError
118
+ ParseError
119
+ SWFParseError
120
+ ABCParseError
121
+ SerializeError
122
+ ResourceError
123
+ ```
124
+
125
+ The CLI catches `FlashkitError` at the top level and prints a clean message. Don't let raw exceptions reach the user.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,281 @@
1
+ Metadata-Version: 2.4
2
+ Name: pyflashkit
3
+ Version: 1.0.0
4
+ Summary: SWF/ABC toolkit for parsing, analyzing, and manipulating Flash files and AVM2 bytecode
5
+ License: MIT
6
+ Classifier: Development Status :: 5 - Production/Stable
7
+ Classifier: Intended Audience :: Developers
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Python :: 3.10
11
+ Classifier: Programming Language :: Python :: 3.11
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: Topic :: Software Development :: Disassemblers
14
+ Classifier: Topic :: Software Development :: Libraries
15
+ Requires-Python: >=3.10
16
+ Description-Content-Type: text/markdown
17
+ License-File: LICENSE
18
+ Provides-Extra: dev
19
+ Requires-Dist: pytest>=7.0; extra == "dev"
20
+ Dynamic: license-file
21
+
22
+ # flashkit
23
+
24
+ Parse, analyze, and manipulate Adobe Flash SWF files and AVM2 bytecode.
25
+
26
+ ## Install
27
+
28
+ ```bash
29
+ pip install -e .
30
+ ```
31
+
32
+ ## Quick start
33
+
34
+ ```python
35
+ from flashkit.workspace import Workspace
36
+
37
+ ws = Workspace()
38
+ ws.load_swf("application.swf")
39
+
40
+ # Find all classes extending Sprite
41
+ for cls in ws.find_classes(extends="Sprite"):
42
+ print(f"{cls.qualified_name} — {len(cls.fields)} fields, {len(cls.methods)} methods")
43
+
44
+ # Inspect a specific class
45
+ player = ws.get_class("PlayerManager")
46
+ print(player.super_name) # "EventDispatcher"
47
+ print(player.interfaces) # ["IDisposable", "ITickable"]
48
+ print(player.fields[0].name, player.fields[0].type_name) # "mHealth", "Number"
49
+
50
+ # Search strings used in bytecode
51
+ from flashkit.analysis import StringIndex
52
+ strings = StringIndex.from_workspace(ws)
53
+ for s in strings.search("config"):
54
+ print(s)
55
+ ```
56
+
57
+ ---
58
+
59
+ ## CLI
60
+
61
+ ### `flashkit info`
62
+
63
+ ```
64
+ $ flashkit info application.swf
65
+ File: application.swf
66
+ Format: SWF
67
+ SWF version: 40
68
+ Tags: 142
69
+ ABC blocks: 1
70
+ Classes: 823
71
+ Methods: 14210
72
+ Strings: 35482
73
+ Packages: 47
74
+ ```
75
+
76
+ ### `flashkit classes`
77
+
78
+ ```bash
79
+ flashkit classes app.swf # all classes
80
+ flashkit classes app.swf -s Manager # search by name
81
+ flashkit classes app.swf -p com.game # filter by package
82
+ flashkit classes app.swf -e Sprite # filter by superclass
83
+ flashkit classes app.swf -i # interfaces only
84
+ flashkit classes app.swf -v # verbose output
85
+ ```
86
+
87
+ ### `flashkit class`
88
+
89
+ ```
90
+ $ flashkit class application.swf PlayerManager
91
+ PlayerManager
92
+ Package: com.game
93
+ Extends: EventDispatcher
94
+ Implements: IDisposable, ITickable
95
+
96
+ Instance Fields (3)
97
+ mHealth: Number
98
+ mName: String
99
+ mLevel: int
100
+
101
+ Instance Methods (5)
102
+ init(): void
103
+ get name(): String
104
+ set name(value: String): void
105
+ takeDamage(amount: Number): void
106
+ serialize(): ByteArray
107
+ ```
108
+
109
+ ### `flashkit strings`
110
+
111
+ ```bash
112
+ flashkit strings app.swf # list all
113
+ flashkit strings app.swf -s config # search
114
+ flashkit strings app.swf -s config -v # with usage locations
115
+ flashkit strings app.swf -s "\\d+" -r # regex
116
+ flashkit strings app.swf -c # classify (URLs, debug)
117
+ ```
118
+
119
+ ### `flashkit tags`
120
+
121
+ ```bash
122
+ flashkit tags app.swf
123
+ ```
124
+
125
+ ### `flashkit disasm`
126
+
127
+ ```bash
128
+ flashkit disasm app.swf --class PlayerManager
129
+ flashkit disasm app.swf --method-index 42
130
+ ```
131
+
132
+ ### `flashkit tree`
133
+
134
+ ```bash
135
+ flashkit tree app.swf BaseEntity # show descendants
136
+ flashkit tree app.swf PlayerManager -a # show ancestors
137
+ ```
138
+
139
+ ### `flashkit callers` / `flashkit callees`
140
+
141
+ ```bash
142
+ flashkit callers app.swf toString
143
+ flashkit callees app.swf PlayerManager.init
144
+ ```
145
+
146
+ ### `flashkit refs`
147
+
148
+ ```bash
149
+ flashkit refs app.swf Point
150
+ ```
151
+
152
+ ### `flashkit packages` / `flashkit extract` / `flashkit build`
153
+
154
+ ```bash
155
+ flashkit packages app.swf # list packages
156
+ flashkit extract app.swf -o ./output # extract ABC blocks
157
+ flashkit build app.swf -o rebuilt.swf # rebuild (compressed)
158
+ flashkit build app.swf -o out.swf -d # rebuild (decompressed)
159
+ ```
160
+
161
+ ---
162
+
163
+ ## Library
164
+
165
+ ### Load and query
166
+
167
+ ```python
168
+ from flashkit.workspace import Workspace
169
+
170
+ ws = Workspace()
171
+ ws.load_swf("application.swf")
172
+ ws.load_swz("module.swz")
173
+
174
+ print(ws.summary())
175
+
176
+ cls = ws.get_class("MyClass")
177
+ print(cls.name, cls.super_name, cls.interfaces)
178
+ print(cls.fields) # list of FieldInfo
179
+ print(cls.methods) # list of MethodInfoResolved
180
+
181
+ ws.find_classes(extends="Sprite")
182
+ ws.find_classes(package="com.example", is_interface=True)
183
+ ```
184
+
185
+ ### Analysis
186
+
187
+ ```python
188
+ from flashkit.analysis import InheritanceGraph, CallGraph, StringIndex
189
+
190
+ graph = InheritanceGraph.from_classes(ws.classes)
191
+ graph.get_children("BaseEntity")
192
+ graph.get_all_parents("MyClass")
193
+ graph.get_implementors("ISerializable")
194
+
195
+ calls = CallGraph.from_workspace(ws)
196
+ calls.get_callers("toString")
197
+ calls.get_callees("MyClass.init")
198
+
199
+ strings = StringIndex.from_workspace(ws)
200
+ strings.search("config")
201
+ strings.url_strings()
202
+ strings.classes_using_string("http://example.com")
203
+ ```
204
+
205
+ <details>
206
+ <summary><strong>Parse SWF and ABC directly</strong></summary>
207
+
208
+ ```python
209
+ from flashkit.swf import parse_swf, TAG_DO_ABC2
210
+ from flashkit.abc import parse_abc, serialize_abc
211
+
212
+ header, tags, version, length = parse_swf(swf_bytes)
213
+
214
+ for tag in tags:
215
+ if tag.tag_type == TAG_DO_ABC2:
216
+ null_idx = tag.payload.index(0, 4)
217
+ abc = parse_abc(tag.payload[null_idx + 1:])
218
+ print(f"{len(abc.instances)} classes, {len(abc.methods)} methods")
219
+
220
+ # Round-trip fidelity: serialize(parse(data)) == data
221
+ assert serialize_abc(abc) == tag.payload[null_idx + 1:]
222
+ ```
223
+
224
+ </details>
225
+
226
+ <details>
227
+ <summary><strong>Build SWF programmatically</strong></summary>
228
+
229
+ ```python
230
+ from flashkit.abc import AbcBuilder, serialize_abc
231
+ from flashkit.swf import SwfBuilder
232
+
233
+ b = AbcBuilder()
234
+ b.simple_class("Player", package="com.game",
235
+ fields=[("hp", "int"), ("name", "String")])
236
+ b.script()
237
+ abc_bytes = serialize_abc(b.build())
238
+
239
+ swf = SwfBuilder(version=40, width=800, height=600, fps=30)
240
+ swf.add_abc("GameCode", abc_bytes)
241
+ swf_bytes = swf.build(compress=True)
242
+ ```
243
+
244
+ </details>
245
+
246
+ <details>
247
+ <summary><strong>Disassemble method bodies</strong></summary>
248
+
249
+ ```python
250
+ from flashkit.abc import decode_instructions
251
+
252
+ for body in abc.method_bodies:
253
+ for instr in decode_instructions(body.code):
254
+ print(f"0x{instr.offset:04X} {instr.mnemonic} {instr.operands}")
255
+ ```
256
+
257
+ </details>
258
+
259
+ ---
260
+
261
+ ## Project structure
262
+
263
+ ```
264
+ flashkit/
265
+ cli/ CLI (one module per command)
266
+ swf/ SWF container (parse, build, tags)
267
+ abc/ AVM2 bytecode (parse, write, disasm, builder)
268
+ info/ Resolved class model (ClassInfo, FieldInfo, MethodInfo)
269
+ workspace/ File loading and class index
270
+ analysis/ Inheritance, call graph, references, strings
271
+ search/ Unified query engine
272
+ ```
273
+
274
+ ## References
275
+
276
+ - [AVM2 Overview (Adobe)](https://www.adobe.com/content/dam/acom/en/devnet/pdf/avm2overview.pdf)
277
+ - [SWF File Format Specification](https://open-flash.github.io/mirrors/swf-spec-19.pdf)
278
+
279
+ ## License
280
+
281
+ MIT