From 76d88b59dcd28b836b2cdaf7908bfd5acaa88ebc Mon Sep 17 00:00:00 2001 From: Mihai Bazon Date: Sat, 22 Sep 2012 13:32:32 +0300 Subject: [PATCH] tree transformer api (WIP) --- lib/compress.js | 8 +- lib/transform.js | 226 +++++++++++++++++++++++++++++++++++++++++++++++ tmp/test-node.js | 34 +++++-- tools/node.js | 1 + 4 files changed, 253 insertions(+), 16 deletions(-) create mode 100644 lib/transform.js diff --git a/lib/compress.js b/lib/compress.js index 5b0e06a0..6813925e 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -1014,6 +1014,7 @@ function Compressor(options, false_by_default) { self = self.clone(); self.expression = self.expression.squeeze(compressor); self.body = self.body.squeeze(compressor); + return self; }); SQUEEZE(AST_Exit, function(self, compressor){ @@ -1569,13 +1570,6 @@ function Compressor(options, false_by_default) { return self; }); - SQUEEZE(AST_Assign, function(self, compressor){ - self = self.clone(); - self.left = self.left.squeeze(compressor); - self.right = self.right.squeeze(compressor); - return self.optimize(compressor); - }); - SQUEEZE(AST_SymbolRef, function(self, compressor){ return self.optimize(compressor); }); diff --git a/lib/transform.js b/lib/transform.js new file mode 100644 index 00000000..743dd6e7 --- /dev/null +++ b/lib/transform.js @@ -0,0 +1,226 @@ +/*********************************************************************** + + A JavaScript tokenizer / parser / beautifier / compressor. + https://github.com/mishoo/UglifyJS2 + + -------------------------------- (C) --------------------------------- + + Author: Mihai Bazon + + http://mihai.bazon.net/blog + + Distributed under the BSD license: + + Copyright 2012 (c) Mihai Bazon + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above + copyright notice, this list of conditions and the following + disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + ***********************************************************************/ + +// Tree transformer helpers. +// XXX: eventually I should refactor the compressor to use this infrastructure. + +function TreeTransformer(before, after) { + this.before = before; + this.after = after; + this.stack = []; +} + +TreeTransformer.prototype = { + push: function (node) { + this.stack.push(node); + }, + pop: function() { + return this.stack.pop(); + }, + parent: function (n) { + return this.stack[this.stack.length - 2 - (n || 0)]; + } +}; + +(function(undefined){ + + function _(node, descend) { + node.DEFMETHOD("transform", function(tw, in_list){ + var x, y; + tw.push(this); + x = tw.before(this, function(){ + descend(x, tw); + }, in_list); + if (x === undefined) { + x = this.clone(); + descend(x, tw); + y = tw.after(this, in_list); + if (y !== undefined) x = y; + } + tw.pop(); + return x; + }); + }; + + function do_list(list, tw) { + return MAP(list, function(node){ + return node.transform(tw, true); + }); + }; + + _(AST_Node, noop); + + _(AST_LabeledStatement, function(self, tw){ + self.label = self.label.transform(tw); + self.body = self.body.transform(tw); + }); + + _(AST_SimpleStatement, function(self, tw){ + self.body = self.body.transform(tw); + }); + + _(AST_BlockStatement, function(self, tw){ + self.body = do_list(self.body, tw); + }); + + _(AST_Block, function(self, tw){ + self.body = do_list(self.body, tw); + }); + + _(AST_DWLoop, function(self, tw){ + self.condition = self.condition.transform(tw); + self.body = self.body.transform(tw); + }); + + _(AST_For, function(self, tw){ + if (self.init) self.init = self.init.transform(tw); + if (self.condition) self.condition = self.condition.transform(tw); + if (self.step) self.step = self.step.transform(tw); + self.body = self.body.transform(tw); + }); + + _(AST_ForIn, function(self, tw){ + self.init = self.init.transform(tw); + self.object = self.object.transform(tw); + self.body = self.body.transform(tw); + }); + + _(AST_With, function(self, tw){ + self.expression = self.expression.transform(tw); + self.body = self.body.transform(tw); + }); + + _(AST_Exit, function(self, tw){ + if (self.value) self.value = self.value.transform(tw); + }); + + _(AST_LoopControl, function(self, tw){ + if (self.label) self.label = self.label.transform(tw); + }); + + _(AST_If, function(self, tw){ + self.condition = self.condition.transform(tw); + self.body = self.body.transform(tw); + if (self.alternative) self.alternative = self.alternative.transform(tw); + }); + + _(AST_Switch, function(self, tw){ + self.expression = self.expression.transform(tw); + self.body = self.body.transform(tw); + }); + + _(AST_Case, function(self, tw){ + self.expression = self.expression.transform(tw); + self.body = do_list(self.body, tw); + }); + + _(AST_Try, function(self, tw){ + self.body = do_list(self.body, tw); + }); + + _(AST_Catch, function(self, tw){ + self.argname = self.argname.transform(tw); + self.body = do_list(self.body, tw); + }); + + _(AST_Definitions, function(self, tw){ + self.definitions = do_list(self.definitions, tw); + }); + + _(AST_VarDef, function(self, tw){ + if (self.value) self.value = self.value.transform(tw); + }); + + _(AST_Lambda, function(self, tw){ + if (self.name) self.name = self.name.transform(tw); + self.argnames = do_list(self.argnames, tw); + self.body = do_list(self.body, tw); + }); + + _(AST_Call, function(self, tw){ + self.expression = self.expression.transform(tw); + self.args = do_list(self.args, tw); + }); + + _(AST_Seq, function(self, tw){ + self.car = self.car.transform(tw); + self.cdr = self.cdr.transform(tw); + }); + + _(AST_Dot, function(self, tw){ + self.expression = self.expression.transform(tw); + }); + + _(AST_Sub, function(self, tw){ + self.expression = self.expression.transform(tw); + self.property = self.property.transform(tw); + }); + + _(AST_Unary, function(self, tw){ + self.expression = self.expression.transform(tw); + }); + + _(AST_Binary, function(self, tw){ + self.left = self.left.transform(tw); + self.right = self.right.transform(tw); + }); + + _(AST_Conditional, function(self, tw){ + self.condition = self.condition.transform(tw); + self.consequent = self.consequent.transform(tw); + self.alternative = self.alternative.transform(tw); + }); + + _(AST_Array, function(self, tw){ + self.elements = do_list(self.elements, tw); + }); + + _(AST_Object, function(self, tw){ + self.properties = do_list(self.properties, tw); + }); + + _(AST_ObjectProperty, function(self, tw){ + self.value = self.value.transform(tw); + }); + +})(); diff --git a/tmp/test-node.js b/tmp/test-node.js index fdabafbf..f2e0626b 100755 --- a/tmp/test-node.js +++ b/tmp/test-node.js @@ -9,15 +9,31 @@ var filename = process.argv[2]; var code = fs.readFileSync(filename, "utf8"); var ast = UglifyJS.parse(code); -ast.figure_out_scope(); -ast = ast.squeeze(UglifyJS.Compressor()); -ast.compute_char_frequency(); -UglifyJS.base54.sort(); +var tt = new UglifyJS.TreeTransformer( + function before(node, descend) { + if (node instanceof UglifyJS.AST_Var) { + //return new UglifyJS.AST_EmptyStatement(node); + return UglifyJS.MAP.skip; + } + }, + function after(node) { + console.log("After ", node.TYPE); + } +); -ast.figure_out_scope(); -ast.scope_warnings(); -ast.mangle_names(); +var x = ast.transform(tt); +sys.print(x.print_to_string({ beautify: true })); -sys.error(UglifyJS.base54.get()); -sys.print(ast.print_to_string({ beautify: true })); +// ast.figure_out_scope(); +// ast = ast.squeeze(UglifyJS.Compressor()); + +// ast.compute_char_frequency(); +// UglifyJS.base54.sort(); + +// ast.figure_out_scope(); +// ast.scope_warnings(); +// ast.mangle_names(); + +// sys.error(UglifyJS.base54.get()); +// sys.print(ast.print_to_string({ beautify: true })); diff --git a/tools/node.js b/tools/node.js index c8d3bd8c..0185d045 100644 --- a/tools/node.js +++ b/tools/node.js @@ -26,6 +26,7 @@ function load_global(file) { load_global("../lib/utils.js"); load_global("../lib/ast.js"); load_global("../lib/parse.js"); +load_global("../lib/transform.js"); load_global("../lib/scope.js"); load_global("../lib/output.js"); load_global("../lib/compress.js"); -- 2.34.1