aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIngvar Stepanyan <me@rreverser.com>2014-08-01 23:31:28 +0300
committerIngvar Stepanyan <me@rreverser.com>2014-08-01 23:45:37 +0300
commit87b72364a466e2dc065f88bbd0bd88c94b9e6519 (patch)
treec11dc12d9c83c44843e706b2c05e5d97ab1deaf3
parent0e3ff1f970b173dddc4f624a8935925ea4cfca3e (diff)
downloadtracifyjs-87b72364a466e2dc065f88bbd0bd88c94b9e6519.tar.gz
tracifyjs-87b72364a466e2dc065f88bbd0bd88c94b9e6519.zip
Fixes and improvements for UglifyJS->SM AST conversion.
* Explicitly forbidden multiple catch clauses as SM-specific feature. * Simplified describing of UglifyJS->Mozilla AST conversion rules. * Moved alias rules to single place. * Removed usage of dynamic type bindings in generated code (speed-up).
-rw-r--r--lib/mozilla-ast.js384
1 files changed, 203 insertions, 181 deletions
diff --git a/lib/mozilla-ast.js b/lib/mozilla-ast.js
index 2d35fb26..d1577308 100644
--- a/lib/mozilla-ast.js
+++ b/lib/mozilla-ast.js
@@ -62,11 +62,15 @@
});
},
TryStatement: function(M) {
+ var handlers = M.handlers || [M.handler];
+ if (handlers.length > 1 || M.guardedHandlers && M.guardedHandlers.length) {
+ throw new Error("Multiple catch clauses are not supported.");
+ }
return new AST_Try({
start : my_start_token(M),
end : my_end_token(M),
body : from_moz(M.block).body,
- bcatch : from_moz(M.handlers ? M.handlers[0] : M.handler),
+ bcatch : from_moz(handlers[0]),
bfinally : M.finalizer ? new AST_Finally(from_moz(M.finalizer)) : null
});
},
@@ -146,8 +150,6 @@
return new AST_RegExp(args);
}
},
- UnaryExpression: From_Moz_Unary,
- UpdateExpression: From_Moz_Unary,
Identifier: function(M) {
var p = FROM_MOZ_STACK[FROM_MOZ_STACK.length - 2];
return new ( p.type == "LabeledStatement" ? AST_Label
@@ -164,137 +166,8 @@
}
};
- AST_Directive.prototype.to_mozilla_ast = function() {
- return set_moz_loc(this, {
- type: "ExpressionStatement",
- expression: set_moz_loc(this, {
- type: "Literal",
- value: this.value
- })
- });
- };
-
- AST_SimpleStatement.prototype.to_mozilla_ast = function() {
- return set_moz_loc(this, {
- type: "ExpressionStatement",
- expression: to_moz(this.body)
- });
- };
-
- AST_SwitchBranch.prototype.to_mozilla_ast = function() {
- return set_moz_loc(this, {
- type: "SwitchCase",
- test: to_moz(this.expression),
- consequent: this.body.map(to_moz)
- });
- };
-
- AST_Try.prototype.to_mozilla_ast = function() {
- return set_moz_loc(this, {
- type: "TryStatement",
- block: {
- type: "BlockStatement",
- body: this.body.map(to_moz)
- },
- handler: to_moz(this.bcatch),
- finalizer: this.bfinally ? this.bfinally.body.map(to_moz) : null
- });
- };
-
- AST_Definitions.prototype.to_mozilla_ast = function() {
- return set_moz_loc(this, {
- type: "VariableDeclaration",
- kind: this instanceof AST_Const ? "const" : "var",
- declarations: this.definitions.map(to_moz)
- });
- };
-
- AST_Seq.prototype.to_mozilla_ast = function() {
- return set_moz_loc(this, {
- type: "SequenceExpression",
- expressions: this.to_array().map(to_moz)
- });
- };
-
- AST_PropAccess.prototype.to_mozilla_ast = function() {
- var isComputed = this instanceof AST_Sub;
- return set_moz_loc(this, {
- type: "MemberExpression",
- object: to_moz(this.expression),
- computed: isComputed,
- property: isComputed ? to_moz(this.property) : {type: "Identifier", name: this.property}
- });
- };
-
- AST_Unary.prototype.to_mozilla_ast = function() {
- return set_moz_loc(this, {
- type: this.operator == "++" || this.operator == "--" ? "UpdateExpression" : "UnaryExpression",
- operator: this.operator,
- prefix: this instanceof AST_UnaryPrefix,
- argument: to_moz(this.argument)
- });
- };
-
- AST_Object.prototype.to_mozilla_ast = function() {
- return set_moz_loc(this, {
- type: "ObjectExpression",
- properties: this.properties.map(to_moz)
- });
- };
-
- AST_ObjectProperty.prototype.to_mozilla_ast = function() {
- var key;
- if (is_identifier_string(this.key) && !RESERVED_WORDS(this.key)) {
- key = {type: "Identifier", name: this.key};
- } else {
- key = {type: "Literal", value: this.key};
- }
- var kind;
- if (this instanceof AST_ObjectKeyVal) {
- kind = "init";
- } else
- if (this instanceof AST_ObjectGetter) {
- kind = "get";
- } else
- if (this instanceof AST_ObjectSetter) {
- kind = "set";
- }
- return set_moz_loc(this, {
- type: "Property",
- kind: kind,
- key: key,
- value: to_moz(this.value)
- });
- };
-
- AST_Symbol.prototype.to_mozilla_ast = function() {
- return set_moz_loc(this, {
- type: "Identifier",
- name: this.name
- });
- };
-
- AST_Null.prototype.to_mozilla_ast =
- AST_Boolean.prototype.to_mozilla_ast =
- AST_Constant.prototype.to_mozilla_ast = function() {
- return set_moz_loc(this, {
- type: "Literal",
- value: this.value
- });
- };
-
- AST_Atom.prototype.to_mozilla_ast = function() {
- return set_moz_loc(this, {
- type: "Identifier",
- name: String(this.value)
- });
- };
-
- AST_Hole.prototype.to_mozilla_ast = function() {
- return null;
- };
-
- function From_Moz_Unary(M) {
+ MOZ_TO_ME.UpdateExpression =
+ MOZ_TO_ME.UnaryExpression = function To_Moz_Unary(M) {
var prefix = "prefix" in M ? M.prefix
: M.type == "UnaryExpression" ? true : false;
return new (prefix ? AST_UnaryPrefix : AST_UnaryPostfix)({
@@ -335,16 +208,152 @@
map("NewExpression", AST_New, "callee>expression, arguments@args");
map("CallExpression", AST_Call, "callee>expression, arguments@args");
- AST_Accessor.prototype.to_mozilla_ast = AST_Function.prototype.to_mozilla_ast;
+ def_to_moz(AST_Directive, function To_Moz_Directive(M) {
+ return {
+ type: "ExpressionStatement",
+ expression: {
+ type: "Literal",
+ value: M.value
+ }
+ };
+ });
- AST_Binary.prototype.to_mozilla_ast = function () {
+ def_to_moz(AST_SimpleStatement, function To_Moz_ExpressionStatement(M) {
return {
- type: this.operator == "&&" || this.operator == "||" ? "LogicalExpression" : "BinaryExpression",
- left: to_moz(this.left),
- operator: this.operator,
- right: to_moz(this.right)
+ type: "ExpressionStatement",
+ expression: to_moz(M.body)
};
- };
+ });
+
+ def_to_moz(AST_SwitchBranch, function To_Moz_SwitchCase(M) {
+ return {
+ type: "SwitchCase",
+ test: to_moz(M.expression),
+ consequent: M.body.map(to_moz)
+ };
+ });
+
+ def_to_moz(AST_Try, function To_Moz_TryStatement(M) {
+ return {
+ type: "TryStatement",
+ block: to_moz_block(M),
+ handler: to_moz(M.bcatch),
+ guardedHandlers: [],
+ finalizer: to_moz(M.bfinally)
+ };
+ });
+
+ def_to_moz(AST_Catch, function To_Moz_CatchClause(M) {
+ return {
+ type: "CatchClause",
+ param: to_moz(M.argname),
+ guard: null,
+ body: to_moz_block(M)
+ };
+ });
+
+ def_to_moz(AST_Definitions, function To_Moz_VariableDeclaration(M) {
+ return {
+ type: "VariableDeclaration",
+ kind: M instanceof AST_Const ? "const" : "var",
+ declarations: M.definitions.map(to_moz)
+ };
+ });
+
+ def_to_moz(AST_Seq, function To_Moz_SequenceExpression(M) {
+ return {
+ type: "SequenceExpression",
+ expressions: M.to_array().map(to_moz)
+ };
+ });
+
+ def_to_moz(AST_PropAccess, function To_Moz_MemberExpression(M) {
+ var isComputed = M instanceof AST_Sub;
+ return {
+ type: "MemberExpression",
+ object: to_moz(M.expression),
+ computed: isComputed,
+ property: isComputed ? to_moz(M.property) : {type: "Identifier", name: M.property}
+ };
+ });
+
+ def_to_moz(AST_Unary, function To_Moz_Unary(M) {
+ return {
+ type: M.operator == "++" || M.operator == "--" ? "UpdateExpression" : "UnaryExpression",
+ operator: M.operator,
+ prefix: M instanceof AST_UnaryPrefix,
+ argument: to_moz(M.argument)
+ };
+ });
+
+ def_to_moz(AST_Binary, function To_Moz_BinaryExpression(M) {
+ return {
+ type: M.operator == "&&" || M.operator == "||" ? "LogicalExpression" : "BinaryExpression",
+ left: to_moz(M.left),
+ operator: M.operator,
+ right: to_moz(M.right)
+ };
+ });
+
+ def_to_moz(AST_Object, function To_Moz_ObjectExpression(M) {
+ return {
+ type: "ObjectExpression",
+ properties: M.properties.map(to_moz)
+ };
+ });
+
+ def_to_moz(AST_ObjectProperty, function To_Moz_Property(M) {
+ var key;
+ if (is_identifier_string(M.key) && !RESERVED_WORDS(M.key)) {
+ key = {type: "Identifier", name: M.key};
+ } else {
+ key = {type: "Literal", value: M.key};
+ }
+ var kind;
+ if (M instanceof AST_ObjectKeyVal) {
+ kind = "init";
+ } else
+ if (M instanceof AST_ObjectGetter) {
+ kind = "get";
+ } else
+ if (M instanceof AST_ObjectSetter) {
+ kind = "set";
+ }
+ return {
+ type: "Property",
+ kind: kind,
+ key: key,
+ value: to_moz(M.value)
+ };
+ });
+
+ def_to_moz(AST_Symbol, function To_Moz_Identifier(M) {
+ return {
+ type: "Identifier",
+ name: M.name
+ };
+ });
+
+ def_to_moz(AST_Constant, function To_Moz_Literal(M) {
+ return {
+ type: "Literal",
+ value: M.value
+ };
+ });
+
+ def_to_moz(AST_Atom, function To_Moz_Atom(M) {
+ return {
+ type: "Identifier",
+ name: String(M.value)
+ };
+ });
+
+ AST_Boolean.DEFMETHOD("to_mozilla_ast", AST_Constant.prototype.to_mozilla_ast);
+ AST_Null.DEFMETHOD("to_mozilla_ast", AST_Constant.prototype.to_mozilla_ast);
+ AST_Hole.DEFMETHOD("to_mozilla_ast", function To_Moz_ArrayHole() { return null });
+
+ AST_Block.DEFMETHOD("to_mozilla_ast", AST_BlockStatement.prototype.to_mozilla_ast);
+ AST_Lambda.DEFMETHOD("to_mozilla_ast", AST_Function.prototype.to_mozilla_ast);
/* -----[ tools ]----- */
@@ -372,40 +381,15 @@
});
};
- function moz_sub_loc(token) {
- return token.line ? {
- line: token.line,
- column: token.col
- } : null;
- };
-
- function set_moz_loc(mynode, moznode) {
- var start = mynode.start;
- var end = mynode.end;
- if (start.pos != null && end.pos != null) {
- moznode.range = [start.pos, end.pos];
- }
- if (start.line) {
- moznode.loc = {
- start: moz_sub_loc(start),
- end: moz_sub_loc(end)
- };
- if (start.file) {
- moznode.loc.source = start.file;
- }
- }
- return moznode;
- };
-
function map(moztype, mytype, propmap) {
var moz_to_me = "function From_Moz_" + moztype + "(M){\n";
- moz_to_me += "return new mytype({\n" +
+ moz_to_me += "return new " + mytype.name + "({\n" +
"start: my_start_token(M),\n" +
"end: my_end_token(M)";
- var me_to_moz = "function To_Moz_" + moztype + "(){\n";
- me_to_moz += "return set_moz_loc(this, {\n" +
- "type: moztype";
+ var me_to_moz = "function To_Moz_" + moztype + "(M){\n";
+ me_to_moz += "return {\n" +
+ "type: " + JSON.stringify(moztype);
if (propmap) propmap.split(/\s*,\s*/).forEach(function(prop){
var m = /([a-z0-9$_]+)(=|@|>|%)([a-z0-9$_]+)/i.exec(prop);
@@ -416,19 +400,19 @@
switch (how) {
case "@":
moz_to_me += "M." + moz + ".map(from_moz)";
- me_to_moz += "this." + my + ".map(to_moz)";
+ me_to_moz += "M." + my + ".map(to_moz)";
break;
case ">":
moz_to_me += "from_moz(M." + moz + ")";
- me_to_moz += "to_moz(this." + my + ")";
+ me_to_moz += "to_moz(M." + my + ")";
break;
case "=":
moz_to_me += "M." + moz;
- me_to_moz += "this." + my;
+ me_to_moz += "M." + my;
break;
case "%":
moz_to_me += "from_moz(M." + moz + ").body";
- me_to_moz += "{type: \"BlockStatement\", body: this." + my + ".map(to_moz)}";
+ me_to_moz += "to_moz_block(M)";
break;
default:
throw new Error("Can't understand operator in propmap: " + prop);
@@ -436,23 +420,23 @@
});
moz_to_me += "\n})\n}";
- me_to_moz += "\n})\n}";
+ me_to_moz += "\n}\n}";
moz_to_me = parse(moz_to_me).print_to_string({ beautify: true });
me_to_moz = parse(me_to_moz).print_to_string({ beautify: true });
//console.log(moz_to_me);
- moz_to_me = new Function("mytype", "my_start_token", "my_end_token", "from_moz", "return(" + moz_to_me + ")")(
- mytype, my_start_token, my_end_token, from_moz
+ moz_to_me = new Function("my_start_token", "my_end_token", "from_moz", "return(" + moz_to_me + ")")(
+ my_start_token, my_end_token, from_moz
);
- me_to_moz = new Function("moztype", "set_moz_loc", "to_moz", "return(" + me_to_moz + ")")(
- moztype, set_moz_loc, to_moz
+ me_to_moz = new Function("to_moz", "to_moz_block", "return(" + me_to_moz + ")")(
+ to_moz, to_moz_block
);
MOZ_TO_ME[moztype] = moz_to_me;
- mytype.prototype.to_mozilla_ast = me_to_moz;
+ def_to_moz(mytype, me_to_moz);
};
- var FROM_MOZ_STACK = null, TO_MOZ_STACK = null;
+ var FROM_MOZ_STACK = null;
function from_moz(node) {
FROM_MOZ_STACK.push(node);
@@ -469,8 +453,46 @@
return ast;
};
+ function moz_sub_loc(token) {
+ return token.line ? {
+ line: token.line,
+ column: token.col
+ } : null;
+ };
+
+ function set_moz_loc(mynode, moznode) {
+ var start = mynode.start;
+ var end = mynode.end;
+ if (start.pos != null && end.pos != null) {
+ moznode.range = [start.pos, end.pos];
+ }
+ if (start.line) {
+ moznode.loc = {
+ start: moz_sub_loc(start),
+ end: moz_sub_loc(end)
+ };
+ if (start.file) {
+ moznode.loc.source = start.file;
+ }
+ }
+ return moznode;
+ };
+
+ function def_to_moz(mytype, handler) {
+ mytype.DEFMETHOD("to_mozilla_ast", function() {
+ return set_moz_loc(this, handler(this));
+ });
+ };
+
function to_moz(node) {
return node != null ? node.to_mozilla_ast() : null;
};
+ function to_moz_block(node) {
+ return {
+ type: "BlockStatement",
+ body: node.body.map(to_moz)
+ };
+ };
+
})();