aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/mozilla-ast.js81
-rw-r--r--test/mocha/spidermonkey.js91
2 files changed, 160 insertions, 12 deletions
diff --git a/lib/mozilla-ast.js b/lib/mozilla-ast.js
index 34332215..12b55dc5 100644
--- a/lib/mozilla-ast.js
+++ b/lib/mozilla-ast.js
@@ -45,20 +45,55 @@
(function(){
- var MOZ_TO_ME = {
- ExpressionStatement: function(M) {
- var expr = M.expression;
- if (expr.type === "Literal" && typeof expr.value === "string") {
- return new AST_Directive({
- start: my_start_token(M),
- end: my_end_token(M),
- value: expr.value
+ var normalize_directives = function(body) {
+ var in_directive = true;
+
+ for (var i = 0; i < body.length; i++) {
+ if (in_directive && body[i] instanceof AST_Statement && body[i].body instanceof AST_String) {
+ body[i] = new AST_Directive({
+ start: body[i].start,
+ end: body[i].end,
+ value: body[i].body.value
});
+ } else if (in_directive && !(body[i] instanceof AST_Statement && body[i].body instanceof AST_String)) {
+ in_directive = false;
}
+ }
+
+ return body;
+ };
+
+ var MOZ_TO_ME = {
+ Program: function(M) {
+ return new AST_Toplevel({
+ start: my_start_token(M),
+ end: my_end_token(M),
+ body: normalize_directives(M.body.map(from_moz))
+ });
+ },
+ FunctionDeclaration: function(M) {
+ return new AST_Defun({
+ start: my_start_token(M),
+ end: my_end_token(M),
+ name: from_moz(M.id),
+ argnames: M.params.map(from_moz),
+ body: normalize_directives(from_moz(M.body).body)
+ });
+ },
+ FunctionExpression: function(M) {
+ return new AST_Function({
+ start: my_start_token(M),
+ end: my_end_token(M),
+ name: from_moz(M.id),
+ argnames: M.params.map(from_moz),
+ body: normalize_directives(from_moz(M.body).body)
+ });
+ },
+ ExpressionStatement: function(M) {
return new AST_SimpleStatement({
start: my_start_token(M),
end: my_end_token(M),
- body: from_moz(expr)
+ body: from_moz(M.expression)
});
},
TryStatement: function(M) {
@@ -194,7 +229,6 @@
});
};
- map("Program", AST_Toplevel, "body@body");
map("EmptyStatement", AST_EmptyStatement);
map("BlockStatement", AST_BlockStatement, "body@body");
map("IfStatement", AST_If, "test>condition, consequent>body, alternate>alternative");
@@ -210,12 +244,10 @@
map("ForStatement", AST_For, "init>init, test>condition, update>step, body>body");
map("ForInStatement", AST_ForIn, "left>init, right>object, body>body");
map("DebuggerStatement", AST_Debugger);
- map("FunctionDeclaration", AST_Defun, "id>name, params@argnames, body%body");
map("VariableDeclarator", AST_VarDef, "id>name, init>value");
map("CatchClause", AST_Catch, "param>argname, body%body");
map("ThisExpression", AST_This);
- map("FunctionExpression", AST_Function, "id>name, params@argnames, body%body");
map("BinaryExpression", AST_Binary, "operator=operator, left>left, right>right");
map("LogicalExpression", AST_Binary, "operator=operator, left>left, right>right");
map("AssignmentExpression", AST_Assign, "operator=operator, left>left, right>right");
@@ -223,6 +255,31 @@
map("NewExpression", AST_New, "callee>expression, arguments@args");
map("CallExpression", AST_Call, "callee>expression, arguments@args");
+ def_to_moz(AST_Toplevel, function To_Moz_Program(M) {
+ return {
+ type: "Program",
+ body: M.body.map(to_moz)
+ };
+ });
+
+ def_to_moz(AST_Defun, function To_Moz_FunctionDeclaration(M) {
+ return {
+ type: "FunctionDeclaration",
+ id: to_moz(M.name),
+ params: M.argnames.map(to_moz),
+ body: to_moz_block(M)
+ }
+ });
+
+ def_to_moz(AST_Function, function To_Moz_FunctionExpression(M) {
+ return {
+ type: "FunctionExpression",
+ id: to_moz(M.name),
+ params: M.argnames.map(to_moz),
+ body: to_moz_block(M)
+ }
+ });
+
def_to_moz(AST_Directive, function To_Moz_Directive(M) {
return {
type: "ExpressionStatement",
diff --git a/test/mocha/spidermonkey.js b/test/mocha/spidermonkey.js
index f507ad1f..c1294525 100644
--- a/test/mocha/spidermonkey.js
+++ b/test/mocha/spidermonkey.js
@@ -1,5 +1,6 @@
var assert = require("assert");
var exec = require("child_process").exec;
+var uglify = require("../../");
describe("spidermonkey export/import sanity test", function() {
it("should produce a functional build when using --self with spidermonkey", function (done) {
@@ -30,4 +31,94 @@ describe("spidermonkey export/import sanity test", function() {
done();
});
});
+
+ it("Should judge between directives and strings correctly on import", function() {
+ var tests = [
+ {
+ input: '"use strict";;"use sloppy"',
+ directives: 1,
+ strings: 1
+ },
+ {
+ input: ';"use strict"',
+ directives: 0,
+ strings: 1
+ },
+ {
+ input: '"use strict"; "use something else";',
+ directives: 2,
+ strings: 0
+ },
+ {
+ input: 'function foo() {"use strict";;"use sloppy" }',
+ directives: 1,
+ strings: 1
+ },
+ {
+ input: 'function foo() {;"use strict" }',
+ directives: 0,
+ strings: 1
+ },
+ {
+ input: 'function foo() {"use strict"; "use something else"; }',
+ directives: 2,
+ strings: 0
+ },
+ {
+ input: 'var foo = function() {"use strict";;"use sloppy" }',
+ directives: 1,
+ strings: 1
+ },
+ {
+ input: 'var foo = function() {;"use strict" }',
+ directives: 0,
+ strings: 1
+ },
+ {
+ input: 'var foo = function() {"use strict"; "use something else"; }',
+ directives: 2,
+ strings: 0
+ },
+ {
+ input: '{"use strict";;"use sloppy" }',
+ directives: 0,
+ strings: 2
+ },
+ {
+ input: '{;"use strict" }',
+ directives: 0,
+ strings: 1
+ },
+ {
+ input: '{"use strict"; "use something else"; }',
+ directives: 0,
+ strings: 2
+ }
+ ];
+
+ var counter_directives;
+ var counter_strings;
+
+ var checkWalker = new uglify.TreeWalker(function(node, descend) {
+ if (node instanceof uglify.AST_String) {
+ counter_strings++;
+ } else if (node instanceof uglify.AST_Directive) {
+ counter_directives++;
+ }
+ });
+
+ for (var i = 0; i < tests.length; i++) {
+ counter_directives = 0;
+ counter_strings = 0;
+
+ var ast = uglify.parse(tests[i].input);
+ var moz_ast = ast.to_mozilla_ast();
+ var from_moz_ast = uglify.AST_Node.from_mozilla_ast(moz_ast);
+
+ from_moz_ast.walk(checkWalker);
+
+ assert.strictEqual(counter_directives, tests[i].directives, "Directives count mismatch for test " + tests[i].input);
+ assert.strictEqual(counter_strings, tests[i].strings, "String count mismatch for test " + tests[i].input);
+ }
+ });
});