diff options
-rw-r--r-- | lib/mozilla-ast.js | 81 | ||||
-rw-r--r-- | test/mocha/spidermonkey.js | 91 |
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); + } + }); }); |