Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Delta Between Two Patch Sets: scripts/decompile.js

Issue 29350140: Issue 4353 - Remove non standard for each syntax (Closed)
Left Patch Set: Created Aug. 24, 2016, 11:08 a.m.
Right Patch Set: Removed unused code Created Aug. 24, 2016, 2:40 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « scripts/basic.js ('k') | scripts/doxygen.js » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 // Decompile a JS file. This will be painful.
Wladimir Palant 2016/08/24 14:21:50 I don't consider it a good measure to modify files
kzar 2016/08/24 14:43:20 Done.
2 include("../utils/dumpast.js");
3 include("../utils/astml.js");
4
5 let visitor = {
6 _visitArray: function (arr, pre, post, comma) {
7 if (pre === undefined) pre = '(';
8 if (post === undefined) post = ')';
9 if (comma === undefined) comma = ', ';
10 output(pre);
11 for (let arg of arr) {
12 arg.visit(this);
13 output(comma);
14 }
15 if (arr.length > 0)
16 unwrite(comma.length);
17 output(post);
18 },
19 _visitMaybeBlock: function (body) {
20 if (body.type == "BlockStatement") {
21 output(" ");
22 body.visit(this);
23 } else {
24 flush().indent();
25 body.visit(this);
26 unindent();
27 }
28 },
29 _visitNeedBlock: function (stmt, noFlush) {
30 if (stmt.type == "EmptyStatement") {
31 output("{}");
32 if (!noFlush)
33 flush();
34 }
35 else if (stmt.type == "ReturnStatement") {
36 output("{").flush().indent();
37 stmt.visit(this);
38 unindent().output("}");
39 if (!noFlush)
40 flush();
41 }
42 else
43 stmt.visit(this);
44 },
45 visitProgram: function (program) {},
46 visitFunctionDeclaration: function (func) {
47 output("function ");
48 if (func.name)
49 output(func.name);
50 this._visitArray(func.arguments, '(', ') ');
51 this._visitNeedBlock(func.body, true);
52 return true;
53 },
54 visitParameter: function (p) {
55 output(p.name);
56 },
57 visitBlockStatement: function (stmt) {
58 output("{").flush().indent();
59 },
60 postvisitBlockStatement: function (stmt) {
61 output("}").unindent().flush();
62 },
63 visitVarStatement: function (stmt) {
64 output(stmt.vartype).output(" ");
65 this._visitArray(stmt.variables, '', '');
66 if (!this._noFlush)
67 output(';').flush();
68 this._noFlush = false;
69 return true;
70 },
71 visitVarDeclaration: function (decl) {
72 output(decl.name);
73 if ("initializer" in decl)
74 output(" = ");
75 },
76 visitLetStatement: function (stmt) {
77 output("let ");
78 this._visitArray(stmt.variables, '(', ')');
79 if (!this._noFlush)
80 output(';').flush();
81 this._noFlush = false;
82 return true;
83 },
84 visitExpressionStatement: function (stmt) {},
85 postvisitExpressionStatement: function (stmt) {
86 output(";").flush();
87 },
88 visitEmptyStatement: function (stmt) { output(";").flush(); },
89 visitIfStatement: function (stmt) {
90 output("if (");
91 stmt.cond.visit(this);
92 output(")");
93 this._visitMaybeBlock(stmt.body);
94 if (stmt.elsebody) {
95 output(" else");
96 this._visitMaybeBlock(stmt.elsebody);
97 }
98 return true;
99 },
100 visitDoWhileStatement: function (stmt) {
101 output("do");
102 this._visitMaybeBlock(stmt.body);
103 output("while (");
104 stmt.cond.visit(this);
105 output(");").flush();
106 return true;
107 },
108 visitWhileStatement: function (stmt) {
109 output("while (");
110 stmt.cond.visit(this);
111 output(")");
112 this._visitMaybeBlock(stmt.body);
113 return true;
114 },
115 visitForStatement: function (stmt) {
116 output("for (");
117 stmt.init.visit(this);
118 stmt.cond.visit(this);
119 if (stmt.cond.type != "EmptyStatement")
120 output("; ");
121 stmt.inc.visit(this);
122 output(")");
123 this._visitMaybeBlock(stmt.body);
124 return true;
125 },
126 visitForInStatement: function (stmt) {
127 output(stmt.itertype).output(" (");
128 this._noFlush = true;
129 stmt.itervar.visit(this);
130 output(" in ");
131 stmt.iterrange.visit(this);
132 output(")");
133 this._visitMaybeBlock(stmt.body);
134 return true;
135 },
136 visitContinueStatement: function (stmt) {
137 output("continue");
138 if ("label" in stmt)
139 output(" ").output(stmt.label);
140 output(";").flush();
141 },
142 visitBreakStatement: function (stmt) {
143 output("break");
144 if ("label" in stmt)
145 output(" ").output(stmt.label);
146 output(";").flush();
147 },
148 visitReturnStatement: function (stmt) { output("return "); },
149 postvisitReturnStatement: function (stmt) { output(";").flush(); },
150 visitWithStatement: function (stmt) {
151 output("with (");
152 stmt.variable.visit(this);
153 output(")");
154 this._visitMaybeBlock(stmt.body);
155 return true;
156 },
157 visitLabeledStatement: function (stmt) { output(stmt.label).output(": "); },
158 visitSwitchStatement: function (stmt) {
159 output("switch (");
160 stmt.expr.visit(this);
161 output(") {").flush().indent();
162 this._visitArray(stmt.cases, '', '', '');
163 output("}").unindent().flush();
164 return true;
165 },
166 visitSwitchCase: function (stmt) {
167 if ("expr" in stmt) {
168 output("case ");
169 stmt.expr.visit(this);
170 output(": ");
171 } else
172 output("default: ");
173 stmt.body.visit(this);
174 return true;
175 },
176 visitThrowStatement: function (stmt) { output("throw "); },
177 postvisitThrowStatement: function (stmt) { output(";").flush(); },
178 visitTryStatement: function (stmt) {
179 output("try ");
180 this._visitNeedBlock(stmt.body);
181 this._visitArray(stmt.catchers, '', '', '\n' + indentStr);
182 if (stmt.fin) {
183 output("finally ");
184 this._visitNeedBlock(stmt.fin);
185 }
186 return true;
187 },
188 visitCatchStatement: function (stmt) {
189 output("catch (");
190 stmt.variable.visit(this);
191 if ("cond" in stmt) {
192 output(" if ");
193 stmt.cond.visit(this);
194 }
195 output(")");
196 this._visitNeedBlock(stmt.body);
197 return true;
198 },
199 visitDebuggerStatement: function (stmt) { output("debugger;").flush(); },
200
201 visitThisExpression: function (expr) { output("this"); },
202 visitMemberExpression: function (expr) {
203 let needparen = expr.precedence + 1 < expr.container.precedence;
204 if (needparen)
205 output("(");
206 expr.container.visit(this);
207 if (needparen)
208 output(")");
209
210 if ("constmember" in expr && /^[_a-zA-Z]\w*$/.test(expr.constmember))
211 output(".").output(expr.constmember);
212 else {
213 output("[");
214 expr.member.visit(this);
215 output("]");
216 }
217 return true;
218 },
219 visitNewExpression: function (expr) {
220 let needparen = expr.precedence < expr.constructor.precedence;
221 output("new ");
222 if (needparen)
223 output("(");
224 expr.constructor.visit(this);
225 if (needparen)
226 output(")");
227 this._visitArray(expr.arguments);
228 return true;
229 },
230 visitCallExpression: function (expr) {
231 let needparen = expr.precedence < expr.func.precedence;
232 if (needparen)
233 output("(");
234 expr.func.visit(this);
235 if (needparen)
236 output(")");
237 this._visitArray(expr.arguments);
238 return true;
239 },
240 visitLiteralExpression: function (expr) {
241 switch (expr.objtype) {
242 case "string":
243 output('"').output(sanitize(expr.value, '"')).output('"');
244 break;
245 case "number":
246 case "boolean":
247 case "regex":
248 output(expr.value.toString());
249 break;
250 case "null":
251 output("null");
252 break;
253 default:
254 throw "Unknown literal " + expr.objtype;
255 };
256 },
257 visitObjectLiteral: function (obj) {
258 output('{').flush().indent();
259 this._visitArray(obj.setters, '', '', ',\n' + indentStr);
260 flush().output('}').unindent();
261 return true;
262 },
263 visitPropertyLiteral: function (prop) {
264 if ("proptype" in prop) {
265 if (prop.value.type == "LiteralExpression") {
266 prop.property.visit(this);
267 output(" ").output(prop.proptype).output(": ");
268 prop.value.visit(this);
269 return true;
270 }
271 if (prop.proptype == "getter")
272 output("get ");
273 else if (prop.proptype == "setter")
274 output("set ");
275 else
276 throw "Unknown type: " + prop.proptype;
277 prop.property.visit(this);
278 if (prop.value.type != "FunctionDeclaration")
279 throw "Expection function, found: " + prop.value.type;
280 if (prop.value.name) {
281 output(" ").output(prop.value.name);
282 }
283 this._visitArray(prop.value.arguments, '(', ') ');
284 this._visitNeedBlock(prop.value.body, true);
285 return true;
286 }
287 prop.property.visit(this);
288 output(": ");
289 prop.value.visit(this);
290 return true;
291 },
292 visitArrayLiteral: function (arr) {
293 this._visitArray(arr.members, '[', ']', ', ');
294 return true;
295 },
296 visitArrayComprehensionExpression: function (arrcomp) {
297 output('[');
298 let enp = arrcomp.element.precedence > 16;
299 if (enp)
300 output("(");
301 arrcomp.element.visit(this);
302 if (enp)
303 output(")");
304 output(" ").output(arrcomp.itertype).output("(");
305 arrcomp.itervar.visit(this);
306 output(" in ");
307 arrcomp.iterrange.visit(this);
308 output(")");
309 if ("iterif" in arrcomp) {
310 output(" if (");
311 arrcomp.iterif.visit(this);
312 output(")");
313 }
314 output("]");
315 return true;
316 },
317 visitIdentifierExpression: function (expr) {
318 output(expr.name);
319 if ("initializer" in expr) {
320 output(" = ");
321 expr.initializer.visit(this);
322 return true;
323 }
324 },
325 visitPostfixExpression: function (expr) {},
326 postvisitPostfixExpression: function (expr) {
327 output(expr.operator);
328 },
329 visitUnaryExpression: function (expr) {
330 if (expr.operator != '()') {
331 output(expr.operator);
332 if (expr.operator.length > 1)
333 output(" ");
334 }
335 let np = expr.precedence < expr.operand.precedence;
336 if (expr.operator == '()' || np) {
337 output("(");
338 expr.operand.visit(this);
339 output(")");
340 return true;
341 }
342 },
343 visitBinaryExpression: function (expr) {
344 let lhp = expr.precedence < expr.lhs.precedence;
345 let rhp = expr.precedence < expr.rhs.precedence;
346 if (lhp)
347 output("(");
348 expr.lhs.visit(this);
349 if (lhp)
350 output(")");
351 output(" ").output(expr.operator).output(" ");
352 if (rhp)
353 output("(");
354 expr.rhs.visit(this);
355 if (rhp)
356 output(")");
357 return true;
358 },
359 visitConditionalExpression: function (expr) {
360 let lhp = expr.precedence < expr.cond.precedence;
361 let mhp = expr.precedence < expr.iftrue.precedence;
362 let rhp = expr.precedence < expr.iffalse.precedence;
363 if (lhp)
364 output("(");
365 expr.cond.visit(this);
366 if (lhp)
367 output(")");
368 output(" ? ");
369 if (mhp)
370 output("(");
371 expr.iftrue.visit(this);
372 if (mhp)
373 output(")");
374 output(" : ");
375 if (rhp)
376 output("(");
377 expr.iffalse.visit(this);
378 if (rhp)
379 output(")");
380 return true;
381 },
382 visitAssignmentExpression: function (expr) {
383 let lhp = expr.precedence < expr.lhs.precedence;
384 let rhp = expr.precedence < expr.rhs.precedence;
385 if (lhp)
386 output("(");
387 expr.lhs.visit(this);
388 if (lhp)
389 output(")");
390 output(" ").output(expr.operator).output("= ");
391 if (rhp)
392 output("(");
393 expr.rhs.visit(this);
394 if (rhp)
395 output(")");
396 return true;
397 },
398 };
399
400 /* Reminder */
401 for (let f in structure) {
402 if (!("visit" + f in visitor))
403 throw "Please visit " + f;
404 }
405
406 function process_js(ast) {
407 if (!ast)
408 return;
409 ast = makeAST(ast);
410 walkAST(ast, visitor);
411 }
412
413 /* Output functions */
414 let buffer = "", indentStr = "";
415 function output(str) {
416 buffer += str;
417 return global;
418 }
419 function unwrite(numChars) {
420 buffer = buffer.substring(0, buffer.length - numChars);
421 return global;
422 }
423 function flush() {
424 _print(buffer);
425 buffer = indentStr;
426 return global;
427 }
428 function indent() {
429 indentStr += " ";
430 buffer = " " + buffer;
431 return global;
432 }
433 function unindent() {
434 indentStr = indentStr.substring(2);
435 buffer = buffer.substring(2);
436 return global;
437 }
438
439 function sanitize(str, q) {
440 function replace(x) {
441 if (x == q) return '\\' + q;
442 if (x == '\\') return '\\\\';
443 if (x == '\b') return '\\b';
444 if (x == '\f') return '\\f';
445 if (x == '\n') return '\\n';
446 if (x == '\r') return '\\r';
447 if (x == '\t') return '\\t';
448 if (x == '\v') return '\\v';
449 let val = x.charCodeAt(0);
450 if (x < ' ') return '\\x' + (val - val % 16) / 16 + (val % 16);
451 return x;
452 }
453
454 let result = "";
455 for (let char of str)
456 result += replace(char);
457 return result;
458 }
LEFTRIGHT

Powered by Google App Engine
This is Rietveld