OLD | NEW |
1 let global = this; | 1 let global = this; |
2 function decompileAST(ast) { | 2 function decompileAST(ast) { |
3 let func = global["decompile" + ast.type]; | 3 let func = global["decompile" + ast.type]; |
4 if (!func) | 4 if (!func) |
5 throw "Unknown type " + ast.type; | 5 throw "Unknown type " + ast.type; |
6 return func(ast); | 6 return func(ast); |
7 } | 7 } |
8 | 8 |
9 function decompileProgram(ast) { | 9 function decompileProgram(ast) { |
10 return [decompileAST(stmt) for each (stmt in ast.body)].join('\n'); | 10 return ast.body.map(decompileAST).join('\n'); |
11 } | 11 } |
12 | 12 |
13 /* Statements */ | 13 /* Statements */ |
14 function decompileEmptyStatement(ast) { | 14 function decompileEmptyStatement(ast) { |
15 return ";" | 15 return ";" |
16 } | 16 } |
17 function decompileBlockStatement(ast) { | 17 function decompileBlockStatement(ast) { |
18 return '{\n' + [decompileAST(stmt) for each (stmt in ast.body)].join('\n') + | 18 return '{\n' + ast.body.map(decompileAST).join('\n') + '\n}\n'; |
19 '\n}\n'; | |
20 } | 19 } |
21 | 20 |
22 function decompileExpressionStatement(ast) { | 21 function decompileExpressionStatement(ast) { |
23 return decompileAST(ast.expression) + ";"; | 22 return decompileAST(ast.expression) + ";"; |
24 } | 23 } |
25 | 24 |
26 function decompileIfStatement(ast) { | 25 function decompileIfStatement(ast) { |
27 let str = "if (" + decompileAST(ast.test) + ")\n"; | 26 let str = "if (" + decompileAST(ast.test) + ")\n"; |
28 str += decompileAST(ast.consequent); | 27 str += decompileAST(ast.consequent); |
29 if (ast.alternate) | 28 if (ast.alternate) |
(...skipping 13 matching lines...) Expand all Loading... |
43 return "continue" + (ast.label ? " " + ast.label.name : "") + ";"; | 42 return "continue" + (ast.label ? " " + ast.label.name : "") + ";"; |
44 } | 43 } |
45 | 44 |
46 function decompileWithStatement(ast) { | 45 function decompileWithStatement(ast) { |
47 return "with (" + decompileAST(ast.object) + ") " + decompileAST(ast.body); | 46 return "with (" + decompileAST(ast.object) + ") " + decompileAST(ast.body); |
48 } | 47 } |
49 | 48 |
50 function decompileSwitchStatement(ast) { | 49 function decompileSwitchStatement(ast) { |
51 let str = "switch (" + decompileAST(ast.discriminant) + ") {\n"; | 50 let str = "switch (" + decompileAST(ast.discriminant) + ") {\n"; |
52 let cases = []; | 51 let cases = []; |
53 for each (let scase in ast.cases) { | 52 for (let scase of ast.cases) { |
54 let casestr = scase.test ? "case " + decompileAST(scase.test) : "default"; | 53 let casestr = scase.test ? "case " + decompileAST(scase.test) : "default"; |
55 casestr += ":\n"; | 54 casestr += ":\n"; |
56 casestr += [decompileAST(stmt) for each (stmt in scase.consequent)] | 55 casestr += scase.consequent.map(decompileAST).join('\n'); |
57 .join('\n'); | |
58 cases.push(casestr); | 56 cases.push(casestr); |
59 } | 57 } |
60 str += cases.join('\n') + '\n}\n'; | 58 str += cases.join('\n') + '\n}\n'; |
61 return str; | 59 return str; |
62 } | 60 } |
63 | 61 |
64 function decompileReturnStatement(ast) { | 62 function decompileReturnStatement(ast) { |
65 return "return" + (ast.argument ? " " + decompileAST(ast.argument) : | 63 return "return" + (ast.argument ? " " + decompileAST(ast.argument) : |
66 "") + ";"; | 64 "") + ";"; |
67 } | 65 } |
68 | 66 |
69 function decompileThrowStatement(ast) { | 67 function decompileThrowStatement(ast) { |
70 return "throw " + decompileAST(ast.argument) + ";"; | 68 return "throw " + decompileAST(ast.argument) + ";"; |
71 } | 69 } |
72 | 70 |
73 function decompileTryStatement(ast) { | 71 function decompileTryStatement(ast) { |
74 let str = "try " + decompileAST(ast.block); | 72 let str = "try " + decompileAST(ast.block); |
75 | 73 |
76 let handlers = []; | 74 let handlers = []; |
77 if (ast.handler && "type" in ast.handler) | 75 if (ast.handler && "type" in ast.handler) |
78 handlers.push(ast.handler); | 76 handlers.push(ast.handler); |
79 else if (ast.handlers) | 77 else if (ast.handlers) |
80 handlers = ast.handlers; | 78 handlers = ast.handlers; |
81 | 79 |
82 let handler_strs = []; | 80 let handler_strs = []; |
83 for each (let handler in handlers) { | 81 for (let handler of handlers) { |
84 let handler_str = "catch (" + decompileAST(handler.param); | 82 let handler_str = "catch (" + decompileAST(handler.param); |
85 if (handler.guard) | 83 if (handler.guard) |
86 handler_str += " if " + decompileAST(handler.guard); | 84 handler_str += " if " + decompileAST(handler.guard); |
87 handler_str += ") " + decompileAST(handler.body); | 85 handler_str += ") " + decompileAST(handler.body); |
88 handler_strs.push(handler_str); | 86 handler_strs.push(handler_str); |
89 } | 87 } |
90 str += handler_strs.join(""); | 88 str += handler_strs.join(""); |
91 if (ast.finalizer) | 89 if (ast.finalizer) |
92 str += " finally " + decompileAST(ast.finalizer); | 90 str += " finally " + decompileAST(ast.finalizer); |
93 return str; | 91 return str; |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
140 str += decompileVariableDeclaration(ast.left, true); | 138 str += decompileVariableDeclaration(ast.left, true); |
141 else | 139 else |
142 str += decompileAST(ast.left); | 140 str += decompileAST(ast.left); |
143 str += " of " + decompileExpr(ast.right, ast) + ") "; | 141 str += " of " + decompileExpr(ast.right, ast) + ") "; |
144 str += decompileAST(ast.body); | 142 str += decompileAST(ast.body); |
145 return str; | 143 return str; |
146 } | 144 } |
147 | 145 |
148 function decompileLetStatement(ast) { | 146 function decompileLetStatement(ast) { |
149 let str = "let ("; | 147 let str = "let ("; |
150 str += [d ? decompileAST(d) : ' ' for each (d in ast.head)].join(', '); | 148 str += ast.head.map(d => d ? decompileAST(d) : ' ').join(', '); |
151 str += ") " + decompileAST(ast.body); | 149 str += ") " + decompileAST(ast.body); |
152 return str; | 150 return str; |
153 } | 151 } |
154 | 152 |
155 function decompileDebuggerStatement(ast) { | 153 function decompileDebuggerStatement(ast) { |
156 return "debugger;"; | 154 return "debugger;"; |
157 } | 155 } |
158 | 156 |
159 function decompileFunctionDeclaration(ast, init, name_ast) { | 157 function decompileFunctionDeclaration(ast, init, name_ast) { |
160 let str = (init ? init : "function") + " "; | 158 let str = (init ? init : "function") + " "; |
161 if (ast.id) | 159 if (ast.id) |
162 str += ast.id.name; | 160 str += ast.id.name; |
163 else if (name_ast) | 161 else if (name_ast) |
164 str += decompileAST(name_ast); | 162 str += decompileAST(name_ast); |
165 str += "("; | 163 str += "("; |
166 str += [decompileAST(param) for each (param in ast.params)].join(', '); | 164 str += ast.params.map(decompileAST).join(', '); |
167 str += ") " + decompileAST(ast.body); | 165 str += ") " + decompileAST(ast.body); |
168 return str; | 166 return str; |
169 } | 167 } |
170 | 168 |
171 function decompileVariableDeclaration(ast, excludeSemi) { | 169 function decompileVariableDeclaration(ast, excludeSemi) { |
172 let inits = []; | 170 let inits = []; |
173 for each (let initializer in ast.declarations) { | 171 for (let initializer of ast.declarations) { |
174 inits.push(decompileAST(initializer)); | 172 inits.push(decompileAST(initializer)); |
175 } | 173 } |
176 return ast.kind + " " + inits.join(', ') + (excludeSemi ? "" : ";"); | 174 return ast.kind + " " + inits.join(', ') + (excludeSemi ? "" : ";"); |
177 } | 175 } |
178 | 176 |
179 function decompileVariableDeclarator(ast) { | 177 function decompileVariableDeclarator(ast) { |
180 if (ast.init) | 178 if (ast.init) |
181 return decompileAST(ast.id) + " = " + decompileAST(ast.init); | 179 return decompileAST(ast.id) + " = " + decompileAST(ast.init); |
182 return decompileAST(ast.id); | 180 return decompileAST(ast.id); |
183 } | 181 } |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
220 else | 218 else |
221 return decompileAST(expr); | 219 return decompileAST(expr); |
222 } | 220 } |
223 | 221 |
224 function decompileThisExpression(ast) { | 222 function decompileThisExpression(ast) { |
225 return "this"; | 223 return "this"; |
226 } | 224 } |
227 | 225 |
228 function decompileArrayExpression(ast) { | 226 function decompileArrayExpression(ast) { |
229 if (ast.elements) | 227 if (ast.elements) |
230 return "[" + [el ? decompileAST(el) : "" for each (el in ast.elements)]. | 228 return "[" + ast.elements.map(el => el ? decompileAST(el) : ""). |
231 join(", ") + "]"; | 229 join(", ") + "]"; |
232 return "[]"; | 230 return "[]"; |
233 } | 231 } |
234 | 232 |
235 function decompileObjectExpression(ast) { | 233 function decompileObjectExpression(ast) { |
236 let props = []; | 234 let props = []; |
237 for each (let prop in ast.properties) { | 235 for (let prop of ast.properties) { |
238 if (prop.kind == "init") | 236 if (prop.kind == "init") |
239 props.push(decompileAST(prop.key) + ": " + decompileAST(prop.value)); | 237 props.push(decompileAST(prop.key) + ": " + decompileAST(prop.value)); |
240 else if (prop.kind == "get" || prop.kind == "set") | 238 else if (prop.kind == "get" || prop.kind == "set") |
241 props.push(decompileFunctionDeclaration(prop.value, prop.kind, prop.key)); | 239 props.push(decompileFunctionDeclaration(prop.value, prop.kind, prop.key)); |
242 else | 240 else |
243 throw "Unknown kind " + prop.kind; | 241 throw "Unknown kind " + prop.kind; |
244 } | 242 } |
245 return "{\n" + props.join(",\n") + "}"; | 243 return "{\n" + props.join(",\n") + "}"; |
246 } | 244 } |
247 | 245 |
248 function decompileFunctionExpression(ast) { | 246 function decompileFunctionExpression(ast) { |
249 return decompileFunctionDeclaration(ast); | 247 return decompileFunctionDeclaration(ast); |
250 } | 248 } |
251 | 249 |
252 function decompileArrowExpression(ast) { | 250 function decompileArrowExpression(ast) { |
253 let str = "(" + ast.params.map(decompileAST).join(", ") + ")"; | 251 let str = "(" + ast.params.map(decompileAST).join(", ") + ")"; |
254 str += " => " + decompileAST(ast.body); | 252 str += " => " + decompileAST(ast.body); |
255 return str; | 253 return str; |
256 } | 254 } |
257 | 255 |
258 function decompileSequenceExpression(ast) { | 256 function decompileSequenceExpression(ast) { |
259 return "(" + [decompileExpr(e, ast) for each (e in ast.expressions)].join(", "
) + ")"; | 257 return "(" + ast.expressions.map(e => decompileExpr(e, ast)).join(", ") + ")"; |
260 } | 258 } |
261 | 259 |
262 function decompileUnaryExpression(ast) { | 260 function decompileUnaryExpression(ast) { |
263 if (ast.prefix) | 261 if (ast.prefix) |
264 return ast.operator + " " + decompileExpr(ast.argument, ast); | 262 return ast.operator + " " + decompileExpr(ast.argument, ast); |
265 throw "ER, wtf?"; | 263 throw "ER, wtf?"; |
266 } | 264 } |
267 | 265 |
268 function decompileBinaryExpression(ast) { | 266 function decompileBinaryExpression(ast) { |
269 return decompileExpr(ast.left, ast) + " " + ast.operator + | 267 return decompileExpr(ast.left, ast) + " " + ast.operator + |
(...skipping 21 matching lines...) Expand all Loading... |
291 | 289 |
292 function decompileConditionalExpression(ast) { | 290 function decompileConditionalExpression(ast) { |
293 return decompileExpr(ast.test, ast) + " ? " + | 291 return decompileExpr(ast.test, ast) + " ? " + |
294 decompileExpr(ast.consequent, ast) + " : " + | 292 decompileExpr(ast.consequent, ast) + " : " + |
295 decompileExpr(ast.alternate, ast); | 293 decompileExpr(ast.alternate, ast); |
296 } | 294 } |
297 | 295 |
298 function decompileNewExpression(ast) { | 296 function decompileNewExpression(ast) { |
299 let str = "new " + decompileAST(ast.callee, ast) + "("; | 297 let str = "new " + decompileAST(ast.callee, ast) + "("; |
300 if (ast.arguments) | 298 if (ast.arguments) |
301 str += [decompileAST(arg) for each (arg in ast.arguments)].join(", "); | 299 str += ast.arguments.map(decompileAST).join(", "); |
302 str += ")"; | 300 str += ")"; |
303 return str; | 301 return str; |
304 } | 302 } |
305 | 303 |
306 function decompileCallExpression(ast) { | 304 function decompileCallExpression(ast) { |
307 return decompileExpr(ast.callee, ast) + "(" + | 305 return decompileExpr(ast.callee, ast) + "(" + |
308 [decompileAST(param) for each (param in ast.arguments)] + ")"; | 306 ast.arguments.map(decompileAST) + ")"; |
309 } | 307 } |
310 | 308 |
311 function decompileMemberExpression(ast) { | 309 function decompileMemberExpression(ast) { |
312 function isIdentifier(ast2) { | 310 function isIdentifier(ast2) { |
313 let val = decompileAST(ast2); | 311 let val = decompileAST(ast2); |
314 if (val.length == 0) return false; | 312 if (val.length == 0) return false; |
315 if (!(val[0] == '_' || val[0] == '$' || | 313 if (!(val[0] == '_' || val[0] == '$' || |
316 (val[0] >= 'a' && val[0] <= 'z') || (val[0] >= 'A' && val[0] <= 'Z'))) | 314 (val[0] >= 'a' && val[0] <= 'z') || (val[0] >= 'A' && val[0] <= 'Z'))) |
317 return false; | 315 return false; |
318 for (let i = 1; i < val.length; i++) { | 316 for (let i = 1; i < val.length; i++) { |
(...skipping 11 matching lines...) Expand all Loading... |
330 '["' + sanitize(decompileAST(ast.property), '"') + '"]' : | 328 '["' + sanitize(decompileAST(ast.property), '"') + '"]' : |
331 '.' + ast.property.name); | 329 '.' + ast.property.name); |
332 } | 330 } |
333 | 331 |
334 function decompileYieldExpression(ast) { | 332 function decompileYieldExpression(ast) { |
335 return "yield" + (ast.argument ? " " + decompileAST(ast.argument) : ""); | 333 return "yield" + (ast.argument ? " " + decompileAST(ast.argument) : ""); |
336 } | 334 } |
337 | 335 |
338 function decompileComprehensionExpression(ast, paren) { | 336 function decompileComprehensionExpression(ast, paren) { |
339 let str = (paren ? paren.l : "[") + decompileAST(ast.body); | 337 let str = (paren ? paren.l : "[") + decompileAST(ast.body); |
340 for each (let block in ast.blocks) { | 338 for (let block of ast.blocks) { |
341 str += (block.each ? " for each " : " for ") | 339 str += (block.each ? " for each " : " for "); |
342 str += "(" + decompileAST(block.left) + " in "; | 340 str += "(" + decompileAST(block.left) + " in "; |
343 str += decompileAST(block.right) + ")"; | 341 str += decompileAST(block.right) + ")"; |
344 } | 342 } |
345 if (ast.filter) | 343 if (ast.filter) |
346 str += " if (" + decompileAST(ast.filter) + ")"; | 344 str += " if (" + decompileAST(ast.filter) + ")"; |
347 return str + (paren ? paren.r : "]"); | 345 return str + (paren ? paren.r : "]"); |
348 } | 346 } |
349 | 347 |
350 function decompileGeneratorExpression(ast) { | 348 function decompileGeneratorExpression(ast) { |
351 return decompileComprehensionExpression(ast, {l: "(", r: ")"}); | 349 return decompileComprehensionExpression(ast, {l: "(", r: ")"}); |
352 } | 350 } |
353 | 351 |
354 function decompileGraphExpression(ast) { | 352 function decompileGraphExpression(ast) { |
355 return "#" + ast.index + "=" + decompileAST(ast.expression); | 353 return "#" + ast.index + "=" + decompileAST(ast.expression); |
356 } | 354 } |
357 | 355 |
358 function decompileGraphIndexExpression(ast) { | 356 function decompileGraphIndexExpression(ast) { |
359 return "#" + ast.index; | 357 return "#" + ast.index; |
360 } | 358 } |
361 | 359 |
362 function decompileLetExpression(ast) { | 360 function decompileLetExpression(ast) { |
363 return decompileLetStatement(ast); | 361 return decompileLetStatement(ast); |
364 } | 362 } |
365 | 363 |
366 /* Patterns */ | 364 /* Patterns */ |
367 | 365 |
368 function decompileObjectPattern(ast) { | 366 function decompileObjectPattern(ast) { |
369 let str = "{"; | 367 let str = "{"; |
370 str += [decompileAST(p.key) + ": " + decompileAST(p.value) | 368 str += ast.properties.map(p => decompileAST(p.key) + ": " + |
371 for each (p in ast.properties)].join(', '); | 369 decompileAST(p.value)).join(', '); |
372 return str + "}"; | 370 return str + "}"; |
373 } | 371 } |
374 | 372 |
375 function decompileArrayPattern(ast) { | 373 function decompileArrayPattern(ast) { |
376 return "[" + | 374 return "[" + ast.elements.map(e => e ? decompileAST(e) : ' ').join(', ') + "]"
; |
377 [e ? decompileAST(e) : ' ' for each (e in ast.elements)].join(', ') + "]"; | |
378 } | 375 } |
379 | 376 |
380 function decompileIdentifier(ast) { return ast.name; } | 377 function decompileIdentifier(ast) { return ast.name; } |
381 | 378 |
382 function sanitize(str, q) { | 379 function sanitize(str, q) { |
383 function replace(x) { | 380 function replace(x) { |
384 if (x == q) return '\\' + q; | 381 if (x == q) return '\\' + q; |
385 if (x == '\\') return '\\\\'; | 382 if (x == '\\') return '\\\\'; |
386 if (x == '\b') return '\\b'; | 383 if (x == '\b') return '\\b'; |
387 if (x == '\f') return '\\f'; | 384 if (x == '\f') return '\\f'; |
388 if (x == '\n') return '\\n'; | 385 if (x == '\n') return '\\n'; |
389 if (x == '\r') return '\\r'; | 386 if (x == '\r') return '\\r'; |
390 if (x == '\t') return '\\t'; | 387 if (x == '\t') return '\\t'; |
391 if (x == '\v') return '\\v'; | 388 if (x == '\v') return '\\v'; |
392 let val = x.charCodeAt(0) | 389 let val = x.charCodeAt(0); |
393 if (x < ' ') return '\\x' + (val - val % 16) / 16 + (val % 16); | 390 if (x < ' ') return '\\x' + (val - val % 16) / 16 + (val % 16); |
394 return x; | 391 return x; |
395 } | 392 } |
396 return [replace(x) for each (x in str)].join(''); | 393 let result = ""; |
| 394 for (let char of str) |
| 395 result += replace(char); |
| 396 return result; |
397 } | 397 } |
398 | 398 |
399 function decompileLiteral(ast) { | 399 function decompileLiteral(ast) { |
400 if (typeof ast.value == "string") | 400 if (typeof ast.value == "string") |
401 return '"' + sanitize(ast.value, '"') + '"'; | 401 return '"' + sanitize(ast.value, '"') + '"'; |
402 if (ast.value === null) | 402 if (ast.value === null) |
403 return "null"; | 403 return "null"; |
404 return ast.value; | 404 return ast.value; |
405 } | 405 } |
406 | 406 |
407 /* E4X */ | |
408 function decompileXMLDefaultDeclaration(ast) { | |
409 return "default xml namespace = " + decompileAST(ast.namespace) + ";"; | |
410 } | |
411 | |
412 function decompileXMLAnyName(ast) { | |
413 return "*"; | |
414 } | |
415 | |
416 function decompileXMLQualifiedIdentifier(ast) { | |
417 let str = decompileAST(ast.left) + "::"; | |
418 if (ast.computed) | |
419 str += "["; | |
420 str += decompileAST(ast.right); | |
421 if (ast.computed) | |
422 str += "]"; | |
423 return str; | |
424 } | |
425 | |
426 function decompileXMLFunctionQualifiedIdentifier(ast) { | |
427 let str = "function::"; | |
428 if (ast.computed) | |
429 str += "["; | |
430 str += decompileAST(ast.right); | |
431 if (ast.computed) | |
432 str += "]"; | |
433 return str; | |
434 } | |
435 | |
436 function decompileXMLAttributeSelector(ast) { | |
437 return "@" + decompileAST(ast.attribute); | |
438 } | |
439 | |
440 function decompileXMLFilterExpression(ast) { | |
441 return decompileAST(ast.left) + ".(" + decompileAST(ast.right) + ")"; | |
442 } | |
443 | |
444 function decompileXMLElement(ast) { | |
445 return [decompileAST(xml) for each (xml in ast.contents)].join(''); | |
446 } | |
447 | |
448 function decompileXMLList(ast) { | |
449 return "<>" + [decompileAST(xml) for each (xml in ast.contents)].join("") + "<
/>"; | |
450 } | |
451 | |
452 function decompileXMLEscape(ast) { | |
453 return "{" + decompileAST(ast.expression) + "}"; | |
454 } | |
455 | |
456 function decompileXMLText(ast) { | |
457 return ast.text; | |
458 } | |
459 | |
460 function tagJoin(strings) { | |
461 let str = strings[0]; | |
462 for (let i = 1; i < strings.length; i++) | |
463 str += (i % 2 ? ' ' : '=') + strings[i]; | |
464 return str; | |
465 } | |
466 | |
467 function decompileXMLStartTag(ast) { | |
468 return "<" + tagJoin([decompileAST(xml) for each (xml in ast.contents)]) + ">"
; | |
469 } | |
470 | |
471 function decompileXMLEndTag(ast) { | |
472 return "</" + tagJoin([decompileAST(xml) for each (xml in ast.contents)]) + ">
"; | |
473 } | |
474 | |
475 function decompileXMLPointTag(ast) { | |
476 return "<" + tagJoin([decompileAST(xml) for each (xml in ast.contents)]) + "/>
"; | |
477 } | |
478 | |
479 function decompileXMLName(ast) { | |
480 if (typeof ast.contents == "string") | |
481 return ast.contents + " "; | |
482 return [decompileAST(xml) for each (xml in ast.contents)].join(''); | |
483 } | |
484 | |
485 function decompileXMLAttribute(ast) { | |
486 return '"' + ast.value + '"'; | |
487 } | |
488 | |
489 function decompileXMLCdata(ast) { | |
490 return "<![CDATA[" + ast.contents + "]]>"; | |
491 } | |
492 | |
493 function decompileXMLComment(ast) { | |
494 return "<!--" + ast.comment + "-->"; | |
495 } | |
496 | |
497 function decompileXMLProcessingInstruction(ast) { | |
498 return "<?" + ast.target + (ast.contents ? " " + ast.contents : "") + "?>"; | |
499 } | |
500 | |
501 function process_js(ast) { | 407 function process_js(ast) { |
502 _print(decompileAST(ast)); | 408 _print(decompileAST(ast)); |
503 } | 409 } |
OLD | NEW |