From da295de82bfa9e1df39f45ee54e8e11ecce5dfb2 Mon Sep 17 00:00:00 2001 From: "Alex Lam S.L" Date: Mon, 8 May 2017 06:23:01 +0800 Subject: [PATCH] support dumping AST (#1879) Re-order `AST_Binary` properties to make dump more readable. closes #769 --- README.md | 5 +++-- bin/uglifyjs | 33 ++++++++++++++++++++++++++++++--- lib/ast.js | 2 +- test/mocha/cli.js | 11 +++++++++++ 4 files changed, 45 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 3ad072cf..d2343728 100644 --- a/README.md +++ b/README.md @@ -95,8 +95,9 @@ The available options are: `wrap_iife` Wrap IIFEs in parenthesis. Note: you may want to disable `negate_iife` under compressor options. - -o, --output Output file (default STDOUT). Specify "spidermonkey" - to dump SpiderMonkey AST format (as JSON) to STDOUT. + -o, --output Output file path (default STDOUT). Specify `ast` or + `spidermonkey` to write UglifyJS or SpiderMonkey AST + as JSON to STDOUT respectively. --comments [filter] Preserve copyright comments in the output. By default this works like Google Closure, keeping JSDoc-style comments that contain "@license" or diff --git a/bin/uglifyjs b/bin/uglifyjs index b67eb6ba..5fa81f3b 100755 --- a/bin/uglifyjs +++ b/bin/uglifyjs @@ -15,6 +15,7 @@ var path = require("path"); var program = require("commander"); var UglifyJS = require("../tools/node"); +var skip_keys = [ "cname", "enclosed", "parent_scope", "scope", "thedef", "uses_eval", "uses_with" ]; var files = {}; var options = { compress: false, @@ -107,6 +108,12 @@ if (program.nameCache) { } } } +if (program.output == "ast") { + options.output = { + ast: true, + code: false + }; +} if (program.parse) { if (program.parse.acorn || program.parse.spidermonkey) { if (program.sourceMap) fatal("ERROR: inline source map only works with built-in parser"); @@ -211,7 +218,23 @@ function run() { } fatal("ERROR: " + ex.message); } - if (program.output == "spidermonkey") { + if (program.output == "ast") { + console.log(JSON.stringify(result.ast, function(key, value) { + if (skip_key(key)) return; + if (value instanceof UglifyJS.AST_Token) return; + if (value instanceof UglifyJS.Dictionary) return; + if (value instanceof UglifyJS.AST_Node) { + var result = { + _class: "AST_" + value.TYPE + }; + value.CTOR.PROPS.forEach(function(prop) { + result[prop] = value[prop]; + }); + return result; + } + return value; + }, 2)); + } else if (program.output == "spidermonkey") { console.log(JSON.stringify(UglifyJS.minify(result.code, { compress: false, mangle: false, @@ -237,8 +260,8 @@ function run() { } function fatal(message) { - console.error(message); - process.exit(1); + console.error(message); + process.exit(1); } // A file glob function that only supports "*" and "?" wildcards in the basename. @@ -352,3 +375,7 @@ function to_cache(key) { } return cache[key]; } + +function skip_key(key) { + return skip_keys.indexOf(key) >= 0; +} diff --git a/lib/ast.js b/lib/ast.js index e61a31e5..962c8f7b 100644 --- a/lib/ast.js +++ b/lib/ast.js @@ -619,7 +619,7 @@ var AST_UnaryPostfix = DEFNODE("UnaryPostfix", null, { $documentation: "Unary postfix expression, i.e. `i++`" }, AST_Unary); -var AST_Binary = DEFNODE("Binary", "left operator right", { +var AST_Binary = DEFNODE("Binary", "operator left right", { $documentation: "Binary expression, i.e. `a + b`", $propdoc: { left: "[AST_Node] left-hand side expression", diff --git a/test/mocha/cli.js b/test/mocha/cli.js index cac920d3..8c7964ac 100644 --- a/test/mocha/cli.js +++ b/test/mocha/cli.js @@ -509,4 +509,15 @@ describe("bin/uglifyjs", function () { return JSON.stringify(map).replace(/"/g, '\\"'); } }); + it("Should dump AST as JSON", function(done) { + var command = uglifyjscmd + " test/input/global_defs/simple.js -mco ast"; + exec(command, function (err, stdout) { + if (err) throw err; + + var ast = JSON.parse(stdout); + assert.strictEqual(ast._class, "AST_Toplevel"); + assert.ok(Array.isArray(ast.body)); + done(); + }); + }); }); -- 2.34.1