diff options
author | Alex Lam S.L <alexlamsl@gmail.com> | 2017-05-15 02:37:53 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-05-15 02:37:53 +0800 |
commit | e005099fb1b9a1b87ac50ba8223255e52cec452d (patch) | |
tree | 5edef6298d3c79fc5352476c2fbfc236b626a9ee /test/mozilla-ast.js | |
parent | 504a436e9daac89f5226280e01ae2818fe4e8436 (diff) | |
download | tracifyjs-e005099fb1b9a1b87ac50ba8223255e52cec452d.tar.gz tracifyjs-e005099fb1b9a1b87ac50ba8223255e52cec452d.zip |
fix & improve coverage of `estree` (#1935)
- fix `estree` conversion of getter/setter
- fix non-directive literal in `to_mozilla_ast()`
- revamp `test/mozilla-ast.js`
- reuse `test/ufuzz.js` for code generation
- use `acorn.parse()` for creating `estree`
- extend `test/ufuzz.js` for `acorn` workaround
- catch variable redefinition
- non-trivial literal as directive
- adjust options for tolerance
Miscellaneous
- optional semi-colon when parsing directives
fixes #1914
closes #1915
Diffstat (limited to 'test/mozilla-ast.js')
-rw-r--r-- | test/mozilla-ast.js | 160 |
1 files changed, 65 insertions, 95 deletions
diff --git a/test/mozilla-ast.js b/test/mozilla-ast.js index 544ce8bc..b8026de5 100644 --- a/test/mozilla-ast.js +++ b/test/mozilla-ast.js @@ -1,103 +1,73 @@ // Testing UglifyJS <-> SpiderMonkey AST conversion -// through generative testing. - -var UglifyJS = require("./node"), - escodegen = require("escodegen"), - esfuzz = require("esfuzz"), - estraverse = require("estraverse"), - prefix = "\r "; - -// Normalizes input AST for UglifyJS in order to get correct comparison. - -function normalizeInput(ast) { - return estraverse.replace(ast, { - enter: function(node, parent) { - switch (node.type) { - // Internally mark all the properties with semi-standard type "Property". - case "ObjectExpression": - node.properties.forEach(function (property) { - property.type = "Property"; - }); - break; - - // Since UglifyJS doesn"t recognize different types of property keys, - // decision on SpiderMonkey node type is based on check whether key - // can be valid identifier or not - so we do in input AST. - case "Property": - var key = node.key; - if (key.type === "Literal" && typeof key.value === "string" && UglifyJS.is_identifier(key.value)) { - node.key = { - type: "Identifier", - name: key.value - }; - } else if (key.type === "Identifier" && !UglifyJS.is_identifier(key.name)) { - node.key = { - type: "Literal", - value: key.name - }; - } - break; - - // UglifyJS internally flattens all the expression sequences - either - // to one element (if sequence contains only one element) or flat list. - case "SequenceExpression": - node.expressions = node.expressions.reduce(function flatten(list, expr) { - return list.concat(expr.type === "SequenceExpression" ? expr.expressions.reduce(flatten, []) : [expr]); - }, []); - if (node.expressions.length === 1) { - return node.expressions[0]; - } - break; - } +"use strict"; + +var acorn = require("acorn"); +var ufuzz = require("./ufuzz"); +var UglifyJS = require(".."); + +function try_beautify(code) { + var beautified = UglifyJS.minify(code, { + compress: false, + mangle: false, + output: { + beautify: true, + bracketize: true } }); + if (beautified.error) { + console.log("// !!! beautify failed !!!"); + console.log(beautified.error.stack); + console.log(code); + } else { + console.log("// (beautified)"); + console.log(beautified.code); + } } -module.exports = function(options) { - console.log("--- UglifyJS <-> Mozilla AST conversion"); - - for (var counter = 0; counter < options.iterations; counter++) { - process.stdout.write(prefix + counter + "/" + options.iterations); - - var ast1 = normalizeInput(esfuzz.generate({ - maxDepth: options.maxDepth - })); - - var ast2 = - UglifyJS - .AST_Node - .from_mozilla_ast(ast1) - .to_mozilla_ast(); - - var astPair = [ - {name: 'expected', value: ast1}, - {name: 'actual', value: ast2} - ]; - - var jsPair = astPair.map(function(item) { - return { - name: item.name, - value: escodegen.generate(item.value) - } - }); - - if (jsPair[0].value !== jsPair[1].value) { - var fs = require("fs"); - var acorn = require("acorn"); - - fs.existsSync("tmp") || fs.mkdirSync("tmp"); - - jsPair.forEach(function (item) { - var fileName = "tmp/dump_" + item.name; - var ast = acorn.parse(item.value); - fs.writeFileSync(fileName + ".js", item.value); - fs.writeFileSync(fileName + ".json", JSON.stringify(ast, null, 2)); - }); - - process.stdout.write("\n"); - throw new Error("Got different outputs, check out tmp/dump_*.{js,json} for codes and ASTs."); +function test(original, estree, description) { + var transformed = UglifyJS.minify(UglifyJS.AST_Node.from_mozilla_ast(estree), { + compress: false, + mangle: false + }); + if (transformed.error || original !== transformed.code) { + console.log("//============================================================="); + console.log("// !!!!!! Failed... round", round); + console.log("// original code"); + try_beautify(original); + console.log(); + console.log(); + console.log("//-------------------------------------------------------------"); + console.log("//", description); + if (transformed.error) { + console.log(transformed.error.stack); + } else { + try_beautify(transformed.code); } + console.log("!!!!!! Failed... round", round); + process.exit(1); } +} - process.stdout.write(prefix + "Probability of error is less than " + (100 / options.iterations) + "%, stopping.\n"); -}; +var num_iterations = ufuzz.num_iterations; +for (var round = 1; round <= num_iterations; round++) { + process.stdout.write(round + " of " + num_iterations + "\r"); + var code = ufuzz.createTopLevelCode(); + var uglified = UglifyJS.minify(code, { + compress: false, + mangle: false, + output: { + ast: true + } + }); + test(uglified.code, uglified.ast.to_mozilla_ast(), "AST_Node.to_mozilla_ast()"); + try { + test(uglified.code, acorn.parse(code), "acorn.parse()"); + } catch (e) { + console.log("//============================================================="); + console.log("// acorn parser failed... round", round); + console.log(e); + console.log("// original code"); + console.log(code); + } +} +console.log(); |