[Pkg-mozext-commits] [adblock-plus] 124/464: True AST decompiler, and a more forceful check script.
David Prévot
taffit at moszumanska.debian.org
Tue Jul 22 20:44:09 UTC 2014
This is an automated email from the git hooks/post-receive script.
taffit pushed a commit to branch master
in repository adblock-plus.
commit ca88e3060aaff2be98f7921cfafb13c0e699a576
Author: Joshua Cranmer <Pidgeot18 at gmail.com>
Date: Wed Jan 12 22:54:58 2011 -0500
True AST decompiler, and a more forceful check script.
---
Makefile | 13 +-
check.py | 19 ++
jshydra_bridge.cpp | 1 +
scripts/astDecompile.js | 486 ++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 514 insertions(+), 5 deletions(-)
diff --git a/Makefile b/Makefile
index 1a55d31..c752c9b 100644
--- a/Makefile
+++ b/Makefile
@@ -47,11 +47,14 @@ echo-variable-%:
@echo "$($*)"
full-check:: jshydra$(BIN_SUFFIX)
- @cp -R $(MOZ_SRCDIR)/js/src/tests jstest
+ @cp -R $(srcdir)/tests jstest
+ @cp check.py jstest
@echo "Decompiling JS ASTs.."
- set -e; \
- for f in $$(find jstest -name '*.js'); do \
+ @set -e; \
+ for f in $$(cd jstest && python check.py | grep -v '^warning:'); do \
echo $$f; \
- ./jshydra$(BIN_SUFFIX) scripts/astDecompile.js --trueast "$(MOZ_SRCDIR)/js/src/tests$${f#jstest}" >$$f; \
+ ./jshydra$(BIN_SUFFIX) scripts/astDecompile.js --trueast "$(srcdir)/tests/$$f" >jstest/$$f; \
done
- #python jstest/jstests.py --tinderbox fake_js.sh
+ python $(srcdir)/tests/jstest.py --tinderbox $(objdir)/js > before.log
+ python jstest/jstests.py --tinderbox $(objdir)/js > after.log
+ diff before.log after.log
diff --git a/check.py b/check.py
new file mode 100644
index 0000000..4c4bdb5
--- /dev/null
+++ b/check.py
@@ -0,0 +1,19 @@
+#!/usr/bin/python
+
+banned = ["js1_5/Regress/regress-31255.js",
+ "js1_5/Regress/regress-351515.js",
+ "js1_5/Regress/regress-89443.js",
+ "js1_5/Regress/regress-98901.js",
+ "js1_8/regress/regress-366941.js",
+ "js1_8/regress/regress-459185.js",
+ "js1_8_1/regress/regress-452498-052.js",
+ "js1_8_1/regress/regress-452498-053.js",
+ "js1_8_1/regress/regress-452498-098.js",
+ "js1_8_1/regress/regress-452498-117.js"]
+
+import manifest
+xul_tester = manifest.NullXULInfoTester()
+test_list = manifest.parse('jstests.list', xul_tester)
+for test in test_list:
+ if test.enable and test.path[-5:] != '-n.js' and test.path not in banned:
+ print test.path
diff --git a/jshydra_bridge.cpp b/jshydra_bridge.cpp
index cc7fdbe..ecaab81 100644
--- a/jshydra_bridge.cpp
+++ b/jshydra_bridge.cpp
@@ -67,6 +67,7 @@ void jshydra_init(const char *file) {
rt = JS_NewRuntime (0x9000000L);
cx = JS_NewContext (rt, 8192);
JS_BeginRequest(cx);
+ JS_SetVersion(cx, JSVERSION_LATEST);
//JS_SetGCZeal(cx, 2);
//JS_SetContextPrivate (this->cx, this);
diff --git a/scripts/astDecompile.js b/scripts/astDecompile.js
new file mode 100644
index 0000000..02dce1e
--- /dev/null
+++ b/scripts/astDecompile.js
@@ -0,0 +1,486 @@
+let global = this;
+function decompileAST(ast) {
+ let func = global["decompile" + ast.type];
+ if (!func)
+ throw "Unknown type " + ast.type;
+ return func(ast);
+}
+
+function decompileProgram(ast) {
+ return [decompileAST(stmt) for each (stmt in ast.body)].join('\n');
+}
+
+/* Statements */
+function decompileEmptyStatement(ast) {
+ return ";"
+}
+function decompileBlockStatement(ast) {
+ return '{\n' + [decompileAST(stmt) for each (stmt in ast.body)].join('\n') +
+ '\n}\n';
+}
+
+function decompileExpressionStatement(ast) {
+ return decompileAST(ast.expression) + ";";
+}
+
+function decompileIfStatement(ast) {
+ let str = "if (" + decompileAST(ast.test) + ")\n";
+ str += decompileAST(ast.consequent);
+ if (ast.alternate)
+ str += " else\n" + decompileAST(ast.alternate);
+ return str;
+}
+
+function decompileLabeledStatement(ast) {
+ return ast.label.name + ": " + decompileAST(ast.body);
+}
+
+function decompileBreakStatement(ast) {
+ return "break" + (ast.label ? " " + ast.label.name : "") + ";";
+}
+
+function decompileContinueStatement(ast) {
+ return "continue" + (ast.label ? " " + ast.label.name : "") + ";";
+}
+
+function decompileWithStatement(ast) {
+ return "with (" + decompileAST(ast.object) + ") " + decompileAST(ast.body);
+}
+
+function decompileSwitchStatement(ast) {
+ let str = "switch (" + decompileAST(ast.discriminant) + ") {\n";
+ let cases = [];
+ for each (let scase in ast.cases) {
+ let casestr = scase.test ? "case " + decompileAST(scase.test) : "default";
+ casestr += ":\n";
+ casestr += [decompileAST(stmt) for each (stmt in scase.consequent)]
+ .join('\n');
+ cases.push(casestr);
+ }
+ str += cases.join('\n') + '\n}\n';
+ return str;
+}
+
+function decompileReturnStatement(ast) {
+ return "return" + (ast.argument ? " " + decompileAST(ast.argument) :
+ "") + ";";
+}
+
+function decompileThrowStatement(ast) {
+ return "throw " + decompileAST(ast.argument);
+}
+
+function decompileTryStatement(ast) {
+ let str = "try " + decompileAST(ast.block);
+
+ let handlers = [];
+ if (ast.handler && "type" in ast.handler)
+ handlers.push(ast.handler);
+ else if (ast.handler)
+ handlers = ast.handler;
+
+ let handler_strs = [];
+ for each (let handler in handlers) {
+ let handler_str = "catch (" + decompileAST(handler.param);
+ if (handler.guard)
+ handler_str += " if " + decompileAST(handler.guard);
+ handler_str += ") " + decompileAST(handler.body);
+ handler_strs.push(handler_str);
+ }
+ str += handler_strs.join("");
+ if (ast.finalizer)
+ str += " finally " + decompileAST(ast.finalizer);
+ return str;
+}
+
+function decompileWhileStatement(ast) {
+ return "while (" + decompileAST(ast.test) + ") " + decompileAST(ast.body);
+}
+
+function decompileDoWhileStatement(ast) {
+ return "do " + decompileAST(ast.body) + " while (" + decompileAST(ast.test) + ");";
+}
+
+function decompileForStatement(ast) {
+ let str = "for (";
+ if (ast.init) {
+ if (ast.init.type == "VariableDeclaration")
+ str += decompileAST(ast.init);
+ else
+ str += decompileAST(ast.init) + ";";
+ } else {
+ str += ";";
+ }
+ if (ast.test)
+ str += decompileAST(ast.test);
+ str += ";";
+ if (ast.update)
+ str += decompileAST(ast.update);
+ str += ") ";
+ return str + decompileAST(ast.body);
+}
+
+function decompileForInStatement(ast) {
+ let str = "for";
+ if (ast.each)
+ str += " each";
+ str += "(";
+ if (ast.left.type == "VariableDeclaration")
+ str += decompileVariableDeclaration(ast.left, true);
+ else
+ str += decompileAST(ast.left);
+ str += " in " + decompileExpr(ast.right, ast) + ") ";
+ str += decompileAST(ast.body);
+ return str;
+}
+
+function decompileLetStatement(ast) {
+ let str = "let (";
+ str += [d ? decompileAST(d) : ' ' for each (d in ast.head)].join(', ');
+ str += ") " + decompileAST(ast.body);
+ return str;
+}
+
+function decompileDebuggerStatement(ast) {
+ return "debugger;";
+}
+
+function decompileFunctionDeclaration(ast, init, name_ast) {
+ let str = (init ? init : "function") + " ";
+ if (ast.id)
+ str += ast.id.name;
+ else if (name_ast)
+ str += decompileAST(name_ast);
+ str += "(";
+ str += [decompileAST(param) for each (param in ast.params)].join(', ');
+ str += ") " + decompileAST(ast.body);
+ return str;
+}
+
+function decompileVariableDeclaration(ast, excludeSemi) {
+ let inits = [];
+ for each (let initializer in ast.declarations) {
+ inits.push(decompileAST(initializer));
+ }
+ return ast.kind + " " + inits.join(', ') + (excludeSemi ? "" : ";");
+}
+
+function decompileVariableDeclarator(ast) {
+ if (ast.init)
+ return ast.id.name + " = " + decompileAST(ast.init);
+ return ast.id.name;
+}
+
+/* Expressions */
+let precedence = {
+ "FunctionExpression": 0,
+ "YieldExpression": 1,
+ "SequenceExpression": 2,
+ "AssignmentExpression": 3,
+ "ConditionalExpression": 4,
+ "||": 5,
+ "&&": 6,
+ "|": 7,
+ "^": 8,
+ "&": 9,
+ "==": 10, "!=": 10, "===": 10, "!==": 10,
+ "<=": 11, ">=": 11, "<": 11, ">": 11, "in": 11,
+ "<<": 12, ">>": 12, ">>>": 12,
+ "+": 13, "-": 13,
+ "*": 14, "/": 14, "%": 14,
+ "UnaryExpression": 15,
+ "UpdateExpression": 16,
+ "NewExpression": 17,
+ "CallExpression": 18, "MemberExpression": 18
+ /* Everything else is 19 */
+};
+
+function getPrecedence(expr) {
+ if (expr.type in precedence)
+ return precedence[expr.type];
+ else if (expr.operator && expr.operator in precedence)
+ return precedence[expr.operator];
+ return 19;
+}
+
+function decompileExpr(expr, par) {
+ if (getPrecedence(expr) < getPrecedence(par))
+ return "(" + decompileAST(expr) + ")";
+ else
+ return decompileAST(expr);
+}
+
+function decompileThisExpression(ast) {
+ return "this";
+}
+
+function decompileArrayExpression(ast) {
+ if (ast.elements)
+ return "[" + [el ? decompileAST(el) : "" for each (el in ast.elements)].
+ join(", ") + "]";
+ return "[]";
+}
+
+function decompileObjectExpression(ast) {
+ let props = [];
+ for each (let prop in ast.properties) {
+ if (prop.kind == "init")
+ props.push(decompileAST(prop.key) + ": " + decompileAST(prop.value));
+ else if (prop.kind == "get" || prop.kind == "set")
+ props.push(decompileFunctionDeclaration(prop.value, prop.kind, prop.key));
+ else
+ throw "Unknown kind " + prop.kind;
+ }
+ return "{\n" + props.join(",\n") + "}";
+}
+
+function decompileFunctionExpression(ast) {
+ return decompileFunctionDeclaration(ast);
+}
+
+function decompileSequenceExpression(ast) {
+ return "(" + [decompileExpr(e, ast) for each (e in ast.expressions)].join(", ") + ")";
+}
+
+function decompileUnaryExpression(ast) {
+ if (ast.prefix)
+ return ast.operator + " " + decompileExpr(ast.argument, ast);
+ throw "ER, wtf?";
+}
+
+function decompileBinaryExpression(ast) {
+ return decompileExpr(ast.left, ast) + " " + ast.operator +
+ " " + decompileExpr(ast.right, ast);
+}
+
+function decompileAssignmentExpression(ast) {
+ return decompileExpr(ast.left, ast) + " " + ast.operator +
+ " " + decompileExpr(ast.right, ast);
+}
+
+function decompileUpdateExpression(ast) {
+ let before = "", after = ast.operator;
+ if (ast.prefix) {
+ before = after;
+ after = "";
+ }
+ return before + decompileExpr(ast.argument, ast) + after;
+}
+
+function decompileLogicalExpression(ast) {
+ return decompileExpr(ast.left, ast) + " " + ast.operator +
+ " " + decompileExpr(ast.right, ast);
+}
+
+function decompileConditionalExpression(ast) {
+ return decompileExpr(ast.test, ast) + " ? " +
+ decompileExpr(ast.consequent, ast) + " : " +
+ decompileExpr(ast.alternate, ast);
+}
+
+function decompileNewExpression(ast) {
+ let str = "new " + decompileAST(ast.callee, ast) + "(";
+ if (ast.arguments)
+ str += [decompileAST(arg) for each (arg in ast.arguments)].join(", ");
+ str += ")";
+ return str;
+}
+
+function decompileCallExpression(ast) {
+ return decompileExpr(ast.callee, ast) + "(" +
+ [decompileAST(param) for each (param in ast.arguments)] + ")";
+}
+
+function decompileMemberExpression(ast) {
+ function isIdentifier(ast2) {
+ let val = decompileAST(ast2);
+ if (val.length == 0) return false;
+ if (!(val[0] == '_' || val[0] == '$' ||
+ (val[0] >= 'a' && val[0] <= 'z') || (val[0] >= 'A' && val[0] <= 'Z')))
+ return false;
+ for (let i = 1; i < val.length; i++) {
+ if (!(val[i] == '_' || val[i] == '$' ||
+ (val[i] >= 'a' && val[i] <= 'z') ||
+ (val[i] >= 'A' && val[i] <= 'Z') ||
+ (val[i] >= '0' && val[i] <= '9')))
+ return false;
+ }
+ return true;
+ }
+ return decompileExpr(ast.object, ast) +
+ (ast.computed ? '[' + decompileAST(ast.property) + ']' :
+ !isIdentifier(ast.property) ?
+ '["' + sanitize(decompileAST(ast.property), '"') + '"]' :
+ '.' + ast.property.name);
+}
+
+function decompileYieldExpression(ast) {
+ return "yield" + (ast.argument ? " " + decompileAST(ast.argument) : "");
+}
+
+function decompileComprehensionExpression(ast, paren) {
+ let str = (paren ? paren.l : "[") + decompileAST(ast.body);
+ for each (let block in ast.blocks) {
+ str += (block.each ? " for each " : " for ")
+ str += "(" + decompileAST(block.left) + " in ";
+ str += decompileAST(block.right) + ")";
+ }
+ if (ast.filter)
+ str += " if (" + decompileAST(ast.filter) + ")";
+ return str + (paren ? paren.r : "]");
+}
+
+function decompileGeneratorExpression(ast) {
+ return decompileComprehensionExpression(ast, {l: "(", r: ")"});
+}
+
+function decompileGraphExpression(ast) {
+ return "#" + ast.index + "=" + decompileAST(ast.expression);
+}
+
+function decompileGraphIndexExpression(ast) {
+ return "#" + ast.index;
+}
+
+function decompileLetExpression(ast) {
+ return decompileLetStatement(ast);
+}
+
+/* Patterns */
+
+function decompileObjectPattern(ast) {
+ let str = "{";
+ str += [decompileAST(p.key) + ": " + decompileAST(p.value)
+ for each (p in ast.properties)].join(', ');
+ return str + "}";
+}
+
+function decompileArrayPattern(ast) {
+ return "[" +
+ [e ? decompileAST(e) : ' ' for each (e in ast.elements)].join(', ') + "]";
+}
+
+function decompileIdentifier(ast) { return ast.name; }
+
+function sanitize(str, q) {
+ function replace(x) {
+ if (x == q) return '\\' + q;
+ if (x == '\\') return '\\\\';
+ if (x == '\b') return '\\b';
+ if (x == '\f') return '\\f';
+ if (x == '\n') return '\\n';
+ if (x == '\r') return '\\r';
+ if (x == '\t') return '\\t';
+ if (x == '\v') return '\\v';
+ let val = x.charCodeAt(0)
+ if (x < ' ') return '\\x' + (val - val % 16) / 16 + (val % 16);
+ return x;
+ }
+ return [replace(x) for each (x in str)].join('');
+}
+
+function decompileLiteral(ast) {
+ if (typeof ast.value == "string")
+ return '"' + sanitize(ast.value, '"') + '"';
+ if (ast.value === null)
+ return "null";
+ return ast.value;
+}
+
+/* E4X */
+function decompileXMLDefaultDeclaration(ast) {
+ return "default xml namespace = " + decompileAST(ast.namespace) + ";";
+}
+
+function decompileXMLAnyName(ast) {
+ return "*";
+}
+
+function decompileXMLQualifiedIdentifier(ast) {
+ let str = decompileAST(ast.left) + "::";
+ if (ast.computed)
+ str += "[";
+ str += decompileAST(ast.right);
+ if (ast.computed)
+ str += "]";
+ return str;
+}
+
+function decompileXMLFunctionQualifiedIdentifier(ast) {
+ let str = "function::";
+ if (ast.computed)
+ str += "[";
+ str += decompileAST(ast.right);
+ if (ast.computed)
+ str += "]";
+ return str;
+}
+
+function decompileXMLAttributeSelector(ast) {
+ return "@" + decompileAST(ast.attribute);
+}
+
+function decompileXMLFilterExpression(ast) {
+ return decompileAST(ast.left) + ".(" + decompileAST(ast.right) + ")";
+}
+
+function decompileXMLElement(ast) {
+ return [decompileAST(xml) for each (xml in ast.contents)].join('');
+}
+
+function decompileXMLList(ast) {
+ return "<>" + [decompileAST(xml) for each (xml in ast.contents)].join("") + "</>";
+}
+
+function decompileXMLEscape(ast) {
+ return "{" + decompileAST(ast.expression) + "}";
+}
+
+function decompileXMLText(ast) {
+ return ast.text;
+}
+
+function tagJoin(strings) {
+ let str = strings[0];
+ for (let i = 1; i < strings.length; i++)
+ str += (i % 2 ? ' ' : '=') + strings[i];
+ return str;
+}
+
+function decompileXMLStartTag(ast) {
+ return "<" + tagJoin([decompileAST(xml) for each (xml in ast.contents)]) + ">";
+}
+
+function decompileXMLEndTag(ast) {
+ return "</" + tagJoin([decompileAST(xml) for each (xml in ast.contents)]) + ">";
+}
+
+function decompileXMLPointTag(ast) {
+ return "<" + tagJoin([decompileAST(xml) for each (xml in ast.contents)]) + "/>";
+}
+
+function decompileXMLName(ast) {
+ if (typeof ast.contents == "string")
+ return ast.contents + " ";
+ return [decompileAST(xml) for each (xml in ast.contents)].join('');
+}
+
+function decompileXMLAttribute(ast) {
+ return '"' + ast.value + '"';
+}
+
+function decompileXMLCdata(ast) {
+ return "<![CDATA[" + ast.contents + "]]>";
+}
+
+function decompileXMLComment(ast) {
+ return "<!--" + ast.comment + "-->";
+}
+
+function decompileXMLProcessingInstruction(ast) {
+ return "<?" + ast.target + (ast.contents ? " " + ast.contents : "") + "?>";
+}
+
+function process_js(ast) {
+ _print(decompileAST(ast));
+}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-mozext/adblock-plus.git
More information about the Pkg-mozext-commits
mailing list