swf-toolkit 0.0.0-stage → 0.1.0

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 (175) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +125 -2
  3. package/README.tr.md +126 -0
  4. package/dist/abc/abc-file.d.ts +168 -0
  5. package/dist/abc/abc-file.js +656 -0
  6. package/dist/abc/analysis.d.ts +36 -0
  7. package/dist/abc/analysis.js +213 -0
  8. package/dist/abc/code.d.ts +59 -0
  9. package/dist/abc/code.js +379 -0
  10. package/dist/abc/constants.d.ts +80 -0
  11. package/dist/abc/constants.js +93 -0
  12. package/dist/abc/interner.d.ts +46 -0
  13. package/dist/abc/interner.js +168 -0
  14. package/dist/abc/model.d.ts +40 -0
  15. package/dist/abc/model.js +146 -0
  16. package/dist/abc/opcodes.d.ts +39 -0
  17. package/dist/abc/opcodes.js +196 -0
  18. package/dist/abc/pcode/assembler.d.ts +42 -0
  19. package/dist/abc/pcode/assembler.js +635 -0
  20. package/dist/abc/pcode/disassembler.d.ts +17 -0
  21. package/dist/abc/pcode/disassembler.js +147 -0
  22. package/dist/abc/pcode/format.d.ts +23 -0
  23. package/dist/abc/pcode/format.js +131 -0
  24. package/dist/abc/pcode/lexer.d.ts +34 -0
  25. package/dist/abc/pcode/lexer.js +183 -0
  26. package/dist/assets/assets.d.ts +26 -0
  27. package/dist/assets/assets.js +151 -0
  28. package/dist/assets/images.d.ts +31 -0
  29. package/dist/assets/images.js +238 -0
  30. package/dist/assets/png.d.ts +12 -0
  31. package/dist/assets/png.js +196 -0
  32. package/dist/assets/sounds.d.ts +37 -0
  33. package/dist/assets/sounds.js +236 -0
  34. package/dist/avm1/avm1.d.ts +55 -0
  35. package/dist/avm1/avm1.js +642 -0
  36. package/dist/avm1/project.d.ts +16 -0
  37. package/dist/avm1/project.js +81 -0
  38. package/dist/cjs/abc/abc-file.d.ts +168 -0
  39. package/dist/cjs/abc/abc-file.js +663 -0
  40. package/dist/cjs/abc/analysis.d.ts +36 -0
  41. package/dist/cjs/abc/analysis.js +221 -0
  42. package/dist/cjs/abc/code.d.ts +59 -0
  43. package/dist/cjs/abc/code.js +387 -0
  44. package/dist/cjs/abc/constants.d.ts +80 -0
  45. package/dist/cjs/abc/constants.js +97 -0
  46. package/dist/cjs/abc/interner.d.ts +46 -0
  47. package/dist/cjs/abc/interner.js +172 -0
  48. package/dist/cjs/abc/model.d.ts +40 -0
  49. package/dist/cjs/abc/model.js +155 -0
  50. package/dist/cjs/abc/opcodes.d.ts +39 -0
  51. package/dist/cjs/abc/opcodes.js +201 -0
  52. package/dist/cjs/abc/pcode/assembler.d.ts +42 -0
  53. package/dist/cjs/abc/pcode/assembler.js +640 -0
  54. package/dist/cjs/abc/pcode/disassembler.d.ts +17 -0
  55. package/dist/cjs/abc/pcode/disassembler.js +152 -0
  56. package/dist/cjs/abc/pcode/format.d.ts +23 -0
  57. package/dist/cjs/abc/pcode/format.js +141 -0
  58. package/dist/cjs/abc/pcode/lexer.d.ts +34 -0
  59. package/dist/cjs/abc/pcode/lexer.js +188 -0
  60. package/dist/cjs/assets/assets.d.ts +26 -0
  61. package/dist/cjs/assets/assets.js +159 -0
  62. package/dist/cjs/assets/images.d.ts +31 -0
  63. package/dist/cjs/assets/images.js +246 -0
  64. package/dist/cjs/assets/png.d.ts +12 -0
  65. package/dist/cjs/assets/png.js +202 -0
  66. package/dist/cjs/assets/sounds.d.ts +37 -0
  67. package/dist/cjs/assets/sounds.js +246 -0
  68. package/dist/cjs/avm1/avm1.d.ts +55 -0
  69. package/dist/cjs/avm1/avm1.js +649 -0
  70. package/dist/cjs/avm1/project.d.ts +16 -0
  71. package/dist/cjs/avm1/project.js +88 -0
  72. package/dist/cjs/compiler/ast.d.ts +285 -0
  73. package/dist/cjs/compiler/ast.js +3 -0
  74. package/dist/cjs/compiler/class-compiler.d.ts +34 -0
  75. package/dist/cjs/compiler/class-compiler.js +440 -0
  76. package/dist/cjs/compiler/codegen.d.ts +144 -0
  77. package/dist/cjs/compiler/codegen.js +1589 -0
  78. package/dist/cjs/compiler/lexer.d.ts +27 -0
  79. package/dist/cjs/compiler/lexer.js +254 -0
  80. package/dist/cjs/compiler/parser.d.ts +58 -0
  81. package/dist/cjs/compiler/parser.js +989 -0
  82. package/dist/cjs/compiler/program.d.ts +29 -0
  83. package/dist/cjs/compiler/program.js +36 -0
  84. package/dist/cjs/compiler/scope.d.ts +22 -0
  85. package/dist/cjs/compiler/scope.js +242 -0
  86. package/dist/cjs/compression/lzma.d.ts +37 -0
  87. package/dist/cjs/compression/lzma.js +575 -0
  88. package/dist/cjs/compression/swf-container.d.ts +19 -0
  89. package/dist/cjs/compression/swf-container.js +92 -0
  90. package/dist/cjs/decompiler/ast.d.ts +228 -0
  91. package/dist/cjs/decompiler/ast.js +455 -0
  92. package/dist/cjs/decompiler/cfg.d.ts +40 -0
  93. package/dist/cjs/decompiler/cfg.js +236 -0
  94. package/dist/cjs/decompiler/class-printer.d.ts +9 -0
  95. package/dist/cjs/decompiler/class-printer.js +173 -0
  96. package/dist/cjs/decompiler/method.d.ts +41 -0
  97. package/dist/cjs/decompiler/method.js +436 -0
  98. package/dist/cjs/decompiler/simulate.d.ts +55 -0
  99. package/dist/cjs/decompiler/simulate.js +591 -0
  100. package/dist/cjs/decompiler/structure.d.ts +48 -0
  101. package/dist/cjs/decompiler/structure.js +764 -0
  102. package/dist/cjs/errors.d.ts +11 -0
  103. package/dist/cjs/errors.js +25 -0
  104. package/dist/cjs/index.d.ts +41 -0
  105. package/dist/cjs/index.js +82 -0
  106. package/dist/cjs/io/reader.d.ts +48 -0
  107. package/dist/cjs/io/reader.js +180 -0
  108. package/dist/cjs/io/writer.d.ts +37 -0
  109. package/dist/cjs/io/writer.js +175 -0
  110. package/dist/cjs/package.json +1 -0
  111. package/dist/cjs/project/pcode-project.d.ts +32 -0
  112. package/dist/cjs/project/pcode-project.js +210 -0
  113. package/dist/cjs/project/source-export.d.ts +12 -0
  114. package/dist/cjs/project/source-export.js +51 -0
  115. package/dist/cjs/project/source-import.d.ts +13 -0
  116. package/dist/cjs/project/source-import.js +73 -0
  117. package/dist/cjs/swf/swf.d.ts +63 -0
  118. package/dist/cjs/swf/swf.js +147 -0
  119. package/dist/cjs/swf/tag-codes.d.ts +77 -0
  120. package/dist/cjs/swf/tag-codes.js +109 -0
  121. package/dist/cjs/swf/tags.d.ts +118 -0
  122. package/dist/cjs/swf/tags.js +330 -0
  123. package/dist/cli.d.ts +2 -0
  124. package/dist/cli.js +296 -0
  125. package/dist/compiler/ast.d.ts +285 -0
  126. package/dist/compiler/ast.js +2 -0
  127. package/dist/compiler/class-compiler.d.ts +34 -0
  128. package/dist/compiler/class-compiler.js +437 -0
  129. package/dist/compiler/codegen.d.ts +144 -0
  130. package/dist/compiler/codegen.js +1585 -0
  131. package/dist/compiler/lexer.d.ts +27 -0
  132. package/dist/compiler/lexer.js +249 -0
  133. package/dist/compiler/parser.d.ts +58 -0
  134. package/dist/compiler/parser.js +984 -0
  135. package/dist/compiler/program.d.ts +29 -0
  136. package/dist/compiler/program.js +32 -0
  137. package/dist/compiler/scope.d.ts +22 -0
  138. package/dist/compiler/scope.js +238 -0
  139. package/dist/compression/lzma.d.ts +37 -0
  140. package/dist/compression/lzma.js +569 -0
  141. package/dist/compression/swf-container.d.ts +19 -0
  142. package/dist/compression/swf-container.js +87 -0
  143. package/dist/decompiler/ast.d.ts +228 -0
  144. package/dist/decompiler/ast.js +441 -0
  145. package/dist/decompiler/cfg.d.ts +40 -0
  146. package/dist/decompiler/cfg.js +231 -0
  147. package/dist/decompiler/class-printer.d.ts +9 -0
  148. package/dist/decompiler/class-printer.js +170 -0
  149. package/dist/decompiler/method.d.ts +41 -0
  150. package/dist/decompiler/method.js +427 -0
  151. package/dist/decompiler/simulate.d.ts +55 -0
  152. package/dist/decompiler/simulate.js +586 -0
  153. package/dist/decompiler/structure.d.ts +48 -0
  154. package/dist/decompiler/structure.js +760 -0
  155. package/dist/errors.d.ts +11 -0
  156. package/dist/errors.js +20 -0
  157. package/dist/index.d.ts +41 -0
  158. package/dist/index.js +49 -0
  159. package/dist/io/reader.d.ts +48 -0
  160. package/dist/io/reader.js +176 -0
  161. package/dist/io/writer.d.ts +37 -0
  162. package/dist/io/writer.js +169 -0
  163. package/dist/project/pcode-project.d.ts +32 -0
  164. package/dist/project/pcode-project.js +203 -0
  165. package/dist/project/source-export.d.ts +12 -0
  166. package/dist/project/source-export.js +47 -0
  167. package/dist/project/source-import.d.ts +13 -0
  168. package/dist/project/source-import.js +70 -0
  169. package/dist/swf/swf.d.ts +63 -0
  170. package/dist/swf/swf.js +143 -0
  171. package/dist/swf/tag-codes.d.ts +77 -0
  172. package/dist/swf/tag-codes.js +105 -0
  173. package/dist/swf/tags.d.ts +118 -0
  174. package/dist/swf/tags.js +316 -0
  175. package/package.json +71 -4
@@ -0,0 +1,81 @@
1
+ /**
2
+ * AS1/AS2 code blocks (DoAction / DoInitAction) export & import as P-code.
3
+ */
4
+ import { mkdir, readFile, readdir, writeFile } from 'node:fs/promises';
5
+ import { join } from 'node:path';
6
+ import { TagCode } from '../swf/tag-codes.js';
7
+ import { RawTag } from '../swf/tags.js';
8
+ import { decodeActions, encodeActions, formatActions, parseActions } from './avm1.js';
9
+ /** All AVM1 code blocks of an SWF (main timeline and sprites). */
10
+ export function actionBlocks(swf) {
11
+ const out = [];
12
+ const frames = new Map();
13
+ for (const { tag, parent, index } of swf.walkTags()) {
14
+ const owner = parent ?? swf;
15
+ if (tag.code === TagCode.ShowFrame)
16
+ frames.set(owner, (frames.get(owner) ?? 0) + 1);
17
+ if (!(tag instanceof RawTag) || (tag.code !== TagCode.DoAction && tag.code !== TagCode.DoInitAction))
18
+ continue;
19
+ const scope = parent ? `sprite${parent.spriteId}` : 'root';
20
+ const init = tag.code === TagCode.DoInitAction;
21
+ const key = `${scope}_f${frames.get(owner) ?? 0}_t${index}${init ? `_init${tag.data[0] | (tag.data[1] << 8)}` : ''}`;
22
+ out.push({ key, tag, offset: init ? 2 : 0 });
23
+ }
24
+ return out;
25
+ }
26
+ export function disassembleBlock(b) {
27
+ return formatActions(decodeActions(b.tag.data.subarray(b.offset)));
28
+ }
29
+ export function assembleBlock(b, text) {
30
+ const code = encodeActions(parseActions(text));
31
+ const data = new Uint8Array(b.offset + code.length);
32
+ data.set(b.tag.data.subarray(0, b.offset), 0);
33
+ data.set(code, b.offset);
34
+ b.tag.data = data;
35
+ }
36
+ export async function exportAs2(swf, dir) {
37
+ await mkdir(dir, { recursive: true });
38
+ const files = [];
39
+ for (const b of actionBlocks(swf)) {
40
+ let text;
41
+ try {
42
+ text = disassembleBlock(b);
43
+ }
44
+ catch (e) {
45
+ text = `; could not decode: ${e.message}\n`;
46
+ }
47
+ const p = join(dir, `${b.key}.as2pcode`);
48
+ await writeFile(p, text, 'utf8');
49
+ files.push(p);
50
+ }
51
+ return files;
52
+ }
53
+ /** Re-assembles blocks whose files changed. Returns the keys that were updated. */
54
+ export async function importAs2(swf, dir) {
55
+ const present = new Set(await readdir(dir));
56
+ const changed = [];
57
+ for (const b of actionBlocks(swf)) {
58
+ const name = `${b.key}.as2pcode`;
59
+ if (!present.has(name))
60
+ continue;
61
+ const text = await readFile(join(dir, name), 'utf8');
62
+ let current;
63
+ try {
64
+ current = disassembleBlock(b);
65
+ }
66
+ catch {
67
+ current = '';
68
+ }
69
+ const norm = (s) => s.split('\n').map((l) => l.replace(/;.*$/, '').trim()).filter(Boolean).join('\n');
70
+ if (norm(text) === norm(current))
71
+ continue;
72
+ try {
73
+ assembleBlock(b, text);
74
+ }
75
+ catch (e) {
76
+ throw new Error(`${name}: ${e.message}`);
77
+ }
78
+ changed.push(b.key);
79
+ }
80
+ return changed;
81
+ }
@@ -0,0 +1,168 @@
1
+ export interface NamespaceInfo {
2
+ kind: number;
3
+ /** String pool index (0 = no name). */
4
+ name: number;
5
+ }
6
+ /**
7
+ * A multiname pool entry. Only the fields relevant for `kind` are meaningful:
8
+ * - QName(A): ns, name
9
+ * - RTQName(A): name
10
+ * - RTQNameL(A): –
11
+ * - Multiname(A): name, nsSet
12
+ * - MultinameL(A): nsSet
13
+ * - TypeName: base, params
14
+ */
15
+ export interface MultinameInfo {
16
+ kind: number;
17
+ ns: number;
18
+ name: number;
19
+ nsSet: number;
20
+ base: number;
21
+ params: number[];
22
+ }
23
+ export interface OptionalParam {
24
+ kind: number;
25
+ value: number;
26
+ }
27
+ export interface MethodInfo {
28
+ paramTypes: number[];
29
+ returnType: number;
30
+ name: number;
31
+ flags: number;
32
+ optional: OptionalParam[];
33
+ paramNames: number[];
34
+ }
35
+ export interface MetadataInfo {
36
+ name: number;
37
+ keys: number[];
38
+ values: number[];
39
+ }
40
+ export interface Trait {
41
+ name: number;
42
+ kind: number;
43
+ /** Upper 4 bits of the kind byte (Final / Override / Metadata). */
44
+ attrs: number;
45
+ /** slot_id for Slot/Const/Class/Function, disp_id for Method/Getter/Setter. */
46
+ id: number;
47
+ /** Slot/Const: type multiname. */
48
+ typeName: number;
49
+ /** Slot/Const: default value index (0 = none). */
50
+ valueIndex: number;
51
+ /** Slot/Const: default value kind (only if valueIndex != 0). */
52
+ valueKind: number;
53
+ /** Class: class index. */
54
+ classIndex: number;
55
+ /** Method/Getter/Setter/Function: method index. */
56
+ method: number;
57
+ metadata: number[];
58
+ }
59
+ export interface InstanceInfo {
60
+ name: number;
61
+ superName: number;
62
+ flags: number;
63
+ protectedNs: number;
64
+ interfaces: number[];
65
+ iinit: number;
66
+ traits: Trait[];
67
+ }
68
+ export interface ClassInfo {
69
+ cinit: number;
70
+ traits: Trait[];
71
+ }
72
+ export interface ScriptInfo {
73
+ init: number;
74
+ traits: Trait[];
75
+ }
76
+ export interface ExceptionInfo {
77
+ from: number;
78
+ to: number;
79
+ target: number;
80
+ excType: number;
81
+ varName: number;
82
+ }
83
+ export interface MethodBody {
84
+ method: number;
85
+ maxStack: number;
86
+ localCount: number;
87
+ initScopeDepth: number;
88
+ maxScopeDepth: number;
89
+ code: Uint8Array;
90
+ exceptions: ExceptionInfo[];
91
+ traits: Trait[];
92
+ }
93
+ export declare function emptyMultiname(kind?: number): MultinameInfo;
94
+ export declare function newTrait(partial: Partial<Trait> & {
95
+ name: number;
96
+ kind: number;
97
+ }): Trait;
98
+ /** A parsed ActionScript Byte Code (ABC) file. */
99
+ export declare class AbcFile {
100
+ minorVersion: number;
101
+ majorVersion: number;
102
+ ints: number[];
103
+ uints: number[];
104
+ doubles: number[];
105
+ strings: string[];
106
+ namespaces: NamespaceInfo[];
107
+ nsSets: number[][];
108
+ multinames: MultinameInfo[];
109
+ methods: MethodInfo[];
110
+ metadata: MetadataInfo[];
111
+ instances: InstanceInfo[];
112
+ classes: ClassInfo[];
113
+ scripts: ScriptInfo[];
114
+ bodies: MethodBody[];
115
+ /** Raw bytes of strings that are not valid UTF-8, keyed by pool index. */
116
+ private rawStrings;
117
+ /** Pools whose count was written as 1 (instead of 0) while empty; preserved for exact round-trips. */
118
+ private onePools;
119
+ private readonly intCache;
120
+ private readonly uintCache;
121
+ private readonly doubleCache;
122
+ private readonly stringCache;
123
+ private readonly nsCache;
124
+ private readonly nsSetCache;
125
+ private readonly mnCache;
126
+ private bodyIndex;
127
+ private bodyIndexSize;
128
+ static parse(bytes: Uint8Array): AbcFile;
129
+ toBytes(): Uint8Array;
130
+ /** String pool index for `s` (adds it if missing). */
131
+ string(s: string): number;
132
+ int(v: number): number;
133
+ uint(v: number): number;
134
+ double(v: number): number;
135
+ /** Namespace pool index. `PrivateNs` entries are always created fresh unless `reuse` is set. */
136
+ namespace(kind: number, name: string | number, reuse?: boolean): number;
137
+ packageNamespace(name: string): number;
138
+ nsSet(namespaces: number[]): number;
139
+ multiname(info: Partial<MultinameInfo> & {
140
+ kind: number;
141
+ }): number;
142
+ /** QName multiname index. `ns` may be a namespace index or a package name. */
143
+ qname(ns: number | string, name: string): number;
144
+ /** QName for a fully qualified name like "flash.display.Sprite" (or "flash.display:Sprite"). */
145
+ qnameFor(qualified: string): number;
146
+ /** Method body for a method index, if the method has one. */
147
+ methodBody(methodIndex: number): MethodBody | undefined;
148
+ /** Namespace URI string (empty for the public/unnamed namespace). */
149
+ namespaceName(nsIndex: number): string;
150
+ /** Local name of a multiname ("*" if any). */
151
+ multinameName(mnIndex: number): string;
152
+ /**
153
+ * Fully qualified dotted name of a multiname, e.g. "flash.display.Sprite".
154
+ * For non-QName multinames this is just the local name.
155
+ */
156
+ qualifiedName(mnIndex: number): string;
157
+ /** Fully qualified name of class `classIndex`. */
158
+ className(classIndex: number): string;
159
+ /** Class index by fully qualified name ("com.example.Foo" or "com.example:Foo"); -1 if not found. */
160
+ findClass(qualified: string): number;
161
+ /** Names of all classes defined in this ABC. */
162
+ classNames(): string[];
163
+ }
164
+ /** Split "a.b.C" / "a.b:C" into package and local name. */
165
+ export declare function splitQualifiedName(qualified: string): {
166
+ pkg: string;
167
+ name: string;
168
+ };