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,88 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.actionBlocks = actionBlocks;
4
+ exports.disassembleBlock = disassembleBlock;
5
+ exports.assembleBlock = assembleBlock;
6
+ exports.exportAs2 = exportAs2;
7
+ exports.importAs2 = importAs2;
8
+ /**
9
+ * AS1/AS2 code blocks (DoAction / DoInitAction) export & import as P-code.
10
+ */
11
+ const promises_1 = require("node:fs/promises");
12
+ const node_path_1 = require("node:path");
13
+ const tag_codes_js_1 = require("../swf/tag-codes.js");
14
+ const tags_js_1 = require("../swf/tags.js");
15
+ const avm1_js_1 = require("./avm1.js");
16
+ /** All AVM1 code blocks of an SWF (main timeline and sprites). */
17
+ function actionBlocks(swf) {
18
+ const out = [];
19
+ const frames = new Map();
20
+ for (const { tag, parent, index } of swf.walkTags()) {
21
+ const owner = parent ?? swf;
22
+ if (tag.code === tag_codes_js_1.TagCode.ShowFrame)
23
+ frames.set(owner, (frames.get(owner) ?? 0) + 1);
24
+ if (!(tag instanceof tags_js_1.RawTag) || (tag.code !== tag_codes_js_1.TagCode.DoAction && tag.code !== tag_codes_js_1.TagCode.DoInitAction))
25
+ continue;
26
+ const scope = parent ? `sprite${parent.spriteId}` : 'root';
27
+ const init = tag.code === tag_codes_js_1.TagCode.DoInitAction;
28
+ const key = `${scope}_f${frames.get(owner) ?? 0}_t${index}${init ? `_init${tag.data[0] | (tag.data[1] << 8)}` : ''}`;
29
+ out.push({ key, tag, offset: init ? 2 : 0 });
30
+ }
31
+ return out;
32
+ }
33
+ function disassembleBlock(b) {
34
+ return (0, avm1_js_1.formatActions)((0, avm1_js_1.decodeActions)(b.tag.data.subarray(b.offset)));
35
+ }
36
+ function assembleBlock(b, text) {
37
+ const code = (0, avm1_js_1.encodeActions)((0, avm1_js_1.parseActions)(text));
38
+ const data = new Uint8Array(b.offset + code.length);
39
+ data.set(b.tag.data.subarray(0, b.offset), 0);
40
+ data.set(code, b.offset);
41
+ b.tag.data = data;
42
+ }
43
+ async function exportAs2(swf, dir) {
44
+ await (0, promises_1.mkdir)(dir, { recursive: true });
45
+ const files = [];
46
+ for (const b of actionBlocks(swf)) {
47
+ let text;
48
+ try {
49
+ text = disassembleBlock(b);
50
+ }
51
+ catch (e) {
52
+ text = `; could not decode: ${e.message}\n`;
53
+ }
54
+ const p = (0, node_path_1.join)(dir, `${b.key}.as2pcode`);
55
+ await (0, promises_1.writeFile)(p, text, 'utf8');
56
+ files.push(p);
57
+ }
58
+ return files;
59
+ }
60
+ /** Re-assembles blocks whose files changed. Returns the keys that were updated. */
61
+ async function importAs2(swf, dir) {
62
+ const present = new Set(await (0, promises_1.readdir)(dir));
63
+ const changed = [];
64
+ for (const b of actionBlocks(swf)) {
65
+ const name = `${b.key}.as2pcode`;
66
+ if (!present.has(name))
67
+ continue;
68
+ const text = await (0, promises_1.readFile)((0, node_path_1.join)(dir, name), 'utf8');
69
+ let current;
70
+ try {
71
+ current = disassembleBlock(b);
72
+ }
73
+ catch {
74
+ current = '';
75
+ }
76
+ const norm = (s) => s.split('\n').map((l) => l.replace(/;.*$/, '').trim()).filter(Boolean).join('\n');
77
+ if (norm(text) === norm(current))
78
+ continue;
79
+ try {
80
+ assembleBlock(b, text);
81
+ }
82
+ catch (e) {
83
+ throw new Error(`${name}: ${e.message}`);
84
+ }
85
+ changed.push(b.key);
86
+ }
87
+ return changed;
88
+ }
@@ -0,0 +1,285 @@
1
+ /** AST produced by the AS3 parser. */
2
+ export interface Pos {
3
+ line: number;
4
+ col: number;
5
+ }
6
+ export interface TypeRef {
7
+ name: string;
8
+ /** Vector.<T> parameters. */
9
+ params?: TypeRef[];
10
+ pos: Pos;
11
+ }
12
+ export type Expr = ({
13
+ k: 'num';
14
+ v: number;
15
+ } | {
16
+ k: 'str';
17
+ v: string;
18
+ } | {
19
+ k: 'bool';
20
+ v: boolean;
21
+ } | {
22
+ k: 'null';
23
+ } | {
24
+ k: 'undefined';
25
+ } | {
26
+ k: 'regex';
27
+ pattern: string;
28
+ flags: string;
29
+ } | {
30
+ k: 'id';
31
+ name: string;
32
+ ns?: string;
33
+ } | {
34
+ k: 'this';
35
+ } | {
36
+ k: 'super';
37
+ } | {
38
+ k: 'member';
39
+ obj: Expr;
40
+ name: string;
41
+ ns?: string;
42
+ attr?: boolean;
43
+ } | {
44
+ k: 'index';
45
+ obj: Expr;
46
+ index: Expr;
47
+ attr?: boolean;
48
+ } | {
49
+ k: 'descendants';
50
+ obj: Expr;
51
+ name: string;
52
+ attr?: boolean;
53
+ } | {
54
+ k: 'filter';
55
+ obj: Expr;
56
+ cond: Expr;
57
+ } | {
58
+ k: 'typeapply';
59
+ base: Expr;
60
+ params: TypeRef[];
61
+ } | {
62
+ k: 'call';
63
+ fn: Expr;
64
+ args: Expr[];
65
+ } | {
66
+ k: 'new';
67
+ ctor: Expr;
68
+ args: Expr[];
69
+ } | {
70
+ k: 'vector';
71
+ type: TypeRef;
72
+ items: Expr[];
73
+ } | {
74
+ k: 'unary';
75
+ op: string;
76
+ e: Expr;
77
+ } | {
78
+ k: 'update';
79
+ op: '++' | '--';
80
+ prefix: boolean;
81
+ e: Expr;
82
+ } | {
83
+ k: 'binary';
84
+ op: string;
85
+ a: Expr;
86
+ b: Expr;
87
+ } | {
88
+ k: 'cond';
89
+ c: Expr;
90
+ t: Expr;
91
+ f: Expr;
92
+ } | {
93
+ k: 'assign';
94
+ op: string;
95
+ target: Expr;
96
+ v: Expr;
97
+ } | {
98
+ k: 'array';
99
+ items: Array<Expr | null>;
100
+ } | {
101
+ k: 'object';
102
+ props: Array<{
103
+ key: string | number;
104
+ value: Expr;
105
+ }>;
106
+ } | {
107
+ k: 'function';
108
+ fn: FunctionDef;
109
+ } | {
110
+ k: 'comma';
111
+ list: Expr[];
112
+ } | {
113
+ k: 'xml';
114
+ text: string;
115
+ }) & {
116
+ pos: Pos;
117
+ };
118
+ export interface Param {
119
+ name: string;
120
+ type?: TypeRef;
121
+ init?: Expr;
122
+ }
123
+ export interface FunctionDef {
124
+ name?: string;
125
+ params: Param[];
126
+ rest?: {
127
+ name: string;
128
+ type?: TypeRef;
129
+ };
130
+ returnType?: TypeRef;
131
+ body?: Stmt[];
132
+ pos: Pos;
133
+ }
134
+ export interface VarDecl {
135
+ name: string;
136
+ type?: TypeRef;
137
+ init?: Expr;
138
+ pos: Pos;
139
+ }
140
+ export interface CatchClause {
141
+ name: string;
142
+ type?: TypeRef;
143
+ body: Stmt[];
144
+ }
145
+ export type Stmt = ({
146
+ k: 'expr';
147
+ e: Expr;
148
+ } | {
149
+ k: 'var';
150
+ isConst: boolean;
151
+ decls: VarDecl[];
152
+ } | {
153
+ k: 'function';
154
+ fn: FunctionDef;
155
+ } | {
156
+ k: 'if';
157
+ c: Expr;
158
+ then: Stmt;
159
+ else?: Stmt;
160
+ } | {
161
+ k: 'while';
162
+ c: Expr;
163
+ body: Stmt;
164
+ } | {
165
+ k: 'dowhile';
166
+ c: Expr;
167
+ body: Stmt;
168
+ } | {
169
+ k: 'for';
170
+ init?: Stmt;
171
+ c?: Expr;
172
+ update?: Expr;
173
+ body: Stmt;
174
+ } | {
175
+ k: 'forin';
176
+ each: boolean;
177
+ decl?: VarDecl;
178
+ target?: Expr;
179
+ obj: Expr;
180
+ body: Stmt;
181
+ } | {
182
+ k: 'switch';
183
+ disc: Expr;
184
+ cases: Array<{
185
+ test: Expr | null;
186
+ body: Stmt[];
187
+ }>;
188
+ } | {
189
+ k: 'try';
190
+ body: Stmt[];
191
+ catches: CatchClause[];
192
+ finally?: Stmt[];
193
+ } | {
194
+ k: 'return';
195
+ e?: Expr;
196
+ } | {
197
+ k: 'throw';
198
+ e: Expr;
199
+ } | {
200
+ k: 'break';
201
+ label?: string;
202
+ } | {
203
+ k: 'continue';
204
+ label?: string;
205
+ } | {
206
+ k: 'block';
207
+ body: Stmt[];
208
+ } | {
209
+ k: 'labeled';
210
+ label: string;
211
+ body: Stmt;
212
+ } | {
213
+ k: 'with';
214
+ obj: Expr;
215
+ body: Stmt;
216
+ } | {
217
+ k: 'dxns';
218
+ e: Expr;
219
+ } | {
220
+ k: 'empty';
221
+ }) & {
222
+ pos: Pos;
223
+ };
224
+ export interface Metadata {
225
+ name: string;
226
+ items: Array<{
227
+ key?: string;
228
+ value: string;
229
+ }>;
230
+ }
231
+ export interface FieldMember {
232
+ k: 'field';
233
+ name: string;
234
+ isStatic: boolean;
235
+ isConst: boolean;
236
+ access: string;
237
+ type?: TypeRef;
238
+ init?: Expr;
239
+ metadata: Metadata[];
240
+ pos: Pos;
241
+ /** Source span [start, end) of the declaration. */
242
+ span: [number, number];
243
+ }
244
+ export interface MethodMember {
245
+ k: 'method';
246
+ name: string;
247
+ kind: 'method' | 'get' | 'set' | 'constructor';
248
+ isStatic: boolean;
249
+ isOverride: boolean;
250
+ isFinal: boolean;
251
+ isNative: boolean;
252
+ access: string;
253
+ fn: FunctionDef;
254
+ metadata: Metadata[];
255
+ pos: Pos;
256
+ span: [number, number];
257
+ }
258
+ export interface StaticBlockMember {
259
+ k: 'static';
260
+ body: Stmt[];
261
+ pos: Pos;
262
+ span: [number, number];
263
+ }
264
+ export type Member = FieldMember | MethodMember | StaticBlockMember;
265
+ export interface ClassDef {
266
+ name: string;
267
+ isInterface: boolean;
268
+ isDynamic: boolean;
269
+ isFinal: boolean;
270
+ access: string;
271
+ extends?: TypeRef;
272
+ implements: TypeRef[];
273
+ members: Member[];
274
+ metadata: Metadata[];
275
+ pos: Pos;
276
+ }
277
+ export interface CompilationUnit {
278
+ package: string;
279
+ imports: string[];
280
+ /** `use namespace x` declarations. */
281
+ useNamespaces: string[];
282
+ classes: ClassDef[];
283
+ /** Package-level functions / variables (rare). */
284
+ functions: MethodMember[];
285
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ /** AST produced by the AS3 parser. */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Compiles an edited AS3 class back into an existing ABC.
3
+ *
4
+ * Only members whose source text changed compared with a baseline (by
5
+ * default the decompiled text of the current bytecode) are recompiled; all
6
+ * other methods keep their original bytecode.
7
+ */
8
+ import type { AbcFile } from '../abc/abc-file.js';
9
+ import { Interner } from '../abc/interner.js';
10
+ export interface CompileClassOptions {
11
+ /** File name used in error messages. */
12
+ source?: string;
13
+ /**
14
+ * Baseline source the edit started from. Members identical to the baseline
15
+ * are not recompiled. Defaults to the decompiled class; pass `null` to
16
+ * recompile every member.
17
+ */
18
+ baseline?: string | null;
19
+ /** Reuse an interner across calls on the same ABC. */
20
+ interner?: Interner;
21
+ /** Exact class index to compile into (for ABCs with duplicate class names). */
22
+ classIndex?: number;
23
+ }
24
+ export interface CompiledMember {
25
+ className: string;
26
+ member: string;
27
+ action: 'replaced' | 'added';
28
+ methodIndex?: number;
29
+ }
30
+ export interface CompileClassResult {
31
+ changes: CompiledMember[];
32
+ }
33
+ /** Compiles every class in `source` into `abc`. */
34
+ export declare function compileClassSource(abc: AbcFile, source: string, options?: CompileClassOptions): CompileClassResult;