From 1ce651ee147cde15ce2921d3a3b13e3abb25bc1f Mon Sep 17 00:00:00 2001 From: Flamefire Date: Sat, 9 Jun 2018 19:40:40 +0200 Subject: [PATCH 1/2] Use standard require --- README.md | 2 +- bin/uglifyjs | 31 ++-- lib/ast.js | 298 ++++++++++++++++++++++++++++++++++---- lib/compress.js | 113 +++++++++++++++ lib/minify.js | 69 ++++++++- lib/mozilla-ast.js | 80 +++++++++- lib/output.js | 90 +++++++++++- lib/parse.js | 117 +++++++++++++++ lib/propmangle.js | 28 ++++ lib/scope.js | 47 ++++++ lib/sourcemap.js | 9 ++ lib/transform.js | 185 ----------------------- lib/utils.js | 47 +++--- test/exports.js | 14 -- test/mocha.js | 1 + test/mocha/cli.js | 2 +- test/node.js | 18 ++- tools/exports.js | 2 + tools/generate-exports.js | 59 ++++++++ tools/node.js | 31 +++- 20 files changed, 967 insertions(+), 276 deletions(-) delete mode 100644 lib/transform.js delete mode 100644 test/exports.js create mode 100644 tools/generate-exports.js diff --git a/README.md b/README.md index 663ce7b4..e2b11fb8 100644 --- a/README.md +++ b/README.md @@ -1047,7 +1047,7 @@ var result = UglifyJS.minify(ast, { Transversal and transformation of the native AST can be performed through [`TreeWalker`](https://github.com/mishoo/UglifyJS2/blob/master/lib/ast.js) and -[`TreeTransformer`](https://github.com/mishoo/UglifyJS2/blob/master/lib/transform.js) +[`TreeTransformer`](https://github.com/mishoo/UglifyJS2/blob/master/lib/ast.js) respectively. ### ESTree / SpiderMonkey AST diff --git a/bin/uglifyjs b/bin/uglifyjs index fb6ae2fb..242eb70b 100755 --- a/bin/uglifyjs +++ b/bin/uglifyjs @@ -100,7 +100,7 @@ if (program.mangleProps) { if (typeof program.mangleProps != "object") program.mangleProps = {}; if (!Array.isArray(program.mangleProps.reserved)) program.mangleProps.reserved = []; require("../tools/domprops").forEach(function(name) { - UglifyJS._push_uniq(program.mangleProps.reserved, name); + UglifyJS.push_uniq(program.mangleProps.reserved, name); }); } if (typeof options.mangle != "object") options.mangle = {}; @@ -144,12 +144,23 @@ if (program.verbose) { } else if (program.warn) { options.warnings = true; } +function getVarNameFromPath(filename) { + var name = /((\w|-)+)(\.js)?$/.exec(filename)[1].replace("-", "_"); + return "__" + name + "_exports"; +} if (program.self) { if (program.args.length) { print_error("WARN: Ignoring input files since --self was passed"); } if (!options.wrap) options.wrap = "UglifyJS"; + files["__require_emulation"] = "var __origExports = exports;" + getVarNameFromPath + "function require(filename){return require[getVarNameFromPath(filename)];}"; simple_glob(UglifyJS.FILES).forEach(function(name) { + var exportCode; + if (/exports\.js$/.test(name)) + exportCode = "var exports = __origExports"; + else + exportCode = "var exports = require['" + getVarNameFromPath(name) + "'] = {};"; + files["_" + name + "_exports"] = exportCode; files[convert_path(name)] = read_file(name); }); run(); @@ -171,11 +182,11 @@ if (program.self) { } function convert_ast(fn) { - return UglifyJS.AST_Node.from_mozilla_ast(Object.keys(files).reduce(fn, null)); + return UglifyJS.ast.AST_Node.from_mozilla_ast(Object.keys(files).reduce(fn, null)); } function run() { - UglifyJS.AST_Node.warn_function = function(msg) { + UglifyJS.ast.AST_Node.warn_function = function(msg) { print_error("WARN: " + msg); }; var content = program.sourceMap && program.sourceMap.content; @@ -249,9 +260,9 @@ function run() { return value.size() ? value.map(symdef) : undefined; } if (skip_key(key)) return; - if (value instanceof UglifyJS.AST_Token) return; + if (value instanceof UglifyJS.ast.AST_Token) return; if (value instanceof UglifyJS.Dictionary) return; - if (value instanceof UglifyJS.AST_Node) { + if (value instanceof UglifyJS.ast.AST_Node) { var result = { _class: "AST_" + value.TYPE }; @@ -348,27 +359,27 @@ function parse_js(flag) { code: false } }).ast.walk(new UglifyJS.TreeWalker(function(node) { - if (node instanceof UglifyJS.AST_Assign) { + if (node instanceof UglifyJS.ast.AST_Assign) { var name = node.left.print_to_string(); var value = node.right; if (flag) { options[name] = value; - } else if (value instanceof UglifyJS.AST_Array) { + } else if (value instanceof UglifyJS.ast.AST_Array) { options[name] = value.elements.map(to_string); } else { options[name] = to_string(value); } return true; } - if (node instanceof UglifyJS.AST_Symbol || node instanceof UglifyJS.AST_PropAccess) { + if (node instanceof UglifyJS.ast.AST_Symbol || node instanceof UglifyJS.ast.AST_PropAccess) { var name = node.print_to_string(); options[name] = true; return true; } - if (!(node instanceof UglifyJS.AST_Sequence)) throw node; + if (!(node instanceof UglifyJS.ast.AST_Sequence)) throw node; function to_string(value) { - return value instanceof UglifyJS.AST_Constant ? value.getValue() : value.print_to_string({ + return value instanceof UglifyJS.ast.AST_Constant ? value.getValue() : value.print_to_string({ quote_keys: true }); } diff --git a/lib/ast.js b/lib/ast.js index c37ba598..37b1c2ba 100644 --- a/lib/ast.js +++ b/lib/ast.js @@ -43,6 +43,13 @@ "use strict"; +var utils = require("./utils"); +var noop = utils.noop; +var string_template = utils.string_template; +var HOP = utils.HOP; +var MAP = utils.MAP; +var merge = utils.merge; + function DEFNODE(type, props, methods, base) { if (typeof base === "undefined") base = AST_Node; props = props ? props.split(/\s+/) : []; @@ -323,34 +330,6 @@ var AST_Toplevel = DEFNODE("Toplevel", "globals", { $documentation: "The toplevel scope", $propdoc: { globals: "[Object/S] a map of name -> SymbolDef for all undeclared names", - }, - wrap_commonjs: function(name) { - var body = this.body; - var wrapped_tl = "(function(exports){'$ORIG';})(typeof " + name + "=='undefined'?(" + name + "={}):" + name + ");"; - wrapped_tl = parse(wrapped_tl); - wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node) { - if (node instanceof AST_Directive && node.value == "$ORIG") { - return MAP.splice(body); - } - })); - return wrapped_tl; - }, - wrap_enclose: function(args_values) { - if (typeof args_values != "string") args_values = ""; - var index = args_values.indexOf(":"); - if (index < 0) index = args_values.length; - var body = this.body; - return parse([ - "(function(", - args_values.slice(0, index), - '){"$ORIG"})(', - args_values.slice(index + 1), - ")" - ].join("")).transform(new TreeTransformer(function(node) { - if (node instanceof AST_Directive && node.value == "$ORIG") { - return MAP.splice(body); - } - })); } }, AST_Scope); @@ -952,3 +931,266 @@ TreeWalker.prototype = { } } }; + +function TreeTransformer(before, after) { + TreeWalker.call(this); + this.before = before; + this.after = after; +} +TreeTransformer.prototype = new TreeWalker; + +(function(DEF) { + function do_list(list, tw) { + return MAP(list, function(node) { + return node.transform(tw, true); + }); + } + + DEF(AST_Node, noop); + DEF(AST_LabeledStatement, function(self, tw) { + self.label = self.label.transform(tw); + self.body = self.body.transform(tw); + }); + DEF(AST_SimpleStatement, function(self, tw) { + self.body = self.body.transform(tw); + }); + DEF(AST_Block, function(self, tw) { + self.body = do_list(self.body, tw); + }); + DEF(AST_Do, function(self, tw) { + self.body = self.body.transform(tw); + self.condition = self.condition.transform(tw); + }); + DEF(AST_While, function(self, tw) { + self.condition = self.condition.transform(tw); + self.body = self.body.transform(tw); + }); + DEF(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); + }); + DEF(AST_ForIn, function(self, tw) { + self.init = self.init.transform(tw); + self.object = self.object.transform(tw); + self.body = self.body.transform(tw); + }); + DEF(AST_With, function(self, tw) { + self.expression = self.expression.transform(tw); + self.body = self.body.transform(tw); + }); + DEF(AST_Exit, function(self, tw) { + if (self.value) self.value = self.value.transform(tw); + }); + DEF(AST_LoopControl, function(self, tw) { + if (self.label) self.label = self.label.transform(tw); + }); + DEF(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); + }); + DEF(AST_Switch, function(self, tw) { + self.expression = self.expression.transform(tw); + self.body = do_list(self.body, tw); + }); + DEF(AST_Case, function(self, tw) { + self.expression = self.expression.transform(tw); + self.body = do_list(self.body, tw); + }); + DEF(AST_Try, function(self, tw) { + self.body = do_list(self.body, tw); + if (self.bcatch) self.bcatch = self.bcatch.transform(tw); + if (self.bfinally) self.bfinally = self.bfinally.transform(tw); + }); + DEF(AST_Catch, function(self, tw) { + self.argname = self.argname.transform(tw); + self.body = do_list(self.body, tw); + }); + DEF(AST_Definitions, function(self, tw) { + self.definitions = do_list(self.definitions, tw); + }); + DEF(AST_VarDef, function(self, tw) { + self.name = self.name.transform(tw); + if (self.value) self.value = self.value.transform(tw); + }); + DEF(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); + }); + DEF(AST_Call, function(self, tw) { + self.expression = self.expression.transform(tw); + self.args = do_list(self.args, tw); + }); + DEF(AST_Sequence, function(self, tw) { + self.expressions = do_list(self.expressions, tw); + }); + DEF(AST_Dot, function(self, tw) { + self.expression = self.expression.transform(tw); + }); + DEF(AST_Sub, function(self, tw) { + self.expression = self.expression.transform(tw); + self.property = self.property.transform(tw); + }); + DEF(AST_Unary, function(self, tw) { + self.expression = self.expression.transform(tw); + }); + DEF(AST_Binary, function(self, tw) { + self.left = self.left.transform(tw); + self.right = self.right.transform(tw); + }); + DEF(AST_Conditional, function(self, tw) { + self.condition = self.condition.transform(tw); + self.consequent = self.consequent.transform(tw); + self.alternative = self.alternative.transform(tw); + }); + DEF(AST_Array, function(self, tw) { + self.elements = do_list(self.elements, tw); + }); + DEF(AST_Object, function(self, tw) { + self.properties = do_list(self.properties, tw); + }); + DEF(AST_ObjectProperty, function(self, tw) { + self.value = self.value.transform(tw); + }); +})(function(node, descend) { + node.DEFMETHOD("transform", function(tw, in_list) { + var x, y; + tw.push(this); + if (tw.before) x = tw.before(this, descend, in_list); + if (typeof x === "undefined") { + x = this; + descend(x, tw); + if (tw.after) { + y = tw.after(x, in_list); + if (typeof y !== "undefined") x = y; + } + } + tw.pop(); + return x; + }); +}); + +/*********************************************************************** +/* Helpers +/**********************************************************************/ + +// return true if the node at the top of the stack (that means the +// innermost node in the current output) is lexically the first in +// a statement. +function first_in_statement(stack) { + var node = stack.parent(-1); + for (var i = 0, p; p = stack.parent(i++); node = p) { + if (p.TYPE == "Call") { + if (p.expression === node) continue; + } else if (p instanceof AST_Binary) { + if (p.left === node) continue; + } else if (p instanceof AST_Conditional) { + if (p.condition === node) continue; + } else if (p instanceof AST_PropAccess) { + if (p.expression === node) continue; + } else if (p instanceof AST_Sequence) { + if (p.expressions[0] === node) continue; + } else if (p instanceof AST_Statement) { + return p.body === node; + } else if (p instanceof AST_UnaryPostfix) { + if (p.expression === node) continue; + } + return false; + } +} + +merge(exports, { + DEFNODE : DEFNODE, + AST_Token : AST_Token, + AST_Node : AST_Node, + AST_Statement : AST_Statement, + AST_Debugger : AST_Debugger, + AST_Directive : AST_Directive, + AST_SimpleStatement : AST_SimpleStatement, + walk_body : walk_body, + AST_Block : AST_Block, + AST_BlockStatement : AST_BlockStatement, + AST_EmptyStatement : AST_EmptyStatement, + AST_StatementWithBody : AST_StatementWithBody, + AST_LabeledStatement : AST_LabeledStatement, + AST_IterationStatement : AST_IterationStatement, + AST_DWLoop : AST_DWLoop, + AST_Do : AST_Do, + AST_While : AST_While, + AST_For : AST_For, + AST_ForIn : AST_ForIn, + AST_With : AST_With, + AST_Scope : AST_Scope, + AST_Toplevel : AST_Toplevel, + AST_Lambda : AST_Lambda, + AST_Accessor : AST_Accessor, + AST_Function : AST_Function, + AST_Defun : AST_Defun, + AST_Jump : AST_Jump, + AST_Exit : AST_Exit, + AST_Return : AST_Return, + AST_Throw : AST_Throw, + AST_LoopControl : AST_LoopControl, + AST_Break : AST_Break, + AST_Continue : AST_Continue, + AST_If : AST_If, + AST_Switch : AST_Switch, + AST_SwitchBranch : AST_SwitchBranch, + AST_Default : AST_Default, + AST_Case : AST_Case, + AST_Try : AST_Try, + AST_Catch : AST_Catch, + AST_Finally : AST_Finally, + AST_Definitions : AST_Definitions, + AST_Var : AST_Var, + AST_VarDef : AST_VarDef, + AST_Call : AST_Call, + AST_New : AST_New, + AST_Sequence : AST_Sequence, + AST_PropAccess : AST_PropAccess, + AST_Dot : AST_Dot, + AST_Sub : AST_Sub, + AST_Unary : AST_Unary, + AST_UnaryPrefix : AST_UnaryPrefix, + AST_UnaryPostfix : AST_UnaryPostfix, + AST_Binary : AST_Binary, + AST_Conditional : AST_Conditional, + AST_Assign : AST_Assign, + AST_Array : AST_Array, + AST_Object : AST_Object, + AST_ObjectProperty : AST_ObjectProperty, + AST_ObjectKeyVal : AST_ObjectKeyVal, + AST_ObjectSetter : AST_ObjectSetter, + AST_ObjectGetter : AST_ObjectGetter, + AST_Symbol : AST_Symbol, + AST_SymbolAccessor : AST_SymbolAccessor, + AST_SymbolDeclaration : AST_SymbolDeclaration, + AST_SymbolVar : AST_SymbolVar, + AST_SymbolFunarg : AST_SymbolFunarg, + AST_SymbolDefun : AST_SymbolDefun, + AST_SymbolLambda : AST_SymbolLambda, + AST_SymbolCatch : AST_SymbolCatch, + AST_Label : AST_Label, + AST_SymbolRef : AST_SymbolRef, + AST_LabelRef : AST_LabelRef, + AST_This : AST_This, + AST_Constant : AST_Constant, + AST_String : AST_String, + AST_Number : AST_Number, + AST_RegExp : AST_RegExp, + AST_Atom : AST_Atom, + AST_Null : AST_Null, + AST_NaN : AST_NaN, + AST_Undefined : AST_Undefined, + AST_Hole : AST_Hole, + AST_Infinity : AST_Infinity, + AST_Boolean : AST_Boolean, + AST_False : AST_False, + AST_True : AST_True, + TreeWalker : TreeWalker, + TreeTransformer : TreeTransformer, + first_in_statement : first_in_statement, +}); diff --git a/lib/compress.js b/lib/compress.js index ad01e48c..e4e5e434 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -43,6 +43,115 @@ "use strict"; +var utils = require("./utils"); +var member = utils.member; +var defaults = utils.defaults; +var merge = utils.merge; +var noop = utils.noop; +var return_false = utils.return_false; +var return_true = utils.return_true; +var return_this = utils.return_this; +var return_null = utils.return_null; +var string_template = utils.string_template; +var remove = utils.remove; +var makePredicate = utils.makePredicate; +var all = utils.all; +var Dictionary = utils.Dictionary; +var HOP = utils.HOP; +var MAP = utils.MAP; + +var ast = require("./ast"); +var walk_body = ast.walk_body; +var TreeWalker = ast.TreeWalker; +var TreeTransformer = ast.TreeTransformer; +var first_in_statement = ast.first_in_statement; +var AST_Node = ast.AST_Node; +var AST_Statement = ast.AST_Statement; +var AST_Debugger = ast.AST_Debugger; +var AST_Directive = ast.AST_Directive; +var AST_SimpleStatement = ast.AST_SimpleStatement; +var AST_Block = ast.AST_Block; +var AST_BlockStatement = ast.AST_BlockStatement; +var AST_EmptyStatement = ast.AST_EmptyStatement; +var AST_LabeledStatement = ast.AST_LabeledStatement; +var AST_IterationStatement = ast.AST_IterationStatement; +var AST_DWLoop = ast.AST_DWLoop; +var AST_Do = ast.AST_Do; +var AST_While = ast.AST_While; +var AST_For = ast.AST_For; +var AST_ForIn = ast.AST_ForIn; +var AST_With = ast.AST_With; +var AST_Scope = ast.AST_Scope; +var AST_Toplevel = ast.AST_Toplevel; +var AST_Lambda = ast.AST_Lambda; +var AST_Accessor = ast.AST_Accessor; +var AST_Function = ast.AST_Function; +var AST_Defun = ast.AST_Defun; +var AST_Jump = ast.AST_Jump; +var AST_Exit = ast.AST_Exit; +var AST_Return = ast.AST_Return; +var AST_LoopControl = ast.AST_LoopControl; +var AST_Break = ast.AST_Break; +var AST_Continue = ast.AST_Continue; +var AST_If = ast.AST_If; +var AST_Switch = ast.AST_Switch; +var AST_SwitchBranch = ast.AST_SwitchBranch; +var AST_Default = ast.AST_Default; +var AST_Case = ast.AST_Case; +var AST_Try = ast.AST_Try; +var AST_Catch = ast.AST_Catch; +var AST_Finally = ast.AST_Finally; +var AST_Definitions = ast.AST_Definitions; +var AST_Var = ast.AST_Var; +var AST_VarDef = ast.AST_VarDef; +var AST_Call = ast.AST_Call; +var AST_New = ast.AST_New; +var AST_Sequence = ast.AST_Sequence; +var AST_PropAccess = ast.AST_PropAccess; +var AST_Dot = ast.AST_Dot; +var AST_Sub = ast.AST_Sub; +var AST_Unary = ast.AST_Unary; +var AST_UnaryPrefix = ast.AST_UnaryPrefix; +var AST_UnaryPostfix = ast.AST_UnaryPostfix; +var AST_Binary = ast.AST_Binary; +var AST_Conditional = ast.AST_Conditional; +var AST_Assign = ast.AST_Assign; +var AST_Array = ast.AST_Array; +var AST_Object = ast.AST_Object; +var AST_ObjectProperty = ast.AST_ObjectProperty; +var AST_ObjectKeyVal = ast.AST_ObjectKeyVal; +var AST_Symbol = ast.AST_Symbol; +var AST_SymbolDeclaration = ast.AST_SymbolDeclaration; +var AST_SymbolVar = ast.AST_SymbolVar; +var AST_SymbolFunarg = ast.AST_SymbolFunarg; +var AST_SymbolDefun = ast.AST_SymbolDefun; +var AST_SymbolLambda = ast.AST_SymbolLambda; +var AST_SymbolCatch = ast.AST_SymbolCatch; +var AST_SymbolRef = ast.AST_SymbolRef; +var AST_This = ast.AST_This; +var AST_Constant = ast.AST_Constant; +var AST_String = ast.AST_String; +var AST_Number = ast.AST_Number; +var AST_RegExp = ast.AST_RegExp; +var AST_Null = ast.AST_Null; +var AST_NaN = ast.AST_NaN; +var AST_Undefined = ast.AST_Undefined; +var AST_Hole = ast.AST_Hole; +var AST_Infinity = ast.AST_Infinity; +var AST_Boolean = ast.AST_Boolean; +var AST_False = ast.AST_False; +var AST_True = ast.AST_True; + +var parse = require("./parse"); +var is_identifier_string = parse.is_identifier_string; +var JS_Parse_Error = parse.JS_Parse_Error; +var PRECEDENCE = parse.PRECEDENCE; +var parse = parse.parse; + +var OutputStream = require("./output").OutputStream; + +require("./scope") + function Compressor(options, false_by_default) { if (!(this instanceof Compressor)) return new Compressor(options, false_by_default); @@ -6401,3 +6510,7 @@ merge(Compressor.prototype, { return opt; }); }); + +merge(exports, { + Compressor : Compressor, +}); diff --git a/lib/minify.js b/lib/minify.js index d84f6825..31d3bb1c 100644 --- a/lib/minify.js +++ b/lib/minify.js @@ -1,5 +1,30 @@ "use strict"; +var utils = require("./utils"); +var defaults = utils.defaults; +var Dictionary = utils.Dictionary; +var HOP = utils.HOP; +var MAP = utils.MAP; +var merge = utils.merge; + +var ast = require("./ast"); +var AST_Node = ast.AST_Node; +var AST_Toplevel = ast.AST_Toplevel; +var AST_Directive = ast.AST_Directive; +var TreeTransformer = ast.TreeTransformer; + +var parse = require("./parse"); +var parse = parse.parse; + +var OutputStream = require("./output").OutputStream; +var Compressor = require("./compress").Compressor; + +var SourceMap = require("./sourcemap").SourceMap; + +var propmangle = require("./propmangle"); +var reserve_quoted_keys = propmangle.reserve_quoted_keys; +var mangle_properties = propmangle.mangle_properties; + var to_ascii = typeof atob == "undefined" ? function(b64) { return new Buffer(b64, "base64").toString(); } : atob; @@ -51,6 +76,35 @@ function to_json(cache) { } function minify(files, options) { + function wrap_commonjs(toplevel_node, name) { + var body = toplevel_node.body; + var wrapped_tl = "(function(exports){'$ORIG';})(typeof " + name + "=='undefined'?(" + name + "={}):" + name + ");"; + wrapped_tl = parse(wrapped_tl); + wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node) { + if (node instanceof AST_Directive && node.value == "$ORIG") { + return MAP.splice(body); + } + })); + return wrapped_tl; + } + function wrap_enclose(toplevel_node, args_values) { + if (typeof args_values != "string") args_values = ""; + var index = args_values.indexOf(":"); + if (index < 0) index = args_values.length; + var body = toplevel_node.body; + return parse([ + "(function(", + args_values.slice(0, index), + '){"$ORIG"})(', + args_values.slice(index + 1), + ")" + ].join("")).transform(new TreeTransformer(function(node) { + if (node instanceof AST_Directive && node.value == "$ORIG") { + return MAP.splice(body); + } + })); + } + var warn_function = AST_Node.warn_function; try { options = defaults(options, { @@ -156,10 +210,10 @@ function minify(files, options) { reserve_quoted_keys(toplevel, quoted_props); } if (options.wrap) { - toplevel = toplevel.wrap_commonjs(options.wrap); + toplevel = wrap_commonjs(toplevel, options.wrap); } if (options.enclose) { - toplevel = toplevel.wrap_enclose(options.enclose); + toplevel = wrap_enclose(toplevel, options.enclose); } if (timings) timings.rename = Date.now(); if (options.rename) { @@ -244,3 +298,14 @@ function minify(files, options) { AST_Node.warn_function = warn_function; } } + +merge(exports, { + to_ascii : to_ascii, + to_base64 : to_base64, + read_source_map : read_source_map, + parse_source_map : parse_source_map, + set_shorthand : set_shorthand, + init_cache : init_cache, + to_json : to_json, + minify : minify, +}); diff --git a/lib/mozilla-ast.js b/lib/mozilla-ast.js index dace808a..1a464ee7 100644 --- a/lib/mozilla-ast.js +++ b/lib/mozilla-ast.js @@ -43,6 +43,84 @@ "use strict"; +var ast = require("./ast"); +var TreeWalker = ast.TreeWalker; +var AST_Token = ast.AST_Token; +var AST_Node = ast.AST_Node; +var AST_Statement = ast.AST_Statement; +var AST_Debugger = ast.AST_Debugger; +var AST_Directive = ast.AST_Directive; +var AST_SimpleStatement = ast.AST_SimpleStatement; +var AST_Block = ast.AST_Block; +var AST_BlockStatement = ast.AST_BlockStatement; +var AST_EmptyStatement = ast.AST_EmptyStatement; +var AST_LabeledStatement = ast.AST_LabeledStatement; +var AST_Do = ast.AST_Do; +var AST_While = ast.AST_While; +var AST_For = ast.AST_For; +var AST_ForIn = ast.AST_ForIn; +var AST_With = ast.AST_With; +var AST_Scope = ast.AST_Scope; +var AST_Toplevel = ast.AST_Toplevel; +var AST_Lambda = ast.AST_Lambda; +var AST_Accessor = ast.AST_Accessor; +var AST_Function = ast.AST_Function; +var AST_Defun = ast.AST_Defun; +var AST_Return = ast.AST_Return; +var AST_Throw = ast.AST_Throw; +var AST_Break = ast.AST_Break; +var AST_Continue = ast.AST_Continue; +var AST_If = ast.AST_If; +var AST_Switch = ast.AST_Switch; +var AST_SwitchBranch = ast.AST_SwitchBranch; +var AST_Default = ast.AST_Default; +var AST_Case = ast.AST_Case; +var AST_Try = ast.AST_Try; +var AST_Catch = ast.AST_Catch; +var AST_Finally = ast.AST_Finally; +var AST_Definitions = ast.AST_Definitions; +var AST_Var = ast.AST_Var; +var AST_VarDef = ast.AST_VarDef; +var AST_Call = ast.AST_Call; +var AST_New = ast.AST_New; +var AST_Sequence = ast.AST_Sequence; +var AST_PropAccess = ast.AST_PropAccess; +var AST_Dot = ast.AST_Dot; +var AST_Sub = ast.AST_Sub; +var AST_Unary = ast.AST_Unary; +var AST_UnaryPrefix = ast.AST_UnaryPrefix; +var AST_UnaryPostfix = ast.AST_UnaryPostfix; +var AST_Binary = ast.AST_Binary; +var AST_Conditional = ast.AST_Conditional; +var AST_Assign = ast.AST_Assign; +var AST_Array = ast.AST_Array; +var AST_Object = ast.AST_Object; +var AST_ObjectProperty = ast.AST_ObjectProperty; +var AST_ObjectKeyVal = ast.AST_ObjectKeyVal; +var AST_ObjectSetter = ast.AST_ObjectSetter; +var AST_ObjectGetter = ast.AST_ObjectGetter; +var AST_Symbol = ast.AST_Symbol; +var AST_SymbolAccessor = ast.AST_SymbolAccessor; +var AST_SymbolVar = ast.AST_SymbolVar; +var AST_SymbolFunarg = ast.AST_SymbolFunarg; +var AST_SymbolDefun = ast.AST_SymbolDefun; +var AST_SymbolLambda = ast.AST_SymbolLambda; +var AST_SymbolCatch = ast.AST_SymbolCatch; +var AST_Label = ast.AST_Label; +var AST_SymbolRef = ast.AST_SymbolRef; +var AST_LabelRef = ast.AST_LabelRef; +var AST_This = ast.AST_This; +var AST_Constant = ast.AST_Constant; +var AST_String = ast.AST_String; +var AST_Number = ast.AST_Number; +var AST_RegExp = ast.AST_RegExp; +var AST_Atom = ast.AST_Atom; +var AST_Null = ast.AST_Null; +var AST_Hole = ast.AST_Hole; +var AST_Boolean = ast.AST_Boolean; +var AST_False = ast.AST_False; +var AST_True = ast.AST_True; + (function() { function normalize_directives(body) { var in_directive = true; @@ -540,7 +618,7 @@ //console.log(moz_to_me); moz_to_me = new Function("U2", "my_start_token", "my_end_token", "from_moz", "return(" + moz_to_me + ")")( - exports, my_start_token, my_end_token, from_moz + ast, my_start_token, my_end_token, from_moz ); me_to_moz = new Function("to_moz", "to_moz_block", "to_moz_scope", "return(" + me_to_moz + ")")( to_moz, to_moz_block, to_moz_scope diff --git a/lib/output.js b/lib/output.js index 1dbc1f6e..19f78fbd 100644 --- a/lib/output.js +++ b/lib/output.js @@ -43,6 +43,88 @@ "use strict"; +var utils = require("./utils"); +var repeat_string = utils.repeat_string; +var defaults = utils.defaults; +var noop = utils.noop; +var return_false = utils.return_false; +var return_true = utils.return_true; +var makePredicate = utils.makePredicate; +var all = utils.all; +var merge = utils.merge; + +var ast = require("./ast"); +var first_in_statement = ast.first_in_statement; +var TreeWalker = ast.TreeWalker; +var AST_Node = ast.AST_Node; +var AST_Statement = ast.AST_Statement; +var AST_Debugger = ast.AST_Debugger; +var AST_Directive = ast.AST_Directive; +var AST_SimpleStatement = ast.AST_SimpleStatement; +var AST_BlockStatement = ast.AST_BlockStatement; +var AST_EmptyStatement = ast.AST_EmptyStatement; +var AST_StatementWithBody = ast.AST_StatementWithBody; +var AST_LabeledStatement = ast.AST_LabeledStatement; +var AST_Do = ast.AST_Do; +var AST_While = ast.AST_While; +var AST_For = ast.AST_For; +var AST_ForIn = ast.AST_ForIn; +var AST_With = ast.AST_With; +var AST_Scope = ast.AST_Scope; +var AST_Toplevel = ast.AST_Toplevel; +var AST_Lambda = ast.AST_Lambda; +var AST_Function = ast.AST_Function; +var AST_Jump = ast.AST_Jump; +var AST_Exit = ast.AST_Exit; +var AST_Return = ast.AST_Return; +var AST_Throw = ast.AST_Throw; +var AST_Break = ast.AST_Break; +var AST_Continue = ast.AST_Continue; +var AST_If = ast.AST_If; +var AST_Switch = ast.AST_Switch; +var AST_SwitchBranch = ast.AST_SwitchBranch; +var AST_Default = ast.AST_Default; +var AST_Case = ast.AST_Case; +var AST_Try = ast.AST_Try; +var AST_Catch = ast.AST_Catch; +var AST_Finally = ast.AST_Finally; +var AST_Definitions = ast.AST_Definitions; +var AST_Var = ast.AST_Var; +var AST_VarDef = ast.AST_VarDef; +var AST_Call = ast.AST_Call; +var AST_New = ast.AST_New; +var AST_Sequence = ast.AST_Sequence; +var AST_PropAccess = ast.AST_PropAccess; +var AST_Dot = ast.AST_Dot; +var AST_Sub = ast.AST_Sub; +var AST_Unary = ast.AST_Unary; +var AST_UnaryPrefix = ast.AST_UnaryPrefix; +var AST_UnaryPostfix = ast.AST_UnaryPostfix; +var AST_Binary = ast.AST_Binary; +var AST_Conditional = ast.AST_Conditional; +var AST_Assign = ast.AST_Assign; +var AST_Array = ast.AST_Array; +var AST_Object = ast.AST_Object; +var AST_ObjectProperty = ast.AST_ObjectProperty; +var AST_ObjectKeyVal = ast.AST_ObjectKeyVal; +var AST_ObjectSetter = ast.AST_ObjectSetter; +var AST_ObjectGetter = ast.AST_ObjectGetter; +var AST_Symbol = ast.AST_Symbol; +var AST_This = ast.AST_This; +var AST_Constant = ast.AST_Constant; +var AST_String = ast.AST_String; +var AST_Number = ast.AST_Number; +var AST_RegExp = ast.AST_RegExp; +var AST_Hole = ast.AST_Hole; + +var parse = require("./parse"); +var is_surrogate_pair_head = parse.is_surrogate_pair_head; +var is_surrogate_pair_tail = parse.is_surrogate_pair_tail; +var is_identifier_char = parse.is_identifier_char; +var is_identifier_string = parse.is_identifier_string; +var PRECEDENCE = parse.PRECEDENCE; +var RESERVED_WORDS = parse.RESERVED_WORDS; + var EXPECT_DIRECTIVE = /^$|[;{][\s\n]*$/; function is_some_comments(comment) { @@ -1337,7 +1419,7 @@ function OutputStream(options) { output.print_string(key); } else if ("" + +key == key && key >= 0) { output.print(make_num(key)); - } else if (RESERVED_WORDS[key] ? !output.option("ie8") : is_identifier_string(key)) { + } else if (parse.RESERVED_WORDS[key] ? !output.option("ie8") : is_identifier_string(key)) { if (quote && output.option("keep_quoted_props")) { output.print_string(key, quote); } else { @@ -1518,3 +1600,9 @@ function OutputStream(options) { output.add_mapping(this.start, this.key); }); })(); + +merge(exports, { + EXPECT_DIRECTIVE : EXPECT_DIRECTIVE, + is_some_comments : is_some_comments, + OutputStream : OutputStream, +}); diff --git a/lib/parse.js b/lib/parse.js index 29df370c..7f35352e 100644 --- a/lib/parse.js +++ b/lib/parse.js @@ -44,6 +44,83 @@ "use strict"; +var utils = require("./utils"); +var characters = utils.characters; +var find_if = utils.find_if; +var configure_error_stack = utils.configure_error_stack; +var defaults = utils.defaults; +var makePredicate = utils.makePredicate; +var all = utils.all; +var HOP = utils.HOP; +var merge = utils.merge; + +var ast = require("./ast"); +var AST_Token = ast.AST_Token; +var AST_Debugger = ast.AST_Debugger; +var AST_Directive = ast.AST_Directive; +var AST_SimpleStatement = ast.AST_SimpleStatement; +var AST_BlockStatement = ast.AST_BlockStatement; +var AST_EmptyStatement = ast.AST_EmptyStatement; +var AST_LabeledStatement = ast.AST_LabeledStatement; +var AST_IterationStatement = ast.AST_IterationStatement; +var AST_Do = ast.AST_Do; +var AST_While = ast.AST_While; +var AST_For = ast.AST_For; +var AST_ForIn = ast.AST_ForIn; +var AST_With = ast.AST_With; +var AST_Toplevel = ast.AST_Toplevel; +var AST_Lambda = ast.AST_Lambda; +var AST_Accessor = ast.AST_Accessor; +var AST_Function = ast.AST_Function; +var AST_Defun = ast.AST_Defun; +var AST_Return = ast.AST_Return; +var AST_Throw = ast.AST_Throw; +var AST_Break = ast.AST_Break; +var AST_Continue = ast.AST_Continue; +var AST_If = ast.AST_If; +var AST_Switch = ast.AST_Switch; +var AST_Default = ast.AST_Default; +var AST_Case = ast.AST_Case; +var AST_Try = ast.AST_Try; +var AST_Catch = ast.AST_Catch; +var AST_Finally = ast.AST_Finally; +var AST_Var = ast.AST_Var; +var AST_VarDef = ast.AST_VarDef; +var AST_Call = ast.AST_Call; +var AST_New = ast.AST_New; +var AST_Sequence = ast.AST_Sequence; +var AST_PropAccess = ast.AST_PropAccess; +var AST_Dot = ast.AST_Dot; +var AST_Sub = ast.AST_Sub; +var AST_UnaryPrefix = ast.AST_UnaryPrefix; +var AST_UnaryPostfix = ast.AST_UnaryPostfix; +var AST_Binary = ast.AST_Binary; +var AST_Conditional = ast.AST_Conditional; +var AST_Assign = ast.AST_Assign; +var AST_Array = ast.AST_Array; +var AST_Object = ast.AST_Object; +var AST_ObjectKeyVal = ast.AST_ObjectKeyVal; +var AST_ObjectSetter = ast.AST_ObjectSetter; +var AST_ObjectGetter = ast.AST_ObjectGetter; +var AST_SymbolAccessor = ast.AST_SymbolAccessor; +var AST_SymbolDeclaration = ast.AST_SymbolDeclaration; +var AST_SymbolVar = ast.AST_SymbolVar; +var AST_SymbolFunarg = ast.AST_SymbolFunarg; +var AST_SymbolDefun = ast.AST_SymbolDefun; +var AST_SymbolLambda = ast.AST_SymbolLambda; +var AST_SymbolCatch = ast.AST_SymbolCatch; +var AST_Label = ast.AST_Label; +var AST_SymbolRef = ast.AST_SymbolRef; +var AST_LabelRef = ast.AST_LabelRef; +var AST_This = ast.AST_This; +var AST_String = ast.AST_String; +var AST_Number = ast.AST_Number; +var AST_RegExp = ast.AST_RegExp; +var AST_Null = ast.AST_Null; +var AST_Hole = ast.AST_Hole; +var AST_False = ast.AST_False; +var AST_True = ast.AST_True; + var KEYWORDS = 'break case catch const continue debugger default delete do else finally for function if in instanceof new return switch throw try typeof var void while with'; var KEYWORDS_ATOM = 'false null true'; var RESERVED_WORDS = 'abstract boolean byte char class double enum export extends final float goto implements import int interface let long native package private protected public short static super synchronized this throws transient volatile yield' @@ -1646,3 +1723,43 @@ function parse($TEXT, options) { return toplevel; }(); } + +merge(exports, { + KEYWORDS : KEYWORDS, + KEYWORDS_ATOM : KEYWORDS_ATOM, + RESERVED_WORDS : RESERVED_WORDS, + KEYWORDS_BEFORE_EXPRESSION : KEYWORDS_BEFORE_EXPRESSION, + OPERATOR_CHARS : OPERATOR_CHARS, + RE_HEX_NUMBER : RE_HEX_NUMBER, + RE_OCT_NUMBER : RE_OCT_NUMBER, + OPERATORS : OPERATORS, + WHITESPACE_CHARS : WHITESPACE_CHARS, + NEWLINE_CHARS : NEWLINE_CHARS, + PUNC_BEFORE_EXPRESSION : PUNC_BEFORE_EXPRESSION, + PUNC_CHARS : PUNC_CHARS, + UNICODE : UNICODE, + is_letter : is_letter, + is_surrogate_pair_head : is_surrogate_pair_head, + is_surrogate_pair_tail : is_surrogate_pair_tail, + is_digit : is_digit, + is_alphanumeric_char : is_alphanumeric_char, + is_unicode_digit : is_unicode_digit, + is_unicode_combining_mark : is_unicode_combining_mark, + is_unicode_connector_punctuation : is_unicode_connector_punctuation, + is_identifier : is_identifier, + is_identifier_start : is_identifier_start, + is_identifier_char : is_identifier_char, + is_identifier_string : is_identifier_string, + parse_js_number : parse_js_number, + JS_Parse_Error : JS_Parse_Error, + js_error : js_error, + is_token : is_token, + EX_EOF : EX_EOF, + tokenizer : tokenizer, + UNARY_PREFIX : UNARY_PREFIX, + UNARY_POSTFIX : UNARY_POSTFIX, + ASSIGNMENT : ASSIGNMENT, + PRECEDENCE : PRECEDENCE, + ATOMIC_START_TOKEN : ATOMIC_START_TOKEN, + parse : parse, +}); diff --git a/lib/propmangle.js b/lib/propmangle.js index 7ad4804d..d7bb135f 100644 --- a/lib/propmangle.js +++ b/lib/propmangle.js @@ -43,6 +43,27 @@ "use strict"; +var utils = require("./utils"); +var defaults = utils.defaults; +var push_uniq = utils.push_uniq; +var Dictionary = utils.Dictionary; +var merge = utils.merge; + +var scope = require("./scope"); +var base54 = scope.base54; + +var ast = require("./ast"); +var TreeWalker = ast.TreeWalker; +var TreeTransformer = ast.TreeTransformer; +var AST_Call = ast.AST_Call; +var AST_Sequence = ast.AST_Sequence; +var AST_Dot = ast.AST_Dot; +var AST_Sub = ast.AST_Sub; +var AST_Conditional = ast.AST_Conditional; +var AST_ObjectProperty = ast.AST_ObjectProperty; +var AST_ObjectKeyVal = ast.AST_ObjectKeyVal; +var AST_String = ast.AST_String; + function find_builtins(reserved) { // NaN will be included due to Number.NaN [ @@ -250,3 +271,10 @@ function mangle_properties(ast, options) { })); } } + +merge(exports, { + find_builtins : find_builtins, + reserve_quoted_keys : reserve_quoted_keys, + addStrings : addStrings, + mangle_properties : mangle_properties, +}); diff --git a/lib/scope.js b/lib/scope.js index d4b13d12..bcd5dd67 100644 --- a/lib/scope.js +++ b/lib/scope.js @@ -43,6 +43,46 @@ "use strict"; +var utils = require("./utils"); +var defaults = utils.defaults; +var return_false = utils.return_false; +var return_this = utils.return_this; +var push_uniq = utils.push_uniq; +var makePredicate = utils.makePredicate; +var Dictionary = utils.Dictionary; +var merge = utils.merge; + +var ast = require("./ast"); +var TreeWalker = ast.TreeWalker; +var AST_Node = ast.AST_Node; +var AST_LabeledStatement = ast.AST_LabeledStatement; +var AST_With = ast.AST_With; +var AST_Scope = ast.AST_Scope; +var AST_Toplevel = ast.AST_Toplevel; +var AST_Lambda = ast.AST_Lambda; +var AST_Function = ast.AST_Function; +var AST_Defun = ast.AST_Defun; +var AST_LoopControl = ast.AST_LoopControl; +var AST_Catch = ast.AST_Catch; +var AST_Call = ast.AST_Call; +var AST_Sequence = ast.AST_Sequence; +var AST_Dot = ast.AST_Dot; +var AST_Sub = ast.AST_Sub; +var AST_Conditional = ast.AST_Conditional; +var AST_Symbol = ast.AST_Symbol; +var AST_SymbolVar = ast.AST_SymbolVar; +var AST_SymbolFunarg = ast.AST_SymbolFunarg; +var AST_SymbolDefun = ast.AST_SymbolDefun; +var AST_SymbolLambda = ast.AST_SymbolLambda; +var AST_SymbolCatch = ast.AST_SymbolCatch; +var AST_Label = ast.AST_Label; +var AST_SymbolRef = ast.AST_SymbolRef; +var AST_String = ast.AST_String; + +var parse = require("./parse"); +var is_identifier = parse.is_identifier; +var parse = parse.parse; + function SymbolDef(scope, orig, init) { this.name = orig.name; this.orig = [ orig ]; @@ -597,3 +637,10 @@ var base54 = (function() { } return base54; })(); + +merge(exports, { + SymbolDef : SymbolDef, + names_in_use : names_in_use, + next_mangled_name : next_mangled_name, + base54 : base54, +}); diff --git a/lib/sourcemap.js b/lib/sourcemap.js index 2feec45d..6001160f 100644 --- a/lib/sourcemap.js +++ b/lib/sourcemap.js @@ -43,6 +43,11 @@ "use strict"; +var MOZ_SourceMap = require("source-map"); +var utils = require("./utils"); +var defaults = utils.defaults; +var merge = utils.merge; + // a small wrapper around fitzgen's source-map library function SourceMap(options) { options = defaults(options, { @@ -102,3 +107,7 @@ function SourceMap(options) { } }; } + +merge(exports, { + SourceMap : SourceMap, +}); diff --git a/lib/transform.js b/lib/transform.js deleted file mode 100644 index 5897aa77..00000000 --- a/lib/transform.js +++ /dev/null @@ -1,185 +0,0 @@ -/*********************************************************************** - - 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. - - ***********************************************************************/ - -"use strict"; - -function TreeTransformer(before, after) { - TreeWalker.call(this); - this.before = before; - this.after = after; -} -TreeTransformer.prototype = new TreeWalker; - -(function(DEF) { - function do_list(list, tw) { - return MAP(list, function(node) { - return node.transform(tw, true); - }); - } - - DEF(AST_Node, noop); - DEF(AST_LabeledStatement, function(self, tw) { - self.label = self.label.transform(tw); - self.body = self.body.transform(tw); - }); - DEF(AST_SimpleStatement, function(self, tw) { - self.body = self.body.transform(tw); - }); - DEF(AST_Block, function(self, tw) { - self.body = do_list(self.body, tw); - }); - DEF(AST_Do, function(self, tw) { - self.body = self.body.transform(tw); - self.condition = self.condition.transform(tw); - }); - DEF(AST_While, function(self, tw) { - self.condition = self.condition.transform(tw); - self.body = self.body.transform(tw); - }); - DEF(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); - }); - DEF(AST_ForIn, function(self, tw) { - self.init = self.init.transform(tw); - self.object = self.object.transform(tw); - self.body = self.body.transform(tw); - }); - DEF(AST_With, function(self, tw) { - self.expression = self.expression.transform(tw); - self.body = self.body.transform(tw); - }); - DEF(AST_Exit, function(self, tw) { - if (self.value) self.value = self.value.transform(tw); - }); - DEF(AST_LoopControl, function(self, tw) { - if (self.label) self.label = self.label.transform(tw); - }); - DEF(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); - }); - DEF(AST_Switch, function(self, tw) { - self.expression = self.expression.transform(tw); - self.body = do_list(self.body, tw); - }); - DEF(AST_Case, function(self, tw) { - self.expression = self.expression.transform(tw); - self.body = do_list(self.body, tw); - }); - DEF(AST_Try, function(self, tw) { - self.body = do_list(self.body, tw); - if (self.bcatch) self.bcatch = self.bcatch.transform(tw); - if (self.bfinally) self.bfinally = self.bfinally.transform(tw); - }); - DEF(AST_Catch, function(self, tw) { - self.argname = self.argname.transform(tw); - self.body = do_list(self.body, tw); - }); - DEF(AST_Definitions, function(self, tw) { - self.definitions = do_list(self.definitions, tw); - }); - DEF(AST_VarDef, function(self, tw) { - self.name = self.name.transform(tw); - if (self.value) self.value = self.value.transform(tw); - }); - DEF(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); - }); - DEF(AST_Call, function(self, tw) { - self.expression = self.expression.transform(tw); - self.args = do_list(self.args, tw); - }); - DEF(AST_Sequence, function(self, tw) { - self.expressions = do_list(self.expressions, tw); - }); - DEF(AST_Dot, function(self, tw) { - self.expression = self.expression.transform(tw); - }); - DEF(AST_Sub, function(self, tw) { - self.expression = self.expression.transform(tw); - self.property = self.property.transform(tw); - }); - DEF(AST_Unary, function(self, tw) { - self.expression = self.expression.transform(tw); - }); - DEF(AST_Binary, function(self, tw) { - self.left = self.left.transform(tw); - self.right = self.right.transform(tw); - }); - DEF(AST_Conditional, function(self, tw) { - self.condition = self.condition.transform(tw); - self.consequent = self.consequent.transform(tw); - self.alternative = self.alternative.transform(tw); - }); - DEF(AST_Array, function(self, tw) { - self.elements = do_list(self.elements, tw); - }); - DEF(AST_Object, function(self, tw) { - self.properties = do_list(self.properties, tw); - }); - DEF(AST_ObjectProperty, function(self, tw) { - self.value = self.value.transform(tw); - }); -})(function(node, descend) { - node.DEFMETHOD("transform", function(tw, in_list) { - var x, y; - tw.push(this); - if (tw.before) x = tw.before(this, descend, in_list); - if (typeof x === "undefined") { - x = this; - descend(x, tw); - if (tw.after) { - y = tw.after(x, in_list); - if (typeof y !== "undefined") x = y; - } - } - tw.pop(); - return x; - }); -}); diff --git a/lib/utils.js b/lib/utils.js index ca4b2d4b..2399811d 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -255,27 +255,26 @@ function HOP(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); } -// return true if the node at the top of the stack (that means the -// innermost node in the current output) is lexically the first in -// a statement. -function first_in_statement(stack) { - var node = stack.parent(-1); - for (var i = 0, p; p = stack.parent(i++); node = p) { - if (p.TYPE == "Call") { - if (p.expression === node) continue; - } else if (p instanceof AST_Binary) { - if (p.left === node) continue; - } else if (p instanceof AST_Conditional) { - if (p.condition === node) continue; - } else if (p instanceof AST_PropAccess) { - if (p.expression === node) continue; - } else if (p instanceof AST_Sequence) { - if (p.expressions[0] === node) continue; - } else if (p instanceof AST_Statement) { - return p.body === node; - } else if (p instanceof AST_UnaryPostfix) { - if (p.expression === node) continue; - } - return false; - } -} +merge(exports, { + characters : characters, + member : member, + find_if : find_if, + repeat_string : repeat_string, + configure_error_stack : configure_error_stack, + DefaultsError : DefaultsError, + defaults : defaults, + merge : merge, + noop : noop, + return_false : return_false, + return_true : return_true, + return_this : return_this, + return_null : return_null, + MAP : MAP, + push_uniq : push_uniq, + string_template : string_template, + remove : remove, + makePredicate : makePredicate, + all : all, + Dictionary : Dictionary, + HOP : HOP, +}); diff --git a/test/exports.js b/test/exports.js deleted file mode 100644 index 997ad513..00000000 --- a/test/exports.js +++ /dev/null @@ -1,14 +0,0 @@ -exports["Compressor"] = Compressor; -exports["JS_Parse_Error"] = JS_Parse_Error; -exports["OutputStream"] = OutputStream; -exports["SourceMap"] = SourceMap; -exports["TreeWalker"] = TreeWalker; -exports["base54"] = base54; -exports["defaults"] = defaults; -exports["mangle_properties"] = mangle_properties; -exports["minify"] = minify; -exports["parse"] = parse; -exports["reserve_quoted_keys"] = reserve_quoted_keys; -exports["string_template"] = string_template; -exports["tokenizer"] = tokenizer; -exports["is_identifier"] = is_identifier; diff --git a/test/mocha.js b/test/mocha.js index 5d65a5a2..bd4a6e28 100644 --- a/test/mocha.js +++ b/test/mocha.js @@ -22,6 +22,7 @@ it = function(title, fn) { tasks.push(fn); }; + fs.readdirSync("test/mocha").filter(function(file) { return /\.js$/.test(file); }).forEach(function(file) { diff --git a/test/mocha/cli.js b/test/mocha/cli.js index 3bc92c30..0745c647 100644 --- a/test/mocha/cli.js +++ b/test/mocha/cli.js @@ -11,7 +11,7 @@ describe("bin/uglifyjs", function() { it("should produce a functional build when using --self", function(done) { this.timeout(30000); var command = uglifyjscmd + ' --self -cm --wrap WrappedUglifyJS'; - exec(command, function(err, stdout) { + exec(command, {maxBuffer: 1024 * 300}, function(err, stdout) { if (err) throw err; eval(stdout); assert.strictEqual(typeof WrappedUglifyJS, "object"); diff --git a/test/node.js b/test/node.js index 22bf325d..7db9c6d5 100644 --- a/test/node.js +++ b/test/node.js @@ -1,6 +1,12 @@ -var fs = require("fs"); - -new Function("MOZ_SourceMap", "exports", require("../tools/node").FILES.map(function(file) { - if (/exports\.js$/.test(file)) file = require.resolve("./exports"); - return fs.readFileSync(file, "utf8"); -}).join("\n\n"))(require("source-map"), exports); +var orig = require("../tools/node"); +// Get all AST-nodes +orig.utils.merge(orig, orig.ast); +orig.SourceMap = require("../lib/sourcemap").SourceMap; +orig.base54 = orig.utils.base54; +orig.defaults = orig.utils.defaults; +orig.mangle_properties = orig.propmangle.mangle_properties; +orig.reserve_quoted_keys = orig.propmangle.reserve_quoted_keys; +orig.JS_Parse_Error = orig.parser.JS_Parse_Error; +orig.tokenizer = orig.parser.tokenizer; +orig.is_identifier = orig.parser.is_identifier; +module.exports = orig; \ No newline at end of file diff --git a/tools/exports.js b/tools/exports.js index c09436ab..72f0561e 100644 --- a/tools/exports.js +++ b/tools/exports.js @@ -1,6 +1,8 @@ +exports["Compressor"] = Compressor; exports["Dictionary"] = Dictionary; exports["TreeWalker"] = TreeWalker; exports["TreeTransformer"] = TreeTransformer; exports["minify"] = minify; exports["parse"] = parse; exports["_push_uniq"] = push_uniq; +exports["string_template"] = string_template; diff --git a/tools/generate-exports.js b/tools/generate-exports.js new file mode 100644 index 00000000..30be127b --- /dev/null +++ b/tools/generate-exports.js @@ -0,0 +1,59 @@ +"use strict"; + +var UglifyJS = require("../tools/node"); +var fs = require("fs"); + +console.log = function (d) { + process.stdout.write(d + '\n'); +}; + +UglifyJS.FILES.forEach(function(filepath){ + var code = fs.readFileSync(filepath, "utf8"); + var filename = filepath.replace(/^.*?([-a-z]+)\.js$/g, "$1"); + + var AST = UglifyJS.parse(code, {filename: filepath}); + + var exportNames = []; + var walker = new UglifyJS.TreeWalker(function(node){ + if (node instanceof UglifyJS.ast.AST_Defun) { + exportNames.push(node.name.name); + } + if (node instanceof UglifyJS.ast.AST_Var) { + var def = node.definitions[0]; + var name = def.name.name; + var value = def.value; + // Skip = foo. + if (value instanceof UglifyJS.ast.AST_Dot && value.property == name) + return true; + // Skip = require(...) + if (value instanceof UglifyJS.ast.AST_Call && value.expression instanceof UglifyJS.ast.AST_SymbolRef && value.expression.name == "require") + return true; + exportNames.push(name); + } + return !(node instanceof UglifyJS.ast.AST_Toplevel); + }); + AST.walk(walker); + // Don't export identifiers starting with underscore + exportNames = exportNames.filter(name => name[0] != "_"); + if (exportNames.length == 0) + return; + // Use (utils.)merge instead of Object.assign for (very) old node + var exports = "merge(exports, {\n" + exportNames.map(function(name){ + return UglifyJS.string_template(' {name} : {name},', { name: name }); + }).join("\n") + "\n});"; + var imports = exportNames.map(function(name){ + return UglifyJS.string_template(UglifyJS.string_template('var {name} = {fn}.{name};', { name: name, fn: filename})); + }); + + console.log("\n// Exports for " + filename); + console.log(exports); + console.log("\n\n// Usage:") + console.log(UglifyJS.string_template('var {fn} = require("../lib/{fn}");', { fn: filename})); + console.log(imports.join("\n")); + + var result = code.replace(/\n+(exports\.\w+ = \w+;\n+)+$/, ""); + result = result.replace(/\n+Object\.assign\(exports, \{[\s\S]*?\}\);\n*$/, ""); + result = result.replace(/\n+merge\(exports, \{[\s\S]*?\}\);\n*$/, ""); + result += "\n\n" + exports + "\n"; + fs.writeFileSync(filepath, result, "utf8"); +}); diff --git a/tools/node.js b/tools/node.js index 2e8f2d5c..174e2b0d 100644 --- a/tools/node.js +++ b/tools/node.js @@ -5,7 +5,6 @@ var FILES = UglifyJS.FILES = [ "../lib/utils.js", "../lib/ast.js", "../lib/parse.js", - "../lib/transform.js", "../lib/scope.js", "../lib/output.js", "../lib/compress.js", @@ -18,7 +17,7 @@ var FILES = UglifyJS.FILES = [ return require.resolve(file); }); -new Function("MOZ_SourceMap", "exports", function() { +/*new Function("MOZ_SourceMap", "exports", function() { var code = FILES.map(function(file) { return fs.readFileSync(file, "utf8"); }); @@ -27,7 +26,33 @@ new Function("MOZ_SourceMap", "exports", function() { }())( require("source-map"), UglifyJS -); +);*/ + +var utils = require("../lib/utils"); +var output = require("../lib/output"); +var OutputStream = output.OutputStream; +var minify = require("../lib/minify").minify; +var ast = require("../lib/ast"); +var compress = require("../lib/compress"); +var parse = require("../lib/parse"); +var propmangle = require("../lib/propmangle"); +require("../lib/mozilla-ast"); + + +exports.utils = utils; +exports.OutputStream = OutputStream; +exports.minify = minify; +exports.ast = ast; +exports.parser = parse; +exports.parse = parse.parse; +exports.Compressor = compress.Compressor; +exports.Dictionary = utils.Dictionary; +exports.TreeWalker = ast.TreeWalker; +exports.TreeTransformer = ast.TreeTransformer; +exports.push_uniq = utils.push_uniq; +exports.string_template = utils.string_template; +exports.describe_ast = describe_ast; +exports.propmangle = propmangle; function describe_ast() { var out = OutputStream({ beautify: true }); From 13196026ebf72a46553c9bd1a1d769b052b34aeb Mon Sep 17 00:00:00 2001 From: Flamefire Date: Wed, 13 Jun 2018 12:50:22 +0200 Subject: [PATCH 2/2] Use AST.Node instead of AST_Node --- bin/uglifyjs | 21 +- lib/ast.js | 85 ++ lib/compress.js | 2190 +++++++++++++++++------------------- lib/minify.js | 25 +- lib/mozilla-ast.js | 277 ++--- lib/output.js | 390 +++---- lib/parse.js | 205 ++-- lib/propmangle.js | 50 +- lib/scope.js | 166 ++- test/mocha/cli.js | 2 +- test/mocha/spidermonkey.js | 2 +- test/node.js | 2 - tools/generate-exports.js | 8 +- tools/node.js | 29 +- 14 files changed, 1611 insertions(+), 1841 deletions(-) diff --git a/bin/uglifyjs b/bin/uglifyjs index 242eb70b..42d929ae 100755 --- a/bin/uglifyjs +++ b/bin/uglifyjs @@ -10,6 +10,7 @@ var info = require("../package.json"); var path = require("path"); var program = require("commander"); var UglifyJS = require("../tools/node"); +var AST = UglifyJS.AST; var skip_keys = [ "cname", "inlined", "parent_scope", "scope", "uses_eval", "uses_with" ]; var files = {}; @@ -182,11 +183,11 @@ if (program.self) { } function convert_ast(fn) { - return UglifyJS.ast.AST_Node.from_mozilla_ast(Object.keys(files).reduce(fn, null)); + return AST.Node.from_mozilla_ast(Object.keys(files).reduce(fn, null)); } function run() { - UglifyJS.ast.AST_Node.warn_function = function(msg) { + AST.Node.warn_function = function(msg) { print_error("WARN: " + msg); }; var content = program.sourceMap && program.sourceMap.content; @@ -260,11 +261,11 @@ function run() { return value.size() ? value.map(symdef) : undefined; } if (skip_key(key)) return; - if (value instanceof UglifyJS.ast.AST_Token) return; + if (value instanceof AST.Token) return; if (value instanceof UglifyJS.Dictionary) return; - if (value instanceof UglifyJS.ast.AST_Node) { + if (value instanceof AST.Node) { var result = { - _class: "AST_" + value.TYPE + _class: "AST." + value.TYPE }; value.CTOR.PROPS.forEach(function(prop) { result[prop] = value[prop]; @@ -359,27 +360,27 @@ function parse_js(flag) { code: false } }).ast.walk(new UglifyJS.TreeWalker(function(node) { - if (node instanceof UglifyJS.ast.AST_Assign) { + if (node instanceof AST.Assign) { var name = node.left.print_to_string(); var value = node.right; if (flag) { options[name] = value; - } else if (value instanceof UglifyJS.ast.AST_Array) { + } else if (value instanceof AST.Array) { options[name] = value.elements.map(to_string); } else { options[name] = to_string(value); } return true; } - if (node instanceof UglifyJS.ast.AST_Symbol || node instanceof UglifyJS.ast.AST_PropAccess) { + if (node instanceof AST.Symbol || node instanceof AST.PropAccess) { var name = node.print_to_string(); options[name] = true; return true; } - if (!(node instanceof UglifyJS.ast.AST_Sequence)) throw node; + if (!(node instanceof AST.Sequence)) throw node; function to_string(value) { - return value instanceof UglifyJS.ast.AST_Constant ? value.getValue() : value.print_to_string({ + return value instanceof AST.Constant ? value.getValue() : value.print_to_string({ quote_keys: true }); } diff --git a/lib/ast.js b/lib/ast.js index 37b1c2ba..46be2cd3 100644 --- a/lib/ast.js +++ b/lib/ast.js @@ -1193,4 +1193,89 @@ merge(exports, { TreeWalker : TreeWalker, TreeTransformer : TreeTransformer, first_in_statement : first_in_statement, + Token : AST_Token, + Node : AST_Node, + Statement : AST_Statement, + Debugger : AST_Debugger, + Directive : AST_Directive, + SimpleStatement : AST_SimpleStatement, + Block : AST_Block, + BlockStatement : AST_BlockStatement, + EmptyStatement : AST_EmptyStatement, + StatementWithBody : AST_StatementWithBody, + LabeledStatement : AST_LabeledStatement, + IterationStatement : AST_IterationStatement, + DWLoop : AST_DWLoop, + Do : AST_Do, + While : AST_While, + For : AST_For, + ForIn : AST_ForIn, + With : AST_With, + Scope : AST_Scope, + Toplevel : AST_Toplevel, + Lambda : AST_Lambda, + Accessor : AST_Accessor, + Function : AST_Function, + Defun : AST_Defun, + Jump : AST_Jump, + Exit : AST_Exit, + Return : AST_Return, + Throw : AST_Throw, + LoopControl : AST_LoopControl, + Break : AST_Break, + Continue : AST_Continue, + If : AST_If, + Switch : AST_Switch, + SwitchBranch : AST_SwitchBranch, + Default : AST_Default, + Case : AST_Case, + Try : AST_Try, + Catch : AST_Catch, + Finally : AST_Finally, + Definitions : AST_Definitions, + Var : AST_Var, + VarDef : AST_VarDef, + Call : AST_Call, + New : AST_New, + Sequence : AST_Sequence, + PropAccess : AST_PropAccess, + Dot : AST_Dot, + Sub : AST_Sub, + Unary : AST_Unary, + UnaryPrefix : AST_UnaryPrefix, + UnaryPostfix : AST_UnaryPostfix, + Binary : AST_Binary, + Conditional : AST_Conditional, + Assign : AST_Assign, + Array : AST_Array, + Object : AST_Object, + ObjectProperty : AST_ObjectProperty, + ObjectKeyVal : AST_ObjectKeyVal, + ObjectSetter : AST_ObjectSetter, + ObjectGetter : AST_ObjectGetter, + Symbol : AST_Symbol, + SymbolAccessor : AST_SymbolAccessor, + SymbolDeclaration : AST_SymbolDeclaration, + SymbolVar : AST_SymbolVar, + SymbolFunarg : AST_SymbolFunarg, + SymbolDefun : AST_SymbolDefun, + SymbolLambda : AST_SymbolLambda, + SymbolCatch : AST_SymbolCatch, + Label : AST_Label, + SymbolRef : AST_SymbolRef, + LabelRef : AST_LabelRef, + This : AST_This, + Constant : AST_Constant, + String : AST_String, + Number : AST_Number, + RegExp : AST_RegExp, + Atom : AST_Atom, + Null : AST_Null, + NaN : AST_NaN, + Undefined : AST_Undefined, + Hole : AST_Hole, + Infinity : AST_Infinity, + Boolean : AST_Boolean, + False : AST_False, + True : AST_True, }); diff --git a/lib/compress.js b/lib/compress.js index e4e5e434..f3c876cc 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -60,87 +60,11 @@ var Dictionary = utils.Dictionary; var HOP = utils.HOP; var MAP = utils.MAP; -var ast = require("./ast"); -var walk_body = ast.walk_body; -var TreeWalker = ast.TreeWalker; -var TreeTransformer = ast.TreeTransformer; -var first_in_statement = ast.first_in_statement; -var AST_Node = ast.AST_Node; -var AST_Statement = ast.AST_Statement; -var AST_Debugger = ast.AST_Debugger; -var AST_Directive = ast.AST_Directive; -var AST_SimpleStatement = ast.AST_SimpleStatement; -var AST_Block = ast.AST_Block; -var AST_BlockStatement = ast.AST_BlockStatement; -var AST_EmptyStatement = ast.AST_EmptyStatement; -var AST_LabeledStatement = ast.AST_LabeledStatement; -var AST_IterationStatement = ast.AST_IterationStatement; -var AST_DWLoop = ast.AST_DWLoop; -var AST_Do = ast.AST_Do; -var AST_While = ast.AST_While; -var AST_For = ast.AST_For; -var AST_ForIn = ast.AST_ForIn; -var AST_With = ast.AST_With; -var AST_Scope = ast.AST_Scope; -var AST_Toplevel = ast.AST_Toplevel; -var AST_Lambda = ast.AST_Lambda; -var AST_Accessor = ast.AST_Accessor; -var AST_Function = ast.AST_Function; -var AST_Defun = ast.AST_Defun; -var AST_Jump = ast.AST_Jump; -var AST_Exit = ast.AST_Exit; -var AST_Return = ast.AST_Return; -var AST_LoopControl = ast.AST_LoopControl; -var AST_Break = ast.AST_Break; -var AST_Continue = ast.AST_Continue; -var AST_If = ast.AST_If; -var AST_Switch = ast.AST_Switch; -var AST_SwitchBranch = ast.AST_SwitchBranch; -var AST_Default = ast.AST_Default; -var AST_Case = ast.AST_Case; -var AST_Try = ast.AST_Try; -var AST_Catch = ast.AST_Catch; -var AST_Finally = ast.AST_Finally; -var AST_Definitions = ast.AST_Definitions; -var AST_Var = ast.AST_Var; -var AST_VarDef = ast.AST_VarDef; -var AST_Call = ast.AST_Call; -var AST_New = ast.AST_New; -var AST_Sequence = ast.AST_Sequence; -var AST_PropAccess = ast.AST_PropAccess; -var AST_Dot = ast.AST_Dot; -var AST_Sub = ast.AST_Sub; -var AST_Unary = ast.AST_Unary; -var AST_UnaryPrefix = ast.AST_UnaryPrefix; -var AST_UnaryPostfix = ast.AST_UnaryPostfix; -var AST_Binary = ast.AST_Binary; -var AST_Conditional = ast.AST_Conditional; -var AST_Assign = ast.AST_Assign; -var AST_Array = ast.AST_Array; -var AST_Object = ast.AST_Object; -var AST_ObjectProperty = ast.AST_ObjectProperty; -var AST_ObjectKeyVal = ast.AST_ObjectKeyVal; -var AST_Symbol = ast.AST_Symbol; -var AST_SymbolDeclaration = ast.AST_SymbolDeclaration; -var AST_SymbolVar = ast.AST_SymbolVar; -var AST_SymbolFunarg = ast.AST_SymbolFunarg; -var AST_SymbolDefun = ast.AST_SymbolDefun; -var AST_SymbolLambda = ast.AST_SymbolLambda; -var AST_SymbolCatch = ast.AST_SymbolCatch; -var AST_SymbolRef = ast.AST_SymbolRef; -var AST_This = ast.AST_This; -var AST_Constant = ast.AST_Constant; -var AST_String = ast.AST_String; -var AST_Number = ast.AST_Number; -var AST_RegExp = ast.AST_RegExp; -var AST_Null = ast.AST_Null; -var AST_NaN = ast.AST_NaN; -var AST_Undefined = ast.AST_Undefined; -var AST_Hole = ast.AST_Hole; -var AST_Infinity = ast.AST_Infinity; -var AST_Boolean = ast.AST_Boolean; -var AST_False = ast.AST_False; -var AST_True = ast.AST_True; +var AST = require("./ast"); +var TreeTransformer = AST.TreeTransformer; +var TreeWalker = AST.TreeWalker; +var first_in_statement = AST.first_in_statement; +var walk_body = AST.walk_body; var parse = require("./parse"); var is_identifier_string = parse.is_identifier_string; @@ -252,7 +176,7 @@ merge(Compressor.prototype, { option: function(key) { return this.options[key] }, exposed: function(def) { if (def.global) for (var i = 0, len = def.orig.length; i < len; i++) - if (!this.toplevel[def.orig[i] instanceof AST_SymbolDefun ? "funcs" : "vars"]) + if (!this.toplevel[def.orig[i] instanceof AST.SymbolDefun ? "funcs" : "vars"]) return true; return false; }, @@ -292,7 +216,7 @@ merge(Compressor.prototype, { }, info: function() { if (this.options.warnings == "verbose") { - AST_Node.warn.apply(AST_Node, arguments); + AST.Node.warn.apply(AST.Node, arguments); } }, warn: function(text, props) { @@ -301,7 +225,7 @@ merge(Compressor.prototype, { var message = string_template(text, props); if (!(message in this.warnings_produced)) { this.warnings_produced[message] = true; - AST_Node.warn.apply(AST_Node, arguments); + AST.Node.warn.apply(AST.Node, arguments); } } }, @@ -310,20 +234,20 @@ merge(Compressor.prototype, { }, before: function(node, descend, in_list) { if (node._squeezed) return node; - var is_scope = node instanceof AST_Scope; + var is_scope = node instanceof AST.Scope; if (is_scope) { node.hoist_properties(this); node.hoist_declarations(this); } - // Before https://github.com/mishoo/UglifyJS2/pull/1602 AST_Node.optimize() - // would call AST_Node.transform() if a different instance of AST_Node is + // Before https://github.com/mishoo/UglifyJS2/pull/1602 AST.Node.optimize() + // would call AST.Node.transform() if a different instance of AST.Node is // produced after OPT(). // This corrupts TreeWalker.stack, which cause AST look-ups to malfunction. - // Migrate and defer all children's AST_Node.transform() to below, which - // will now happen after this parent AST_Node has been properly substituted + // Migrate and defer all children's AST.Node.transform() to below, which + // will now happen after this parent AST.Node has been properly substituted // thus gives a consistent AST snapshot. descend(node, this); - // Existing code relies on how AST_Node.optimize() worked, and omitting the + // Existing code relies on how AST.Node.optimize() worked, and omitting the // following replacement call would result in degraded efficiency of both // output and performance. descend(node, this); @@ -338,52 +262,52 @@ merge(Compressor.prototype, { }); (function(OPT) { - OPT(AST_Node, function(self, compressor) { + OPT(AST.Node, function(self, compressor) { return self; }); - AST_Node.DEFMETHOD("equivalent_to", function(node) { + AST.Node.DEFMETHOD("equivalent_to", function(node) { return this.TYPE == node.TYPE && this.print_to_string() == node.print_to_string(); }); - AST_Scope.DEFMETHOD("process_expression", function(insert, compressor) { + AST.Scope.DEFMETHOD("process_expression", function(insert, compressor) { var self = this; var tt = new TreeTransformer(function(node) { - if (insert && node instanceof AST_SimpleStatement) { - return make_node(AST_Return, node, { + if (insert && node instanceof AST.SimpleStatement) { + return make_node(AST.Return, node, { value: node.body }); } - if (!insert && node instanceof AST_Return) { + if (!insert && node instanceof AST.Return) { if (compressor) { var value = node.value && node.value.drop_side_effect_free(compressor, true); - return value ? make_node(AST_SimpleStatement, node, { + return value ? make_node(AST.SimpleStatement, node, { body: value - }) : make_node(AST_EmptyStatement, node); + }) : make_node(AST.EmptyStatement, node); } - return make_node(AST_SimpleStatement, node, { - body: node.value || make_node(AST_UnaryPrefix, node, { + return make_node(AST.SimpleStatement, node, { + body: node.value || make_node(AST.UnaryPrefix, node, { operator: "void", - expression: make_node(AST_Number, node, { + expression: make_node(AST.Number, node, { value: 0 }) }) }); } - if (node instanceof AST_Lambda && node !== self) { + if (node instanceof AST.Lambda && node !== self) { return node; } - if (node instanceof AST_Block) { + if (node instanceof AST.Block) { var index = node.body.length - 1; if (index >= 0) { node.body[index] = node.body[index].transform(tt); } - } else if (node instanceof AST_If) { + } else if (node instanceof AST.If) { node.body = node.body.transform(tt); if (node.alternative) { node.alternative = node.alternative.transform(tt); } - } else if (node instanceof AST_With) { + } else if (node instanceof AST.With) { node.body = node.body.transform(tt); } return node; @@ -393,22 +317,22 @@ merge(Compressor.prototype, { function read_property(obj, key) { key = get_value(key); - if (key instanceof AST_Node) return; + if (key instanceof AST.Node) return; var value; - if (obj instanceof AST_Array) { + if (obj instanceof AST.Array) { var elements = obj.elements; if (key == "length") return make_node_from_constant(elements.length, obj); if (typeof key == "number" && key in elements) value = elements[key]; - } else if (obj instanceof AST_Object) { + } else if (obj instanceof AST.Object) { key = "" + key; var props = obj.properties; for (var i = props.length; --i >= 0;) { var prop = props[i]; - if (!(prop instanceof AST_ObjectKeyVal)) return; + if (!(prop instanceof AST.ObjectKeyVal)) return; if (!value && props[i].key === key) value = props[i].value; } } - return value instanceof AST_SymbolRef && value.fixed_value() || value; + return value instanceof AST.SymbolRef && value.fixed_value() || value; } function is_modified(compressor, tw, node, value, level, immutable) { @@ -416,28 +340,28 @@ merge(Compressor.prototype, { var lhs = is_lhs(node, parent); if (lhs) return lhs; if (!immutable - && parent instanceof AST_Call + && parent instanceof AST.Call && parent.expression === node && !parent.is_expr_pure(compressor) - && (!(value instanceof AST_Function) - || !(parent instanceof AST_New) && value.contains_this())) { + && (!(value instanceof AST.Function) + || !(parent instanceof AST.New) && value.contains_this())) { return true; } - if (parent instanceof AST_Array) { + if (parent instanceof AST.Array) { return is_modified(compressor, tw, parent, parent, level + 1); } - if (parent instanceof AST_ObjectKeyVal && node === parent.value) { + if (parent instanceof AST.ObjectKeyVal && node === parent.value) { var obj = tw.parent(level + 1); return is_modified(compressor, tw, obj, obj, level + 2); } - if (parent instanceof AST_PropAccess && parent.expression === node) { + if (parent instanceof AST.PropAccess && parent.expression === node) { var prop = read_property(value, parent.property); return !immutable && is_modified(compressor, tw, parent, prop, level + 1); } } (function(def) { - def(AST_Node, noop); + def(AST.Node, noop); function reset_def(tw, compressor, def) { def.assignments = 0; @@ -451,11 +375,11 @@ merge(Compressor.prototype, { } else { def.fixed = false; } - if (def.fixed instanceof AST_Defun && !all(def.references, function(ref) { + if (def.fixed instanceof AST.Defun && !all(def.references, function(ref) { var scope = ref.scope; do { if (def.scope === scope) return true; - } while (scope instanceof AST_Function && (scope = scope.parent_scope)); + } while (scope instanceof AST.Function && (scope = scope.parent_scope)); })) { tw.defun_ids[def.id] = false; } @@ -480,7 +404,7 @@ merge(Compressor.prototype, { scope.may_call_this = noop; if (!scope.contains_this()) return; scope.functions.each(function(def) { - if (def.init instanceof AST_Defun && !(def.id in tw.defun_ids)) { + if (def.init instanceof AST.Defun && !(def.id in tw.defun_ids)) { tw.defun_ids[def.id] = false; } }); @@ -513,7 +437,7 @@ merge(Compressor.prototype, { function walk_defuns(tw, scope) { scope.functions.each(function(def) { - if (def.init instanceof AST_Defun && !tw.defun_visited[def.id]) { + if (def.init instanceof AST.Defun && !tw.defun_visited[def.id]) { tw.defun_ids[def.id] = tw.safe_ids; def.init.walk(tw); } @@ -536,12 +460,12 @@ merge(Compressor.prototype, { if (tw.safe_ids[def.id]) { if (def.fixed == null) { var orig = def.orig[0]; - if (orig instanceof AST_SymbolFunarg || orig.name == "arguments") return false; - def.fixed = make_node(AST_Undefined, orig); + if (orig instanceof AST.SymbolFunarg || orig.name == "arguments") return false; + def.fixed = make_node(AST.Undefined, orig); } return true; } - return def.fixed instanceof AST_Defun; + return def.fixed instanceof AST.Defun; } function safe_to_assign(tw, def, scope, value) { @@ -555,12 +479,12 @@ merge(Compressor.prototype, { if (!safe_to_read(tw, def)) return false; if (def.fixed === false) return false; if (def.fixed != null && (!value || def.references.length > def.assignments)) return false; - if (def.fixed instanceof AST_Defun) { - return value instanceof AST_Node && def.fixed.parent_scope === scope; + if (def.fixed instanceof AST.Defun) { + return value instanceof AST.Node && def.fixed.parent_scope === scope; } return all(def.orig, function(sym) { - return !(sym instanceof AST_SymbolDefun - || sym instanceof AST_SymbolLambda); + return !(sym instanceof AST.SymbolDefun + || sym instanceof AST.SymbolLambda); }); } @@ -574,47 +498,47 @@ merge(Compressor.prototype, { function is_immutable(value) { if (!value) return false; return value.is_constant() - || value instanceof AST_Lambda - || value instanceof AST_This; + || value instanceof AST.Lambda + || value instanceof AST.This; } function mark_escaped(tw, d, scope, node, value, level, depth) { var parent = tw.parent(level); if (value && value.is_constant()) return; - if (parent instanceof AST_Assign && parent.operator == "=" && node === parent.right - || parent instanceof AST_Call && (node !== parent.expression || parent instanceof AST_New) - || parent instanceof AST_Exit && node === parent.value && node.scope !== d.scope - || parent instanceof AST_VarDef && node === parent.value) { + if (parent instanceof AST.Assign && parent.operator == "=" && node === parent.right + || parent instanceof AST.Call && (node !== parent.expression || parent instanceof AST.New) + || parent instanceof AST.Exit && node === parent.value && node.scope !== d.scope + || parent instanceof AST.VarDef && node === parent.value) { if (depth > 1 && !(value && value.is_constant_expression(scope))) depth = 1; if (!d.escaped || d.escaped > depth) d.escaped = depth; return; - } else if (parent instanceof AST_Array - || parent instanceof AST_Binary && lazy_op[parent.operator] - || parent instanceof AST_Conditional && node !== parent.condition - || parent instanceof AST_Sequence && node === parent.tail_node()) { + } else if (parent instanceof AST.Array + || parent instanceof AST.Binary && lazy_op[parent.operator] + || parent instanceof AST.Conditional && node !== parent.condition + || parent instanceof AST.Sequence && node === parent.tail_node()) { mark_escaped(tw, d, scope, parent, parent, level + 1, depth); - } else if (parent instanceof AST_ObjectKeyVal && node === parent.value) { + } else if (parent instanceof AST.ObjectKeyVal && node === parent.value) { var obj = tw.parent(level + 1); mark_escaped(tw, d, scope, obj, obj, level + 2, depth); - } else if (parent instanceof AST_PropAccess && node === parent.expression) { + } else if (parent instanceof AST.PropAccess && node === parent.expression) { value = read_property(value, parent.property); mark_escaped(tw, d, scope, parent, value, level + 1, depth + 1); if (value) return; } if (level > 0) return; - if (parent instanceof AST_Sequence && node !== parent.tail_node()) return; - if (parent instanceof AST_SimpleStatement) return; + if (parent instanceof AST.Sequence && node !== parent.tail_node()) return; + if (parent instanceof AST.SimpleStatement) return; d.direct_access = true; } var suppressor = new TreeWalker(function(node) { - if (!(node instanceof AST_Symbol)) return; + if (!(node instanceof AST.Symbol)) return; var d = node.definition(); if (!d) return; - if (node instanceof AST_SymbolRef) d.references.push(node); + if (node instanceof AST.SymbolRef) d.references.push(node); d.fixed = false; }); - def(AST_Accessor, function(tw, descend, compressor) { + def(AST.Accessor, function(tw, descend, compressor) { push(tw); reset_variables(tw, compressor, this); descend(); @@ -622,10 +546,10 @@ merge(Compressor.prototype, { walk_defuns(tw, this); return true; }); - def(AST_Assign, function(tw, descend, compressor) { + def(AST.Assign, function(tw, descend, compressor) { var node = this; var sym = node.left; - if (!(sym instanceof AST_SymbolRef)) return; + if (!(sym instanceof AST.SymbolRef)) return; var d = sym.definition(); var fixed = d.fixed; if (!fixed && node.operator != "=") return; @@ -639,9 +563,9 @@ merge(Compressor.prototype, { d.fixed = eq ? function() { return node.right; } : function() { - return make_node(AST_Binary, node, { + return make_node(AST.Binary, node, { operator: node.operator.slice(0, -1), - left: fixed instanceof AST_Node ? fixed : fixed(), + left: fixed instanceof AST.Node ? fixed : fixed(), right: node.right }); }; @@ -651,7 +575,7 @@ merge(Compressor.prototype, { mark_escaped(tw, d, sym.scope, node, value, 0, 1); return true; }); - def(AST_Binary, function(tw) { + def(AST.Binary, function(tw) { if (!lazy_op[this.operator]) return; this.left.walk(tw); push(tw); @@ -659,19 +583,19 @@ merge(Compressor.prototype, { pop(tw); return true; }); - def(AST_Call, function(tw, descend) { - tw.find_parent(AST_Scope).may_call_this(); + def(AST.Call, function(tw, descend) { + tw.find_parent(AST.Scope).may_call_this(); var exp = this.expression; - if (!(exp instanceof AST_SymbolRef)) return; + if (!(exp instanceof AST.SymbolRef)) return; var def = exp.definition(); - if (!(def.fixed instanceof AST_Defun)) return; + if (!(def.fixed instanceof AST.Defun)) return; var defun = mark_defun(tw, def); if (!defun) return; descend(); defun.walk(tw); return true; }); - def(AST_Case, function(tw) { + def(AST.Case, function(tw) { push(tw); this.expression.walk(tw); pop(tw); @@ -680,7 +604,7 @@ merge(Compressor.prototype, { pop(tw); return true; }); - def(AST_Conditional, function(tw) { + def(AST.Conditional, function(tw) { this.condition.walk(tw); push(tw); this.consequent.walk(tw); @@ -690,13 +614,13 @@ merge(Compressor.prototype, { pop(tw); return true; }); - def(AST_Default, function(tw, descend) { + def(AST.Default, function(tw, descend) { push(tw); descend(); pop(tw); return true; }); - def(AST_Defun, function(tw, descend, compressor) { + def(AST.Defun, function(tw, descend, compressor) { var id = this.name.definition().id; if (tw.defun_visited[id]) return true; if (tw.defun_ids[id] !== tw.safe_ids) return true; @@ -709,7 +633,7 @@ merge(Compressor.prototype, { walk_defuns(tw, this); return true; }); - def(AST_Do, function(tw) { + def(AST.Do, function(tw) { var saved_loop = tw.in_loop; tw.in_loop = this; push(tw); @@ -723,7 +647,7 @@ merge(Compressor.prototype, { tw.in_loop = saved_loop; return true; }); - def(AST_For, function(tw) { + def(AST.For, function(tw) { if (this.init) this.init.walk(tw); var saved_loop = tw.in_loop; tw.in_loop = this; @@ -741,7 +665,7 @@ merge(Compressor.prototype, { tw.in_loop = saved_loop; return true; }); - def(AST_ForIn, function(tw) { + def(AST.ForIn, function(tw) { this.init.walk(suppressor); this.object.walk(tw); var saved_loop = tw.in_loop; @@ -752,14 +676,14 @@ merge(Compressor.prototype, { tw.in_loop = saved_loop; return true; }); - def(AST_Function, function(tw, descend, compressor) { + def(AST.Function, function(tw, descend, compressor) { var node = this; node.inlined = false; push(tw); reset_variables(tw, compressor, node); var iife; if (!node.name - && (iife = tw.parent()) instanceof AST_Call + && (iife = tw.parent()) instanceof AST.Call && iife.expression === node) { // Virtually turn IIFE parameters into variable definitions: // (function(a,b) {...})(c,d) => (function() {var a=c,b=d; ...})() @@ -768,7 +692,7 @@ merge(Compressor.prototype, { var d = arg.definition(); if (!node.uses_arguments && d.fixed === undefined) { d.fixed = function() { - return iife.args[i] || make_node(AST_Undefined, iife); + return iife.args[i] || make_node(AST.Undefined, iife); }; tw.loop_ids[d.id] = tw.in_loop; mark(tw, d, true); @@ -782,7 +706,7 @@ merge(Compressor.prototype, { walk_defuns(tw, node); return true; }); - def(AST_If, function(tw) { + def(AST.If, function(tw) { this.condition.walk(tw); push(tw); this.body.walk(tw); @@ -794,21 +718,21 @@ merge(Compressor.prototype, { } return true; }); - def(AST_LabeledStatement, function(tw) { + def(AST.LabeledStatement, function(tw) { push(tw); this.body.walk(tw); pop(tw); return true; }); - def(AST_SymbolCatch, function() { + def(AST.SymbolCatch, function() { this.definition().fixed = false; }); - def(AST_SymbolRef, function(tw, descend, compressor) { + def(AST.SymbolRef, function(tw, descend, compressor) { var d = this.definition(); d.references.push(this); if (d.references.length == 1 && !d.fixed - && d.orig[0] instanceof AST_SymbolDefun) { + && d.orig[0] instanceof AST.SymbolDefun) { tw.loop_ids[d.id] = tw.in_loop; } var value; @@ -816,10 +740,10 @@ merge(Compressor.prototype, { d.fixed = false; } else if (d.fixed) { value = this.fixed_value(); - if (value instanceof AST_Lambda && recursive_ref(tw, d)) { + if (value instanceof AST.Lambda && recursive_ref(tw, d)) { d.recursive_refs++; } else if (value && ref_once(tw, compressor, d)) { - d.single_use = value instanceof AST_Lambda && !value.pinned() + d.single_use = value instanceof AST.Lambda && !value.pinned() || d.scope === this.scope && value.is_constant_expression(); } else { d.single_use = false; @@ -834,13 +758,13 @@ merge(Compressor.prototype, { } mark_escaped(tw, d, this.scope, this, value, 0, 1); var parent; - if (d.fixed instanceof AST_Defun - && !((parent = tw.parent()) instanceof AST_Call && parent.expression === this)) { + if (d.fixed instanceof AST.Defun + && !((parent = tw.parent()) instanceof AST.Call && parent.expression === this)) { var defun = mark_defun(tw, d); if (defun) defun.walk(tw); } }); - def(AST_Toplevel, function(tw, descend, compressor) { + def(AST.Toplevel, function(tw, descend, compressor) { this.globals.each(function(def) { reset_def(tw, compressor, def); }); @@ -851,7 +775,7 @@ merge(Compressor.prototype, { walk_defuns(tw, this); return true; }); - def(AST_Try, function(tw) { + def(AST.Try, function(tw) { push(tw); walk_body(this, tw); pop(tw); @@ -863,11 +787,11 @@ merge(Compressor.prototype, { if (this.bfinally) this.bfinally.walk(tw); return true; }); - def(AST_Unary, function(tw, descend) { + def(AST.Unary, function(tw, descend) { var node = this; if (node.operator != "++" && node.operator != "--") return; var exp = node.expression; - if (!(exp instanceof AST_SymbolRef)) return; + if (!(exp instanceof AST.SymbolRef)) return; var d = exp.definition(); var fixed = d.fixed; if (!fixed) return; @@ -876,13 +800,13 @@ merge(Compressor.prototype, { d.assignments++; d.chained = true; d.fixed = function() { - return make_node(AST_Binary, node, { + return make_node(AST.Binary, node, { operator: node.operator.slice(0, -1), - left: make_node(AST_UnaryPrefix, node, { + left: make_node(AST.UnaryPrefix, node, { operator: "+", - expression: fixed instanceof AST_Node ? fixed : fixed() + expression: fixed instanceof AST.Node ? fixed : fixed() }), - right: make_node(AST_Number, node, { + right: make_node(AST.Number, node, { value: 1 }) }); @@ -890,7 +814,7 @@ merge(Compressor.prototype, { mark(tw, d, true); return true; }); - def(AST_VarDef, function(tw, descend) { + def(AST.VarDef, function(tw, descend) { var node = this; var d = node.name.definition(); if (node.value) { @@ -908,7 +832,7 @@ merge(Compressor.prototype, { } } }); - def(AST_While, function(tw, descend) { + def(AST.While, function(tw, descend) { var saved_loop = tw.in_loop; tw.in_loop = this; push(tw); @@ -921,7 +845,7 @@ merge(Compressor.prototype, { node.DEFMETHOD("reduce_vars", func); }); - AST_Toplevel.DEFMETHOD("reset_opt_flags", function(compressor) { + AST.Toplevel.DEFMETHOD("reset_opt_flags", function(compressor) { var tw = new TreeWalker(compressor.option("reduce_vars") ? function(node, descend) { node._squeezed = false; node._optimized = false; @@ -930,10 +854,10 @@ merge(Compressor.prototype, { node._squeezed = false; node._optimized = false; }); - // Flow control for visiting `AST_Defun`s + // Flow control for visiting `AST.Defun`s tw.defun_ids = Object.create(null); tw.defun_visited = Object.create(null); - // Record the loop body in which `AST_SymbolDeclaration` is first encountered + // Record the loop body in which `AST.SymbolDeclaration` is first encountered tw.in_loop = null; tw.loop_ids = Object.create(null); // Stack of look-up tables to keep track of whether a `SymbolDef` has been @@ -944,23 +868,23 @@ merge(Compressor.prototype, { this.walk(tw); }); - AST_Symbol.DEFMETHOD("fixed_value", function() { + AST.Symbol.DEFMETHOD("fixed_value", function() { var fixed = this.definition().fixed; - if (!fixed || fixed instanceof AST_Node) return fixed; + if (!fixed || fixed instanceof AST.Node) return fixed; return fixed(); }); - AST_SymbolRef.DEFMETHOD("is_immutable", function() { + AST.SymbolRef.DEFMETHOD("is_immutable", function() { var orig = this.definition().orig; - return orig.length == 1 && orig[0] instanceof AST_SymbolLambda; + return orig.length == 1 && orig[0] instanceof AST.SymbolLambda; }); function is_lhs_read_only(lhs) { - if (lhs instanceof AST_This) return true; - if (lhs instanceof AST_SymbolRef) return lhs.definition().orig[0] instanceof AST_SymbolLambda; - if (lhs instanceof AST_PropAccess) { + if (lhs instanceof AST.This) return true; + if (lhs instanceof AST.SymbolRef) return lhs.definition().orig[0] instanceof AST.SymbolLambda; + if (lhs instanceof AST.PropAccess) { lhs = lhs.expression; - if (lhs instanceof AST_SymbolRef) { + if (lhs instanceof AST.SymbolRef) { if (lhs.is_immutable()) return false; lhs = lhs.fixed_value(); } @@ -974,8 +898,8 @@ merge(Compressor.prototype, { function find_variable(compressor, name) { var scope, i = 0; while (scope = compressor.parent(i++)) { - if (scope instanceof AST_Scope) break; - if (scope instanceof AST_Catch) { + if (scope instanceof AST.Scope) break; + if (scope instanceof AST.Catch) { scope = scope.argname.definition().scope; break; } @@ -994,7 +918,7 @@ merge(Compressor.prototype, { function make_sequence(orig, expressions) { if (expressions.length == 1) return expressions[0]; - return make_node(AST_Sequence, orig, { + return make_node(AST.Sequence, orig, { expressions: expressions.reduce(merge_sequence, []) }); } @@ -1002,31 +926,31 @@ merge(Compressor.prototype, { function make_node_from_constant(val, orig) { switch (typeof val) { case "string": - return make_node(AST_String, orig, { + return make_node(AST.String, orig, { value: val }); case "number": - if (isNaN(val)) return make_node(AST_NaN, orig); + if (isNaN(val)) return make_node(AST.NaN, orig); if (isFinite(val)) { - return 1 / val < 0 ? make_node(AST_UnaryPrefix, orig, { + return 1 / val < 0 ? make_node(AST.UnaryPrefix, orig, { operator: "-", - expression: make_node(AST_Number, orig, { value: -val }) - }) : make_node(AST_Number, orig, { value: val }); + expression: make_node(AST.Number, orig, { value: -val }) + }) : make_node(AST.Number, orig, { value: val }); } - return val < 0 ? make_node(AST_UnaryPrefix, orig, { + return val < 0 ? make_node(AST.UnaryPrefix, orig, { operator: "-", - expression: make_node(AST_Infinity, orig) - }) : make_node(AST_Infinity, orig); + expression: make_node(AST.Infinity, orig) + }) : make_node(AST.Infinity, orig); case "boolean": - return make_node(val ? AST_True : AST_False, orig); + return make_node(val ? AST.True : AST.False, orig); case "undefined": - return make_node(AST_Undefined, orig); + return make_node(AST.Undefined, orig); default: if (val === null) { - return make_node(AST_Null, orig, { value: null }); + return make_node(AST.Null, orig, { value: null }); } if (val instanceof RegExp) { - return make_node(AST_RegExp, orig, { value: val }); + return make_node(AST.RegExp, orig, { value: val }); } throw new Error(string_template("Can't handle constant of type: {type}", { type: typeof val @@ -1035,7 +959,7 @@ merge(Compressor.prototype, { } function needs_unbinding(compressor, val) { - return val instanceof AST_PropAccess + return val instanceof AST.PropAccess || compressor.has_directive("use strict") && is_undeclared_ref(val) && val.name == "eval"; @@ -1045,15 +969,15 @@ merge(Compressor.prototype, { // func(something) because that changes the meaning of // the func (becomes lexical instead of global). function maintain_this_binding(compressor, parent, orig, val) { - if (parent instanceof AST_UnaryPrefix && parent.operator == "delete" + if (parent instanceof AST.UnaryPrefix && parent.operator == "delete" || parent.TYPE == "Call" && parent.expression === orig && needs_unbinding(compressor, val)) { - return make_sequence(orig, [ make_node(AST_Number, orig, { value: 0 }), val ]); + return make_sequence(orig, [ make_node(AST.Number, orig, { value: 0 }), val ]); } return val; } function merge_sequence(array, node) { - if (node instanceof AST_Sequence) { + if (node instanceof AST.Sequence) { array.push.apply(array, node.expressions); } else { array.push(node); @@ -1063,51 +987,51 @@ merge(Compressor.prototype, { function as_statement_array(thing) { if (thing === null) return []; - if (thing instanceof AST_BlockStatement) return thing.body; - if (thing instanceof AST_EmptyStatement) return []; - if (thing instanceof AST_Statement) return [ thing ]; + if (thing instanceof AST.BlockStatement) return thing.body; + if (thing instanceof AST.EmptyStatement) return []; + if (thing instanceof AST.Statement) return [ thing ]; throw new Error("Can't convert thing to statement array"); } function is_empty(thing) { if (thing === null) return true; - if (thing instanceof AST_EmptyStatement) return true; - if (thing instanceof AST_BlockStatement) return thing.body.length == 0; + if (thing instanceof AST.EmptyStatement) return true; + if (thing instanceof AST.BlockStatement) return thing.body.length == 0; return false; } function loop_body(x) { - if (x instanceof AST_IterationStatement) { - return x.body instanceof AST_BlockStatement ? x.body : x; + if (x instanceof AST.IterationStatement) { + return x.body instanceof AST.BlockStatement ? x.body : x; } return x; } function root_expr(prop) { - while (prop instanceof AST_PropAccess) prop = prop.expression; + while (prop instanceof AST.PropAccess) prop = prop.expression; return prop; } function is_iife_call(node) { if (node.TYPE != "Call") return false; - return node.expression instanceof AST_Function || is_iife_call(node.expression); + return node.expression instanceof AST.Function || is_iife_call(node.expression); } function is_undeclared_ref(node) { - return node instanceof AST_SymbolRef && node.definition().undeclared; + return node instanceof AST.SymbolRef && node.definition().undeclared; } var global_names = makePredicate("Array Boolean clearInterval clearTimeout console Date decodeURI decodeURIComponent encodeURI encodeURIComponent Error escape eval EvalError Function isFinite isNaN JSON Math Number parseFloat parseInt RangeError ReferenceError RegExp Object setInterval setTimeout String SyntaxError TypeError unescape URIError"); - AST_SymbolRef.DEFMETHOD("is_declared", function(compressor) { + AST.SymbolRef.DEFMETHOD("is_declared", function(compressor) { return !this.definition().undeclared || compressor.option("unsafe") && global_names[this.name]; }); var identifier_atom = makePredicate("Infinity NaN undefined"); function is_identifier_atom(node) { - return node instanceof AST_Infinity - || node instanceof AST_NaN - || node instanceof AST_Undefined; + return node instanceof AST.Infinity + || node instanceof AST.NaN + || node instanceof AST.Undefined; } function tighten_body(statements, compressor) { @@ -1138,14 +1062,14 @@ merge(Compressor.prototype, { function find_loop_scope_try() { var node = compressor.self(), level = 0; do { - if (node instanceof AST_Catch || node instanceof AST_Finally) { + if (node instanceof AST.Catch || node instanceof AST.Finally) { level++; - } else if (node instanceof AST_IterationStatement) { + } else if (node instanceof AST.IterationStatement) { in_loop = true; - } else if (node instanceof AST_Scope) { + } else if (node instanceof AST.Scope) { scope = node; break; - } else if (node instanceof AST_Try) { + } else if (node instanceof AST.Try) { in_try = true; } } while (node = compressor.parent(level++)); @@ -1189,7 +1113,7 @@ merge(Compressor.prototype, { // Replace variable with assignment when found var hit_lhs, hit_rhs; if (can_replace - && !(node instanceof AST_SymbolDeclaration) + && !(node instanceof AST.SymbolDeclaration) && (scan_lhs && (hit_lhs = lhs.equivalent_to(node)) || scan_rhs && (hit_rhs = scan_rhs(node, this)))) { if (stop_if_hit && (hit_rhs || !lhs_local || !replace_all)) { @@ -1201,7 +1125,7 @@ merge(Compressor.prototype, { return node; } else { replaced++; - if (value_def && candidate instanceof AST_VarDef) return node; + if (value_def && candidate instanceof AST.VarDef) return node; } CHANGED = abort = true; compressor.info("Collapsing {name} [{file}:{line},{col}]", { @@ -1210,18 +1134,18 @@ merge(Compressor.prototype, { line: node.start.line, col: node.start.col }); - if (candidate instanceof AST_UnaryPostfix) { - return make_node(AST_UnaryPrefix, candidate, candidate); + if (candidate instanceof AST.UnaryPostfix) { + return make_node(AST.UnaryPrefix, candidate, candidate); } - if (candidate instanceof AST_VarDef) { + if (candidate instanceof AST.VarDef) { var def = candidate.name.definition(); if (def.references.length - def.replaced == 1 && !compressor.exposed(def)) { def.replaced++; return maintain_this_binding(compressor, parent, node, candidate.value); } - return make_node(AST_Assign, candidate, { + return make_node(AST.Assign, candidate, { operator: "=", - left: make_node(AST_SymbolRef, candidate.name, candidate.name), + left: make_node(AST.SymbolRef, candidate.name, candidate.name), right: candidate.value }); } @@ -1233,7 +1157,7 @@ merge(Compressor.prototype, { var sym; if (is_last_node(node, parent) || may_throw(node)) { stop_after = node; - if (node instanceof AST_Scope) abort = true; + if (node instanceof AST.Scope) abort = true; } return handle_custom_scan_order(node); }, function(node) { @@ -1252,7 +1176,7 @@ merge(Compressor.prototype, { return node; } // Replace variable when found - if (node instanceof AST_SymbolRef + if (node instanceof AST.SymbolRef && node.name == def.name) { if (!--replaced) abort = true; if (is_lhs(node, multi_replacer.parent())) return node; @@ -1261,7 +1185,7 @@ merge(Compressor.prototype, { return candidate.value.clone(); } // Skip (non-executed) functions and (leading) default case in switch statements - if (node instanceof AST_Default || node instanceof AST_Scope) return node; + if (node instanceof AST.Default || node instanceof AST.Scope) return node; }); while (--stat_index >= 0) { // Treat parameters as collapsible in IIFE, i.e. @@ -1293,7 +1217,7 @@ merge(Compressor.prototype, { var may_throw = candidate.may_throw(compressor) ? in_try ? function(node) { return node.has_side_effects(compressor); } : side_effects_external : return_false; - var funarg = candidate.name instanceof AST_SymbolFunarg; + var funarg = candidate.name instanceof AST.SymbolFunarg; var hit = funarg; var abort = false, replaced = 0, can_replace = !args || !hit; if (!can_replace) { @@ -1324,13 +1248,13 @@ merge(Compressor.prototype, { function handle_custom_scan_order(node) { // Skip (non-executed) functions - if (node instanceof AST_Scope) return node; + if (node instanceof AST.Scope) return node; // Scan case expressions first in a switch statement - if (node instanceof AST_Switch) { + if (node instanceof AST.Switch) { node.expression = node.expression.transform(scanner); for (var i = 0, len = node.body.length; !abort && i < len; i++) { var branch = node.body[i]; - if (branch instanceof AST_Case) { + if (branch instanceof AST.Case) { if (!hit) { if (branch !== hit_stack[hit_index]) continue; hit_index++; @@ -1345,59 +1269,59 @@ merge(Compressor.prototype, { } function should_stop(node, parent) { - if (parent instanceof AST_For) return node !== parent.init; - if (node instanceof AST_Assign) { + if (parent instanceof AST.For) return node !== parent.init; + if (node instanceof AST.Assign) { return node.operator != "=" && lhs.equivalent_to(node.left); } - if (node instanceof AST_Call) { - return lhs instanceof AST_PropAccess && lhs.equivalent_to(node.expression); + if (node instanceof AST.Call) { + return lhs instanceof AST.PropAccess && lhs.equivalent_to(node.expression); } - if (node instanceof AST_Debugger) return true; - if (node instanceof AST_IterationStatement) return !(node instanceof AST_For); - if (node instanceof AST_LoopControl) return true; - if (node instanceof AST_Try) return true; - if (node instanceof AST_With) return true; + if (node instanceof AST.Debugger) return true; + if (node instanceof AST.IterationStatement) return !(node instanceof AST.For); + if (node instanceof AST.LoopControl) return true; + if (node instanceof AST.Try) return true; + if (node instanceof AST.With) return true; if (replace_all) return false; - return node instanceof AST_SymbolRef && !node.is_declared(compressor); + return node instanceof AST.SymbolRef && !node.is_declared(compressor); } function in_conditional(node, parent) { - if (parent instanceof AST_Binary) return lazy_op[parent.operator] && parent.left !== node; - if (parent instanceof AST_Conditional) return parent.condition !== node; - return parent instanceof AST_If && parent.condition !== node; + if (parent instanceof AST.Binary) return lazy_op[parent.operator] && parent.left !== node; + if (parent instanceof AST.Conditional) return parent.condition !== node; + return parent instanceof AST.If && parent.condition !== node; } function is_last_node(node, parent) { - if (node instanceof AST_Call) return true; - if (node instanceof AST_Exit) { - return side_effects || lhs instanceof AST_PropAccess || may_modify(lhs); + if (node instanceof AST.Call) return true; + if (node instanceof AST.Exit) { + return side_effects || lhs instanceof AST.PropAccess || may_modify(lhs); } - if (node instanceof AST_PropAccess) { + if (node instanceof AST.PropAccess) { return side_effects || node.expression.may_throw_on_access(compressor); } - if (node instanceof AST_SymbolRef) { + if (node instanceof AST.SymbolRef) { if (symbol_in_lvalues(node, parent)) { return !parent || parent.operator != "=" || parent.left !== node; } return side_effects && may_modify(node); } - if (node instanceof AST_This) return symbol_in_lvalues(node, parent); - if (node instanceof AST_VarDef) { + if (node instanceof AST.This) return symbol_in_lvalues(node, parent); + if (node instanceof AST.VarDef) { if (!node.value) return false; return node.name.name in lvalues || side_effects && may_modify(node.name); } var sym = is_lhs(node.left, node); if (sym && sym.name in lvalues) return true; - if (sym instanceof AST_PropAccess) return true; + if (sym instanceof AST.PropAccess) return true; } function extract_args() { var iife, fn = compressor.self(); - if (fn instanceof AST_Function + if (fn instanceof AST.Function && !fn.name && !fn.uses_arguments && !fn.pinned() - && (iife = compressor.parent()) instanceof AST_Call + && (iife = compressor.parent()) instanceof AST.Call && iife.expression === fn) { var fn_strict = compressor.has_directive("use strict"); if (fn_strict && !member(fn_strict, fn.body)) fn_strict = false; @@ -1407,33 +1331,33 @@ merge(Compressor.prototype, { for (var i = len; --i >= 0;) { var sym = fn.argnames[i]; var arg = iife.args[i]; - args.unshift(make_node(AST_VarDef, sym, { + args.unshift(make_node(AST.VarDef, sym, { name: sym, value: arg })); if (sym.name in names) continue; names[sym.name] = true; if (!arg) { - arg = make_node(AST_Undefined, sym).transform(compressor); - } else if (arg instanceof AST_Lambda && arg.pinned()) { + arg = make_node(AST.Undefined, sym).transform(compressor); + } else if (arg instanceof AST.Lambda && arg.pinned()) { arg = null; } else { arg.walk(new TreeWalker(function(node) { if (!arg) return true; - if (node instanceof AST_SymbolRef && fn.variables.has(node.name)) { + if (node instanceof AST.SymbolRef && fn.variables.has(node.name)) { var s = node.definition().scope; if (s !== scope) while (s = s.parent_scope) { if (s === scope) return true; } arg = null; } - if (node instanceof AST_This && (fn_strict || !this.find_parent(AST_Scope))) { + if (node instanceof AST.This && (fn_strict || !this.find_parent(AST.Scope))) { arg = null; return true; } })); } - if (arg) candidates.unshift([ make_node(AST_VarDef, sym, { + if (arg) candidates.unshift([ make_node(AST.VarDef, sym, { name: sym, value: arg }) ]); @@ -1443,64 +1367,64 @@ merge(Compressor.prototype, { function extract_candidates(expr) { hit_stack.push(expr); - if (expr instanceof AST_Assign) { + if (expr instanceof AST.Assign) { candidates.push(hit_stack.slice()); extract_candidates(expr.right); - } else if (expr instanceof AST_Binary) { + } else if (expr instanceof AST.Binary) { extract_candidates(expr.left); extract_candidates(expr.right); - } else if (expr instanceof AST_Call) { + } else if (expr instanceof AST.Call) { extract_candidates(expr.expression); expr.args.forEach(extract_candidates); - } else if (expr instanceof AST_Case) { + } else if (expr instanceof AST.Case) { extract_candidates(expr.expression); - } else if (expr instanceof AST_Conditional) { + } else if (expr instanceof AST.Conditional) { extract_candidates(expr.condition); extract_candidates(expr.consequent); extract_candidates(expr.alternative); - } else if (expr instanceof AST_Definitions) { + } else if (expr instanceof AST.Definitions) { expr.definitions.forEach(extract_candidates); - } else if (expr instanceof AST_DWLoop) { + } else if (expr instanceof AST.DWLoop) { extract_candidates(expr.condition); - if (!(expr.body instanceof AST_Block)) { + if (!(expr.body instanceof AST.Block)) { extract_candidates(expr.body); } - } else if (expr instanceof AST_Exit) { + } else if (expr instanceof AST.Exit) { if (expr.value) extract_candidates(expr.value); - } else if (expr instanceof AST_For) { + } else if (expr instanceof AST.For) { if (expr.init) extract_candidates(expr.init); if (expr.condition) extract_candidates(expr.condition); if (expr.step) extract_candidates(expr.step); - if (!(expr.body instanceof AST_Block)) { + if (!(expr.body instanceof AST.Block)) { extract_candidates(expr.body); } - } else if (expr instanceof AST_ForIn) { + } else if (expr instanceof AST.ForIn) { extract_candidates(expr.object); - if (!(expr.body instanceof AST_Block)) { + if (!(expr.body instanceof AST.Block)) { extract_candidates(expr.body); } - } else if (expr instanceof AST_If) { + } else if (expr instanceof AST.If) { extract_candidates(expr.condition); - if (!(expr.body instanceof AST_Block)) { + if (!(expr.body instanceof AST.Block)) { extract_candidates(expr.body); } - if (expr.alternative && !(expr.alternative instanceof AST_Block)) { + if (expr.alternative && !(expr.alternative instanceof AST.Block)) { extract_candidates(expr.alternative); } - } else if (expr instanceof AST_Sequence) { + } else if (expr instanceof AST.Sequence) { expr.expressions.forEach(extract_candidates); - } else if (expr instanceof AST_SimpleStatement) { + } else if (expr instanceof AST.SimpleStatement) { extract_candidates(expr.body); - } else if (expr instanceof AST_Switch) { + } else if (expr instanceof AST.Switch) { extract_candidates(expr.expression); expr.body.forEach(extract_candidates); - } else if (expr instanceof AST_Unary) { + } else if (expr instanceof AST.Unary) { if (expr.operator == "++" || expr.operator == "--") { candidates.push(hit_stack.slice()); } else { extract_candidates(expr.expression); } - } else if (expr instanceof AST_VarDef) { + } else if (expr instanceof AST.VarDef) { if (expr.value) { var def = expr.name.definition(); if (def.references.length > def.replaced) { @@ -1514,56 +1438,56 @@ merge(Compressor.prototype, { function find_stop(node, level, write_only) { var parent = scanner.parent(level); - if (parent instanceof AST_Assign) { + if (parent instanceof AST.Assign) { if (write_only - && !(parent.left instanceof AST_PropAccess + && !(parent.left instanceof AST.PropAccess || parent.left.name in lvalues)) { return find_stop(parent, level + 1, write_only); } return node; } - if (parent instanceof AST_Binary) { + if (parent instanceof AST.Binary) { if (write_only && (!lazy_op[parent.operator] || parent.left === node)) { return find_stop(parent, level + 1, write_only); } return node; } - if (parent instanceof AST_Call) return node; - if (parent instanceof AST_Case) return node; - if (parent instanceof AST_Conditional) { + if (parent instanceof AST.Call) return node; + if (parent instanceof AST.Case) return node; + if (parent instanceof AST.Conditional) { if (write_only && parent.condition === node) { return find_stop(parent, level + 1, write_only); } return node; } - if (parent instanceof AST_Definitions) { + if (parent instanceof AST.Definitions) { return find_stop(parent, level + 1, true); } - if (parent instanceof AST_Exit) { + if (parent instanceof AST.Exit) { return write_only ? find_stop(parent, level + 1, write_only) : node; } - if (parent instanceof AST_If) { + if (parent instanceof AST.If) { if (write_only && parent.condition === node) { return find_stop(parent, level + 1, write_only); } return node; } - if (parent instanceof AST_IterationStatement) return node; - if (parent instanceof AST_Sequence) { + if (parent instanceof AST.IterationStatement) return node; + if (parent instanceof AST.Sequence) { return find_stop(parent, level + 1, parent.tail_node() !== node); } - if (parent instanceof AST_SimpleStatement) { + if (parent instanceof AST.SimpleStatement) { return find_stop(parent, level + 1, true); } - if (parent instanceof AST_Switch) return node; - if (parent instanceof AST_Unary) return node; - if (parent instanceof AST_VarDef) return node; + if (parent instanceof AST.Switch) return node; + if (parent instanceof AST.Unary) return node; + if (parent instanceof AST.VarDef) return node; return null; } function mangleable_var(var_def) { var value = var_def.value; - if (!(value instanceof AST_SymbolRef)) return; + if (!(value instanceof AST.SymbolRef)) return; if (value.name == "arguments") return; var def = value.definition(); if (def.undeclared) return; @@ -1571,47 +1495,47 @@ merge(Compressor.prototype, { } function get_lhs(expr) { - if (expr instanceof AST_VarDef) { + if (expr instanceof AST.VarDef) { var def = expr.name.definition(); if (!member(expr.name, def.orig)) return; var referenced = def.references.length - def.replaced; var declared = def.orig.length - def.eliminated; - if (declared > 1 && !(expr.name instanceof AST_SymbolFunarg) + if (declared > 1 && !(expr.name instanceof AST.SymbolFunarg) || (referenced > 1 ? mangleable_var(expr) : !compressor.exposed(def))) { - return make_node(AST_SymbolRef, expr.name, expr.name); + return make_node(AST.SymbolRef, expr.name, expr.name); } } else { - return expr[expr instanceof AST_Assign ? "left" : "expression"]; + return expr[expr instanceof AST.Assign ? "left" : "expression"]; } } function get_rhs(expr) { - if (!(candidate instanceof AST_Assign && candidate.operator == "=")) return; + if (!(candidate instanceof AST.Assign && candidate.operator == "=")) return; return candidate.right; } function get_rvalue(expr) { - return expr[expr instanceof AST_Assign ? "right" : "value"]; + return expr[expr instanceof AST.Assign ? "right" : "value"]; } function foldable(expr) { - if (expr instanceof AST_SymbolRef) { + if (expr instanceof AST.SymbolRef) { var value = expr.evaluate(compressor); if (value === expr) return rhs_exact_match; return rhs_fuzzy_match(value, rhs_exact_match); } - if (expr instanceof AST_This) return rhs_exact_match; + if (expr instanceof AST.This) return rhs_exact_match; if (expr.is_truthy()) return rhs_fuzzy_match(true, return_false); if (expr.is_constant()) { return rhs_fuzzy_match(expr.evaluate(compressor), rhs_exact_match); } - if (!(lhs instanceof AST_SymbolRef)) return false; + if (!(lhs instanceof AST.SymbolRef)) return false; if (expr.has_side_effects(compressor)) return false; var circular; var def = lhs.definition(); expr.walk(new TreeWalker(function(node) { if (circular) return true; - if (node instanceof AST_SymbolRef && node.definition() === def) { + if (node instanceof AST.SymbolRef && node.definition() === def) { circular = true; } })); @@ -1638,12 +1562,12 @@ merge(Compressor.prototype, { function get_lvalues(expr) { var lvalues = Object.create(null); - if (candidate instanceof AST_VarDef) { + if (candidate instanceof AST.VarDef) { lvalues[candidate.name.name] = lhs; } var tw = new TreeWalker(function(node) { var sym = root_expr(node); - if (sym instanceof AST_SymbolRef || sym instanceof AST_This) { + if (sym instanceof AST.SymbolRef || sym instanceof AST.This) { lvalues[sym.name] = lvalues[sym.name] || is_modified(compressor, tw, node, node, 0); } }); @@ -1652,10 +1576,10 @@ merge(Compressor.prototype, { } function remove_candidate(expr) { - if (expr.name instanceof AST_SymbolFunarg) { + if (expr.name instanceof AST.SymbolFunarg) { var index = compressor.self().argnames.indexOf(expr.name); var args = compressor.parent().args; - if (args[index]) args[index] = make_node(AST_Number, args[index], { + if (args[index]) args[index] = make_node(AST.Number, args[index], { value: 0 }); return true; @@ -1665,14 +1589,14 @@ merge(Compressor.prototype, { if (found) return node; if (node === expr || node.body === expr) { found = true; - if (node instanceof AST_VarDef) { + if (node instanceof AST.VarDef) { node.value = null; return node; } return in_list ? MAP.skip : null; } }, function(node) { - if (node instanceof AST_Sequence) switch (node.expressions.length) { + if (node instanceof AST.Sequence) switch (node.expressions.length) { case 0: return null; case 1: return node.expressions[0]; } @@ -1681,25 +1605,25 @@ merge(Compressor.prototype, { function is_lhs_local(lhs) { var sym = root_expr(lhs); - return sym instanceof AST_SymbolRef + return sym instanceof AST.SymbolRef && sym.definition().scope === scope && !(in_loop && (sym.name in lvalues && lvalues[sym.name] !== lhs - || candidate instanceof AST_Unary - || candidate instanceof AST_Assign && candidate.operator != "=")); + || candidate instanceof AST.Unary + || candidate instanceof AST.Assign && candidate.operator != "=")); } function value_has_side_effects(expr) { - if (expr instanceof AST_Unary) return false; + if (expr instanceof AST.Unary) return false; return get_rvalue(expr).has_side_effects(compressor); } function replace_all_symbols() { if (side_effects) return false; if (value_def) return true; - if (lhs instanceof AST_SymbolRef) { + if (lhs instanceof AST.SymbolRef) { var def = lhs.definition(); - if (def.references.length - def.replaced == (candidate instanceof AST_VarDef ? 1 : 2)) { + if (def.references.length - def.replaced == (candidate instanceof AST.VarDef ? 1 : 2)) { return true; } } @@ -1709,30 +1633,30 @@ merge(Compressor.prototype, { function symbol_in_lvalues(sym, parent) { var lvalue = lvalues[sym.name]; if (!lvalue) return; - if (lvalue !== lhs) return !(parent instanceof AST_Call); + if (lvalue !== lhs) return !(parent instanceof AST.Call); scan_rhs = false; } function may_modify(sym) { var def = sym.definition(); - if (def.orig.length == 1 && def.orig[0] instanceof AST_SymbolDefun) return false; + if (def.orig.length == 1 && def.orig[0] instanceof AST.SymbolDefun) return false; if (def.scope !== scope) return true; return !all(def.references, function(ref) { var s = ref.scope; - // "block" scope within AST_Catch + // "block" scope within AST.Catch if (s.TYPE == "Scope") s = s.parent_scope; return s === scope; }); } function side_effects_external(node, lhs) { - if (node instanceof AST_Assign) return side_effects_external(node.left, true); - if (node instanceof AST_Unary) return side_effects_external(node.expression, true); - if (node instanceof AST_VarDef) return node.value && side_effects_external(node.value); + if (node instanceof AST.Assign) return side_effects_external(node.left, true); + if (node instanceof AST.Unary) return side_effects_external(node.expression, true); + if (node instanceof AST.VarDef) return node.value && side_effects_external(node.value); if (lhs) { - if (node instanceof AST_Dot) return side_effects_external(node.expression, true); - if (node instanceof AST_Sub) return side_effects_external(node.expression, true); - if (node instanceof AST_SymbolRef) return node.definition().scope !== scope; + if (node instanceof AST.Dot) return side_effects_external(node.expression, true); + if (node instanceof AST.Sub) return side_effects_external(node.expression, true); + if (node instanceof AST.SymbolRef) return node.definition().scope !== scope; } return false; } @@ -1742,15 +1666,15 @@ merge(Compressor.prototype, { var seen_dirs = []; for (var i = 0; i < statements.length;) { var stat = statements[i]; - if (stat instanceof AST_BlockStatement) { + if (stat instanceof AST.BlockStatement) { CHANGED = true; eliminate_spurious_blocks(stat.body); [].splice.apply(statements, [i, 1].concat(stat.body)); i += stat.body.length; - } else if (stat instanceof AST_EmptyStatement) { + } else if (stat instanceof AST.EmptyStatement) { CHANGED = true; statements.splice(i, 1); - } else if (stat instanceof AST_Directive) { + } else if (stat instanceof AST.Directive) { if (seen_dirs.indexOf(stat.value) < 0) { i++; seen_dirs.push(stat.value); @@ -1765,28 +1689,28 @@ merge(Compressor.prototype, { function handle_if_return(statements, compressor) { var self = compressor.self(); var multiple_if_returns = has_multiple_if_returns(statements); - var in_lambda = self instanceof AST_Lambda; + var in_lambda = self instanceof AST.Lambda; for (var i = statements.length; --i >= 0;) { var stat = statements[i]; var j = next_index(i); var next = statements[j]; - if (in_lambda && !next && stat instanceof AST_Return) { + if (in_lambda && !next && stat instanceof AST.Return) { if (!stat.value) { CHANGED = true; statements.splice(i, 1); continue; } - if (stat.value instanceof AST_UnaryPrefix && stat.value.operator == "void") { + if (stat.value instanceof AST.UnaryPrefix && stat.value.operator == "void") { CHANGED = true; - statements[i] = make_node(AST_SimpleStatement, stat, { + statements[i] = make_node(AST.SimpleStatement, stat, { body: stat.value.expression }); continue; } } - if (stat instanceof AST_If) { + if (stat instanceof AST.If) { var ab = aborts(stat.body); if (can_merge_flow(ab)) { if (ab.label) { @@ -1796,10 +1720,10 @@ merge(Compressor.prototype, { stat = stat.clone(); stat.condition = stat.condition.negate(compressor); var body = as_statement_array_with_return(stat.body, ab); - stat.body = make_node(AST_BlockStatement, stat, { + stat.body = make_node(AST.BlockStatement, stat, { body: as_statement_array(stat.alternative).concat(extract_functions()) }); - stat.alternative = make_node(AST_BlockStatement, stat, { + stat.alternative = make_node(AST.BlockStatement, stat, { body: body }); statements[i] = stat.transform(compressor); @@ -1813,11 +1737,11 @@ merge(Compressor.prototype, { } CHANGED = true; stat = stat.clone(); - stat.body = make_node(AST_BlockStatement, stat.body, { + stat.body = make_node(AST.BlockStatement, stat.body, { body: as_statement_array(stat.body).concat(extract_functions()) }); var body = as_statement_array_with_return(stat.alternative, ab); - stat.alternative = make_node(AST_BlockStatement, stat.alternative, { + stat.alternative = make_node(AST.BlockStatement, stat.alternative, { body: body }); statements[i] = stat.transform(compressor); @@ -1825,22 +1749,22 @@ merge(Compressor.prototype, { } } - if (stat instanceof AST_If && stat.body instanceof AST_Return) { + if (stat instanceof AST.If && stat.body instanceof AST.Return) { var value = stat.body.value; //--- // pretty silly case, but: // if (foo()) return; return; ==> foo(); return; if (!value && !stat.alternative - && (in_lambda && !next || next instanceof AST_Return && !next.value)) { + && (in_lambda && !next || next instanceof AST.Return && !next.value)) { CHANGED = true; - statements[i] = make_node(AST_SimpleStatement, stat.condition, { + statements[i] = make_node(AST.SimpleStatement, stat.condition, { body: stat.condition }); continue; } //--- // if (foo()) return x; return y; ==> return foo() ? x : y; - if (value && !stat.alternative && next instanceof AST_Return && next.value) { + if (value && !stat.alternative && next instanceof AST.Return && next.value) { CHANGED = true; stat = stat.clone(); stat.alternative = next; @@ -1852,10 +1776,10 @@ merge(Compressor.prototype, { // if (foo()) return x; [ return ; ] ==> return foo() ? x : undefined; if (value && !stat.alternative && (!next && in_lambda && multiple_if_returns - || next instanceof AST_Return)) { + || next instanceof AST.Return)) { CHANGED = true; stat = stat.clone(); - stat.alternative = next || make_node(AST_Return, stat, { + stat.alternative = next || make_node(AST.Return, stat, { value: null }); statements.splice(i, 1, stat.transform(compressor)); @@ -1870,14 +1794,14 @@ merge(Compressor.prototype, { // the example code. var prev = statements[prev_index(i)]; if (compressor.option("sequences") && in_lambda && !stat.alternative - && prev instanceof AST_If && prev.body instanceof AST_Return - && next_index(j) == statements.length && next instanceof AST_SimpleStatement) { + && prev instanceof AST.If && prev.body instanceof AST.Return + && next_index(j) == statements.length && next instanceof AST.SimpleStatement) { CHANGED = true; stat = stat.clone(); - stat.alternative = make_node(AST_BlockStatement, next, { + stat.alternative = make_node(AST.BlockStatement, next, { body: [ next, - make_node(AST_Return, next, { + make_node(AST.Return, next, { value: null }) ] @@ -1893,7 +1817,7 @@ merge(Compressor.prototype, { var n = 0; for (var i = statements.length; --i >= 0;) { var stat = statements[i]; - if (stat instanceof AST_If && stat.body instanceof AST_Return) { + if (stat instanceof AST.If && stat.body instanceof AST.Return) { if (++n > 1) return true; } } @@ -1901,22 +1825,22 @@ merge(Compressor.prototype, { } function is_return_void(value) { - return !value || value instanceof AST_UnaryPrefix && value.operator == "void"; + return !value || value instanceof AST.UnaryPrefix && value.operator == "void"; } function can_merge_flow(ab) { if (!ab) return false; - var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab) : null; - return ab instanceof AST_Return && in_lambda && is_return_void(ab.value) - || ab instanceof AST_Continue && self === loop_body(lct) - || ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct; + var lct = ab instanceof AST.LoopControl ? compressor.loopcontrol_target(ab) : null; + return ab instanceof AST.Return && in_lambda && is_return_void(ab.value) + || ab instanceof AST.Continue && self === loop_body(lct) + || ab instanceof AST.Break && lct instanceof AST.BlockStatement && self === lct; } function extract_functions() { var tail = statements.slice(i + 1); statements.length = i + 1; return tail.filter(function(stat) { - if (stat instanceof AST_Defun) { + if (stat instanceof AST.Defun) { statements.push(stat); return false; } @@ -1927,7 +1851,7 @@ merge(Compressor.prototype, { function as_statement_array_with_return(node, ab) { var body = as_statement_array(node).slice(0, -1); if (ab.value) { - body.push(make_node(AST_SimpleStatement, ab.value, { + body.push(make_node(AST.SimpleStatement, ab.value, { body: ab.value.expression })); } @@ -1937,7 +1861,7 @@ merge(Compressor.prototype, { function next_index(i) { for (var j = i + 1, len = statements.length; j < len; j++) { var stat = statements[j]; - if (!(stat instanceof AST_Var && declarations_only(stat))) { + if (!(stat instanceof AST.Var && declarations_only(stat))) { break; } } @@ -1947,7 +1871,7 @@ merge(Compressor.prototype, { function prev_index(i) { for (var j = i; --j >= 0;) { var stat = statements[j]; - if (!(stat instanceof AST_Var && declarations_only(stat))) { + if (!(stat instanceof AST.Var && declarations_only(stat))) { break; } } @@ -1960,12 +1884,12 @@ merge(Compressor.prototype, { var self = compressor.self(); for (var i = 0, n = 0, len = statements.length; i < len; i++) { var stat = statements[i]; - if (stat instanceof AST_LoopControl) { + if (stat instanceof AST.LoopControl) { var lct = compressor.loopcontrol_target(stat); - if (stat instanceof AST_Break - && !(lct instanceof AST_IterationStatement) + if (stat instanceof AST.Break + && !(lct instanceof AST.IterationStatement) && loop_body(lct) === self - || stat instanceof AST_Continue + || stat instanceof AST.Continue && loop_body(lct) === self) { if (stat.label) { remove(stat.label.thedef.references, stat); @@ -2000,18 +1924,18 @@ merge(Compressor.prototype, { function push_seq() { if (!seq.length) return; var body = make_sequence(seq[0], seq); - statements[n++] = make_node(AST_SimpleStatement, body, { body: body }); + statements[n++] = make_node(AST.SimpleStatement, body, { body: body }); seq = []; } for (var i = 0, len = statements.length; i < len; i++) { var stat = statements[i]; - if (stat instanceof AST_SimpleStatement) { + if (stat instanceof AST.SimpleStatement) { if (seq.length >= compressor.sequences_limit) push_seq(); var body = stat.body; if (seq.length > 0) body = body.drop_side_effect_free(compressor); if (body) merge_sequence(seq, body); - } else if (stat instanceof AST_Definitions && declarations_only(stat) - || stat instanceof AST_Defun) { + } else if (stat instanceof AST.Definitions && declarations_only(stat) + || stat instanceof AST.Defun) { statements[n++] = stat; } else { push_seq(); @@ -2024,11 +1948,11 @@ merge(Compressor.prototype, { } function to_simple_statement(block, decls) { - if (!(block instanceof AST_BlockStatement)) return block; + if (!(block instanceof AST.BlockStatement)) return block; var stat = null; for (var i = 0, len = block.body.length; i < len; i++) { var line = block.body[i]; - if (line instanceof AST_Var && declarations_only(line)) { + if (line instanceof AST.Var && declarations_only(line)) { decls.push(line); } else if (stat) { return false; @@ -2050,14 +1974,14 @@ merge(Compressor.prototype, { for (var i = 0; i < statements.length; i++) { var stat = statements[i]; if (prev) { - if (stat instanceof AST_Exit) { - stat.value = cons_seq(stat.value || make_node(AST_Undefined, stat).transform(compressor)); - } else if (stat instanceof AST_For) { - if (!(stat.init instanceof AST_Definitions)) { + if (stat instanceof AST.Exit) { + stat.value = cons_seq(stat.value || make_node(AST.Undefined, stat).transform(compressor)); + } else if (stat instanceof AST.For) { + if (!(stat.init instanceof AST.Definitions)) { var abort = false; prev.body.walk(new TreeWalker(function(node) { - if (abort || node instanceof AST_Scope) return true; - if (node instanceof AST_Binary && node.operator == "in") { + if (abort || node instanceof AST.Scope) return true; + if (node instanceof AST.Binary && node.operator == "in") { abort = true; return true; } @@ -2071,25 +1995,25 @@ merge(Compressor.prototype, { } } } - } else if (stat instanceof AST_ForIn) { + } else if (stat instanceof AST.ForIn) { stat.object = cons_seq(stat.object); - } else if (stat instanceof AST_If) { + } else if (stat instanceof AST.If) { stat.condition = cons_seq(stat.condition); - } else if (stat instanceof AST_Switch) { + } else if (stat instanceof AST.Switch) { stat.expression = cons_seq(stat.expression); - } else if (stat instanceof AST_With) { + } else if (stat instanceof AST.With) { stat.expression = cons_seq(stat.expression); } } - if (compressor.option("conditionals") && stat instanceof AST_If) { + if (compressor.option("conditionals") && stat instanceof AST.If) { var decls = []; var body = to_simple_statement(stat.body, decls); var alt = to_simple_statement(stat.alternative, decls); if (body !== false && alt !== false && decls.length > 0) { var len = decls.length; - decls.push(make_node(AST_If, stat, { + decls.push(make_node(AST.If, stat, { condition: stat.condition, - body: body || make_node(AST_EmptyStatement, stat.body), + body: body || make_node(AST.EmptyStatement, stat.body), alternative: alt })); decls.unshift(n, 1); @@ -2102,28 +2026,28 @@ merge(Compressor.prototype, { } } statements[n++] = stat; - prev = stat instanceof AST_SimpleStatement ? stat : null; + prev = stat instanceof AST.SimpleStatement ? stat : null; } statements.length = n; } function join_object_assignments(defn, body) { var exprs; - if (body instanceof AST_Assign) { + if (body instanceof AST.Assign) { exprs = [ body ]; - } else if (body instanceof AST_Sequence) { + } else if (body instanceof AST.Sequence) { exprs = body.expressions.slice(); } if (!exprs) return; - if (defn instanceof AST_Definitions) { + if (defn instanceof AST.Definitions) { var def = defn.definitions[defn.definitions.length - 1]; if (trim_object_assignments(def.name, def.value, exprs)) return exprs; } for (var i = exprs.length - 1; --i >= 0;) { var expr = exprs[i]; - if (!(expr instanceof AST_Assign)) continue; + if (!(expr instanceof AST.Assign)) continue; if (expr.operator != "=") continue; - if (!(expr.left instanceof AST_SymbolRef)) continue; + if (!(expr.left instanceof AST.SymbolRef)) continue; var tail = exprs.slice(i + 1); if (!trim_object_assignments(expr.left, expr.right, tail)) continue; return exprs.slice(0, i + 1).concat(tail); @@ -2131,22 +2055,22 @@ merge(Compressor.prototype, { } function trim_object_assignments(name, value, exprs) { - if (!(value instanceof AST_Object)) return; + if (!(value instanceof AST.Object)) return; var trimmed = false; do { var node = exprs[0]; - if (!(node instanceof AST_Assign)) break; + if (!(node instanceof AST.Assign)) break; if (node.operator != "=") break; - if (!(node.left instanceof AST_PropAccess)) break; + if (!(node.left instanceof AST.PropAccess)) break; var sym = node.left.expression; - if (!(sym instanceof AST_SymbolRef)) break; + if (!(sym instanceof AST.SymbolRef)) break; if (name.name != sym.name) break; if (!node.right.is_constant_expression(scope)) break; var prop = node.left.property; - if (prop instanceof AST_Node) { + if (prop instanceof AST.Node) { prop = prop.evaluate(compressor); } - if (prop instanceof AST_Node) break; + if (prop instanceof AST.Node) break; prop = "" + prop; var diff = compressor.has_directive("use strict") ? function(node) { return node.key != prop && node.key.name != prop; @@ -2154,7 +2078,7 @@ merge(Compressor.prototype, { return node.key.name != prop; }; if (!all(value.properties, diff)) break; - value.properties.push(make_node(AST_ObjectKeyVal, node, { + value.properties.push(make_node(AST.ObjectKeyVal, node, { key: prop, value: node.right })); @@ -2169,7 +2093,7 @@ merge(Compressor.prototype, { for (var i = 0, j = -1, len = statements.length; i < len; i++) { var stat = statements[i]; var prev = statements[j]; - if (stat instanceof AST_Definitions) { + if (stat instanceof AST.Definitions) { if (prev && prev.TYPE == stat.TYPE) { prev.definitions = prev.definitions.concat(stat.definitions); CHANGED = true; @@ -2180,15 +2104,15 @@ merge(Compressor.prototype, { statements[++j] = stat; defs = stat; } - } else if (stat instanceof AST_Exit) { + } else if (stat instanceof AST.Exit) { stat.value = extract_object_assignments(stat.value); - } else if (stat instanceof AST_For) { + } else if (stat instanceof AST.For) { var exprs = join_object_assignments(prev, stat.init); if (exprs) { CHANGED = true; stat.init = exprs.length ? make_sequence(stat.init, exprs) : null; statements[++j] = stat; - } else if (prev instanceof AST_Var && (!stat.init || stat.init.TYPE == prev.TYPE)) { + } else if (prev instanceof AST.Var && (!stat.init || stat.init.TYPE == prev.TYPE)) { if (stat.init) { prev.definitions = prev.definitions.concat(stat.init.definitions); } @@ -2203,11 +2127,11 @@ merge(Compressor.prototype, { } else { statements[++j] = stat; } - } else if (stat instanceof AST_ForIn) { + } else if (stat instanceof AST.ForIn) { stat.object = extract_object_assignments(stat.object); - } else if (stat instanceof AST_If) { + } else if (stat instanceof AST.If) { stat.condition = extract_object_assignments(stat.condition); - } else if (stat instanceof AST_SimpleStatement) { + } else if (stat instanceof AST.SimpleStatement) { var exprs = join_object_assignments(prev, stat.body); if (exprs) { CHANGED = true; @@ -2215,9 +2139,9 @@ merge(Compressor.prototype, { stat.body = make_sequence(stat.body, exprs); } statements[++j] = stat; - } else if (stat instanceof AST_Switch) { + } else if (stat instanceof AST.Switch) { stat.expression = extract_object_assignments(stat.expression); - } else if (stat instanceof AST_With) { + } else if (stat instanceof AST.With) { stat.expression = extract_object_assignments(stat.expression); } else { statements[++j] = stat; @@ -2232,7 +2156,7 @@ merge(Compressor.prototype, { CHANGED = true; if (exprs.length) { return make_sequence(value, exprs); - } else if (value instanceof AST_Sequence) { + } else if (value instanceof AST.Sequence) { return value.tail_node().left; } else { return value.left; @@ -2244,33 +2168,33 @@ merge(Compressor.prototype, { } function extract_declarations_from_unreachable_code(compressor, stat, target) { - if (!(stat instanceof AST_Defun)) { + if (!(stat instanceof AST.Defun)) { compressor.warn("Dropping unreachable code [{file}:{line},{col}]", stat.start); } stat.walk(new TreeWalker(function(node) { - if (node instanceof AST_Definitions) { + if (node instanceof AST.Definitions) { compressor.warn("Declarations in unreachable code! [{file}:{line},{col}]", node.start); node.remove_initializers(); target.push(node); return true; } - if (node instanceof AST_Defun) { + if (node instanceof AST.Defun) { target.push(node); return true; } - if (node instanceof AST_Scope) { + if (node instanceof AST.Scope) { return true; } })); } function get_value(key) { - if (key instanceof AST_Constant) { + if (key instanceof AST.Constant) { return key.getValue(); } - if (key instanceof AST_UnaryPrefix + if (key instanceof AST.UnaryPrefix && key.operator == "void" - && key.expression instanceof AST_Constant) { + && key.expression instanceof AST.Constant) { return; } return key; @@ -2278,8 +2202,8 @@ merge(Compressor.prototype, { function is_undefined(node, compressor) { return node.is_undefined - || node instanceof AST_Undefined - || node instanceof AST_UnaryPrefix + || node instanceof AST.Undefined + || node instanceof AST.UnaryPrefix && node.operator == "void" && !node.expression.has_side_effects(compressor); } @@ -2287,18 +2211,18 @@ merge(Compressor.prototype, { // is_truthy() // return true if `!!node === true` (function(def) { - def(AST_Node, return_false); - def(AST_Array, return_true); - def(AST_Assign, function() { + def(AST.Node, return_false); + def(AST.Array, return_true); + def(AST.Assign, function() { return this.operator == "=" && this.right.is_truthy(); }); - def(AST_Lambda, return_true); - def(AST_Object, return_true); - def(AST_RegExp, return_true); - def(AST_Sequence, function() { + def(AST.Lambda, return_true); + def(AST.Object, return_true); + def(AST.RegExp, return_true); + def(AST.Sequence, function() { return this.tail_node().is_truthy(); }); - def(AST_SymbolRef, function() { + def(AST.SymbolRef, function() { var fixed = this.fixed_value(); return fixed && fixed.is_truthy(); }); @@ -2307,9 +2231,9 @@ merge(Compressor.prototype, { }); // may_throw_on_access() - // returns true if this node may be null, undefined or contain `AST_Accessor` + // returns true if this node may be null, undefined or contain `AST.Accessor` (function(def) { - AST_Node.DEFMETHOD("may_throw_on_access", function(compressor) { + AST.Node.DEFMETHOD("may_throw_on_access", function(compressor) { return !compressor.option("pure_getters") || this._dot_throw(compressor); }); @@ -2318,44 +2242,44 @@ merge(Compressor.prototype, { return /strict/.test(compressor.option("pure_getters")); } - def(AST_Node, is_strict); - def(AST_Null, return_true); - def(AST_Undefined, return_true); - def(AST_Constant, return_false); - def(AST_Array, return_false); - def(AST_Object, function(compressor) { + def(AST.Node, is_strict); + def(AST.Null, return_true); + def(AST.Undefined, return_true); + def(AST.Constant, return_false); + def(AST.Array, return_false); + def(AST.Object, function(compressor) { if (!is_strict(compressor)) return false; for (var i = this.properties.length; --i >=0;) - if (this.properties[i].value instanceof AST_Accessor) return true; + if (this.properties[i].value instanceof AST.Accessor) return true; return false; }); - def(AST_Lambda, return_false); - def(AST_UnaryPostfix, return_false); - def(AST_UnaryPrefix, function() { + def(AST.Lambda, return_false); + def(AST.UnaryPostfix, return_false); + def(AST.UnaryPrefix, function() { return this.operator == "void"; }); - def(AST_Binary, function(compressor) { + def(AST.Binary, function(compressor) { return (this.operator == "&&" || this.operator == "||") && (this.left._dot_throw(compressor) || this.right._dot_throw(compressor)); }) - def(AST_Assign, function(compressor) { + def(AST.Assign, function(compressor) { return this.operator == "=" && this.right._dot_throw(compressor); }) - def(AST_Conditional, function(compressor) { + def(AST.Conditional, function(compressor) { return this.consequent._dot_throw(compressor) || this.alternative._dot_throw(compressor); }) - def(AST_Dot, function(compressor) { + def(AST.Dot, function(compressor) { if (!is_strict(compressor)) return false; var exp = this.expression; - if (exp instanceof AST_SymbolRef) exp = exp.fixed_value(); - return !(exp instanceof AST_Lambda && this.property == "prototype"); + if (exp instanceof AST.SymbolRef) exp = exp.fixed_value(); + return !(exp instanceof AST.Lambda && this.property == "prototype"); }); - def(AST_Sequence, function(compressor) { + def(AST.Sequence, function(compressor) { return this.tail_node()._dot_throw(compressor); }); - def(AST_SymbolRef, function(compressor) { + def(AST.SymbolRef, function(compressor) { if (this.is_undefined) return true; if (!is_strict(compressor)) return false; if (is_undeclared_ref(this) && this.is_declared(compressor)) return false; @@ -2373,53 +2297,53 @@ merge(Compressor.prototype, { (function(def) { var unary_bool = makePredicate("! delete"); var binary_bool = makePredicate("in instanceof == != === !== < <= >= >"); - def(AST_Node, return_false); - def(AST_UnaryPrefix, function() { + def(AST.Node, return_false); + def(AST.UnaryPrefix, function() { return unary_bool[this.operator]; }); - def(AST_Binary, function() { + def(AST.Binary, function() { return binary_bool[this.operator] || lazy_op[this.operator] && this.left.is_boolean() && this.right.is_boolean(); }); - def(AST_Conditional, function() { + def(AST.Conditional, function() { return this.consequent.is_boolean() && this.alternative.is_boolean(); }); - def(AST_Assign, function() { + def(AST.Assign, function() { return this.operator == "=" && this.right.is_boolean(); }); - def(AST_Sequence, function() { + def(AST.Sequence, function() { return this.tail_node().is_boolean(); }); - def(AST_True, return_true); - def(AST_False, return_true); + def(AST.True, return_true); + def(AST.False, return_true); })(function(node, func) { node.DEFMETHOD("is_boolean", func); }); // methods to determine if an expression has a numeric result type (function(def) { - def(AST_Node, return_false); - def(AST_Number, return_true); + def(AST.Node, return_false); + def(AST.Number, return_true); var unary = makePredicate("+ - ~ ++ --"); - def(AST_Unary, function() { + def(AST.Unary, function() { return unary[this.operator]; }); var binary = makePredicate("- * / % & | ^ << >> >>>"); - def(AST_Binary, function(compressor) { + def(AST.Binary, function(compressor) { return binary[this.operator] || this.operator == "+" && this.left.is_number(compressor) && this.right.is_number(compressor); }); - def(AST_Assign, function(compressor) { + def(AST.Assign, function(compressor) { return binary[this.operator.slice(0, -1)] || this.operator == "=" && this.right.is_number(compressor); }); - def(AST_Sequence, function(compressor) { + def(AST.Sequence, function(compressor) { return this.tail_node().is_number(compressor); }); - def(AST_Conditional, function(compressor) { + def(AST.Conditional, function(compressor) { return this.consequent.is_number(compressor) && this.alternative.is_number(compressor); }); })(function(node, func) { @@ -2428,22 +2352,22 @@ merge(Compressor.prototype, { // methods to determine if an expression has a string result type (function(def) { - def(AST_Node, return_false); - def(AST_String, return_true); - def(AST_UnaryPrefix, function() { + def(AST.Node, return_false); + def(AST.String, return_true); + def(AST.UnaryPrefix, function() { return this.operator == "typeof"; }); - def(AST_Binary, function(compressor) { + def(AST.Binary, function(compressor) { return this.operator == "+" && (this.left.is_string(compressor) || this.right.is_string(compressor)); }); - def(AST_Assign, function(compressor) { + def(AST.Assign, function(compressor) { return (this.operator == "=" || this.operator == "+=") && this.right.is_string(compressor); }); - def(AST_Sequence, function(compressor) { + def(AST.Sequence, function(compressor) { return this.tail_node().is_string(compressor); }); - def(AST_Conditional, function(compressor) { + def(AST.Conditional, function(compressor) { return this.consequent.is_string(compressor) && this.alternative.is_string(compressor); }); })(function(node, func) { @@ -2454,12 +2378,12 @@ merge(Compressor.prototype, { var unary_side_effects = makePredicate("delete ++ --"); function is_lhs(node, parent) { - if (parent instanceof AST_Unary && unary_side_effects[parent.operator]) return parent.expression; - if (parent instanceof AST_Assign && parent.left === node) return node; + if (parent instanceof AST.Unary && unary_side_effects[parent.operator]) return parent.expression; + if (parent instanceof AST.Assign && parent.left === node) return node; } (function(def) { - AST_Node.DEFMETHOD("resolve_defines", function(compressor) { + AST.Node.DEFMETHOD("resolve_defines", function(compressor) { if (!compressor.option("global_defs")) return; var def = this._find_defs(compressor, ""); if (def) { @@ -2467,7 +2391,7 @@ merge(Compressor.prototype, { do { node = parent; parent = compressor.parent(level++); - } while (parent instanceof AST_PropAccess && parent.expression === node); + } while (parent instanceof AST.PropAccess && parent.expression === node); if (is_lhs(node, parent)) { compressor.warn('global_defs ' + this.print_to_string() + ' redefined [{file}:{line},{col}]', this.start); } else { @@ -2476,8 +2400,8 @@ merge(Compressor.prototype, { } }); function to_node(value, orig) { - if (value instanceof AST_Node) return make_node(value.CTOR, orig, value); - if (Array.isArray(value)) return make_node(AST_Array, orig, { + if (value instanceof AST.Node) return make_node(value.CTOR, orig, value); + if (Array.isArray(value)) return make_node(AST.Array, orig, { elements: value.map(function(value) { return to_node(value, orig); }) @@ -2485,30 +2409,30 @@ merge(Compressor.prototype, { if (value && typeof value == "object") { var props = []; for (var key in value) if (HOP(value, key)) { - props.push(make_node(AST_ObjectKeyVal, orig, { + props.push(make_node(AST.ObjectKeyVal, orig, { key: key, value: to_node(value[key], orig) })); } - return make_node(AST_Object, orig, { + return make_node(AST.Object, orig, { properties: props }); } return make_node_from_constant(value, orig); } - def(AST_Node, noop); - def(AST_Dot, function(compressor, suffix) { + def(AST.Node, noop); + def(AST.Dot, function(compressor, suffix) { return this.expression._find_defs(compressor, "." + this.property + suffix); }); - def(AST_SymbolRef, function(compressor, suffix) { + def(AST.SymbolRef, function(compressor, suffix) { if (!this.global()) return; var name; var defines = compressor.option("global_defs"); if (defines && HOP(defines, (name = this.name + suffix))) { var node = to_node(defines[name], this); - var top = compressor.find_parent(AST_Toplevel); + var top = compressor.find_parent(AST.Toplevel); node.walk(new TreeWalker(function(node) { - if (node instanceof AST_SymbolRef) { + if (node instanceof AST.SymbolRef) { node.scope = top; node.thedef = top.def_global(node); } @@ -2527,9 +2451,9 @@ merge(Compressor.prototype, { } function best_of_statement(ast1, ast2) { - return best_of_expression(make_node(AST_SimpleStatement, ast1, { + return best_of_expression(make_node(AST.SimpleStatement, ast1, { body: ast1 - }), make_node(AST_SimpleStatement, ast2, { + }), make_node(AST.SimpleStatement, ast2, { body: ast2 })).body; } @@ -2636,8 +2560,8 @@ merge(Compressor.prototype, { // then its value is returned; otherwise the element itself // is returned. // They can be distinguished as constant value is never a - // descendant of AST_Node. - AST_Node.DEFMETHOD("evaluate", function(compressor) { + // descendant of AST.Node. + AST.Node.DEFMETHOD("evaluate", function(compressor) { if (!compressor.option("evaluate")) return this; var cached = []; var val = this._eval(compressor, cached, 1); @@ -2649,26 +2573,26 @@ merge(Compressor.prototype, { return val; }); var unaryPrefix = makePredicate("! ~ - + void"); - AST_Node.DEFMETHOD("is_constant", function() { + AST.Node.DEFMETHOD("is_constant", function() { // Accomodate when compress option evaluate=false // as well as the common constant expressions !0 and -1 - if (this instanceof AST_Constant) { - return !(this instanceof AST_RegExp); + if (this instanceof AST.Constant) { + return !(this instanceof AST.RegExp); } else { - return this instanceof AST_UnaryPrefix - && this.expression instanceof AST_Constant + return this instanceof AST.UnaryPrefix + && this.expression instanceof AST.Constant && unaryPrefix[this.operator]; } }); - def(AST_Statement, function() { + def(AST.Statement, function() { throw new Error(string_template("Cannot evaluate a statement [{file}:{line},{col}]", this.start)); }); - def(AST_Lambda, return_this); - def(AST_Node, return_this); - def(AST_Constant, function() { + def(AST.Lambda, return_this); + def(AST.Node, return_this); + def(AST.Constant, function() { return this.getValue(); }); - def(AST_Function, function(compressor) { + def(AST.Function, function(compressor) { if (compressor.option("unsafe")) { var fn = function() {}; fn.node = this; @@ -2679,7 +2603,7 @@ merge(Compressor.prototype, { } return this; }); - def(AST_Array, function(compressor, cached, depth) { + def(AST.Array, function(compressor, cached, depth) { if (compressor.option("unsafe")) { var elements = []; for (var i = 0, len = this.elements.length; i < len; i++) { @@ -2692,22 +2616,22 @@ merge(Compressor.prototype, { } return this; }); - def(AST_Object, function(compressor, cached, depth) { + def(AST.Object, function(compressor, cached, depth) { if (compressor.option("unsafe")) { var val = {}; for (var i = 0, len = this.properties.length; i < len; i++) { var prop = this.properties[i]; var key = prop.key; - if (key instanceof AST_Symbol) { + if (key instanceof AST.Symbol) { key = key.name; - } else if (key instanceof AST_Node) { + } else if (key instanceof AST.Node) { key = key._eval(compressor, cached, depth); if (key === prop.key) return this; } if (typeof Object.prototype[key] === 'function') { return this; } - if (prop.value instanceof AST_Function) continue; + if (prop.value instanceof AST.Function) continue; val[key] = prop.value._eval(compressor, cached, depth); if (val[key] === prop.value) return this; } @@ -2716,15 +2640,15 @@ merge(Compressor.prototype, { return this; }); var non_converting_unary = makePredicate("! typeof void"); - def(AST_UnaryPrefix, function(compressor, cached, depth) { + def(AST.UnaryPrefix, function(compressor, cached, depth) { var e = this.expression; // Function would be evaluated to an array and so typeof would // incorrectly return 'object'. Hence making is a special case. if (compressor.option("typeofs") && this.operator == "typeof" - && (e instanceof AST_Lambda - || e instanceof AST_SymbolRef - && e.fixed_value() instanceof AST_Lambda)) { + && (e instanceof AST.Lambda + || e instanceof AST.SymbolRef + && e.fixed_value() instanceof AST.Lambda)) { return typeof function(){}; } if (!non_converting_unary[this.operator]) depth++; @@ -2745,7 +2669,7 @@ merge(Compressor.prototype, { return this; }); var non_converting_binary = makePredicate("&& || === !=="); - def(AST_Binary, function(compressor, cached, depth) { + def(AST.Binary, function(compressor, cached, depth) { if (!non_converting_binary[this.operator]) depth++; var left = this.left._eval(compressor, cached, depth); if (left === this.left) return this; @@ -2777,20 +2701,20 @@ merge(Compressor.prototype, { default: return this; } - if (isNaN(result) && compressor.find_parent(AST_With)) { + if (isNaN(result) && compressor.find_parent(AST.With)) { // leave original expression as is return this; } return result; }); - def(AST_Conditional, function(compressor, cached, depth) { + def(AST.Conditional, function(compressor, cached, depth) { var condition = this.condition._eval(compressor, cached, depth); if (condition === this.condition) return this; var node = condition ? this.consequent : this.alternative; var value = node._eval(compressor, cached, depth); return value === node ? this : value; }); - def(AST_SymbolRef, function(compressor, cached, depth) { + def(AST.SymbolRef, function(compressor, cached, depth) { var fixed = this.fixed_value(); if (!fixed) return this; var value; @@ -2839,10 +2763,10 @@ merge(Compressor.prototype, { ], }; convert_to_predicate(static_values); - def(AST_PropAccess, function(compressor, cached, depth) { + def(AST.PropAccess, function(compressor, cached, depth) { if (compressor.option("unsafe")) { var key = this.property; - if (key instanceof AST_Node) { + if (key instanceof AST.Node) { key = key._eval(compressor, cached, depth); if (key === this.property) return this; } @@ -2868,11 +2792,11 @@ merge(Compressor.prototype, { } return this; }); - def(AST_Call, function(compressor, cached, depth) { + def(AST.Call, function(compressor, cached, depth) { var exp = this.expression; - if (compressor.option("unsafe") && exp instanceof AST_PropAccess) { + if (compressor.option("unsafe") && exp instanceof AST.PropAccess) { var key = exp.property; - if (key instanceof AST_Node) { + if (key instanceof AST.Node) { key = key._eval(compressor, cached, depth); if (key === exp.property) return this; } @@ -2908,7 +2832,7 @@ merge(Compressor.prototype, { } return this; }); - def(AST_New, return_this); + def(AST.New, return_this); })(function(node, func) { node.DEFMETHOD("_eval", func); }); @@ -2916,7 +2840,7 @@ merge(Compressor.prototype, { // method to negate an expression (function(def) { function basic_negation(exp) { - return make_node(AST_UnaryPrefix, exp, { + return make_node(AST.UnaryPrefix, exp, { operator: "!", expression: exp }); @@ -2924,39 +2848,39 @@ merge(Compressor.prototype, { function best(orig, alt, first_in_statement) { var negated = basic_negation(orig); if (first_in_statement) { - var stat = make_node(AST_SimpleStatement, alt, { + var stat = make_node(AST.SimpleStatement, alt, { body: alt }); return best_of_expression(negated, stat) === stat ? alt : negated; } return best_of_expression(negated, alt); } - def(AST_Node, function() { + def(AST.Node, function() { return basic_negation(this); }); - def(AST_Statement, function() { + def(AST.Statement, function() { throw new Error("Cannot negate a statement"); }); - def(AST_Function, function() { + def(AST.Function, function() { return basic_negation(this); }); - def(AST_UnaryPrefix, function() { + def(AST.UnaryPrefix, function() { if (this.operator == "!") return this.expression; return basic_negation(this); }); - def(AST_Sequence, function(compressor) { + def(AST.Sequence, function(compressor) { var expressions = this.expressions.slice(); expressions.push(expressions.pop().negate(compressor)); return make_sequence(this, expressions); }); - def(AST_Conditional, function(compressor, first_in_statement) { + def(AST.Conditional, function(compressor, first_in_statement) { var self = this.clone(); self.consequent = self.consequent.negate(compressor); self.alternative = self.alternative.negate(compressor); return best(this, self, first_in_statement); }); - def(AST_Binary, function(compressor, first_in_statement) { + def(AST.Binary, function(compressor, first_in_statement) { var self = this.clone(), op = this.operator; if (compressor.option("unsafe_comps")) { switch (op) { @@ -2991,29 +2915,29 @@ merge(Compressor.prototype, { }); var global_pure_fns = makePredicate("Boolean decodeURI decodeURIComponent Date encodeURI encodeURIComponent Error escape EvalError isFinite isNaN Number Object parseFloat parseInt RangeError ReferenceError String SyntaxError TypeError unescape URIError"); - AST_Call.DEFMETHOD("is_expr_pure", function(compressor) { + AST.Call.DEFMETHOD("is_expr_pure", function(compressor) { if (compressor.option("unsafe")) { var expr = this.expression; if (is_undeclared_ref(expr) && global_pure_fns[expr.name]) return true; - if (expr instanceof AST_Dot && is_undeclared_ref(expr.expression)) { + if (expr instanceof AST.Dot && is_undeclared_ref(expr.expression)) { var static_fn = static_fns[expr.expression.name]; return static_fn && static_fn[expr.property]; } } return this.pure || !compressor.pure_funcs(this); }); - AST_Node.DEFMETHOD("is_call_pure", return_false); - AST_Dot.DEFMETHOD("is_call_pure", function(compressor) { + AST.Node.DEFMETHOD("is_call_pure", return_false); + AST.Dot.DEFMETHOD("is_call_pure", function(compressor) { if (!compressor.option("unsafe")) return; var expr = this.expression; var map; - if (expr instanceof AST_Array) { + if (expr instanceof AST.Array) { map = native_fns.Array; } else if (expr.is_boolean()) { map = native_fns.Boolean; } else if (expr.is_number(compressor)) { map = native_fns.Number; - } else if (expr instanceof AST_RegExp) { + } else if (expr instanceof AST.RegExp) { map = native_fns.RegExp; } else if (expr.is_string(compressor)) { map = native_fns.String; @@ -3025,11 +2949,11 @@ merge(Compressor.prototype, { // determine if expression has side effects (function(def) { - def(AST_Node, return_true); + def(AST.Node, return_true); - def(AST_EmptyStatement, return_false); - def(AST_Constant, return_false); - def(AST_This, return_false); + def(AST.EmptyStatement, return_false); + def(AST.Constant, return_false); + def(AST.This, return_false); function any(list, compressor) { for (var i = list.length; --i >= 0;) @@ -3038,10 +2962,10 @@ merge(Compressor.prototype, { return false; } - def(AST_Block, function(compressor) { + def(AST.Block, function(compressor) { return any(this.body, compressor); }); - def(AST_Call, function(compressor) { + def(AST.Call, function(compressor) { if (!this.is_expr_pure(compressor) && (!this.expression.is_call_pure(compressor) || this.expression.has_side_effects(compressor))) { @@ -3049,74 +2973,74 @@ merge(Compressor.prototype, { } return any(this.args, compressor); }); - def(AST_Switch, function(compressor) { + def(AST.Switch, function(compressor) { return this.expression.has_side_effects(compressor) || any(this.body, compressor); }); - def(AST_Case, function(compressor) { + def(AST.Case, function(compressor) { return this.expression.has_side_effects(compressor) || any(this.body, compressor); }); - def(AST_Try, function(compressor) { + def(AST.Try, function(compressor) { return any(this.body, compressor) || this.bcatch && this.bcatch.has_side_effects(compressor) || this.bfinally && this.bfinally.has_side_effects(compressor); }); - def(AST_If, function(compressor) { + def(AST.If, function(compressor) { return this.condition.has_side_effects(compressor) || this.body && this.body.has_side_effects(compressor) || this.alternative && this.alternative.has_side_effects(compressor); }); - def(AST_LabeledStatement, function(compressor) { + def(AST.LabeledStatement, function(compressor) { return this.body.has_side_effects(compressor); }); - def(AST_SimpleStatement, function(compressor) { + def(AST.SimpleStatement, function(compressor) { return this.body.has_side_effects(compressor); }); - def(AST_Lambda, return_false); - def(AST_Binary, function(compressor) { + def(AST.Lambda, return_false); + def(AST.Binary, function(compressor) { return this.left.has_side_effects(compressor) || this.right.has_side_effects(compressor); }); - def(AST_Assign, return_true); - def(AST_Conditional, function(compressor) { + def(AST.Assign, return_true); + def(AST.Conditional, function(compressor) { return this.condition.has_side_effects(compressor) || this.consequent.has_side_effects(compressor) || this.alternative.has_side_effects(compressor); }); - def(AST_Unary, function(compressor) { + def(AST.Unary, function(compressor) { return unary_side_effects[this.operator] || this.expression.has_side_effects(compressor); }); - def(AST_SymbolRef, function(compressor) { + def(AST.SymbolRef, function(compressor) { return !this.is_declared(compressor); }); - def(AST_SymbolDeclaration, return_false); - def(AST_Object, function(compressor) { + def(AST.SymbolDeclaration, return_false); + def(AST.Object, function(compressor) { return any(this.properties, compressor); }); - def(AST_ObjectProperty, function(compressor) { + def(AST.ObjectProperty, function(compressor) { return this.value.has_side_effects(compressor); }); - def(AST_Array, function(compressor) { + def(AST.Array, function(compressor) { return any(this.elements, compressor); }); - def(AST_Dot, function(compressor) { + def(AST.Dot, function(compressor) { return this.expression.may_throw_on_access(compressor) || this.expression.has_side_effects(compressor); }); - def(AST_Sub, function(compressor) { + def(AST.Sub, function(compressor) { return this.expression.may_throw_on_access(compressor) || this.expression.has_side_effects(compressor) || this.property.has_side_effects(compressor); }); - def(AST_Sequence, function(compressor) { + def(AST.Sequence, function(compressor) { return any(this.expressions, compressor); }); - def(AST_Definitions, function(compressor) { + def(AST.Definitions, function(compressor) { return any(this.definitions, compressor); }); - def(AST_VarDef, function(compressor) { + def(AST.VarDef, function(compressor) { return this.value; }); })(function(node, func) { @@ -3125,13 +3049,13 @@ merge(Compressor.prototype, { // determine if expression may throw (function(def) { - def(AST_Node, return_true); + def(AST.Node, return_true); - def(AST_Constant, return_false); - def(AST_EmptyStatement, return_false); - def(AST_Lambda, return_false); - def(AST_SymbolDeclaration, return_false); - def(AST_This, return_false); + def(AST.Constant, return_false); + def(AST.EmptyStatement, return_false); + def(AST.Lambda, return_false); + def(AST.SymbolDeclaration, return_false); + def(AST.This, return_false); function any(list, compressor) { for (var i = list.length; --i >= 0;) @@ -3140,93 +3064,93 @@ merge(Compressor.prototype, { return false; } - def(AST_Array, function(compressor) { + def(AST.Array, function(compressor) { return any(this.elements, compressor); }); - def(AST_Assign, function(compressor) { + def(AST.Assign, function(compressor) { if (this.right.may_throw(compressor)) return true; if (!compressor.has_directive("use strict") && this.operator == "=" - && this.left instanceof AST_SymbolRef) { + && this.left instanceof AST.SymbolRef) { return false; } return this.left.may_throw(compressor); }); - def(AST_Binary, function(compressor) { + def(AST.Binary, function(compressor) { return this.left.may_throw(compressor) || this.right.may_throw(compressor); }); - def(AST_Block, function(compressor) { + def(AST.Block, function(compressor) { return any(this.body, compressor); }); - def(AST_Call, function(compressor) { + def(AST.Call, function(compressor) { if (any(this.args, compressor)) return true; if (this.is_expr_pure(compressor)) return false; if (this.expression.may_throw(compressor)) return true; - return !(this.expression instanceof AST_Lambda) + return !(this.expression instanceof AST.Lambda) || any(this.expression.body, compressor); }); - def(AST_Case, function(compressor) { + def(AST.Case, function(compressor) { return this.expression.may_throw(compressor) || any(this.body, compressor); }); - def(AST_Conditional, function(compressor) { + def(AST.Conditional, function(compressor) { return this.condition.may_throw(compressor) || this.consequent.may_throw(compressor) || this.alternative.may_throw(compressor); }); - def(AST_Definitions, function(compressor) { + def(AST.Definitions, function(compressor) { return any(this.definitions, compressor); }); - def(AST_Dot, function(compressor) { + def(AST.Dot, function(compressor) { return this.expression.may_throw_on_access(compressor) || this.expression.may_throw(compressor); }); - def(AST_If, function(compressor) { + def(AST.If, function(compressor) { return this.condition.may_throw(compressor) || this.body && this.body.may_throw(compressor) || this.alternative && this.alternative.may_throw(compressor); }); - def(AST_LabeledStatement, function(compressor) { + def(AST.LabeledStatement, function(compressor) { return this.body.may_throw(compressor); }); - def(AST_Object, function(compressor) { + def(AST.Object, function(compressor) { return any(this.properties, compressor); }); - def(AST_ObjectProperty, function(compressor) { + def(AST.ObjectProperty, function(compressor) { return this.value.may_throw(compressor); }); - def(AST_Return, function(compressor) { + def(AST.Return, function(compressor) { return this.value && this.value.may_throw(compressor); }); - def(AST_Sequence, function(compressor) { + def(AST.Sequence, function(compressor) { return any(this.expressions, compressor); }); - def(AST_SimpleStatement, function(compressor) { + def(AST.SimpleStatement, function(compressor) { return this.body.may_throw(compressor); }); - def(AST_Sub, function(compressor) { + def(AST.Sub, function(compressor) { return this.expression.may_throw_on_access(compressor) || this.expression.may_throw(compressor) || this.property.may_throw(compressor); }); - def(AST_Switch, function(compressor) { + def(AST.Switch, function(compressor) { return this.expression.may_throw(compressor) || any(this.body, compressor); }); - def(AST_SymbolRef, function(compressor) { + def(AST.SymbolRef, function(compressor) { return !this.is_declared(compressor); }); - def(AST_Try, function(compressor) { + def(AST.Try, function(compressor) { return this.bcatch ? this.bcatch.may_throw(compressor) : any(this.body, compressor) || this.bfinally && this.bfinally.may_throw(compressor); }); - def(AST_Unary, function(compressor) { - if (this.operator == "typeof" && this.expression instanceof AST_SymbolRef) + def(AST.Unary, function(compressor) { + if (this.operator == "typeof" && this.expression instanceof AST.SymbolRef) return false; return this.expression.may_throw(compressor); }); - def(AST_VarDef, function(compressor) { + def(AST.VarDef, function(compressor) { if (!this.value) return false; return this.value.may_throw(compressor); }); @@ -3242,14 +3166,14 @@ merge(Compressor.prototype, { return false; return true; } - def(AST_Node, return_false); - def(AST_Constant, return_true); - def(AST_Lambda, function(scope) { + def(AST.Node, return_false); + def(AST.Constant, return_true); + def(AST.Lambda, function(scope) { var self = this; var result = true; self.walk(new TreeWalker(function(node) { if (!result) return true; - if (node instanceof AST_SymbolRef) { + if (node instanceof AST.SymbolRef) { if (self.inlined) { result = false; return true; @@ -3271,19 +3195,19 @@ merge(Compressor.prototype, { })); return result; }); - def(AST_Unary, function() { + def(AST.Unary, function() { return this.expression.is_constant_expression(); }); - def(AST_Binary, function() { + def(AST.Binary, function() { return this.left.is_constant_expression() && this.right.is_constant_expression(); }); - def(AST_Array, function() { + def(AST.Array, function() { return all(this.elements); }); - def(AST_Object, function() { + def(AST.Object, function() { return all(this.properties); }); - def(AST_ObjectProperty, function() { + def(AST.ObjectProperty, function() { return this.value.is_constant_expression(); }); })(function(node, func) { @@ -3295,15 +3219,15 @@ merge(Compressor.prototype, { return thing && thing.aborts(); } (function(def) { - def(AST_Statement, return_null); - def(AST_Jump, return_this); + def(AST.Statement, return_null); + def(AST.Jump, return_this); function block_aborts() { var n = this.body.length; return n > 0 && aborts(this.body[n - 1]); } - def(AST_BlockStatement, block_aborts); - def(AST_SwitchBranch, block_aborts); - def(AST_If, function() { + def(AST.BlockStatement, block_aborts); + def(AST.SwitchBranch, block_aborts); + def(AST.If, function() { return this.alternative && aborts(this.body) && aborts(this.alternative) && this; }); })(function(node, func) { @@ -3312,42 +3236,42 @@ merge(Compressor.prototype, { /* -----[ optimizers ]----- */ - OPT(AST_Directive, function(self, compressor) { + OPT(AST.Directive, function(self, compressor) { if (compressor.has_directive(self.value) !== self) { - return make_node(AST_EmptyStatement, self); + return make_node(AST.EmptyStatement, self); } return self; }); - OPT(AST_Debugger, function(self, compressor) { + OPT(AST.Debugger, function(self, compressor) { if (compressor.option("drop_debugger")) - return make_node(AST_EmptyStatement, self); + return make_node(AST.EmptyStatement, self); return self; }); - OPT(AST_LabeledStatement, function(self, compressor) { - if (self.body instanceof AST_Break + OPT(AST.LabeledStatement, function(self, compressor) { + if (self.body instanceof AST.Break && compressor.loopcontrol_target(self.body) === self.body) { - return make_node(AST_EmptyStatement, self); + return make_node(AST.EmptyStatement, self); } return self.label.references.length == 0 ? self.body : self; }); - OPT(AST_Block, function(self, compressor) { + OPT(AST.Block, function(self, compressor) { tighten_body(self.body, compressor); return self; }); - OPT(AST_BlockStatement, function(self, compressor) { + OPT(AST.BlockStatement, function(self, compressor) { tighten_body(self.body, compressor); switch (self.body.length) { case 1: return self.body[0]; - case 0: return make_node(AST_EmptyStatement, self); + case 0: return make_node(AST.EmptyStatement, self); } return self; }); - OPT(AST_Lambda, function(self, compressor) { + OPT(AST.Lambda, function(self, compressor) { tighten_body(self.body, compressor); if (compressor.option("side_effects") && self.body.length == 1 @@ -3357,23 +3281,23 @@ merge(Compressor.prototype, { return self; }); - AST_Scope.DEFMETHOD("drop_unused", function(compressor) { + AST.Scope.DEFMETHOD("drop_unused", function(compressor) { if (!compressor.option("unused")) return; if (compressor.has_directive("use asm")) return; var self = this; if (self.pinned()) return; - var drop_funcs = !(self instanceof AST_Toplevel) || compressor.toplevel.funcs; - var drop_vars = !(self instanceof AST_Toplevel) || compressor.toplevel.vars; + var drop_funcs = !(self instanceof AST.Toplevel) || compressor.toplevel.funcs; + var drop_vars = !(self instanceof AST.Toplevel) || compressor.toplevel.vars; var assign_as_unused = /keep_assign/.test(compressor.option("unused")) ? return_false : function(node, props) { var sym; - if (node instanceof AST_Assign && (node.write_only || node.operator == "=")) { + if (node instanceof AST.Assign && (node.write_only || node.operator == "=")) { sym = node.left; - } else if (node instanceof AST_Unary && node.write_only) { + } else if (node instanceof AST.Unary && node.write_only) { sym = node.expression; } if (/strict/.test(compressor.option("pure_getters"))) { - while (sym instanceof AST_PropAccess && !sym.expression.may_throw_on_access(compressor)) { - if (sym instanceof AST_Sub) props.unshift(sym.property); + while (sym instanceof AST.PropAccess && !sym.expression.may_throw_on_access(compressor)) { + if (sym instanceof AST.Sub) props.unshift(sym.property); sym = sym.expression; } } @@ -3384,7 +3308,7 @@ merge(Compressor.prototype, { var fixed_ids = Object.create(null); var value_read = Object.create(null); var value_modified = Object.create(null); - if (self instanceof AST_Toplevel && compressor.top_retain) { + if (self instanceof AST.Toplevel && compressor.top_retain) { self.variables.each(function(def) { if (compressor.top_retain(def) && !(def.id in in_use_ids)) { in_use_ids[def.id] = true; @@ -3399,7 +3323,7 @@ merge(Compressor.prototype, { var scope = this; var tw = new TreeWalker(function(node, descend) { if (node === self) return; - if (node instanceof AST_Defun) { + if (node instanceof AST.Defun) { var node_def = node.name.definition(); if (!drop_funcs && scope === self) { if (!(node_def.id in in_use_ids)) { @@ -3410,13 +3334,13 @@ merge(Compressor.prototype, { initializations.add(node_def.id, node); return true; // don't go in nested scopes } - if (node instanceof AST_SymbolFunarg && scope === self) { + if (node instanceof AST.SymbolFunarg && scope === self) { var_defs_by_id.add(node.definition().id, node); } - if (node instanceof AST_Definitions && scope === self) { + if (node instanceof AST.Definitions && scope === self) { node.definitions.forEach(function(def) { var node_def = def.name.definition(); - if (def.name instanceof AST_SymbolVar) { + if (def.name instanceof AST.SymbolVar) { var_defs_by_id.add(node_def.id, def); } if (!drop_vars) { @@ -3456,16 +3380,16 @@ merge(Compressor.prototype, { var parent = tt.parent(); if (drop_vars) { var props = [], sym = assign_as_unused(node, props); - if (sym instanceof AST_SymbolRef) { + if (sym instanceof AST.SymbolRef) { var def = sym.definition(); var in_use = def.id in in_use_ids; var value = null; - if (node instanceof AST_Assign) { + if (node instanceof AST.Assign) { if (!in_use || node.left === sym && def.id in fixed_ids && fixed_ids[def.id] !== node) { value = node.right; } } else if (!in_use) { - value = make_node(AST_Number, node, { + value = make_node(AST.Number, node, { value: 0 }); } @@ -3478,7 +3402,7 @@ merge(Compressor.prototype, { } } if (scope !== self) return; - if (node instanceof AST_Function + if (node instanceof AST.Function && node.name && !compressor.option("keep_fnames")) { var def = node.name.definition(); @@ -3488,7 +3412,7 @@ merge(Compressor.prototype, { if (!(def.id in in_use_ids) || def.orig.length > 1) node.name = null; } - if (node instanceof AST_Lambda && !(node instanceof AST_Accessor)) { + if (node instanceof AST.Lambda && !(node instanceof AST.Accessor)) { var trim = !compressor.option("keep_fargs"); for (var a = node.argnames, i = a.length; --i >= 0;) { var sym = a[i]; @@ -3504,15 +3428,15 @@ merge(Compressor.prototype, { } } } - if (drop_funcs && node instanceof AST_Defun && node !== self) { + if (drop_funcs && node instanceof AST.Defun && node !== self) { var def = node.name.definition(); if (!(def.id in in_use_ids)) { compressor[node.name.unreferenced() ? "warn" : "info"]("Dropping unused function {name} [{file}:{line},{col}]", template(node.name)); def.eliminated++; - return make_node(AST_EmptyStatement, node); + return make_node(AST.EmptyStatement, node); } } - if (node instanceof AST_Definitions && !(parent instanceof AST_ForIn && parent.init === node)) { + if (node instanceof AST.Definitions && !(parent instanceof AST.ForIn && parent.init === node)) { // place uninitialized names at the start var body = [], head = [], tail = []; // for unused names whose initialization has @@ -3526,14 +3450,14 @@ merge(Compressor.prototype, { if (def.value && sym.id in fixed_ids && fixed_ids[sym.id] !== def) { def.value = def.value.drop_side_effect_free(compressor); } - if (def.name instanceof AST_SymbolVar) { + if (def.name instanceof AST.SymbolVar) { var var_defs = var_defs_by_id.get(sym.id); if (var_defs.length > 1 && (!def.value || sym.orig.indexOf(def.name) > sym.eliminated)) { compressor.warn("Dropping duplicated definition of variable {name} [{file}:{line},{col}]", template(def.name)); if (def.value) { - var ref = make_node(AST_SymbolRef, def.name, def.name); + var ref = make_node(AST.SymbolRef, def.name, def.name); sym.references.push(ref); - var assign = make_node(AST_Assign, def, { + var assign = make_node(AST.Assign, def, { operator: "=", left: ref, right: def.value @@ -3554,7 +3478,7 @@ merge(Compressor.prototype, { side_effects.push(def.value); def.value = make_sequence(def.value, side_effects); } else { - body.push(make_node(AST_SimpleStatement, node, { + body.push(make_node(AST.SimpleStatement, node, { body: make_sequence(node, side_effects) })); } @@ -3564,7 +3488,7 @@ merge(Compressor.prototype, { } else { head.push(def); } - } else if (sym.orig[0] instanceof AST_SymbolCatch) { + } else if (sym.orig[0] instanceof AST.SymbolCatch) { var value = def.value && def.value.drop_side_effect_free(compressor); if (value) side_effects.push(value); def.value = null; @@ -3585,17 +3509,17 @@ merge(Compressor.prototype, { body.push(node); } if (side_effects.length > 0) { - body.push(make_node(AST_SimpleStatement, node, { + body.push(make_node(AST.SimpleStatement, node, { body: make_sequence(node, side_effects) })); } switch (body.length) { case 0: - return in_list ? MAP.skip : make_node(AST_EmptyStatement, node); + return in_list ? MAP.skip : make_node(AST.EmptyStatement, node); case 1: return body[0]; default: - return in_list ? MAP.splice(body) : make_node(AST_BlockStatement, node, { + return in_list ? MAP.splice(body) : make_node(AST.BlockStatement, node, { body: body }); } @@ -3606,24 +3530,24 @@ merge(Compressor.prototype, { // https://github.com/mishoo/UglifyJS2/issues/1838 // that's an invalid AST. // We fix it at this stage by moving the `var` outside the `for`. - if (node instanceof AST_For) { + if (node instanceof AST.For) { descend(node, this); var block; - if (node.init instanceof AST_BlockStatement) { + if (node.init instanceof AST.BlockStatement) { block = node.init; node.init = block.body.pop(); block.body.push(node); } - if (node.init instanceof AST_SimpleStatement) { + if (node.init instanceof AST.SimpleStatement) { node.init = node.init.body; } else if (is_empty(node.init)) { node.init = null; } return !block ? node : in_list ? MAP.splice(block.body) : block; } - if (node instanceof AST_LabeledStatement && node.body instanceof AST_For) { + if (node instanceof AST.LabeledStatement && node.body instanceof AST.For) { descend(node, this); - if (node.body instanceof AST_BlockStatement) { + if (node.body instanceof AST.BlockStatement) { var block = node.body; node.body = block.body.pop(); block.body.push(node); @@ -3631,7 +3555,7 @@ merge(Compressor.prototype, { } return node; } - if (node instanceof AST_Scope) { + if (node instanceof AST.Scope) { var save_scope = scope; scope = node; descend(node, this); @@ -3664,12 +3588,12 @@ merge(Compressor.prototype, { function scan_ref_scoped(node, descend) { var node_def, props = [], sym = assign_as_unused(node, props); - if (sym instanceof AST_SymbolRef + if (sym instanceof AST.SymbolRef && self.variables.get(sym.name) === (node_def = sym.definition())) { props.forEach(function(prop) { prop.walk(tw); }); - if (node instanceof AST_Assign) { + if (node instanceof AST.Assign) { node.right.walk(tw); if (node.left === sym) { if (!node_def.chained && sym.fixed_value() === node.right) { @@ -3687,7 +3611,7 @@ merge(Compressor.prototype, { } return true; } - if (node instanceof AST_SymbolRef) { + if (node instanceof AST.SymbolRef) { node_def = node.definition(); if (!(node_def.id in in_use_ids)) { in_use_ids[node_def.id] = true; @@ -3695,7 +3619,7 @@ merge(Compressor.prototype, { } return true; } - if (node instanceof AST_Scope) { + if (node instanceof AST.Scope) { var save_scope = scope; scope = node; descend(); @@ -3705,7 +3629,7 @@ merge(Compressor.prototype, { } }); - AST_Scope.DEFMETHOD("hoist_declarations", function(compressor) { + AST.Scope.DEFMETHOD("hoist_declarations", function(compressor) { if (compressor.has_directive("use asm")) return; var hoist_funs = compressor.option("hoist_funs"); var hoist_vars = compressor.option("hoist_vars"); @@ -3716,8 +3640,8 @@ merge(Compressor.prototype, { var var_decl = 0; self.walk(new TreeWalker(function(node) { if (var_decl > 1) return true; - if (node instanceof AST_Scope && node !== self) return true; - if (node instanceof AST_Var) { + if (node instanceof AST.Scope && node !== self) return true; + if (node instanceof AST.Var) { var_decl++; return true; } @@ -3730,41 +3654,41 @@ merge(Compressor.prototype, { var vars = new Dictionary(), vars_found = 0; var tt = new TreeTransformer(function(node) { if (node === self) return; - if (node instanceof AST_Directive) { + if (node instanceof AST.Directive) { dirs.push(node); - return make_node(AST_EmptyStatement, node); + return make_node(AST.EmptyStatement, node); } - if (hoist_funs && node instanceof AST_Defun + if (hoist_funs && node instanceof AST.Defun && (tt.parent() === self || !compressor.has_directive("use strict"))) { hoisted.push(node); - return make_node(AST_EmptyStatement, node); + return make_node(AST.EmptyStatement, node); } - if (hoist_vars && node instanceof AST_Var) { + if (hoist_vars && node instanceof AST.Var) { node.definitions.forEach(function(def) { vars.set(def.name.name, def); ++vars_found; }); var seq = node.to_assignments(compressor); var p = tt.parent(); - if (p instanceof AST_ForIn && p.init === node) { + if (p instanceof AST.ForIn && p.init === node) { if (seq) return seq; var def = node.definitions[0].name; - return make_node(AST_SymbolRef, def, def); + return make_node(AST.SymbolRef, def, def); } - if (p instanceof AST_For && p.init === node) return seq; - if (!seq) return make_node(AST_EmptyStatement, node); - return make_node(AST_SimpleStatement, node, { + if (p instanceof AST.For && p.init === node) return seq; + if (!seq) return make_node(AST.EmptyStatement, node); + return make_node(AST.SimpleStatement, node, { body: seq }); } - if (node instanceof AST_Scope) return node; + if (node instanceof AST.Scope) return node; }); self.transform(tt); if (vars_found > 0) { // collect only vars which don't show up in self's arguments list var defs = []; vars.each(function(def, name) { - if (self instanceof AST_Lambda + if (self instanceof AST.Lambda && !all(self.argnames, function(argname) { return argname.name != name; })) { @@ -3779,11 +3703,11 @@ merge(Compressor.prototype, { if (defs.length > 0) { // try to merge in assignments for (var i = 0; i < self.body.length;) { - if (self.body[i] instanceof AST_SimpleStatement) { + if (self.body[i] instanceof AST.SimpleStatement) { var expr = self.body[i].body, sym, assign; - if (expr instanceof AST_Assign + if (expr instanceof AST.Assign && expr.operator == "=" - && (sym = expr.left) instanceof AST_Symbol + && (sym = expr.left) instanceof AST.Symbol && vars.has(sym.name)) { var def = vars.get(sym.name); @@ -3794,10 +3718,10 @@ merge(Compressor.prototype, { self.body.splice(i, 1); continue; } - if (expr instanceof AST_Sequence - && (assign = expr.expressions[0]) instanceof AST_Assign + if (expr instanceof AST.Sequence + && (assign = expr.expressions[0]) instanceof AST.Assign && assign.operator == "=" - && (sym = assign.left) instanceof AST_Symbol + && (sym = assign.left) instanceof AST.Symbol && vars.has(sym.name)) { var def = vars.get(sym.name); @@ -3809,18 +3733,18 @@ merge(Compressor.prototype, { continue; } } - if (self.body[i] instanceof AST_EmptyStatement) { + if (self.body[i] instanceof AST.EmptyStatement) { self.body.splice(i, 1); continue; } - if (self.body[i] instanceof AST_BlockStatement) { + if (self.body[i] instanceof AST.BlockStatement) { var tmp = [ i, 1 ].concat(self.body[i].body); self.body.splice.apply(self.body, tmp); continue; } break; } - defs = make_node(AST_Var, self, { + defs = make_node(AST.Var, self, { definitions: defs }); hoisted.push(defs); @@ -3829,7 +3753,7 @@ merge(Compressor.prototype, { self.body = dirs.concat(hoisted, self.body); }); - AST_Scope.DEFMETHOD("var_names", function() { + AST.Scope.DEFMETHOD("var_names", function() { var var_names = this._var_names; if (!var_names) { this._var_names = var_names = Object.create(null); @@ -3843,7 +3767,7 @@ merge(Compressor.prototype, { return var_names; }); - AST_Scope.DEFMETHOD("make_var_name", function(prefix) { + AST.Scope.DEFMETHOD("make_var_name", function(prefix) { var var_names = this.var_names(); prefix = prefix.replace(/(?:^[^a-z_$]|[^a-z0-9_$])/ig, "_"); var name = prefix; @@ -3852,13 +3776,13 @@ merge(Compressor.prototype, { return name; }); - AST_Scope.DEFMETHOD("hoist_properties", function(compressor) { + AST.Scope.DEFMETHOD("hoist_properties", function(compressor) { if (!compressor.option("hoist_props") || compressor.has_directive("use asm")) return; var self = this; - var top_retain = self instanceof AST_Toplevel && compressor.top_retain || return_false; + var top_retain = self instanceof AST.Toplevel && compressor.top_retain || return_false; var defs_by_id = Object.create(null); self.transform(new TreeTransformer(function(node, descend) { - if (node instanceof AST_Assign + if (node instanceof AST.Assign && node.operator == "=" && node.write_only && can_hoist(node.left, node.right, 1)) { @@ -3868,34 +3792,34 @@ merge(Compressor.prototype, { var decls = []; node.right.properties.forEach(function(prop) { var decl = make_sym(node.left, prop.key); - decls.push(make_node(AST_VarDef, node, { + decls.push(make_node(AST.VarDef, node, { name: decl, value: null })); - var sym = make_node(AST_SymbolRef, node, { + var sym = make_node(AST.SymbolRef, node, { name: decl.name, scope: self, thedef: decl.definition() }); sym.reference({}); - assignments.push(make_node(AST_Assign, node, { + assignments.push(make_node(AST.Assign, node, { operator: "=", left: sym, right: prop.value })); }); defs_by_id[node.left.definition().id] = defs; - self.body.splice(self.body.indexOf(this.stack[1]) + 1, 0, make_node(AST_Var, node, { + self.body.splice(self.body.indexOf(this.stack[1]) + 1, 0, make_node(AST.Var, node, { definitions: decls })); return make_sequence(node, assignments); } - if (node instanceof AST_VarDef && can_hoist(node.name, node.value, 0)) { + if (node instanceof AST.VarDef && can_hoist(node.name, node.value, 0)) { descend(node, this); var defs = new Dictionary(); var var_defs = []; node.value.properties.forEach(function(prop) { - var_defs.push(make_node(AST_VarDef, node, { + var_defs.push(make_node(AST.VarDef, node, { name: make_sym(node.name, prop.key), value: prop.value })); @@ -3903,11 +3827,11 @@ merge(Compressor.prototype, { defs_by_id[node.name.definition().id] = defs; return MAP.splice(var_defs); } - if (node instanceof AST_PropAccess && node.expression instanceof AST_SymbolRef) { + if (node instanceof AST.PropAccess && node.expression instanceof AST.SymbolRef) { var defs = defs_by_id[node.expression.definition().id]; if (defs) { var def = defs.get(get_value(node.property)); - var sym = make_node(AST_SymbolRef, node, { + var sym = make_node(AST.SymbolRef, node, { name: def.name, scope: node.expression.scope, thedef: def @@ -3927,11 +3851,11 @@ merge(Compressor.prototype, { if (def.single_use) return; if (top_retain(def)) return; if (sym.fixed_value() !== right) return; - return right instanceof AST_Object; + return right instanceof AST.Object; } function make_sym(sym, key) { - var new_var = make_node(AST_SymbolVar, sym, { + var new_var = make_node(AST.SymbolVar, sym, { name: self.make_var_name(sym.name + "_" + key), scope: self }); @@ -3965,10 +3889,10 @@ merge(Compressor.prototype, { return changed ? ret.length ? ret : null : nodes; } - def(AST_Node, return_this); - def(AST_Constant, return_null); - def(AST_This, return_null); - def(AST_Call, function(compressor, first_in_statement) { + def(AST.Node, return_this); + def(AST.Constant, return_null); + def(AST.This, return_null); + def(AST.Call, function(compressor, first_in_statement) { if (!this.is_expr_pure(compressor)) { if (this.expression.is_call_pure(compressor)) { var exprs = this.args.slice(); @@ -3976,17 +3900,17 @@ merge(Compressor.prototype, { exprs = trim(exprs, compressor, first_in_statement); return exprs && make_sequence(this, exprs); } - if (this.expression instanceof AST_Function + if (this.expression instanceof AST.Function && (!this.expression.name || !this.expression.name.definition().references.length)) { var node = this.clone(); var exp = node.expression; exp.process_expression(false, compressor); exp.walk(new TreeWalker(function(node) { - if (node instanceof AST_Return && node.value) { + if (node instanceof AST.Return && node.value) { node.value = node.value.drop_side_effect_free(compressor); return true; } - if (node instanceof AST_Scope && node !== exp) return true; + if (node instanceof AST.Scope && node !== exp) return true; })); return node; } @@ -3998,9 +3922,9 @@ merge(Compressor.prototype, { var args = trim(this.args, compressor, first_in_statement); return args && make_sequence(this, args); }); - def(AST_Accessor, return_null); - def(AST_Function, return_null); - def(AST_Binary, function(compressor, first_in_statement) { + def(AST.Accessor, return_null); + def(AST.Function, return_null); + def(AST.Binary, function(compressor, first_in_statement) { var right = this.right.drop_side_effect_free(compressor); if (!right) return this.left.drop_side_effect_free(compressor, first_in_statement); if (lazy_op[this.operator]) { @@ -4014,30 +3938,30 @@ merge(Compressor.prototype, { return make_sequence(this, [ left, right ]); } }); - def(AST_Assign, function(compressor) { + def(AST.Assign, function(compressor) { var left = this.left; if (left.has_side_effects(compressor) || compressor.has_directive("use strict") - && left instanceof AST_PropAccess + && left instanceof AST.PropAccess && left.expression.is_constant()) { return this; } this.write_only = true; - if (root_expr(left).is_constant_expression(compressor.find_parent(AST_Scope))) { + if (root_expr(left).is_constant_expression(compressor.find_parent(AST.Scope))) { return this.right.drop_side_effect_free(compressor); } return this; }); - def(AST_Conditional, function(compressor) { + def(AST.Conditional, function(compressor) { var consequent = this.consequent.drop_side_effect_free(compressor); var alternative = this.alternative.drop_side_effect_free(compressor); if (consequent === this.consequent && alternative === this.alternative) return this; - if (!consequent) return alternative ? make_node(AST_Binary, this, { + if (!consequent) return alternative ? make_node(AST.Binary, this, { operator: "||", left: this.condition, right: alternative }) : this.condition.drop_side_effect_free(compressor); - if (!alternative) return make_node(AST_Binary, this, { + if (!alternative) return make_node(AST.Binary, this, { operator: "&&", left: this.condition, right: consequent @@ -4047,12 +3971,12 @@ merge(Compressor.prototype, { node.alternative = alternative; return node; }); - def(AST_Unary, function(compressor, first_in_statement) { + def(AST.Unary, function(compressor, first_in_statement) { if (unary_side_effects[this.operator]) { this.write_only = !this.expression.has_side_effects(compressor); return this; } - if (this.operator == "typeof" && this.expression instanceof AST_SymbolRef) return null; + if (this.operator == "typeof" && this.expression instanceof AST.SymbolRef) return null; var expression = this.expression.drop_side_effect_free(compressor, first_in_statement); if (first_in_statement && expression && is_iife_call(expression)) { if (expression === this.expression && this.operator == "!") return this; @@ -4060,25 +3984,25 @@ merge(Compressor.prototype, { } return expression; }); - def(AST_SymbolRef, function(compressor) { + def(AST.SymbolRef, function(compressor) { return this.is_declared(compressor) ? null : this; }); - def(AST_Object, function(compressor, first_in_statement) { + def(AST.Object, function(compressor, first_in_statement) { var values = trim(this.properties, compressor, first_in_statement); return values && make_sequence(this, values); }); - def(AST_ObjectProperty, function(compressor, first_in_statement) { + def(AST.ObjectProperty, function(compressor, first_in_statement) { return this.value.drop_side_effect_free(compressor, first_in_statement); }); - def(AST_Array, function(compressor, first_in_statement) { + def(AST.Array, function(compressor, first_in_statement) { var values = trim(this.elements, compressor, first_in_statement); return values && make_sequence(this, values); }); - def(AST_Dot, function(compressor, first_in_statement) { + def(AST.Dot, function(compressor, first_in_statement) { if (this.expression.may_throw_on_access(compressor)) return this; return this.expression.drop_side_effect_free(compressor, first_in_statement); }); - def(AST_Sub, function(compressor, first_in_statement) { + def(AST.Sub, function(compressor, first_in_statement) { if (this.expression.may_throw_on_access(compressor)) return this; var expression = this.expression.drop_side_effect_free(compressor, first_in_statement); if (!expression) return this.property.drop_side_effect_free(compressor, first_in_statement); @@ -4086,7 +4010,7 @@ merge(Compressor.prototype, { if (!property) return expression; return make_sequence(this, [ expression, property ]); }); - def(AST_Sequence, function(compressor) { + def(AST.Sequence, function(compressor) { var last = this.tail_node(); var expr = last.drop_side_effect_free(compressor); if (expr === last) return this; @@ -4098,99 +4022,99 @@ merge(Compressor.prototype, { node.DEFMETHOD("drop_side_effect_free", func); }); - OPT(AST_SimpleStatement, function(self, compressor) { + OPT(AST.SimpleStatement, function(self, compressor) { if (compressor.option("side_effects")) { var body = self.body; var node = body.drop_side_effect_free(compressor, true); if (!node) { compressor.warn("Dropping side-effect-free statement [{file}:{line},{col}]", self.start); - return make_node(AST_EmptyStatement, self); + return make_node(AST.EmptyStatement, self); } if (node !== body) { - return make_node(AST_SimpleStatement, self, { body: node }); + return make_node(AST.SimpleStatement, self, { body: node }); } } return self; }); - OPT(AST_While, function(self, compressor) { - return compressor.option("loops") ? make_node(AST_For, self, self).optimize(compressor) : self; + OPT(AST.While, function(self, compressor) { + return compressor.option("loops") ? make_node(AST.For, self, self).optimize(compressor) : self; }); function has_break_or_continue(loop, parent) { var found = false; var tw = new TreeWalker(function(node) { - if (found || node instanceof AST_Scope) return true; - if (node instanceof AST_LoopControl && tw.loopcontrol_target(node) === loop) { + if (found || node instanceof AST.Scope) return true; + if (node instanceof AST.LoopControl && tw.loopcontrol_target(node) === loop) { return found = true; } }); - if (parent instanceof AST_LabeledStatement) tw.push(parent); + if (parent instanceof AST.LabeledStatement) tw.push(parent); tw.push(loop); loop.body.walk(tw); return found; } - OPT(AST_Do, function(self, compressor) { + OPT(AST.Do, function(self, compressor) { if (!compressor.option("loops")) return self; var cond = self.condition.is_truthy() || self.condition.tail_node().evaluate(compressor); - if (!(cond instanceof AST_Node)) { - if (cond) return make_node(AST_For, self, { - body: make_node(AST_BlockStatement, self.body, { + if (!(cond instanceof AST.Node)) { + if (cond) return make_node(AST.For, self, { + body: make_node(AST.BlockStatement, self.body, { body: [ self.body, - make_node(AST_SimpleStatement, self.condition, { + make_node(AST.SimpleStatement, self.condition, { body: self.condition }) ] }) }).optimize(compressor); if (!has_break_or_continue(self, compressor.parent())) { - return make_node(AST_BlockStatement, self.body, { + return make_node(AST.BlockStatement, self.body, { body: [ self.body, - make_node(AST_SimpleStatement, self.condition, { + make_node(AST.SimpleStatement, self.condition, { body: self.condition }) ] }).optimize(compressor); } } - if (self.body instanceof AST_SimpleStatement) return make_node(AST_For, self, { + if (self.body instanceof AST.SimpleStatement) return make_node(AST.For, self, { condition: make_sequence(self.condition, [ self.body.body, self.condition ]), - body: make_node(AST_EmptyStatement, self) + body: make_node(AST.EmptyStatement, self) }).optimize(compressor); return self; }); function if_break_in_loop(self, compressor) { - var first = self.body instanceof AST_BlockStatement ? self.body.body[0] : self.body; + var first = self.body instanceof AST.BlockStatement ? self.body.body[0] : self.body; if (compressor.option("dead_code") && is_break(first)) { var body = []; - if (self.init instanceof AST_Statement) { + if (self.init instanceof AST.Statement) { body.push(self.init); } else if (self.init) { - body.push(make_node(AST_SimpleStatement, self.init, { + body.push(make_node(AST.SimpleStatement, self.init, { body: self.init })); } if (self.condition) { - body.push(make_node(AST_SimpleStatement, self.condition, { + body.push(make_node(AST.SimpleStatement, self.condition, { body: self.condition })); } extract_declarations_from_unreachable_code(compressor, self.body, body); - return make_node(AST_BlockStatement, self, { + return make_node(AST.BlockStatement, self, { body: body }); } - if (first instanceof AST_If) { + if (first instanceof AST.If) { if (is_break(first.body)) { if (self.condition) { - self.condition = make_node(AST_Binary, self.condition, { + self.condition = make_node(AST.Binary, self.condition, { left: self.condition, operator: "&&", right: first.condition.negate(compressor), @@ -4201,7 +4125,7 @@ merge(Compressor.prototype, { drop_it(first.alternative); } else if (is_break(first.alternative)) { if (self.condition) { - self.condition = make_node(AST_Binary, self.condition, { + self.condition = make_node(AST.Binary, self.condition, { left: self.condition, operator: "&&", right: first.condition, @@ -4215,18 +4139,18 @@ merge(Compressor.prototype, { return self; function is_break(node) { - return node instanceof AST_Break + return node instanceof AST.Break && compressor.loopcontrol_target(node) === compressor.self(); } function drop_it(rest) { rest = as_statement_array(rest); - if (self.body instanceof AST_BlockStatement) { + if (self.body instanceof AST.BlockStatement) { self.body = self.body.clone(); self.body.body = rest.concat(self.body.body.slice(1)); self.body = self.body.transform(compressor); } else { - self.body = make_node(AST_BlockStatement, self.body, { + self.body = make_node(AST.BlockStatement, self.body, { body: rest }).transform(compressor); } @@ -4234,14 +4158,14 @@ merge(Compressor.prototype, { } } - OPT(AST_For, function(self, compressor) { + OPT(AST.For, function(self, compressor) { if (!compressor.option("loops")) return self; if (compressor.option("side_effects") && self.init) { self.init = self.init.drop_side_effect_free(compressor); } if (self.condition) { var cond = self.condition.evaluate(compressor); - if (!(cond instanceof AST_Node)) { + if (!(cond instanceof AST.Node)) { if (cond) self.condition = null; else if (!compressor.option("dead_code")) { var orig = self.condition; @@ -4249,29 +4173,29 @@ merge(Compressor.prototype, { self.condition = best_of_expression(self.condition.transform(compressor), orig); } } - if (cond instanceof AST_Node) { + if (cond instanceof AST.Node) { cond = self.condition.is_truthy() || self.condition.tail_node().evaluate(compressor); } if (!cond) { if (compressor.option("dead_code")) { var body = []; extract_declarations_from_unreachable_code(compressor, self.body, body); - if (self.init instanceof AST_Statement) { + if (self.init instanceof AST.Statement) { body.push(self.init); } else if (self.init) { - body.push(make_node(AST_SimpleStatement, self.init, { + body.push(make_node(AST.SimpleStatement, self.init, { body: self.init })); } - body.push(make_node(AST_SimpleStatement, self.condition, { + body.push(make_node(AST.SimpleStatement, self.condition, { body: self.condition })); - return make_node(AST_BlockStatement, self, { body: body }).optimize(compressor); + return make_node(AST.BlockStatement, self, { body: body }).optimize(compressor); } - } else if (self.condition && !(cond instanceof AST_Node)) { - self.body = make_node(AST_BlockStatement, self.body, { + } else if (self.condition && !(cond instanceof AST.Node)) { + self.body = make_node(AST.BlockStatement, self.body, { body: [ - make_node(AST_SimpleStatement, self.condition, { + make_node(AST.SimpleStatement, self.condition, { body: self.condition }), self.body @@ -4283,7 +4207,7 @@ merge(Compressor.prototype, { return if_break_in_loop(self, compressor); }); - OPT(AST_If, function(self, compressor) { + OPT(AST.If, function(self, compressor) { if (is_empty(self.alternative)) self.alternative = null; if (!compressor.option("conditionals")) return self; @@ -4292,35 +4216,35 @@ merge(Compressor.prototype, { // “has no side effects”; also it doesn't work for cases like // `x && true`, though it probably should. var cond = self.condition.evaluate(compressor); - if (!compressor.option("dead_code") && !(cond instanceof AST_Node)) { + if (!compressor.option("dead_code") && !(cond instanceof AST.Node)) { var orig = self.condition; self.condition = make_node_from_constant(cond, orig); self.condition = best_of_expression(self.condition.transform(compressor), orig); } if (compressor.option("dead_code")) { - if (cond instanceof AST_Node) { + if (cond instanceof AST.Node) { cond = self.condition.is_truthy() || self.condition.tail_node().evaluate(compressor); } if (!cond) { compressor.warn("Condition always false [{file}:{line},{col}]", self.condition.start); var body = []; extract_declarations_from_unreachable_code(compressor, self.body, body); - body.push(make_node(AST_SimpleStatement, self.condition, { + body.push(make_node(AST.SimpleStatement, self.condition, { body: self.condition })); if (self.alternative) body.push(self.alternative); - return make_node(AST_BlockStatement, self, { body: body }).optimize(compressor); - } else if (!(cond instanceof AST_Node)) { + return make_node(AST.BlockStatement, self, { body: body }).optimize(compressor); + } else if (!(cond instanceof AST.Node)) { compressor.warn("Condition always true [{file}:{line},{col}]", self.condition.start); var body = []; if (self.alternative) { extract_declarations_from_unreachable_code(compressor, self.alternative, body); } - body.push(make_node(AST_SimpleStatement, self.condition, { + body.push(make_node(AST.SimpleStatement, self.condition, { body: self.condition })); body.push(self.body); - return make_node(AST_BlockStatement, self, { body: body }).optimize(compressor); + return make_node(AST.BlockStatement, self, { body: body }).optimize(compressor); } } var negated = self.condition.negate(compressor); @@ -4333,73 +4257,73 @@ merge(Compressor.prototype, { // here because they are only used in an equality comparison later on. self.condition = negated; var tmp = self.body; - self.body = self.alternative || make_node(AST_EmptyStatement, self); + self.body = self.alternative || make_node(AST.EmptyStatement, self); self.alternative = tmp; } if (is_empty(self.body) && is_empty(self.alternative)) { - return make_node(AST_SimpleStatement, self.condition, { + return make_node(AST.SimpleStatement, self.condition, { body: self.condition.clone() }).optimize(compressor); } - if (self.body instanceof AST_SimpleStatement - && self.alternative instanceof AST_SimpleStatement) { - return make_node(AST_SimpleStatement, self, { - body: make_node(AST_Conditional, self, { + if (self.body instanceof AST.SimpleStatement + && self.alternative instanceof AST.SimpleStatement) { + return make_node(AST.SimpleStatement, self, { + body: make_node(AST.Conditional, self, { condition : self.condition, consequent : self.body.body, alternative : self.alternative.body }) }).optimize(compressor); } - if (is_empty(self.alternative) && self.body instanceof AST_SimpleStatement) { + if (is_empty(self.alternative) && self.body instanceof AST.SimpleStatement) { if (self_condition_length === negated_length && !negated_is_best - && self.condition instanceof AST_Binary && self.condition.operator == "||") { + && self.condition instanceof AST.Binary && self.condition.operator == "||") { // although the code length of self.condition and negated are the same, // negated does not require additional surrounding parentheses. // see https://github.com/mishoo/UglifyJS2/issues/979 negated_is_best = true; } - if (negated_is_best) return make_node(AST_SimpleStatement, self, { - body: make_node(AST_Binary, self, { + if (negated_is_best) return make_node(AST.SimpleStatement, self, { + body: make_node(AST.Binary, self, { operator : "||", left : negated, right : self.body.body }) }).optimize(compressor); - return make_node(AST_SimpleStatement, self, { - body: make_node(AST_Binary, self, { + return make_node(AST.SimpleStatement, self, { + body: make_node(AST.Binary, self, { operator : "&&", left : self.condition, right : self.body.body }) }).optimize(compressor); } - if (self.body instanceof AST_EmptyStatement - && self.alternative instanceof AST_SimpleStatement) { - return make_node(AST_SimpleStatement, self, { - body: make_node(AST_Binary, self, { + if (self.body instanceof AST.EmptyStatement + && self.alternative instanceof AST.SimpleStatement) { + return make_node(AST.SimpleStatement, self, { + body: make_node(AST.Binary, self, { operator : "||", left : self.condition, right : self.alternative.body }) }).optimize(compressor); } - if (self.body instanceof AST_Exit - && self.alternative instanceof AST_Exit + if (self.body instanceof AST.Exit + && self.alternative instanceof AST.Exit && self.body.TYPE == self.alternative.TYPE) { return make_node(self.body.CTOR, self, { - value: make_node(AST_Conditional, self, { + value: make_node(AST.Conditional, self, { condition : self.condition, - consequent : self.body.value || make_node(AST_Undefined, self.body), - alternative : self.alternative.value || make_node(AST_Undefined, self.alternative) + consequent : self.body.value || make_node(AST.Undefined, self.body), + alternative : self.alternative.value || make_node(AST.Undefined, self.alternative) }).transform(compressor) }).optimize(compressor); } - if (self.body instanceof AST_If + if (self.body instanceof AST.If && !self.body.alternative && !self.alternative) { - self = make_node(AST_If, self, { - condition: make_node(AST_Binary, self.condition, { + self = make_node(AST.If, self, { + condition: make_node(AST.Binary, self.condition, { operator: "&&", left: self.condition, right: self.body.condition @@ -4412,7 +4336,7 @@ merge(Compressor.prototype, { if (self.alternative) { var alt = self.alternative; self.alternative = null; - return make_node(AST_BlockStatement, self, { + return make_node(AST.BlockStatement, self, { body: [ self, alt ] }).optimize(compressor); } @@ -4422,24 +4346,24 @@ merge(Compressor.prototype, { self.body = self.alternative; self.condition = negated_is_best ? negated : self.condition.negate(compressor); self.alternative = null; - return make_node(AST_BlockStatement, self, { + return make_node(AST.BlockStatement, self, { body: [ self, body ] }).optimize(compressor); } return self; }); - OPT(AST_Switch, function(self, compressor) { + OPT(AST.Switch, function(self, compressor) { if (!compressor.option("switches")) return self; var branch; var value = self.expression.evaluate(compressor); - if (!(value instanceof AST_Node)) { + if (!(value instanceof AST.Node)) { var orig = self.expression; self.expression = make_node_from_constant(value, orig); self.expression = best_of_expression(self.expression.transform(compressor), orig); } if (!compressor.option("dead_code")) return self; - if (value instanceof AST_Node) { + if (value instanceof AST.Node) { value = self.expression.tail_node().evaluate(compressor); } var decl = []; @@ -4448,19 +4372,19 @@ merge(Compressor.prototype, { var exact_match; for (var i = 0, len = self.body.length; i < len && !exact_match; i++) { branch = self.body[i]; - if (branch instanceof AST_Default) { + if (branch instanceof AST.Default) { if (!default_branch) { default_branch = branch; } else { eliminate_branch(branch, body[body.length - 1]); } - } else if (!(value instanceof AST_Node)) { + } else if (!(value instanceof AST.Node)) { var exp = branch.expression.evaluate(compressor); - if (!(exp instanceof AST_Node) && exp !== value) { + if (!(exp instanceof AST.Node) && exp !== value) { eliminate_branch(branch, body[body.length - 1]); continue; } - if (exp instanceof AST_Node) exp = branch.expression.tail_node().evaluate(compressor); + if (exp instanceof AST.Node) exp = branch.expression.tail_node().evaluate(compressor); if (exp === value) { exact_match = branch; if (default_branch) { @@ -4474,7 +4398,7 @@ merge(Compressor.prototype, { if (aborts(branch)) { var prev = body[body.length - 1]; if (aborts(prev) && prev.body.length == branch.body.length - && make_node(AST_BlockStatement, prev, prev).equivalent_to(make_node(AST_BlockStatement, branch, branch))) { + && make_node(AST.BlockStatement, prev, prev).equivalent_to(make_node(AST.BlockStatement, branch, branch))) { prev.body = []; } } @@ -4487,15 +4411,15 @@ merge(Compressor.prototype, { self.body = body; while (branch = body[body.length - 1]) { var stat = branch.body[branch.body.length - 1]; - if (stat instanceof AST_Break && compressor.loopcontrol_target(stat) === self) + if (stat instanceof AST.Break && compressor.loopcontrol_target(stat) === self) branch.body.pop(); - if (branch.body.length || branch instanceof AST_Case + if (branch.body.length || branch instanceof AST.Case && (default_branch || branch.expression.has_side_effects(compressor))) break; if (body.pop() === default_branch) default_branch = null; } if (body.length == 0) { - return make_node(AST_BlockStatement, self, { - body: decl.concat(make_node(AST_SimpleStatement, self.expression, { + return make_node(AST.BlockStatement, self, { + body: decl.concat(make_node(AST.SimpleStatement, self.expression, { body: self.expression })) }).optimize(compressor); @@ -4504,22 +4428,22 @@ merge(Compressor.prototype, { var has_break = false; var tw = new TreeWalker(function(node) { if (has_break - || node instanceof AST_Lambda - || node instanceof AST_SimpleStatement) return true; - if (node instanceof AST_Break && tw.loopcontrol_target(node) === self) + || node instanceof AST.Lambda + || node instanceof AST.SimpleStatement) return true; + if (node instanceof AST.Break && tw.loopcontrol_target(node) === self) has_break = true; }); self.walk(tw); if (!has_break) { var statements = body[0].body.slice(); var exp = body[0].expression; - if (exp) statements.unshift(make_node(AST_SimpleStatement, exp, { + if (exp) statements.unshift(make_node(AST.SimpleStatement, exp, { body: exp })); - statements.unshift(make_node(AST_SimpleStatement, self.expression, { + statements.unshift(make_node(AST.SimpleStatement, self.expression, { body:self.expression })); - return make_node(AST_BlockStatement, self, { + return make_node(AST.BlockStatement, self, { body: statements }).optimize(compressor); } @@ -4535,7 +4459,7 @@ merge(Compressor.prototype, { } }); - OPT(AST_Try, function(self, compressor) { + OPT(AST.Try, function(self, compressor) { tighten_body(self.body, compressor); if (self.bcatch && self.bfinally && all(self.bfinally.body, is_empty)) self.bfinally = null; if (compressor.option("dead_code") && all(self.body, is_empty)) { @@ -4543,7 +4467,7 @@ merge(Compressor.prototype, { if (self.bcatch) { extract_declarations_from_unreachable_code(compressor, self.bcatch, body); body.forEach(function(stat) { - if (!(stat instanceof AST_Definitions)) return; + if (!(stat instanceof AST.Definitions)) return; stat.definitions.forEach(function(var_def) { var def = var_def.name.definition().redefined(); if (!def) return; @@ -4553,25 +4477,25 @@ merge(Compressor.prototype, { }); } if (self.bfinally) body = body.concat(self.bfinally.body); - return make_node(AST_BlockStatement, self, { + return make_node(AST.BlockStatement, self, { body: body }).optimize(compressor); } return self; }); - AST_Definitions.DEFMETHOD("remove_initializers", function() { + AST.Definitions.DEFMETHOD("remove_initializers", function() { this.definitions.forEach(function(def) { def.value = null; }); }); - AST_Definitions.DEFMETHOD("to_assignments", function(compressor) { + AST.Definitions.DEFMETHOD("to_assignments", function(compressor) { var reduce_vars = compressor.option("reduce_vars"); var assignments = this.definitions.reduce(function(a, def) { if (def.value) { - var name = make_node(AST_SymbolRef, def.name, def.name); - a.push(make_node(AST_Assign, def, { + var name = make_node(AST.SymbolRef, def.name, def.name); + a.push(make_node(AST.Assign, def, { operator : "=", left : name, right : def.value @@ -4587,18 +4511,18 @@ merge(Compressor.prototype, { return make_sequence(this, assignments); }); - OPT(AST_Definitions, function(self, compressor) { + OPT(AST.Definitions, function(self, compressor) { if (self.definitions.length == 0) - return make_node(AST_EmptyStatement, self); + return make_node(AST.EmptyStatement, self); return self; }); - AST_Call.DEFMETHOD("lift_sequences", function(compressor) { + AST.Call.DEFMETHOD("lift_sequences", function(compressor) { if (!compressor.option("sequences")) return this; var exp = this.expression; - if (!(exp instanceof AST_Sequence)) return this; + if (!(exp instanceof AST.Sequence)) return this; var tail = exp.tail_node(); - if (needs_unbinding(compressor, tail) && !(this instanceof AST_New)) return this; + if (needs_unbinding(compressor, tail) && !(this instanceof AST.New)) return this; var expressions = exp.expressions.slice(0, -1); var node = this.clone(); node.expression = tail; @@ -4606,17 +4530,17 @@ merge(Compressor.prototype, { return make_sequence(this, expressions).optimize(compressor); }); - OPT(AST_Call, function(self, compressor) { + OPT(AST.Call, function(self, compressor) { var seq = self.lift_sequences(compressor); if (seq !== self) { return seq; } var exp = self.expression; var fn = exp; - if (compressor.option("reduce_vars") && fn instanceof AST_SymbolRef) { + if (compressor.option("reduce_vars") && fn instanceof AST.SymbolRef) { fn = fn.fixed_value(); } - var is_func = fn instanceof AST_Lambda; + var is_func = fn instanceof AST.Lambda; if (compressor.option("unused") && is_func && !fn.uses_arguments @@ -4629,7 +4553,7 @@ merge(Compressor.prototype, { if (node) { self.args[pos++] = node; } else if (!trim) { - self.args[pos++] = make_node(AST_Number, self.args[i], { + self.args[pos++] = make_node(AST.Number, self.args[i], { value: 0 }); continue; @@ -4645,40 +4569,40 @@ merge(Compressor.prototype, { if (is_undeclared_ref(exp)) switch (exp.name) { case "Array": if (self.args.length != 1) { - return make_node(AST_Array, self, { + return make_node(AST.Array, self, { elements: self.args }).optimize(compressor); } break; case "Object": if (self.args.length == 0) { - return make_node(AST_Object, self, { + return make_node(AST.Object, self, { properties: [] }); } break; case "String": - if (self.args.length == 0) return make_node(AST_String, self, { + if (self.args.length == 0) return make_node(AST.String, self, { value: "" }); - if (self.args.length <= 1) return make_node(AST_Binary, self, { + if (self.args.length <= 1) return make_node(AST.Binary, self, { left: self.args[0], operator: "+", - right: make_node(AST_String, self, { value: "" }) + right: make_node(AST.String, self, { value: "" }) }).optimize(compressor); break; case "Number": - if (self.args.length == 0) return make_node(AST_Number, self, { + if (self.args.length == 0) return make_node(AST.Number, self, { value: 0 }); - if (self.args.length == 1) return make_node(AST_UnaryPrefix, self, { + if (self.args.length == 1) return make_node(AST.UnaryPrefix, self, { expression: self.args[0], operator: "+" }).optimize(compressor); case "Boolean": - if (self.args.length == 0) return make_node(AST_False, self); - if (self.args.length == 1) return make_node(AST_UnaryPrefix, self, { - expression: make_node(AST_UnaryPrefix, self, { + if (self.args.length == 0) return make_node(AST.False, self); + if (self.args.length == 1) return make_node(AST.UnaryPrefix, self, { + expression: make_node(AST.UnaryPrefix, self, { expression: self.args[0], operator: "!" }), @@ -4693,7 +4617,7 @@ merge(Compressor.prototype, { return arg !== value; })) { try { - return best_of(compressor, self, make_node(AST_RegExp, self, { + return best_of(compressor, self, make_node(AST.RegExp, self, { value: RegExp.apply(RegExp, params), })); } catch (ex) { @@ -4706,18 +4630,18 @@ merge(Compressor.prototype, { } } break; - } else if (exp instanceof AST_Dot) switch(exp.property) { + } else if (exp instanceof AST.Dot) switch(exp.property) { case "toString": if (self.args.length == 0 && !exp.expression.may_throw_on_access(compressor)) { - return make_node(AST_Binary, self, { - left: make_node(AST_String, self, { value: "" }), + return make_node(AST.Binary, self, { + left: make_node(AST.String, self, { value: "" }), operator: "+", right: exp.expression }).optimize(compressor); } break; case "join": - if (exp.expression instanceof AST_Array) EXIT: { + if (exp.expression instanceof AST.Array) EXIT: { var separator; if (self.args.length > 0) { separator = self.args[0].evaluate(compressor); @@ -4731,7 +4655,7 @@ merge(Compressor.prototype, { consts.push(value); } else { if (consts.length > 0) { - elements.push(make_node(AST_String, self, { + elements.push(make_node(AST.String, self, { value: consts.join(separator) })); consts.length = 0; @@ -4740,18 +4664,18 @@ merge(Compressor.prototype, { } }); if (consts.length > 0) { - elements.push(make_node(AST_String, self, { + elements.push(make_node(AST.String, self, { value: consts.join(separator) })); } - if (elements.length == 0) return make_node(AST_String, self, { value: "" }); + if (elements.length == 0) return make_node(AST.String, self, { value: "" }); if (elements.length == 1) { if (elements[0].is_string(compressor)) { return elements[0]; } - return make_node(AST_Binary, elements[0], { + return make_node(AST.Binary, elements[0], { operator : "+", - left : make_node(AST_String, self, { value: "" }), + left : make_node(AST.String, self, { value: "" }), right : elements[0] }); } @@ -4761,10 +4685,10 @@ merge(Compressor.prototype, { || elements[1].is_string(compressor)) { first = elements.shift(); } else { - first = make_node(AST_String, self, { value: "" }); + first = make_node(AST.String, self, { value: "" }); } return elements.reduce(function(prev, el) { - return make_node(AST_Binary, el, { + return make_node(AST.Binary, el, { operator : "+", left : prev, right : el @@ -4785,7 +4709,7 @@ merge(Compressor.prototype, { var arg = self.args[0]; var index = arg ? arg.evaluate(compressor) : 0; if (index !== arg) { - return make_node(AST_Sub, exp, { + return make_node(AST.Sub, exp, { expression: exp.expression, property: make_node_from_constant(index | 0, arg || exp) }).optimize(compressor); @@ -4793,11 +4717,11 @@ merge(Compressor.prototype, { } break; case "apply": - if (self.args.length == 2 && self.args[1] instanceof AST_Array) { + if (self.args.length == 2 && self.args[1] instanceof AST.Array) { var args = self.args[1].elements.slice(); args.unshift(self.args[0]); - return make_node(AST_Call, self, { - expression: make_node(AST_Dot, exp, { + return make_node(AST.Call, self, { + expression: make_node(AST.Dot, exp, { expression: exp.expression, property: "call" }), @@ -4807,17 +4731,17 @@ merge(Compressor.prototype, { break; case "call": var func = exp.expression; - if (func instanceof AST_SymbolRef) { + if (func instanceof AST.SymbolRef) { func = func.fixed_value(); } - if (func instanceof AST_Lambda && !func.contains_this()) { + if (func instanceof AST.Lambda && !func.contains_this()) { return (self.args.length ? make_sequence(this, [ self.args[0], - make_node(AST_Call, self, { + make_node(AST.Call, self, { expression: exp.expression, args: self.args.slice(1) }) - ]) : make_node(AST_Call, self, { + ]) : make_node(AST.Call, self, { expression: exp.expression, args: [] })).optimize(compressor); @@ -4829,12 +4753,12 @@ merge(Compressor.prototype, { && is_undeclared_ref(exp) && exp.name == "Function") { // new Function() => function(){} - if (self.args.length == 0) return make_node(AST_Function, self, { + if (self.args.length == 0) return make_node(AST.Function, self, { argnames: [], body: [] }); if (all(self.args, function(x) { - return x instanceof AST_String; + return x instanceof AST.String; })) { // quite a corner-case, but we can handle it: // https://github.com/mishoo/UglifyJS2/issues/203 @@ -4854,20 +4778,20 @@ merge(Compressor.prototype, { var fun; ast.walk(new TreeWalker(function(node) { if (fun) return true; - if (node instanceof AST_Lambda) { + if (node instanceof AST.Lambda) { fun = node; return true; } })); var code = OutputStream(); - AST_BlockStatement.prototype._codegen.call(fun, fun, code); + AST.BlockStatement.prototype._codegen.call(fun, fun, code); self.args = [ - make_node(AST_String, self, { + make_node(AST.String, self, { value: fun.argnames.map(function(arg) { return arg.print_to_string(); }).join(",") }), - make_node(AST_String, self.args[self.args.length - 1], { + make_node(AST.String, self.args[self.args.length - 1], { value: code.get().replace(/^\{|\}$/g, "") }) ]; @@ -4884,13 +4808,13 @@ merge(Compressor.prototype, { } var stat = is_func && fn.body[0]; var can_inline = compressor.option("inline") && !self.is_expr_pure(compressor); - if (can_inline && stat instanceof AST_Return) { + if (can_inline && stat instanceof AST.Return) { var value = stat.value; if (!value || value.is_constant_expression()) { if (value) { value = value.clone(true); } else { - value = make_node(AST_Undefined, self); + value = make_node(AST.Undefined, self); } var args = self.args.concat(value); return make_sequence(self, args).optimize(compressor); @@ -4901,7 +4825,7 @@ merge(Compressor.prototype, { if (can_inline && !fn.uses_arguments && !fn.pinned() - && !(fn.name && fn instanceof AST_Function) + && !(fn.name && fn instanceof AST.Function) && (value = can_flatten_body(stat)) && (exp === fn || compressor.option("unused") @@ -4915,23 +4839,23 @@ merge(Compressor.prototype, { return make_sequence(self, flatten_fn()).optimize(compressor); } if (compressor.option("side_effects") && all(fn.body, is_empty)) { - var args = self.args.concat(make_node(AST_Undefined, self)); + var args = self.args.concat(make_node(AST.Undefined, self)); return make_sequence(self, args).optimize(compressor); } } if (compressor.option("drop_console")) { - if (exp instanceof AST_PropAccess) { + if (exp instanceof AST.PropAccess) { var name = exp.expression; while (name.expression) { name = name.expression; } if (is_undeclared_ref(name) && name.name == "console") { - return make_node(AST_Undefined, self).optimize(compressor); + return make_node(AST.Undefined, self).optimize(compressor); } } } if (compressor.option("negate_iife") - && compressor.parent() instanceof AST_SimpleStatement + && compressor.parent() instanceof AST.SimpleStatement && is_iife_call(self)) { return self.negate(compressor, true); } @@ -4943,13 +4867,13 @@ merge(Compressor.prototype, { return self; function return_value(stat) { - if (!stat) return make_node(AST_Undefined, self); - if (stat instanceof AST_Return) { - if (!stat.value) return make_node(AST_Undefined, self); + if (!stat) return make_node(AST.Undefined, self); + if (stat instanceof AST.Return) { + if (!stat.value) return make_node(AST.Undefined, self); return stat.value.clone(true); } - if (stat instanceof AST_SimpleStatement) { - return make_node(AST_UnaryPrefix, stat, { + if (stat instanceof AST.SimpleStatement) { + return make_node(AST.UnaryPrefix, stat, { operator: "void", expression: stat.body.clone(true) }); @@ -4964,13 +4888,13 @@ merge(Compressor.prototype, { stat = null; for (var i = 0; i < len; i++) { var line = fn.body[i]; - if (line instanceof AST_Var) { + if (line instanceof AST.Var) { if (stat && !all(line.definitions, function(var_def) { return !var_def.value; })) { return false; } - } else if (line instanceof AST_EmptyStatement) { + } else if (line instanceof AST.EmptyStatement) { continue; } else if (stat) { return false; @@ -5000,7 +4924,7 @@ merge(Compressor.prototype, { var len = fn.body.length; for (var i = 0; i < len; i++) { var stat = fn.body[i]; - if (!(stat instanceof AST_Var)) continue; + if (!(stat instanceof AST.Var)) continue; if (!safe_to_inject) return false; for (var j = stat.definitions.length; --j >= 0;) { var name = stat.definitions[j].name; @@ -5019,15 +4943,15 @@ merge(Compressor.prototype, { var catches = Object.create(null); do { scope = compressor.parent(++level); - if (scope instanceof AST_Catch) { + if (scope instanceof AST.Catch) { catches[scope.argname.name] = true; - } else if (scope instanceof AST_IterationStatement) { + } else if (scope instanceof AST.IterationStatement) { in_loop = []; - } else if (scope instanceof AST_SymbolRef) { - if (scope.fixed_value() instanceof AST_Scope) return false; + } else if (scope instanceof AST.SymbolRef) { + if (scope.fixed_value() instanceof AST.Scope) return false; } - } while (!(scope instanceof AST_Scope)); - var safe_to_inject = !(scope instanceof AST_Toplevel) || compressor.toplevel.vars; + } while (!(scope instanceof AST.Scope)); + var safe_to_inject = !(scope instanceof AST.Toplevel) || compressor.toplevel.vars; var inline = compressor.option("inline"); if (!can_inject_vars(catches, inline >= 3 && safe_to_inject)) return false; if (!can_inject_args(catches, inline >= 2 && safe_to_inject)) return false; @@ -5040,14 +4964,14 @@ merge(Compressor.prototype, { scope.enclosed.push(def); if (!scope.var_names()[name.name]) { scope.var_names()[name.name] = true; - decls.push(make_node(AST_VarDef, name, { + decls.push(make_node(AST.VarDef, name, { name: name, value: null })); } - var sym = make_node(AST_SymbolRef, name, name); + var sym = make_node(AST.SymbolRef, name, name); def.references.push(sym); - if (value) expressions.push(make_node(AST_Assign, self, { + if (value) expressions.push(make_node(AST.Assign, self, { operator: "=", left: sym, right: value @@ -5065,9 +4989,9 @@ merge(Compressor.prototype, { if (name.__unused || scope.var_names()[name.name]) { if (value) expressions.push(value); } else { - var symbol = make_node(AST_SymbolVar, name, name); + var symbol = make_node(AST.SymbolVar, name, name); name.definition().orig.push(symbol); - if (!value && in_loop) value = make_node(AST_Undefined, self); + if (!value && in_loop) value = make_node(AST.Undefined, self); append_var(decls, expressions, symbol, value); } } @@ -5079,7 +5003,7 @@ merge(Compressor.prototype, { var pos = expressions.length; for (var i = 0, lines = fn.body.length; i < lines; i++) { var stat = fn.body[i]; - if (!(stat instanceof AST_Var)) continue; + if (!(stat instanceof AST.Var)) continue; for (var j = 0, defs = stat.definitions.length; j < defs; j++) { var var_def = stat.definitions[j]; var name = var_def.name; @@ -5093,12 +5017,12 @@ merge(Compressor.prototype, { return argname.name != name.name; })) { var def = fn.variables.get(name.name); - var sym = make_node(AST_SymbolRef, name, name); + var sym = make_node(AST.SymbolRef, name, name); def.references.push(sym); - expressions.splice(pos++, 0, make_node(AST_Assign, var_def, { + expressions.splice(pos++, 0, make_node(AST.Assign, var_def, { operator: "=", left: sym, - right: make_node(AST_Undefined, name) + right: make_node(AST.Undefined, name) })); } } @@ -5113,7 +5037,7 @@ merge(Compressor.prototype, { expressions.push(value); if (decls.length) { i = scope.body.indexOf(compressor.parent(level - 1)) + 1; - scope.body.splice(i, 0, make_node(AST_Var, fn, { + scope.body.splice(i, 0, make_node(AST.Var, fn, { definitions: decls })); } @@ -5121,7 +5045,7 @@ merge(Compressor.prototype, { } }); - OPT(AST_New, function(self, compressor) { + OPT(AST.New, function(self, compressor) { var seq = self.lift_sequences(compressor); if (seq !== self) { return seq; @@ -5135,14 +5059,14 @@ merge(Compressor.prototype, { case "Function": case "Error": case "Array": - return make_node(AST_Call, self, self).transform(compressor); + return make_node(AST.Call, self, self).transform(compressor); } } } return self; }); - OPT(AST_Sequence, function(self, compressor) { + OPT(AST.Sequence, function(self, compressor) { if (!compressor.option("side_effects")) return self; var expressions = []; filter_for_side_effects(); @@ -5150,7 +5074,7 @@ merge(Compressor.prototype, { trim_right_for_undefined(); if (end == 0) { self = maintain_this_binding(compressor, compressor.parent(), compressor.self(), expressions[0]); - if (!(self instanceof AST_Sequence)) self = self.optimize(compressor); + if (!(self instanceof AST.Sequence)) self = self.optimize(compressor); return self; } self.expressions = expressions; @@ -5171,7 +5095,7 @@ merge(Compressor.prototype, { function trim_right_for_undefined() { while (end > 0 && is_undefined(expressions[end], compressor)) end--; if (end < expressions.length - 1) { - expressions[end] = make_node(AST_UnaryPrefix, self, { + expressions[end] = make_node(AST.UnaryPrefix, self, { operator : "void", expression : expressions[end] }); @@ -5180,8 +5104,8 @@ merge(Compressor.prototype, { } }); - AST_Unary.DEFMETHOD("lift_sequences", function(compressor) { - if (compressor.option("sequences") && this.expression instanceof AST_Sequence) { + AST.Unary.DEFMETHOD("lift_sequences", function(compressor) { + if (compressor.option("sequences") && this.expression instanceof AST.Sequence) { var x = this.expression.expressions.slice(); var e = this.clone(); e.expression = x.pop(); @@ -5191,22 +5115,22 @@ merge(Compressor.prototype, { return this; }); - OPT(AST_UnaryPostfix, function(self, compressor) { + OPT(AST.UnaryPostfix, function(self, compressor) { return self.lift_sequences(compressor); }); - OPT(AST_UnaryPrefix, function(self, compressor) { + OPT(AST.UnaryPrefix, function(self, compressor) { var e = self.expression; if (self.operator == "delete" - && !(e instanceof AST_SymbolRef - || e instanceof AST_PropAccess + && !(e instanceof AST.SymbolRef + || e instanceof AST.PropAccess || is_identifier_atom(e))) { - if (e instanceof AST_Sequence) { + if (e instanceof AST.Sequence) { e = e.expressions.slice(); - e.push(make_node(AST_True, self)); + e.push(make_node(AST.True, self)); return make_sequence(self, e).optimize(compressor); } - return make_sequence(self, [ e, make_node(AST_True, self) ]).optimize(compressor); + return make_sequence(self, [ e, make_node(AST.True, self) ]).optimize(compressor); } var seq = self.lift_sequences(compressor); if (seq !== self) { @@ -5218,19 +5142,19 @@ merge(Compressor.prototype, { self.expression = e; return self; } else { - return make_node(AST_Undefined, self).optimize(compressor); + return make_node(AST.Undefined, self).optimize(compressor); } } if (compressor.option("booleans")) { if (self.operator == "!" && e.is_truthy()) { - return make_sequence(self, [ e, make_node(AST_False, self) ]).optimize(compressor); + return make_sequence(self, [ e, make_node(AST.False, self) ]).optimize(compressor); } else if (compressor.in_boolean_context()) switch (self.operator) { case "!": - if (e instanceof AST_UnaryPrefix && e.operator == "!") { + if (e instanceof AST.UnaryPrefix && e.operator == "!") { // !!foo ==> foo, if we're in boolean context return e.expression; } - if (e instanceof AST_Binary) { + if (e instanceof AST.Binary) { self = best_of(compressor, self, e.negate(compressor, first_in_statement(compressor))); } break; @@ -5238,21 +5162,21 @@ merge(Compressor.prototype, { // typeof always returns a non-empty string, thus it's // always true in booleans compressor.warn("Boolean expression always true [{file}:{line},{col}]", self.start); - return (e instanceof AST_SymbolRef ? make_node(AST_True, self) : make_sequence(self, [ + return (e instanceof AST.SymbolRef ? make_node(AST.True, self) : make_sequence(self, [ e, - make_node(AST_True, self) + make_node(AST.True, self) ])).optimize(compressor); } } - if (self.operator == "-" && e instanceof AST_Infinity) { + if (self.operator == "-" && e instanceof AST.Infinity) { e = e.transform(compressor); } - if (e instanceof AST_Binary + if (e instanceof AST.Binary && (self.operator == "+" || self.operator == "-") && (e.operator == "*" || e.operator == "/" || e.operator == "%")) { - return make_node(AST_Binary, self, { + return make_node(AST.Binary, self, { operator: e.operator, - left: make_node(AST_UnaryPrefix, e.left, { + left: make_node(AST.UnaryPrefix, e.left, { operator: self.operator, expression: e.left }), @@ -5261,7 +5185,7 @@ merge(Compressor.prototype, { } // avoids infinite recursion of numerals if (self.operator != "-" - || !(e instanceof AST_Number || e instanceof AST_Infinity)) { + || !(e instanceof AST.Number || e instanceof AST.Infinity)) { var ev = self.evaluate(compressor); if (ev !== self) { ev = make_node_from_constant(ev, self).optimize(compressor); @@ -5271,17 +5195,17 @@ merge(Compressor.prototype, { return self; }); - AST_Binary.DEFMETHOD("lift_sequences", function(compressor) { + AST.Binary.DEFMETHOD("lift_sequences", function(compressor) { if (compressor.option("sequences")) { - if (this.left instanceof AST_Sequence) { + if (this.left instanceof AST.Sequence) { var x = this.left.expressions.slice(); var e = this.clone(); e.left = x.pop(); x.push(e); return make_sequence(this, x).optimize(compressor); } - if (this.right instanceof AST_Sequence && !this.left.has_side_effects(compressor)) { - var assign = this.operator == "=" && this.left instanceof AST_SymbolRef; + if (this.right instanceof AST.Sequence && !this.left.has_side_effects(compressor)) { + var assign = this.operator == "=" && this.left instanceof AST.SymbolRef; var x = this.right.expressions; var last = x.length - 1; for (var i = 0; i < last; i++) { @@ -5307,12 +5231,12 @@ merge(Compressor.prototype, { var commutativeOperators = makePredicate("== === != !== * & | ^"); function is_object(node) { - return node instanceof AST_Array - || node instanceof AST_Lambda - || node instanceof AST_Object; + return node instanceof AST.Array + || node instanceof AST.Lambda + || node instanceof AST.Object; } - OPT(AST_Binary, function(self, compressor) { + OPT(AST.Binary, function(self, compressor) { function reversible() { return self.left.is_constant() || self.right.is_constant() @@ -5334,7 +5258,7 @@ merge(Compressor.prototype, { // left side might have could not influence the // result. hence, force switch. - if (!(self.left instanceof AST_Binary + if (!(self.left instanceof AST.Binary && PRECEDENCE[self.left.operator] >= PRECEDENCE[self.operator])) { reverse(); } @@ -5356,28 +5280,28 @@ merge(Compressor.prototype, { case "!=": // void 0 == x => null == x if (!is_strict_comparison && is_undefined(self.left, compressor)) { - self.left = make_node(AST_Null, self.left); + self.left = make_node(AST.Null, self.left); } // "undefined" == typeof x => undefined === x else if (compressor.option("typeofs") - && self.left instanceof AST_String + && self.left instanceof AST.String && self.left.value == "undefined" - && self.right instanceof AST_UnaryPrefix + && self.right instanceof AST.UnaryPrefix && self.right.operator == "typeof") { var expr = self.right.expression; - if (expr instanceof AST_SymbolRef ? expr.is_declared(compressor) - : !(expr instanceof AST_PropAccess && compressor.option("ie8"))) { + if (expr instanceof AST.SymbolRef ? expr.is_declared(compressor) + : !(expr instanceof AST.PropAccess && compressor.option("ie8"))) { self.right = expr; - self.left = make_node(AST_Undefined, self.left).optimize(compressor); + self.left = make_node(AST.Undefined, self.left).optimize(compressor); if (self.operator.length == 2) self.operator += "="; } } // obj !== obj => false - else if (self.left instanceof AST_SymbolRef - && self.right instanceof AST_SymbolRef + else if (self.left instanceof AST.SymbolRef + && self.right instanceof AST.SymbolRef && self.left.definition() === self.right.definition() && is_object(self.left.fixed_value())) { - return make_node(self.operator[0] == "=" ? AST_True : AST_False, self); + return make_node(self.operator[0] == "=" ? AST.True : AST.False, self); } break; case "&&": @@ -5386,21 +5310,21 @@ merge(Compressor.prototype, { if (lhs.operator == self.operator) { lhs = lhs.right; } - if (lhs instanceof AST_Binary + if (lhs instanceof AST.Binary && lhs.operator == (self.operator == "&&" ? "!==" : "===") - && self.right instanceof AST_Binary + && self.right instanceof AST.Binary && lhs.operator == self.right.operator - && (is_undefined(lhs.left, compressor) && self.right.left instanceof AST_Null - || lhs.left instanceof AST_Null && is_undefined(self.right.left, compressor)) + && (is_undefined(lhs.left, compressor) && self.right.left instanceof AST.Null + || lhs.left instanceof AST.Null && is_undefined(self.right.left, compressor)) && !lhs.right.has_side_effects(compressor) && lhs.right.equivalent_to(self.right.right)) { - var combined = make_node(AST_Binary, self, { + var combined = make_node(AST.Binary, self, { operator: lhs.operator.slice(0, -1), - left: make_node(AST_Null, self), + left: make_node(AST.Null, self), right: lhs.right }); if (lhs !== self.left) { - combined = make_node(AST_Binary, self, { + combined = make_node(AST.Binary, self, { operator: self.operator, left: self.left.left, right: combined @@ -5417,21 +5341,21 @@ merge(Compressor.prototype, { compressor.warn("+ in boolean context always true [{file}:{line},{col}]", self.start); return make_sequence(self, [ self.right, - make_node(AST_True, self) + make_node(AST.True, self) ]).optimize(compressor); } if (rr && typeof rr == "string") { compressor.warn("+ in boolean context always true [{file}:{line},{col}]", self.start); return make_sequence(self, [ self.left, - make_node(AST_True, self) + make_node(AST.True, self) ]).optimize(compressor); } } if (compressor.option("comparisons") && self.is_boolean()) { - if (!(compressor.parent() instanceof AST_Binary) - || compressor.parent() instanceof AST_Assign) { - var negated = make_node(AST_UnaryPrefix, self, { + if (!(compressor.parent() instanceof AST.Binary) + || compressor.parent() instanceof AST.Assign) { + var negated = make_node(AST.UnaryPrefix, self, { operator: "!", expression: self.negate(compressor, first_in_statement(compressor)) }); @@ -5443,19 +5367,19 @@ merge(Compressor.prototype, { } } if (self.operator == "+") { - if (self.right instanceof AST_String + if (self.right instanceof AST.String && self.right.getValue() == "" && self.left.is_string(compressor)) { return self.left; } - if (self.left instanceof AST_String + if (self.left instanceof AST.String && self.left.getValue() == "" && self.right.is_string(compressor)) { return self.right; } - if (self.left instanceof AST_Binary + if (self.left instanceof AST.Binary && self.left.operator == "+" - && self.left.left instanceof AST_String + && self.left.left instanceof AST.String && self.left.left.getValue() == "" && self.right.is_string(compressor)) { self.left = self.left.right; @@ -5469,7 +5393,7 @@ merge(Compressor.prototype, { if (!ll) { compressor.warn("Condition left of && always false [{file}:{line},{col}]", self.start); return maintain_this_binding(compressor, compressor.parent(), compressor.self(), self.left).optimize(compressor); - } else if (!(ll instanceof AST_Node)) { + } else if (!(ll instanceof AST.Node)) { compressor.warn("Condition left of && always true [{file}:{line},{col}]", self.start); return make_sequence(self, [ self.left, self.right ]).optimize(compressor); } @@ -5479,10 +5403,10 @@ merge(Compressor.prototype, { compressor.warn("Boolean && always false [{file}:{line},{col}]", self.start); return make_sequence(self, [ self.left, - make_node(AST_False, self) + make_node(AST.False, self) ]).optimize(compressor); } else self.falsy = true; - } else if (!(rr instanceof AST_Node)) { + } else if (!(rr instanceof AST.Node)) { var parent = compressor.parent(); if (parent.operator == "&&" && parent.left === compressor.self() || compressor.option("booleans") && compressor.in_boolean_context()) { @@ -5493,7 +5417,7 @@ merge(Compressor.prototype, { // x || false && y ---> x ? y : false if (self.left.operator == "||") { var lr = self.left.right.evaluate(compressor); - if (!lr) return make_node(AST_Conditional, self, { + if (!lr) return make_node(AST.Conditional, self, { condition: self.left.left, consequent: self.right, alternative: self.left.right @@ -5505,7 +5429,7 @@ merge(Compressor.prototype, { if (!ll) { compressor.warn("Condition left of || always false [{file}:{line},{col}]", self.start); return make_sequence(self, [ self.left, self.right ]).optimize(compressor); - } else if (!(ll instanceof AST_Node)) { + } else if (!(ll instanceof AST.Node)) { compressor.warn("Condition left of || always true [{file}:{line},{col}]", self.start); return maintain_this_binding(compressor, compressor.parent(), compressor.self(), self.left).optimize(compressor); } @@ -5517,18 +5441,18 @@ merge(Compressor.prototype, { compressor.warn("Dropping side-effect-free || [{file}:{line},{col}]", self.start); return self.left.optimize(compressor); } - } else if (!(rr instanceof AST_Node)) { + } else if (!(rr instanceof AST.Node)) { if (compressor.option("booleans") && compressor.in_boolean_context()) { compressor.warn("Boolean || always true [{file}:{line},{col}]", self.start); return make_sequence(self, [ self.left, - make_node(AST_True, self) + make_node(AST.True, self) ]).optimize(compressor); } else self.truthy = true; } if (self.left.operator == "&&") { var lr = self.left.right.evaluate(compressor); - if (lr && !(lr instanceof AST_Node)) return make_node(AST_Conditional, self, { + if (lr && !(lr instanceof AST.Node)) return make_node(AST.Conditional, self, { condition: self.left.left, consequent: self.left.right, alternative: self.right @@ -5540,14 +5464,14 @@ merge(Compressor.prototype, { switch (self.operator) { case "+": // "foo" + ("bar" + x) => "foobar" + x - if (self.left instanceof AST_Constant - && self.right instanceof AST_Binary + if (self.left instanceof AST.Constant + && self.right instanceof AST.Binary && self.right.operator == "+" - && self.right.left instanceof AST_Constant + && self.right.left instanceof AST.Constant && self.right.is_string(compressor)) { - self = make_node(AST_Binary, self, { + self = make_node(AST.Binary, self, { operator: "+", - left: make_node(AST_String, self.left, { + left: make_node(AST.String, self.left, { value: "" + self.left.getValue() + self.right.left.getValue(), start: self.left.start, end: self.right.left.end @@ -5556,15 +5480,15 @@ merge(Compressor.prototype, { }); } // (x + "foo") + "bar" => x + "foobar" - if (self.right instanceof AST_Constant - && self.left instanceof AST_Binary + if (self.right instanceof AST.Constant + && self.left instanceof AST.Binary && self.left.operator == "+" - && self.left.right instanceof AST_Constant + && self.left.right instanceof AST.Constant && self.left.is_string(compressor)) { - self = make_node(AST_Binary, self, { + self = make_node(AST.Binary, self, { operator: "+", left: self.left.left, - right: make_node(AST_String, self.right, { + right: make_node(AST.String, self.right, { value: "" + self.left.right.getValue() + self.right.getValue(), start: self.left.right.start, end: self.right.end @@ -5572,20 +5496,20 @@ merge(Compressor.prototype, { }); } // (x + "foo") + ("bar" + y) => (x + "foobar") + y - if (self.left instanceof AST_Binary + if (self.left instanceof AST.Binary && self.left.operator == "+" && self.left.is_string(compressor) - && self.left.right instanceof AST_Constant - && self.right instanceof AST_Binary + && self.left.right instanceof AST.Constant + && self.right instanceof AST.Binary && self.right.operator == "+" - && self.right.left instanceof AST_Constant + && self.right.left instanceof AST.Constant && self.right.is_string(compressor)) { - self = make_node(AST_Binary, self, { + self = make_node(AST.Binary, self, { operator: "+", - left: make_node(AST_Binary, self.left, { + left: make_node(AST.Binary, self.left, { operator: "+", left: self.left.left, - right: make_node(AST_String, self.left.right, { + right: make_node(AST.String, self.left.right, { value: "" + self.left.right.getValue() + self.right.left.getValue(), start: self.left.right.start, end: self.right.left.end @@ -5595,10 +5519,10 @@ merge(Compressor.prototype, { }); } // a + -b => a - b - if (self.right instanceof AST_UnaryPrefix + if (self.right instanceof AST.UnaryPrefix && self.right.operator == "-" && self.left.is_number(compressor)) { - self = make_node(AST_Binary, self, { + self = make_node(AST.Binary, self, { operator: "-", left: self.left, right: self.right.expression @@ -5606,11 +5530,11 @@ merge(Compressor.prototype, { break; } // -a + b => b - a - if (self.left instanceof AST_UnaryPrefix + if (self.left instanceof AST.UnaryPrefix && self.left.operator == "-" && reversible() && self.right.is_number(compressor)) { - self = make_node(AST_Binary, self, { + self = make_node(AST.Binary, self, { operator: "-", left: self.right, right: self.left.expression @@ -5626,16 +5550,16 @@ merge(Compressor.prototype, { if (self.left.is_number(compressor) && self.right.is_number(compressor) && reversible() - && !(self.left instanceof AST_Binary + && !(self.left instanceof AST.Binary && self.left.operator != self.operator && PRECEDENCE[self.left.operator] >= PRECEDENCE[self.operator])) { - var reversed = make_node(AST_Binary, self, { + var reversed = make_node(AST.Binary, self, { operator: self.operator, left: self.right, right: self.left }); - if (self.right instanceof AST_Constant - && !(self.left instanceof AST_Constant)) { + if (self.right instanceof AST.Constant + && !(self.left instanceof AST.Constant)) { self = best_of(compressor, reversed, self); } else { self = best_of(compressor, self, reversed); @@ -5643,11 +5567,11 @@ merge(Compressor.prototype, { } if (associative && self.is_number(compressor)) { // a + (b + c) => (a + b) + c - if (self.right instanceof AST_Binary + if (self.right instanceof AST.Binary && self.right.operator == self.operator) { - self = make_node(AST_Binary, self, { + self = make_node(AST.Binary, self, { operator: self.operator, - left: make_node(AST_Binary, self.left, { + left: make_node(AST.Binary, self.left, { operator: self.operator, left: self.left, right: self.right.left, @@ -5659,13 +5583,13 @@ merge(Compressor.prototype, { } // (n + 2) + 3 => 5 + n // (2 * n) * 3 => 6 + n - if (self.right instanceof AST_Constant - && self.left instanceof AST_Binary + if (self.right instanceof AST.Constant + && self.left instanceof AST.Binary && self.left.operator == self.operator) { - if (self.left.left instanceof AST_Constant) { - self = make_node(AST_Binary, self, { + if (self.left.left instanceof AST.Constant) { + self = make_node(AST.Binary, self, { operator: self.operator, - left: make_node(AST_Binary, self.left, { + left: make_node(AST.Binary, self.left, { operator: self.operator, left: self.left.left, right: self.right, @@ -5674,10 +5598,10 @@ merge(Compressor.prototype, { }), right: self.left.right }); - } else if (self.left.right instanceof AST_Constant) { - self = make_node(AST_Binary, self, { + } else if (self.left.right instanceof AST.Constant) { + self = make_node(AST.Binary, self, { operator: self.operator, - left: make_node(AST_Binary, self.left, { + left: make_node(AST.Binary, self.left, { operator: self.operator, left: self.left.right, right: self.right, @@ -5689,17 +5613,17 @@ merge(Compressor.prototype, { } } // (a | 1) | (2 | d) => (3 | a) | b - if (self.left instanceof AST_Binary + if (self.left instanceof AST.Binary && self.left.operator == self.operator - && self.left.right instanceof AST_Constant - && self.right instanceof AST_Binary + && self.left.right instanceof AST.Constant + && self.right instanceof AST.Binary && self.right.operator == self.operator - && self.right.left instanceof AST_Constant) { - self = make_node(AST_Binary, self, { + && self.right.left instanceof AST.Constant) { + self = make_node(AST.Binary, self, { operator: self.operator, - left: make_node(AST_Binary, self.left, { + left: make_node(AST.Binary, self.left, { operator: self.operator, - left: make_node(AST_Binary, self.left.left, { + left: make_node(AST.Binary, self.left.left, { operator: self.operator, left: self.left.right, right: self.right.left, @@ -5718,7 +5642,7 @@ merge(Compressor.prototype, { // x || (y || z) ==> x || y || z // x + ("y" + z) ==> x + "y" + z // "x" + (y + "z")==> "x" + y + "z" - if (self.right instanceof AST_Binary + if (self.right instanceof AST.Binary && self.right.operator == self.operator && (lazy_op[self.operator] || (self.operator == "+" @@ -5726,7 +5650,7 @@ merge(Compressor.prototype, { || (self.left.is_string(compressor) && self.right.right.is_string(compressor)))))) { - self.left = make_node(AST_Binary, self.left, { + self.left = make_node(AST.Binary, self.left, { operator : self.operator, left : self.left, right : self.right.left @@ -5752,7 +5676,7 @@ merge(Compressor.prototype, { function recursive_ref(compressor, def) { var node; for (var i = 0; node = compressor.parent(i); i++) { - if (node instanceof AST_Lambda) { + if (node instanceof AST.Lambda) { var name = node.name; if (name && name.definition() === def) break; } @@ -5760,7 +5684,7 @@ merge(Compressor.prototype, { return node; } - OPT(AST_SymbolRef, function(self, compressor) { + OPT(AST.SymbolRef, function(self, compressor) { var def = self.resolve_defines(compressor); if (def) { return def.optimize(compressor); @@ -5768,14 +5692,14 @@ merge(Compressor.prototype, { // testing against !self.scope.uses_with first is an optimization if (!compressor.option("ie8") && is_undeclared_ref(self) - && (!self.scope.uses_with || !compressor.find_parent(AST_With))) { + && (!self.scope.uses_with || !compressor.find_parent(AST.With))) { switch (self.name) { case "undefined": - return make_node(AST_Undefined, self).optimize(compressor); + return make_node(AST.Undefined, self).optimize(compressor); case "NaN": - return make_node(AST_NaN, self).optimize(compressor); + return make_node(AST.NaN, self).optimize(compressor); case "Infinity": - return make_node(AST_Infinity, self).optimize(compressor); + return make_node(AST.Infinity, self).optimize(compressor); } } var parent = compressor.parent(); @@ -5783,8 +5707,8 @@ merge(Compressor.prototype, { var d = self.definition(); var fixed = self.fixed_value(); var single_use = d.single_use - && !(parent instanceof AST_Call && parent.is_expr_pure(compressor)); - if (single_use && fixed instanceof AST_Lambda) { + && !(parent instanceof AST.Call && parent.is_expr_pure(compressor)); + if (single_use && fixed instanceof AST.Lambda) { if (d.scope !== self.scope && (!compressor.option("reduce_funcs") || d.escaped == 1 @@ -5792,12 +5716,12 @@ merge(Compressor.prototype, { single_use = false; } else if (recursive_ref(compressor, d)) { single_use = false; - } else if (d.scope !== self.scope || d.orig[0] instanceof AST_SymbolFunarg) { + } else if (d.scope !== self.scope || d.orig[0] instanceof AST.SymbolFunarg) { single_use = fixed.is_constant_expression(self.scope); if (single_use == "f") { var scope = self.scope; do { - if (scope instanceof AST_Defun || scope instanceof AST_Function) { + if (scope instanceof AST.Defun || scope instanceof AST.Function) { scope.inlined = true; } } while (scope = scope.parent_scope); @@ -5805,24 +5729,24 @@ merge(Compressor.prototype, { } } if (single_use && fixed) { - if (fixed instanceof AST_Defun) { + if (fixed instanceof AST.Defun) { fixed._squeezed = true; - fixed = make_node(AST_Function, fixed, fixed); + fixed = make_node(AST.Function, fixed, fixed); } var value; - if (d.recursive_refs > 0 && fixed.name instanceof AST_SymbolDefun) { + if (d.recursive_refs > 0 && fixed.name instanceof AST.SymbolDefun) { value = fixed.clone(true); var defun_def = value.name.definition(); var lambda_def = value.variables.get(value.name.name); var name = lambda_def && lambda_def.orig[0]; - if (!(name instanceof AST_SymbolLambda)) { - name = make_node(AST_SymbolLambda, value.name, value.name); + if (!(name instanceof AST.SymbolLambda)) { + name = make_node(AST.SymbolLambda, value.name, value.name); name.scope = value; value.name = name; lambda_def = value.def_function(name); } value.walk(new TreeWalker(function(node) { - if (node instanceof AST_SymbolRef && node.definition() === defun_def) { + if (node instanceof AST.SymbolRef && node.definition() === defun_def) { node.thedef = lambda_def; lambda_def.references.push(node); } @@ -5835,8 +5759,8 @@ merge(Compressor.prototype, { } if (fixed && d.should_replace === undefined) { var init; - if (fixed instanceof AST_This) { - if (!(d.orig[0] instanceof AST_SymbolFunarg) + if (fixed instanceof AST.This) { + if (!(d.orig[0] instanceof AST.SymbolFunarg) && all(d.references, function(ref) { return d.scope === ref.scope; })) { @@ -5882,7 +5806,7 @@ merge(Compressor.prototype, { function has_symbol_ref(value) { var found; value.walk(new TreeWalker(function(node) { - if (node instanceof AST_SymbolRef) found = true; + if (node instanceof AST.SymbolRef) found = true; if (found) return true; })); return found; @@ -5890,14 +5814,14 @@ merge(Compressor.prototype, { }); function is_atomic(lhs, self) { - return lhs instanceof AST_SymbolRef || lhs.TYPE === self.TYPE; + return lhs instanceof AST.SymbolRef || lhs.TYPE === self.TYPE; } - OPT(AST_Undefined, function(self, compressor) { + OPT(AST.Undefined, function(self, compressor) { if (compressor.option("unsafe_undefined")) { var undef = find_variable(compressor, "undefined"); if (undef) { - var ref = make_node(AST_SymbolRef, self, { + var ref = make_node(AST.SymbolRef, self, { name : "undefined", scope : undef.scope, thedef : undef @@ -5908,42 +5832,42 @@ merge(Compressor.prototype, { } var lhs = is_lhs(compressor.self(), compressor.parent()); if (lhs && is_atomic(lhs, self)) return self; - return make_node(AST_UnaryPrefix, self, { + return make_node(AST.UnaryPrefix, self, { operator: "void", - expression: make_node(AST_Number, self, { + expression: make_node(AST.Number, self, { value: 0 }) }); }); - OPT(AST_Infinity, function(self, compressor) { + OPT(AST.Infinity, function(self, compressor) { var lhs = is_lhs(compressor.self(), compressor.parent()); if (lhs && is_atomic(lhs, self)) return self; if (compressor.option("keep_infinity") && !(lhs && !is_atomic(lhs, self)) && !find_variable(compressor, "Infinity")) return self; - return make_node(AST_Binary, self, { + return make_node(AST.Binary, self, { operator: "/", - left: make_node(AST_Number, self, { + left: make_node(AST.Number, self, { value: 1 }), - right: make_node(AST_Number, self, { + right: make_node(AST.Number, self, { value: 0 }) }); }); - OPT(AST_NaN, function(self, compressor) { + OPT(AST.NaN, function(self, compressor) { var lhs = is_lhs(compressor.self(), compressor.parent()); if (lhs && !is_atomic(lhs, self) || find_variable(compressor, "NaN")) { - return make_node(AST_Binary, self, { + return make_node(AST.Binary, self, { operator: "/", - left: make_node(AST_Number, self, { + left: make_node(AST.Number, self, { value: 0 }), - right: make_node(AST_Number, self, { + right: make_node(AST.Number, self, { value: 0 }) }); @@ -5955,15 +5879,15 @@ merge(Compressor.prototype, { var reachable = false; var find_ref = new TreeWalker(function(node) { if (reachable) return true; - if (node instanceof AST_SymbolRef && member(node.definition(), defs)) { + if (node instanceof AST.SymbolRef && member(node.definition(), defs)) { return reachable = true; } }); var scan_scope = new TreeWalker(function(node) { if (reachable) return true; - if (node instanceof AST_Scope && node !== self) { + if (node instanceof AST.Scope && node !== self) { var parent = scan_scope.parent(); - if (parent instanceof AST_Call && parent.expression === node) return; + if (parent instanceof AST.Call && parent.expression === node) return; node.walk(find_ref); return true; } @@ -5974,40 +5898,40 @@ merge(Compressor.prototype, { var ASSIGN_OPS = makePredicate("+ - / * % >> << >>> | ^ &"); var ASSIGN_OPS_COMMUTATIVE = makePredicate("* | ^ &"); - OPT(AST_Assign, function(self, compressor) { + OPT(AST.Assign, function(self, compressor) { var def; if (compressor.option("dead_code") - && self.left instanceof AST_SymbolRef - && (def = self.left.definition()).scope === compressor.find_parent(AST_Lambda)) { + && self.left instanceof AST.SymbolRef + && (def = self.left.definition()).scope === compressor.find_parent(AST.Lambda)) { var level = 0, node, parent = self; do { node = parent; parent = compressor.parent(level++); - if (parent instanceof AST_Exit) { + if (parent instanceof AST.Exit) { if (in_try(level, parent)) break; if (is_reachable(def.scope, [ def ])) break; if (self.operator == "=") return self.right; def.fixed = false; - return make_node(AST_Binary, self, { + return make_node(AST.Binary, self, { operator: self.operator.slice(0, -1), left: self.left, right: self.right }).optimize(compressor); } - } while (parent instanceof AST_Binary && parent.right === node - || parent instanceof AST_Sequence && parent.tail_node() === node); + } while (parent instanceof AST.Binary && parent.right === node + || parent instanceof AST.Sequence && parent.tail_node() === node); } self = self.lift_sequences(compressor); - if (self.operator == "=" && self.left instanceof AST_SymbolRef && self.right instanceof AST_Binary) { + if (self.operator == "=" && self.left instanceof AST.SymbolRef && self.right instanceof AST.Binary) { // x = expr1 OP expr2 - if (self.right.left instanceof AST_SymbolRef + if (self.right.left instanceof AST.SymbolRef && self.right.left.name == self.left.name && ASSIGN_OPS[self.right.operator]) { // x = x - 2 ---> x -= 2 self.operator = self.right.operator + "="; self.right = self.right.right; } - else if (self.right.right instanceof AST_SymbolRef + else if (self.right.right instanceof AST.SymbolRef && self.right.right.name == self.left.name && ASSIGN_OPS_COMMUTATIVE[self.right.operator] && !self.right.left.has_side_effects(compressor)) { @@ -6020,13 +5944,13 @@ merge(Compressor.prototype, { function in_try(level, node) { var right = self.right; - self.right = make_node(AST_Null, right); + self.right = make_node(AST.Null, right); var may_throw = node.may_throw(compressor); self.right = right; var scope = self.left.definition().scope; var parent; while ((parent = compressor.parent(level++)) !== scope) { - if (parent instanceof AST_Try) { + if (parent instanceof AST.Try) { if (parent.bfinally) return true; if (may_throw && parent.bcatch) return true; } @@ -6034,10 +5958,10 @@ merge(Compressor.prototype, { } }); - OPT(AST_Conditional, function(self, compressor) { + OPT(AST.Conditional, function(self, compressor) { if (!compressor.option("conditionals")) return self; // This looks like lift_sequences(), should probably be under "sequences" - if (self.condition instanceof AST_Sequence) { + if (self.condition instanceof AST.Sequence) { var expressions = self.condition.expressions.slice(); self.condition = expressions.pop(); expressions.push(self); @@ -6047,13 +5971,13 @@ merge(Compressor.prototype, { if (!cond) { compressor.warn("Condition always false [{file}:{line},{col}]", self.start); return make_sequence(self, [ self.condition, self.alternative ]).optimize(compressor); - } else if (!(cond instanceof AST_Node)) { + } else if (!(cond instanceof AST.Node)) { compressor.warn("Condition always true [{file}:{line},{col}]", self.start); return make_sequence(self, [ self.condition, self.consequent ]).optimize(compressor); } var negated = cond.negate(compressor, first_in_statement(compressor)); if (best_of(compressor, cond, negated) === negated) { - self = make_node(AST_Conditional, self, { + self = make_node(AST.Conditional, self, { condition: negated, consequent: self.alternative, alternative: self.consequent @@ -6063,10 +5987,10 @@ merge(Compressor.prototype, { var consequent = self.consequent; var alternative = self.alternative; // x?x:y --> x||y - if (condition instanceof AST_SymbolRef - && consequent instanceof AST_SymbolRef + if (condition instanceof AST.SymbolRef + && consequent instanceof AST.SymbolRef && condition.definition() === consequent.definition()) { - return make_node(AST_Binary, self, { + return make_node(AST.Binary, self, { operator: "||", left: condition, right: alternative @@ -6076,17 +6000,17 @@ merge(Compressor.prototype, { // | // v // exp = foo ? something : something_else; - if (consequent instanceof AST_Assign - && alternative instanceof AST_Assign + if (consequent instanceof AST.Assign + && alternative instanceof AST.Assign && consequent.operator == alternative.operator && consequent.left.equivalent_to(alternative.left) && (!self.condition.has_side_effects(compressor) || consequent.operator == "=" && !consequent.left.has_side_effects(compressor))) { - return make_node(AST_Assign, self, { + return make_node(AST.Assign, self, { operator: consequent.operator, left: consequent.left, - right: make_node(AST_Conditional, self, { + right: make_node(AST.Conditional, self, { condition: self.condition, consequent: consequent.right, alternative: alternative.right @@ -6095,7 +6019,7 @@ merge(Compressor.prototype, { } // x ? y(a) : y(b) --> y(x ? a : b) var arg_index; - if (consequent instanceof AST_Call + if (consequent instanceof AST.Call && alternative.TYPE === consequent.TYPE && consequent.args.length > 0 && consequent.args.length == alternative.args.length @@ -6104,7 +6028,7 @@ merge(Compressor.prototype, { && !consequent.expression.has_side_effects(compressor) && typeof (arg_index = single_arg_diff()) == "number") { var node = consequent.clone(); - node.args[arg_index] = make_node(AST_Conditional, self, { + node.args[arg_index] = make_node(AST.Conditional, self, { condition: self.condition, consequent: consequent.args[arg_index], alternative: alternative.args[arg_index] @@ -6112,10 +6036,10 @@ merge(Compressor.prototype, { return node; } // x?y?z:a:a --> x&&y?z:a - if (consequent instanceof AST_Conditional + if (consequent instanceof AST.Conditional && consequent.alternative.equivalent_to(alternative)) { - return make_node(AST_Conditional, self, { - condition: make_node(AST_Binary, self, { + return make_node(AST.Conditional, self, { + condition: make_node(AST.Binary, self, { left: self.condition, operator: "&&", right: consequent.condition @@ -6132,10 +6056,10 @@ merge(Compressor.prototype, { ]).optimize(compressor); } // x ? (y, w) : (z, w) --> x ? y : z, w - if ((consequent instanceof AST_Sequence || alternative instanceof AST_Sequence) + if ((consequent instanceof AST.Sequence || alternative instanceof AST.Sequence) && consequent.tail_node().equivalent_to(alternative.tail_node())) { return make_sequence(self, [ - make_node(AST_Conditional, self, { + make_node(AST.Conditional, self, { condition: self.condition, consequent: pop_seq(consequent), alternative: pop_seq(alternative) @@ -6144,12 +6068,12 @@ merge(Compressor.prototype, { ]).optimize(compressor); } // x ? y || z : z --> x && y || z - if (consequent instanceof AST_Binary + if (consequent instanceof AST.Binary && consequent.operator == "||" && consequent.right.equivalent_to(alternative)) { - return make_node(AST_Binary, self, { + return make_node(AST.Binary, self, { operator: "||", - left: make_node(AST_Binary, self, { + left: make_node(AST.Binary, self, { operator: "&&", left: self.condition, right: consequent.left @@ -6164,7 +6088,7 @@ merge(Compressor.prototype, { return booleanize(self.condition); } // c ? true : x ---> !!c || x - return make_node(AST_Binary, self, { + return make_node(AST.Binary, self, { operator: "||", left: booleanize(self.condition), right: self.alternative @@ -6176,7 +6100,7 @@ merge(Compressor.prototype, { return booleanize(self.condition.negate(compressor)); } // c ? false : x ---> !c && x - return make_node(AST_Binary, self, { + return make_node(AST.Binary, self, { operator: "&&", left: booleanize(self.condition.negate(compressor)), right: self.alternative @@ -6184,7 +6108,7 @@ merge(Compressor.prototype, { } if (is_true(self.alternative)) { // c ? x : true ---> !c || x - return make_node(AST_Binary, self, { + return make_node(AST.Binary, self, { operator: "||", left: booleanize(self.condition.negate(compressor)), right: self.consequent @@ -6192,7 +6116,7 @@ merge(Compressor.prototype, { } if (is_false(self.alternative)) { // c ? x : false ---> !!c && x - return make_node(AST_Binary, self, { + return make_node(AST.Binary, self, { operator: "&&", left: booleanize(self.condition), right: self.consequent @@ -6204,32 +6128,32 @@ merge(Compressor.prototype, { function booleanize(node) { if (node.is_boolean()) return node; // !!expression - return make_node(AST_UnaryPrefix, node, { + return make_node(AST.UnaryPrefix, node, { operator: "!", expression: node.negate(compressor) }); } - // AST_True or !0 + // AST.True or !0 function is_true(node) { - return node instanceof AST_True + return node instanceof AST.True || in_bool - && node instanceof AST_Constant + && node instanceof AST.Constant && node.getValue() - || (node instanceof AST_UnaryPrefix + || (node instanceof AST.UnaryPrefix && node.operator == "!" - && node.expression instanceof AST_Constant + && node.expression instanceof AST.Constant && !node.expression.getValue()); } - // AST_False or !1 + // AST.False or !1 function is_false(node) { - return node instanceof AST_False + return node instanceof AST.False || in_bool - && node instanceof AST_Constant + && node instanceof AST.Constant && !node.getValue() - || (node instanceof AST_UnaryPrefix + || (node instanceof AST.UnaryPrefix && node.operator == "!" - && node.expression instanceof AST_Constant + && node.expression instanceof AST.Constant && node.expression.getValue()); } @@ -6247,20 +6171,20 @@ merge(Compressor.prototype, { } function pop_seq(node) { - if (!(node instanceof AST_Sequence)) return make_node(AST_Number, node, { + if (!(node instanceof AST.Sequence)) return make_node(AST.Number, node, { value: 0 }); return make_sequence(node, node.expressions.slice(0, -1)); } }); - OPT(AST_Boolean, function(self, compressor) { + OPT(AST.Boolean, function(self, compressor) { if (!compressor.option("booleans")) return self; - if (compressor.in_boolean_context()) return make_node(AST_Number, self, { + if (compressor.in_boolean_context()) return make_node(AST.Number, self, { value: +self.value }); var p = compressor.parent(); - if (p instanceof AST_Binary && (p.operator == "==" || p.operator == "!=")) { + if (p instanceof AST.Binary && (p.operator == "==" || p.operator == "!=")) { compressor.warn("Non-strict equality against boolean: {operator} {value} [{file}:{line},{col}]", { operator : p.operator, value : self.value, @@ -6268,19 +6192,19 @@ merge(Compressor.prototype, { line : p.start.line, col : p.start.col, }); - return make_node(AST_Number, self, { + return make_node(AST.Number, self, { value: +self.value }); } - return make_node(AST_UnaryPrefix, self, { + return make_node(AST.UnaryPrefix, self, { operator: "!", - expression: make_node(AST_Number, self, { + expression: make_node(AST.Number, self, { value: 1 - self.value }) }); }); - OPT(AST_Sub, function(self, compressor) { + OPT(AST.Sub, function(self, compressor) { var expr = self.expression; var prop = self.property; if (compressor.option("properties")) { @@ -6300,7 +6224,7 @@ merge(Compressor.prototype, { var property = "" + key; if (is_identifier_string(property) && property.length <= prop.print_to_string().length + 1) { - return make_node(AST_Dot, self, { + return make_node(AST.Dot, self, { expression: expr, property: property }).optimize(compressor); @@ -6316,7 +6240,7 @@ merge(Compressor.prototype, { } } if (compressor.option("properties") && compressor.option("side_effects") - && prop instanceof AST_Number && expr instanceof AST_Array) { + && prop instanceof AST.Number && expr instanceof AST.Array) { var index = prop.getValue(); var elements = expr.elements; if (index in elements) { @@ -6330,7 +6254,7 @@ merge(Compressor.prototype, { } } var retValue = elements[index]; - retValue = retValue instanceof AST_Hole ? make_node(AST_Undefined, retValue) : retValue; + retValue = retValue instanceof AST.Hole ? make_node(AST.Undefined, retValue) : retValue; if (!flatten) values.unshift(retValue); while (--i >= 0) { var value = elements[i].drop_side_effect_free(compressor); @@ -6340,11 +6264,11 @@ merge(Compressor.prototype, { if (flatten) { values.push(retValue); return make_sequence(self, values).optimize(compressor); - } else return make_node(AST_Sub, self, { - expression: make_node(AST_Array, expr, { + } else return make_node(AST.Sub, self, { + expression: make_node(AST.Array, expr, { elements: values }), - property: make_node(AST_Number, prop, { + property: make_node(AST.Number, prop, { value: index }) }); @@ -6352,16 +6276,16 @@ merge(Compressor.prototype, { } var fn; if (compressor.option("arguments") - && expr instanceof AST_SymbolRef + && expr instanceof AST.SymbolRef && expr.name == "arguments" && expr.definition().orig.length == 1 - && (fn = expr.scope) instanceof AST_Lambda - && prop instanceof AST_Number) { + && (fn = expr.scope) instanceof AST.Lambda + && prop instanceof AST.Number) { var index = prop.getValue(); var argname = fn.argnames[index]; if (!argname && !compressor.option("keep_fargs")) { while (index >= fn.argnames.length) { - argname = make_node(AST_SymbolFunarg, fn, { + argname = make_node(AST.SymbolFunarg, fn, { name: fn.make_var_name("argument_" + fn.argnames.length), scope: fn }); @@ -6370,7 +6294,7 @@ merge(Compressor.prototype, { } } if (argname) { - var sym = make_node(AST_SymbolRef, self, argname); + var sym = make_node(AST.SymbolRef, self, argname); sym.reference({}); return sym; } @@ -6383,39 +6307,39 @@ merge(Compressor.prototype, { return self; }); - AST_Scope.DEFMETHOD("contains_this", function() { + AST.Scope.DEFMETHOD("contains_this", function() { var result; var self = this; self.walk(new TreeWalker(function(node) { if (result) return true; - if (node instanceof AST_This) return result = true; - if (node !== self && node instanceof AST_Scope) return true; + if (node instanceof AST.This) return result = true; + if (node !== self && node instanceof AST.Scope) return true; })); return result; }); - AST_PropAccess.DEFMETHOD("flatten_object", function(key, compressor) { + AST.PropAccess.DEFMETHOD("flatten_object", function(key, compressor) { if (!compressor.option("properties")) return; var expr = this.expression; - if (expr instanceof AST_Object) { + if (expr instanceof AST.Object) { var props = expr.properties; for (var i = props.length; --i >= 0;) { var prop = props[i]; if ("" + prop.key == key) { if (!all(props, function(prop) { - return prop instanceof AST_ObjectKeyVal; + return prop instanceof AST.ObjectKeyVal; })) break; var value = prop.value; - if (value instanceof AST_Function - && !(compressor.parent() instanceof AST_New) + if (value instanceof AST.Function + && !(compressor.parent() instanceof AST.New) && value.contains_this()) break; - return make_node(AST_Sub, this, { - expression: make_node(AST_Array, expr, { + return make_node(AST.Sub, this, { + expression: make_node(AST.Array, expr, { elements: props.map(function(prop) { return prop.value; }) }), - property: make_node(AST_Number, this, { + property: make_node(AST.Number, this, { value: i }) }); @@ -6424,7 +6348,7 @@ merge(Compressor.prototype, { } }); - OPT(AST_Dot, function(self, compressor) { + OPT(AST.Dot, function(self, compressor) { if (self.property == "arguments" || self.property == "caller") { compressor.warn("Function.protoype.{prop} not supported [{file}:{line},{col}]", { prop: self.property, @@ -6439,38 +6363,38 @@ merge(Compressor.prototype, { } if (is_lhs(self, compressor.parent())) return self; if (compressor.option("unsafe_proto") - && self.expression instanceof AST_Dot + && self.expression instanceof AST.Dot && self.expression.property == "prototype") { var exp = self.expression.expression; if (is_undeclared_ref(exp)) switch (exp.name) { case "Array": - self.expression = make_node(AST_Array, self.expression, { + self.expression = make_node(AST.Array, self.expression, { elements: [] }); break; case "Function": - self.expression = make_node(AST_Function, self.expression, { + self.expression = make_node(AST.Function, self.expression, { argnames: [], body: [] }); break; case "Number": - self.expression = make_node(AST_Number, self.expression, { + self.expression = make_node(AST.Number, self.expression, { value: 0 }); break; case "Object": - self.expression = make_node(AST_Object, self.expression, { + self.expression = make_node(AST.Object, self.expression, { properties: [] }); break; case "RegExp": - self.expression = make_node(AST_RegExp, self.expression, { + self.expression = make_node(AST.RegExp, self.expression, { value: /t/ }); break; case "String": - self.expression = make_node(AST_String, self.expression, { + self.expression = make_node(AST.String, self.expression, { value: "" }); break; @@ -6486,14 +6410,14 @@ merge(Compressor.prototype, { return self; }); - OPT(AST_Return, function(self, compressor) { + OPT(AST.Return, function(self, compressor) { if (self.value && is_undefined(self.value, compressor)) { self.value = null; } return self; }); - OPT(AST_VarDef, function(self, compressor) { + OPT(AST.VarDef, function(self, compressor) { var defines = compressor.option("global_defs"); if (defines && HOP(defines, self.name.name)) { compressor.warn('global_defs ' + self.name.name + ' redefined [{file}:{line},{col}]', self.start); diff --git a/lib/minify.js b/lib/minify.js index 31d3bb1c..07f768fb 100644 --- a/lib/minify.js +++ b/lib/minify.js @@ -7,11 +7,8 @@ var HOP = utils.HOP; var MAP = utils.MAP; var merge = utils.merge; -var ast = require("./ast"); -var AST_Node = ast.AST_Node; -var AST_Toplevel = ast.AST_Toplevel; -var AST_Directive = ast.AST_Directive; -var TreeTransformer = ast.TreeTransformer; +var AST = require("./ast"); +var TreeTransformer = AST.TreeTransformer; var parse = require("./parse"); var parse = parse.parse; @@ -35,7 +32,7 @@ var to_base64 = typeof btoa == "undefined" ? function(str) { function read_source_map(name, code) { var match = /\n\/\/# sourceMappingURL=data:application\/json(;.*?)?;base64,(.*)/.exec(code); if (!match) { - AST_Node.warn("inline source map not found: " + name); + AST.Node.warn("inline source map not found: " + name); return null; } return to_ascii(match[2]); @@ -81,7 +78,7 @@ function minify(files, options) { var wrapped_tl = "(function(exports){'$ORIG';})(typeof " + name + "=='undefined'?(" + name + "={}):" + name + ");"; wrapped_tl = parse(wrapped_tl); wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node) { - if (node instanceof AST_Directive && node.value == "$ORIG") { + if (node instanceof AST.Directive && node.value == "$ORIG") { return MAP.splice(body); } })); @@ -99,13 +96,13 @@ function minify(files, options) { args_values.slice(index + 1), ")" ].join("")).transform(new TreeTransformer(function(node) { - if (node instanceof AST_Directive && node.value == "$ORIG") { + if (node instanceof AST.Directive && node.value == "$ORIG") { return MAP.splice(body); } })); } - var warn_function = AST_Node.warn_function; + var warn_function = AST.Node.warn_function; try { options = defaults(options, { compress: {}, @@ -170,14 +167,14 @@ function minify(files, options) { }, true); } var warnings = []; - if (options.warnings && !AST_Node.warn_function) { - AST_Node.warn_function = function(warning) { + if (options.warnings && !AST.Node.warn_function) { + AST.Node.warn_function = function(warning) { warnings.push(warning); }; } if (timings) timings.parse = Date.now(); var source_maps, toplevel; - if (files instanceof AST_Toplevel) { + if (files instanceof AST.Toplevel) { toplevel = files; } else { if (typeof files == "string") { @@ -246,7 +243,7 @@ function minify(files, options) { root: options.sourceMap.root }); if (options.sourceMap.includeSources) { - if (files instanceof AST_Toplevel) { + if (files instanceof AST.Toplevel) { throw new Error("original source content unavailable"); } else for (var name in files) if (HOP(files, name)) { options.output.source_map.get().setSourceContent(name, files[name]); @@ -295,7 +292,7 @@ function minify(files, options) { } catch (ex) { return { error: ex }; } finally { - AST_Node.warn_function = warn_function; + AST.Node.warn_function = warn_function; } } diff --git a/lib/mozilla-ast.js b/lib/mozilla-ast.js index 1a464ee7..21372379 100644 --- a/lib/mozilla-ast.js +++ b/lib/mozilla-ast.js @@ -43,95 +43,20 @@ "use strict"; -var ast = require("./ast"); -var TreeWalker = ast.TreeWalker; -var AST_Token = ast.AST_Token; -var AST_Node = ast.AST_Node; -var AST_Statement = ast.AST_Statement; -var AST_Debugger = ast.AST_Debugger; -var AST_Directive = ast.AST_Directive; -var AST_SimpleStatement = ast.AST_SimpleStatement; -var AST_Block = ast.AST_Block; -var AST_BlockStatement = ast.AST_BlockStatement; -var AST_EmptyStatement = ast.AST_EmptyStatement; -var AST_LabeledStatement = ast.AST_LabeledStatement; -var AST_Do = ast.AST_Do; -var AST_While = ast.AST_While; -var AST_For = ast.AST_For; -var AST_ForIn = ast.AST_ForIn; -var AST_With = ast.AST_With; -var AST_Scope = ast.AST_Scope; -var AST_Toplevel = ast.AST_Toplevel; -var AST_Lambda = ast.AST_Lambda; -var AST_Accessor = ast.AST_Accessor; -var AST_Function = ast.AST_Function; -var AST_Defun = ast.AST_Defun; -var AST_Return = ast.AST_Return; -var AST_Throw = ast.AST_Throw; -var AST_Break = ast.AST_Break; -var AST_Continue = ast.AST_Continue; -var AST_If = ast.AST_If; -var AST_Switch = ast.AST_Switch; -var AST_SwitchBranch = ast.AST_SwitchBranch; -var AST_Default = ast.AST_Default; -var AST_Case = ast.AST_Case; -var AST_Try = ast.AST_Try; -var AST_Catch = ast.AST_Catch; -var AST_Finally = ast.AST_Finally; -var AST_Definitions = ast.AST_Definitions; -var AST_Var = ast.AST_Var; -var AST_VarDef = ast.AST_VarDef; -var AST_Call = ast.AST_Call; -var AST_New = ast.AST_New; -var AST_Sequence = ast.AST_Sequence; -var AST_PropAccess = ast.AST_PropAccess; -var AST_Dot = ast.AST_Dot; -var AST_Sub = ast.AST_Sub; -var AST_Unary = ast.AST_Unary; -var AST_UnaryPrefix = ast.AST_UnaryPrefix; -var AST_UnaryPostfix = ast.AST_UnaryPostfix; -var AST_Binary = ast.AST_Binary; -var AST_Conditional = ast.AST_Conditional; -var AST_Assign = ast.AST_Assign; -var AST_Array = ast.AST_Array; -var AST_Object = ast.AST_Object; -var AST_ObjectProperty = ast.AST_ObjectProperty; -var AST_ObjectKeyVal = ast.AST_ObjectKeyVal; -var AST_ObjectSetter = ast.AST_ObjectSetter; -var AST_ObjectGetter = ast.AST_ObjectGetter; -var AST_Symbol = ast.AST_Symbol; -var AST_SymbolAccessor = ast.AST_SymbolAccessor; -var AST_SymbolVar = ast.AST_SymbolVar; -var AST_SymbolFunarg = ast.AST_SymbolFunarg; -var AST_SymbolDefun = ast.AST_SymbolDefun; -var AST_SymbolLambda = ast.AST_SymbolLambda; -var AST_SymbolCatch = ast.AST_SymbolCatch; -var AST_Label = ast.AST_Label; -var AST_SymbolRef = ast.AST_SymbolRef; -var AST_LabelRef = ast.AST_LabelRef; -var AST_This = ast.AST_This; -var AST_Constant = ast.AST_Constant; -var AST_String = ast.AST_String; -var AST_Number = ast.AST_Number; -var AST_RegExp = ast.AST_RegExp; -var AST_Atom = ast.AST_Atom; -var AST_Null = ast.AST_Null; -var AST_Hole = ast.AST_Hole; -var AST_Boolean = ast.AST_Boolean; -var AST_False = ast.AST_False; -var AST_True = ast.AST_True; +var AST = require("./ast"); +var TreeWalker = AST.TreeWalker; (function() { function normalize_directives(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({ + 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)) { + } else if (in_directive && !(body[i] instanceof AST.Statement && body[i].body instanceof AST.String)) { in_directive = false; } } @@ -140,14 +65,14 @@ var AST_True = ast.AST_True; var MOZ_TO_ME = { Program: function(M) { - return new AST_Toplevel({ + 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({ + return new AST.Defun({ start: my_start_token(M), end: my_end_token(M), name: from_moz(M.id), @@ -156,7 +81,7 @@ var AST_True = ast.AST_True; }); }, FunctionExpression: function(M) { - return new AST_Function({ + return new AST.Function({ start: my_start_token(M), end: my_end_token(M), name: from_moz(M.id), @@ -165,7 +90,7 @@ var AST_True = ast.AST_True; }); }, ExpressionStatement: function(M) { - return new AST_SimpleStatement({ + return new AST.SimpleStatement({ start: my_start_token(M), end: my_end_token(M), body: from_moz(M.expression) @@ -176,12 +101,12 @@ var AST_True = ast.AST_True; if (handlers.length > 1 || M.guardedHandlers && M.guardedHandlers.length) { throw new Error("Multiple catch clauses are not supported."); } - return new AST_Try({ + return new AST.Try({ start : my_start_token(M), end : my_end_token(M), body : from_moz(M.block).body, bcatch : from_moz(handlers[0]), - bfinally : M.finalizer ? new AST_Finally(from_moz(M.finalizer)) : null + bfinally : M.finalizer ? new AST.Finally(from_moz(M.finalizer)) : null }); }, Property: function(M) { @@ -192,25 +117,25 @@ var AST_True = ast.AST_True; key : key.type == "Identifier" ? key.name : key.value, value : from_moz(M.value) }; - if (M.kind == "init") return new AST_ObjectKeyVal(args); - args.key = new AST_SymbolAccessor({ + if (M.kind == "init") return new AST.ObjectKeyVal(args); + args.key = new AST.SymbolAccessor({ name: args.key }); - args.value = new AST_Accessor(args.value); - if (M.kind == "get") return new AST_ObjectGetter(args); - if (M.kind == "set") return new AST_ObjectSetter(args); + args.value = new AST.Accessor(args.value); + if (M.kind == "get") return new AST.ObjectGetter(args); + if (M.kind == "set") return new AST.ObjectSetter(args); }, ArrayExpression: function(M) { - return new AST_Array({ + return new AST.Array({ start : my_start_token(M), end : my_end_token(M), elements : M.elements.map(function(elem) { - return elem === null ? new AST_Hole() : from_moz(elem); + return elem === null ? new AST.Hole() : from_moz(elem); }) }); }, ObjectExpression: function(M) { - return new AST_Object({ + return new AST.Object({ start : my_start_token(M), end : my_end_token(M), properties : M.properties.map(function(prop) { @@ -220,14 +145,14 @@ var AST_True = ast.AST_True; }); }, SequenceExpression: function(M) { - return new AST_Sequence({ + return new AST.Sequence({ start : my_start_token(M), end : my_end_token(M), expressions: M.expressions.map(from_moz) }); }, MemberExpression: function(M) { - return new (M.computed ? AST_Sub : AST_Dot)({ + return new (M.computed ? AST.Sub : AST.Dot)({ start : my_start_token(M), end : my_end_token(M), property : M.computed ? from_moz(M.property) : M.property.name, @@ -235,7 +160,7 @@ var AST_True = ast.AST_True; }); }, SwitchCase: function(M) { - return new (M.test ? AST_Case : AST_Default)({ + return new (M.test ? AST.Case : AST.Default)({ start : my_start_token(M), end : my_end_token(M), expression : from_moz(M.test), @@ -243,7 +168,7 @@ var AST_True = ast.AST_True; }); }, VariableDeclaration: function(M) { - return new AST_Var({ + return new AST.Var({ start : my_start_token(M), end : my_end_token(M), definitions : M.declarations.map(from_moz) @@ -254,38 +179,38 @@ var AST_True = ast.AST_True; start : my_start_token(M), end : my_end_token(M) }; - if (val === null) return new AST_Null(args); + if (val === null) return new AST.Null(args); var rx = M.regex; if (rx && rx.pattern) { // RegExpLiteral as per ESTree AST spec args.value = new RegExp(rx.pattern, rx.flags); args.value.raw_source = rx.pattern; - return new AST_RegExp(args); + return new AST.RegExp(args); } else if (rx) { // support legacy RegExp args.value = M.regex && M.raw ? M.raw : val; - return new AST_RegExp(args); + return new AST.RegExp(args); } switch (typeof val) { case "string": args.value = val; - return new AST_String(args); + return new AST.String(args); case "number": args.value = val; - return new AST_Number(args); + return new AST.Number(args); case "boolean": - return new (val ? AST_True : AST_False)(args); + return new (val ? AST.True : AST.False)(args); } }, Identifier: function(M) { var p = FROM_MOZ_STACK[FROM_MOZ_STACK.length - 2]; - return new ( p.type == "LabeledStatement" ? AST_Label - : p.type == "VariableDeclarator" && p.id === M ? AST_SymbolVar - : p.type == "FunctionExpression" ? (p.id === M ? AST_SymbolLambda : AST_SymbolFunarg) - : p.type == "FunctionDeclaration" ? (p.id === M ? AST_SymbolDefun : AST_SymbolFunarg) - : p.type == "CatchClause" ? AST_SymbolCatch - : p.type == "BreakStatement" || p.type == "ContinueStatement" ? AST_LabelRef - : AST_SymbolRef)({ + return new ( p.type == "LabeledStatement" ? AST.Label + : p.type == "VariableDeclarator" && p.id === M ? AST.SymbolVar + : p.type == "FunctionExpression" ? (p.id === M ? AST.SymbolLambda : AST.SymbolFunarg) + : p.type == "FunctionDeclaration" ? (p.id === M ? AST.SymbolDefun : AST.SymbolFunarg) + : p.type == "CatchClause" ? AST.SymbolCatch + : p.type == "BreakStatement" || p.type == "ContinueStatement" ? AST.LabelRef + : AST.SymbolRef)({ start : my_start_token(M), end : my_end_token(M), name : M.name @@ -297,7 +222,7 @@ var AST_True = ast.AST_True; MOZ_TO_ME.UnaryExpression = function To_Moz_Unary(M) { var prefix = "prefix" in M ? M.prefix : M.type == "UnaryExpression" ? true : false; - return new (prefix ? AST_UnaryPrefix : AST_UnaryPostfix)({ + return new (prefix ? AST.UnaryPrefix : AST.UnaryPostfix)({ start : my_start_token(M), end : my_end_token(M), operator : M.operator, @@ -305,37 +230,37 @@ var AST_True = ast.AST_True; }); }; - map("EmptyStatement", AST_EmptyStatement); - map("BlockStatement", AST_BlockStatement, "body@body"); - map("IfStatement", AST_If, "test>condition, consequent>body, alternate>alternative"); - map("LabeledStatement", AST_LabeledStatement, "label>label, body>body"); - map("BreakStatement", AST_Break, "label>label"); - map("ContinueStatement", AST_Continue, "label>label"); - map("WithStatement", AST_With, "object>expression, body>body"); - map("SwitchStatement", AST_Switch, "discriminant>expression, cases@body"); - map("ReturnStatement", AST_Return, "argument>value"); - map("ThrowStatement", AST_Throw, "argument>value"); - map("WhileStatement", AST_While, "test>condition, body>body"); - map("DoWhileStatement", AST_Do, "test>condition, body>body"); - 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("VariableDeclarator", AST_VarDef, "id>name, init>value"); - map("CatchClause", AST_Catch, "param>argname, body%body"); + map("EmptyStatement", AST.EmptyStatement); + map("BlockStatement", AST.BlockStatement, "body@body"); + map("IfStatement", AST.If, "test>condition, consequent>body, alternate>alternative"); + map("LabeledStatement", AST.LabeledStatement, "label>label, body>body"); + map("BreakStatement", AST.Break, "label>label"); + map("ContinueStatement", AST.Continue, "label>label"); + map("WithStatement", AST.With, "object>expression, body>body"); + map("SwitchStatement", AST.Switch, "discriminant>expression, cases@body"); + map("ReturnStatement", AST.Return, "argument>value"); + map("ThrowStatement", AST.Throw, "argument>value"); + map("WhileStatement", AST.While, "test>condition, body>body"); + map("DoWhileStatement", AST.Do, "test>condition, body>body"); + 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("VariableDeclarator", AST.VarDef, "id>name, init>value"); + map("CatchClause", AST.Catch, "param>argname, body%body"); - map("ThisExpression", AST_This); - 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"); - map("ConditionalExpression", AST_Conditional, "test>condition, consequent>consequent, alternate>alternative"); - map("NewExpression", AST_New, "callee>expression, arguments@args"); - map("CallExpression", AST_Call, "callee>expression, arguments@args"); + map("ThisExpression", AST.This); + 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"); + map("ConditionalExpression", AST.Conditional, "test>condition, consequent>consequent, alternate>alternative"); + 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) { + def_to_moz(AST.Toplevel, function To_Moz_Program(M) { return to_moz_scope("Program", M); }); - def_to_moz(AST_Defun, function To_Moz_FunctionDeclaration(M) { + def_to_moz(AST.Defun, function To_Moz_FunctionDeclaration(M) { return { type: "FunctionDeclaration", id: to_moz(M.name), @@ -344,7 +269,7 @@ var AST_True = ast.AST_True; } }); - def_to_moz(AST_Function, function To_Moz_FunctionExpression(M) { + def_to_moz(AST.Function, function To_Moz_FunctionExpression(M) { return { type: "FunctionExpression", id: to_moz(M.name), @@ -353,7 +278,7 @@ var AST_True = ast.AST_True; } }); - def_to_moz(AST_Directive, function To_Moz_Directive(M) { + def_to_moz(AST.Directive, function To_Moz_Directive(M) { return { type: "ExpressionStatement", expression: { @@ -363,14 +288,14 @@ var AST_True = ast.AST_True; }; }); - def_to_moz(AST_SimpleStatement, function To_Moz_ExpressionStatement(M) { + def_to_moz(AST.SimpleStatement, function To_Moz_ExpressionStatement(M) { return { type: "ExpressionStatement", expression: to_moz(M.body) }; }); - def_to_moz(AST_SwitchBranch, function To_Moz_SwitchCase(M) { + def_to_moz(AST.SwitchBranch, function To_Moz_SwitchCase(M) { return { type: "SwitchCase", test: to_moz(M.expression), @@ -378,7 +303,7 @@ var AST_True = ast.AST_True; }; }); - def_to_moz(AST_Try, function To_Moz_TryStatement(M) { + def_to_moz(AST.Try, function To_Moz_TryStatement(M) { return { type: "TryStatement", block: to_moz_block(M), @@ -388,7 +313,7 @@ var AST_True = ast.AST_True; }; }); - def_to_moz(AST_Catch, function To_Moz_CatchClause(M) { + def_to_moz(AST.Catch, function To_Moz_CatchClause(M) { return { type: "CatchClause", param: to_moz(M.argname), @@ -397,7 +322,7 @@ var AST_True = ast.AST_True; }; }); - def_to_moz(AST_Definitions, function To_Moz_VariableDeclaration(M) { + def_to_moz(AST.Definitions, function To_Moz_VariableDeclaration(M) { return { type: "VariableDeclaration", kind: "var", @@ -405,15 +330,15 @@ var AST_True = ast.AST_True; }; }); - def_to_moz(AST_Sequence, function To_Moz_SequenceExpression(M) { + def_to_moz(AST.Sequence, function To_Moz_SequenceExpression(M) { return { type: "SequenceExpression", expressions: M.expressions.map(to_moz) }; }); - def_to_moz(AST_PropAccess, function To_Moz_MemberExpression(M) { - var isComputed = M instanceof AST_Sub; + def_to_moz(AST.PropAccess, function To_Moz_MemberExpression(M) { + var isComputed = M instanceof AST.Sub; return { type: "MemberExpression", object: to_moz(M.expression), @@ -422,16 +347,16 @@ var AST_True = ast.AST_True; }; }); - def_to_moz(AST_Unary, function To_Moz_Unary(M) { + def_to_moz(AST.Unary, function To_Moz_Unary(M) { return { type: M.operator == "++" || M.operator == "--" ? "UpdateExpression" : "UnaryExpression", operator: M.operator, - prefix: M instanceof AST_UnaryPrefix, + prefix: M instanceof AST.UnaryPrefix, argument: to_moz(M.expression) }; }); - def_to_moz(AST_Binary, function To_Moz_BinaryExpression(M) { + def_to_moz(AST.Binary, function To_Moz_BinaryExpression(M) { return { type: M.operator == "&&" || M.operator == "||" ? "LogicalExpression" : "BinaryExpression", left: to_moz(M.left), @@ -440,33 +365,33 @@ var AST_True = ast.AST_True; }; }); - def_to_moz(AST_Array, function To_Moz_ArrayExpression(M) { + def_to_moz(AST.Array, function To_Moz_ArrayExpression(M) { return { type: "ArrayExpression", elements: M.elements.map(to_moz) }; }); - def_to_moz(AST_Object, function To_Moz_ObjectExpression(M) { + def_to_moz(AST.Object, function To_Moz_ObjectExpression(M) { return { type: "ObjectExpression", properties: M.properties.map(to_moz) }; }); - def_to_moz(AST_ObjectProperty, function To_Moz_Property(M) { + def_to_moz(AST.ObjectProperty, function To_Moz_Property(M) { var key = { type: "Literal", - value: M.key instanceof AST_SymbolAccessor ? M.key.name : M.key + value: M.key instanceof AST.SymbolAccessor ? M.key.name : M.key }; var kind; - if (M instanceof AST_ObjectKeyVal) { + if (M instanceof AST.ObjectKeyVal) { kind = "init"; } else - if (M instanceof AST_ObjectGetter) { + if (M instanceof AST.ObjectGetter) { kind = "get"; } else - if (M instanceof AST_ObjectSetter) { + if (M instanceof AST.ObjectSetter) { kind = "set"; } return { @@ -477,7 +402,7 @@ var AST_True = ast.AST_True; }; }); - def_to_moz(AST_Symbol, function To_Moz_Identifier(M) { + def_to_moz(AST.Symbol, function To_Moz_Identifier(M) { var def = M.definition(); return { type: "Identifier", @@ -485,7 +410,7 @@ var AST_True = ast.AST_True; }; }); - def_to_moz(AST_RegExp, function To_Moz_RegExpLiteral(M) { + def_to_moz(AST.RegExp, function To_Moz_RegExpLiteral(M) { var flags = M.value.toString().match(/[gimuy]*$/)[0]; var value = "/" + M.value.raw_source + "/" + flags; return { @@ -499,7 +424,7 @@ var AST_True = ast.AST_True; }; }); - def_to_moz(AST_Constant, function To_Moz_Literal(M) { + def_to_moz(AST.Constant, function To_Moz_Literal(M) { var value = M.value; if (typeof value === 'number' && (value < 0 || (value === 0 && 1 / value < 0))) { return { @@ -520,19 +445,19 @@ var AST_True = ast.AST_True; }; }); - def_to_moz(AST_Atom, function To_Moz_Atom(M) { + def_to_moz(AST.Atom, function To_Moz_Atom(M) { return { type: "Identifier", name: String(M.value) }; }); - AST_Boolean.DEFMETHOD("to_mozilla_ast", AST_Constant.prototype.to_mozilla_ast); - AST_Null.DEFMETHOD("to_mozilla_ast", AST_Constant.prototype.to_mozilla_ast); - AST_Hole.DEFMETHOD("to_mozilla_ast", function To_Moz_ArrayHole() { return null }); + AST.Boolean.DEFMETHOD("to_mozilla_ast", AST.Constant.prototype.to_mozilla_ast); + AST.Null.DEFMETHOD("to_mozilla_ast", AST.Constant.prototype.to_mozilla_ast); + AST.Hole.DEFMETHOD("to_mozilla_ast", function To_Moz_ArrayHole() { return null }); - AST_Block.DEFMETHOD("to_mozilla_ast", AST_BlockStatement.prototype.to_mozilla_ast); - AST_Lambda.DEFMETHOD("to_mozilla_ast", AST_Function.prototype.to_mozilla_ast); + AST.Block.DEFMETHOD("to_mozilla_ast", AST.BlockStatement.prototype.to_mozilla_ast); + AST.Lambda.DEFMETHOD("to_mozilla_ast", AST.Function.prototype.to_mozilla_ast); /* -----[ tools ]----- */ @@ -545,7 +470,7 @@ var AST_True = ast.AST_True; function my_start_token(moznode) { var loc = moznode.loc, start = loc && loc.start; var range = moznode.range; - return new AST_Token({ + return new AST.Token({ file : loc && loc.source, line : start && start.line, col : start && start.column, @@ -560,7 +485,7 @@ var AST_True = ast.AST_True; function my_end_token(moznode) { var loc = moznode.loc, end = loc && loc.end; var range = moznode.range; - return new AST_Token({ + return new AST.Token({ file : loc && loc.source, line : end && end.line, col : end && end.column, @@ -618,7 +543,7 @@ var AST_True = ast.AST_True; //console.log(moz_to_me); moz_to_me = new Function("U2", "my_start_token", "my_end_token", "from_moz", "return(" + moz_to_me + ")")( - ast, my_start_token, my_end_token, from_moz + AST, my_start_token, my_end_token, from_moz ); me_to_moz = new Function("to_moz", "to_moz_block", "to_moz_scope", "return(" + me_to_moz + ")")( to_moz, to_moz_block, to_moz_scope @@ -636,16 +561,16 @@ var AST_True = ast.AST_True; return ret; } - AST_Node.from_mozilla_ast = function(node) { + AST.Node.from_mozilla_ast = function(node) { var save_stack = FROM_MOZ_STACK; FROM_MOZ_STACK = []; var ast = from_moz(node); FROM_MOZ_STACK = save_stack; ast.walk(new TreeWalker(function(node) { - if (node instanceof AST_LabelRef) { + if (node instanceof AST.LabelRef) { for (var level = 0, parent; parent = this.parent(level); level++) { - if (parent instanceof AST_Scope) break; - if (parent instanceof AST_LabeledStatement && parent.label.name == node.name) { + if (parent instanceof AST.Scope) break; + if (parent instanceof AST.LabeledStatement && parent.label.name == node.name) { node.thedef = parent.label; break; } @@ -696,8 +621,8 @@ var AST_True = ast.AST_True; function to_moz_scope(type, node) { var body = node.body.map(to_moz); - if (node.body[0] instanceof AST_SimpleStatement && node.body[0].body instanceof AST_String) { - body.unshift(to_moz(new AST_EmptyStatement(node.body[0]))); + if (node.body[0] instanceof AST.SimpleStatement && node.body[0].body instanceof AST.String) { + body.unshift(to_moz(new AST.EmptyStatement(node.body[0]))); } return { type: type, diff --git a/lib/output.js b/lib/output.js index 19f78fbd..e5bbc594 100644 --- a/lib/output.js +++ b/lib/output.js @@ -53,69 +53,9 @@ var makePredicate = utils.makePredicate; var all = utils.all; var merge = utils.merge; -var ast = require("./ast"); -var first_in_statement = ast.first_in_statement; -var TreeWalker = ast.TreeWalker; -var AST_Node = ast.AST_Node; -var AST_Statement = ast.AST_Statement; -var AST_Debugger = ast.AST_Debugger; -var AST_Directive = ast.AST_Directive; -var AST_SimpleStatement = ast.AST_SimpleStatement; -var AST_BlockStatement = ast.AST_BlockStatement; -var AST_EmptyStatement = ast.AST_EmptyStatement; -var AST_StatementWithBody = ast.AST_StatementWithBody; -var AST_LabeledStatement = ast.AST_LabeledStatement; -var AST_Do = ast.AST_Do; -var AST_While = ast.AST_While; -var AST_For = ast.AST_For; -var AST_ForIn = ast.AST_ForIn; -var AST_With = ast.AST_With; -var AST_Scope = ast.AST_Scope; -var AST_Toplevel = ast.AST_Toplevel; -var AST_Lambda = ast.AST_Lambda; -var AST_Function = ast.AST_Function; -var AST_Jump = ast.AST_Jump; -var AST_Exit = ast.AST_Exit; -var AST_Return = ast.AST_Return; -var AST_Throw = ast.AST_Throw; -var AST_Break = ast.AST_Break; -var AST_Continue = ast.AST_Continue; -var AST_If = ast.AST_If; -var AST_Switch = ast.AST_Switch; -var AST_SwitchBranch = ast.AST_SwitchBranch; -var AST_Default = ast.AST_Default; -var AST_Case = ast.AST_Case; -var AST_Try = ast.AST_Try; -var AST_Catch = ast.AST_Catch; -var AST_Finally = ast.AST_Finally; -var AST_Definitions = ast.AST_Definitions; -var AST_Var = ast.AST_Var; -var AST_VarDef = ast.AST_VarDef; -var AST_Call = ast.AST_Call; -var AST_New = ast.AST_New; -var AST_Sequence = ast.AST_Sequence; -var AST_PropAccess = ast.AST_PropAccess; -var AST_Dot = ast.AST_Dot; -var AST_Sub = ast.AST_Sub; -var AST_Unary = ast.AST_Unary; -var AST_UnaryPrefix = ast.AST_UnaryPrefix; -var AST_UnaryPostfix = ast.AST_UnaryPostfix; -var AST_Binary = ast.AST_Binary; -var AST_Conditional = ast.AST_Conditional; -var AST_Assign = ast.AST_Assign; -var AST_Array = ast.AST_Array; -var AST_Object = ast.AST_Object; -var AST_ObjectProperty = ast.AST_ObjectProperty; -var AST_ObjectKeyVal = ast.AST_ObjectKeyVal; -var AST_ObjectSetter = ast.AST_ObjectSetter; -var AST_ObjectGetter = ast.AST_ObjectGetter; -var AST_Symbol = ast.AST_Symbol; -var AST_This = ast.AST_This; -var AST_Constant = ast.AST_Constant; -var AST_String = ast.AST_String; -var AST_Number = ast.AST_Number; -var AST_RegExp = ast.AST_RegExp; -var AST_Hole = ast.AST_Hole; +var AST = require("./ast"); +var first_in_statement = AST.first_in_statement; +var TreeWalker = AST.TreeWalker; var parse = require("./parse"); var is_surrogate_pair_head = parse.is_surrogate_pair_head; @@ -299,7 +239,7 @@ function OutputStream(options) { !mapping.name && mapping.token.type == "name" ? mapping.token.value : mapping.name ); } catch(ex) { - AST_Node.warn("Couldn't figure out mapping for {file}:{line},{col} → {cline},{ccol} [{name}]", { + AST.Node.warn("Couldn't figure out mapping for {file}:{line},{col} → {cline},{ccol} [{name}]", { file: mapping.token.file, line: mapping.token.line, col: mapping.token.col, @@ -330,7 +270,7 @@ function OutputStream(options) { current_col = right.length; } if (current_col > options.max_line_len) { - AST_Node.warn("Output exceeds {max_line_len} characters", options); + AST.Node.warn("Output exceeds {max_line_len} characters", options); } } if (might_add_newline) { @@ -559,17 +499,17 @@ function OutputStream(options) { } comments._dumped = self; - if (node instanceof AST_Exit && node.value) { + if (node instanceof AST.Exit && node.value) { var tw = new TreeWalker(function(node) { var parent = tw.parent(); - if (parent instanceof AST_Exit - || parent instanceof AST_Binary && parent.left === node + if (parent instanceof AST.Exit + || parent instanceof AST.Binary && parent.left === node || parent.TYPE == "Call" && parent.expression === node - || parent instanceof AST_Conditional && parent.condition === node - || parent instanceof AST_Dot && parent.expression === node - || parent instanceof AST_Sequence && parent.expressions[0] === node - || parent instanceof AST_Sub && parent.expression === node - || parent instanceof AST_UnaryPostfix) { + || parent instanceof AST.Conditional && parent.condition === node + || parent instanceof AST.Dot && parent.expression === node + || parent instanceof AST.Sequence && parent.expressions[0] === node + || parent instanceof AST.Sub && parent.expression === node + || parent instanceof AST.UnaryPostfix) { var text = node.start.comments_before; if (text && text._dumped !== self) { text._dumped = self; @@ -632,7 +572,7 @@ function OutputStream(options) { if (!token) return; var comments = token[tail ? "comments_before" : "comments_after"]; if (!comments || comments._dumped === self) return; - if (!(node instanceof AST_Statement || all(comments, function(c) { + if (!(node instanceof AST.Statement || all(comments, function(c) { return !/comment[134]/.test(c.type); }))) return; comments._dumped = self; @@ -725,12 +665,12 @@ function OutputStream(options) { var active_scope = null; var use_asm = null; - AST_Node.DEFMETHOD("print", function(stream, force_parens) { + AST.Node.DEFMETHOD("print", function(stream, force_parens) { var self = this, generator = self._codegen; - if (self instanceof AST_Scope) { + if (self instanceof AST.Scope) { active_scope = self; } - else if (!use_asm && self instanceof AST_Directive && self.value == "use asm") { + else if (!use_asm && self instanceof AST.Directive && self.value == "use asm") { use_asm = active_scope; } function doit() { @@ -750,9 +690,9 @@ function OutputStream(options) { use_asm = null; } }); - AST_Node.DEFMETHOD("_print", AST_Node.prototype.print); + AST.Node.DEFMETHOD("_print", AST.Node.prototype.print); - AST_Node.DEFMETHOD("print_to_string", function(options) { + AST.Node.DEFMETHOD("print_to_string", function(options) { var s = OutputStream(options); this.print(s); return s.get(); @@ -770,25 +710,25 @@ function OutputStream(options) { } } - PARENS(AST_Node, return_false); + PARENS(AST.Node, return_false); // a function expression needs parens around it when it's provably // the first token to appear in a statement. - PARENS(AST_Function, function(output) { + PARENS(AST.Function, function(output) { if (!output.has_parens() && first_in_statement(output)) { return true; } if (output.option('webkit')) { var p = output.parent(); - if (p instanceof AST_PropAccess && p.expression === this) { + if (p instanceof AST.PropAccess && p.expression === this) { return true; } } if (output.option('wrap_iife')) { var p = output.parent(); - return p instanceof AST_Call && p.expression === this; + return p instanceof AST.Call && p.expression === this; } return false; @@ -796,43 +736,43 @@ function OutputStream(options) { // same goes for an object literal, because otherwise it would be // interpreted as a block of code. - PARENS(AST_Object, function(output) { + PARENS(AST.Object, function(output) { return !output.has_parens() && first_in_statement(output); }); - PARENS(AST_Unary, function(output) { + PARENS(AST.Unary, function(output) { var p = output.parent(); - return p instanceof AST_PropAccess && p.expression === this - || p instanceof AST_Call && p.expression === this; + return p instanceof AST.PropAccess && p.expression === this + || p instanceof AST.Call && p.expression === this; }); - PARENS(AST_Sequence, function(output) { + PARENS(AST.Sequence, function(output) { var p = output.parent(); - return p instanceof AST_Call // (foo, bar)() or foo(1, (2, 3), 4) - || p instanceof AST_Unary // !(foo, bar, baz) - || p instanceof AST_Binary // 1 + (2, 3) + 4 ==> 8 - || p instanceof AST_VarDef // var a = (1, 2), b = a + a; ==> b == 4 - || p instanceof AST_PropAccess // (1, {foo:2}).foo or (1, {foo:2})["foo"] ==> 2 - || p instanceof AST_Array // [ 1, (2, 3), 4 ] ==> [ 1, 3, 4 ] - || p instanceof AST_ObjectProperty // { foo: (1, 2) }.foo ==> 2 - || p instanceof AST_Conditional /* (false, true) ? (a = 10, b = 20) : (c = 30) + return p instanceof AST.Call // (foo, bar)() or foo(1, (2, 3), 4) + || p instanceof AST.Unary // !(foo, bar, baz) + || p instanceof AST.Binary // 1 + (2, 3) + 4 ==> 8 + || p instanceof AST.VarDef // var a = (1, 2), b = a + a; ==> b == 4 + || p instanceof AST.PropAccess // (1, {foo:2}).foo or (1, {foo:2})["foo"] ==> 2 + || p instanceof AST.Array // [ 1, (2, 3), 4 ] ==> [ 1, 3, 4 ] + || p instanceof AST.ObjectProperty // { foo: (1, 2) }.foo ==> 2 + || p instanceof AST.Conditional /* (false, true) ? (a = 10, b = 20) : (c = 30) * ==> 20 (side effect, set a := 10 and b := 20) */ ; }); - PARENS(AST_Binary, function(output) { + PARENS(AST.Binary, function(output) { var p = output.parent(); // (foo && bar)() - if (p instanceof AST_Call && p.expression === this) + if (p instanceof AST.Call && p.expression === this) return true; // typeof (foo && bar) - if (p instanceof AST_Unary) + if (p instanceof AST.Unary) return true; // (foo && bar)["prop"], (foo && bar).prop - if (p instanceof AST_PropAccess && p.expression === this) + if (p instanceof AST.PropAccess && p.expression === this) return true; // this deals with precedence: 3 * (2 + 1) - if (p instanceof AST_Binary) { + if (p instanceof AST.Binary) { var po = p.operator, pp = PRECEDENCE[po]; var so = this.operator, sp = PRECEDENCE[so]; if (pp > sp @@ -843,9 +783,9 @@ function OutputStream(options) { } }); - PARENS(AST_PropAccess, function(output) { + PARENS(AST.PropAccess, function(output) { var p = output.parent(); - if (p instanceof AST_New && p.expression === this) { + if (p instanceof AST.New && p.expression === this) { // i.e. new (foo.bar().baz) // // if there's one call into this subtree, then we need @@ -854,8 +794,8 @@ function OutputStream(options) { // expression. var parens = false; this.walk(new TreeWalker(function(node) { - if (parens || node instanceof AST_Scope) return true; - if (node instanceof AST_Call) { + if (parens || node instanceof AST.Scope) return true; + if (node instanceof AST.Call) { parens = true; return true; } @@ -864,31 +804,31 @@ function OutputStream(options) { } }); - PARENS(AST_Call, function(output) { + PARENS(AST.Call, function(output) { var p = output.parent(), p1; - if (p instanceof AST_New && p.expression === this) + if (p instanceof AST.New && p.expression === this) return true; // workaround for Safari bug. // https://bugs.webkit.org/show_bug.cgi?id=123506 - return this.expression instanceof AST_Function - && p instanceof AST_PropAccess + return this.expression instanceof AST.Function + && p instanceof AST.PropAccess && p.expression === this - && (p1 = output.parent(1)) instanceof AST_Assign + && (p1 = output.parent(1)) instanceof AST.Assign && p1.left === p; }); - PARENS(AST_New, function(output) { + PARENS(AST.New, function(output) { var p = output.parent(); if (!need_constructor_parens(this, output) - && (p instanceof AST_PropAccess // (new Date).getTime(), (new Date)["getTime"]() - || p instanceof AST_Call && p.expression === this)) // (new foo)(bar) + && (p instanceof AST.PropAccess // (new Date).getTime(), (new Date)["getTime"]() + || p instanceof AST.Call && p.expression === this)) // (new foo)(bar) return true; }); - PARENS(AST_Number, function(output) { + PARENS(AST.Number, function(output) { var p = output.parent(); - if (p instanceof AST_PropAccess && p.expression === this) { + if (p instanceof AST.PropAccess && p.expression === this) { var value = this.getValue(); if (value < 0 || /^0/.test(make_num(value))) { return true; @@ -896,32 +836,32 @@ function OutputStream(options) { } }); - PARENS([ AST_Assign, AST_Conditional ], function(output) { + PARENS([ AST.Assign, AST.Conditional ], function(output) { var p = output.parent(); // !(a = false) → true - if (p instanceof AST_Unary) + if (p instanceof AST.Unary) return true; // 1 + (a = 2) + 3 → 6, side effect setting a = 2 - if (p instanceof AST_Binary && !(p instanceof AST_Assign)) + if (p instanceof AST.Binary && !(p instanceof AST.Assign)) return true; // (a = func)() —or— new (a = Object)() - if (p instanceof AST_Call && p.expression === this) + if (p instanceof AST.Call && p.expression === this) return true; // (a = foo) ? bar : baz - if (p instanceof AST_Conditional && p.condition === this) + if (p instanceof AST.Conditional && p.condition === this) return true; // (a = foo)["prop"] —or— (a = foo).prop - if (p instanceof AST_PropAccess && p.expression === this) + if (p instanceof AST.PropAccess && p.expression === this) return true; }); /* -----[ PRINTERS ]----- */ - DEFPRINT(AST_Directive, function(self, output) { + DEFPRINT(AST.Directive, function(self, output) { output.print_string(self.value, self.quote); output.semicolon(); }); - DEFPRINT(AST_Debugger, function(self, output) { + DEFPRINT(AST.Debugger, function(self, output) { output.print("debugger"); output.semicolon(); }); @@ -932,13 +872,13 @@ function OutputStream(options) { var last = body.length - 1; in_directive = allow_directives; body.forEach(function(stmt, i) { - if (in_directive === true && !(stmt instanceof AST_Directive || - stmt instanceof AST_EmptyStatement || - (stmt instanceof AST_SimpleStatement && stmt.body instanceof AST_String) + if (in_directive === true && !(stmt instanceof AST.Directive || + stmt instanceof AST.EmptyStatement || + (stmt instanceof AST.SimpleStatement && stmt.body instanceof AST.String) )) { in_directive = false; } - if (!(stmt instanceof AST_EmptyStatement)) { + if (!(stmt instanceof AST.EmptyStatement)) { output.indent(); stmt.print(output); if (!(i == last && is_toplevel)) { @@ -947,8 +887,8 @@ function OutputStream(options) { } } if (in_directive === true && - stmt instanceof AST_SimpleStatement && - stmt.body instanceof AST_String + stmt instanceof AST.SimpleStatement && + stmt.body instanceof AST.String ) { in_directive = false; } @@ -956,24 +896,24 @@ function OutputStream(options) { in_directive = false; } - AST_StatementWithBody.DEFMETHOD("_do_print_body", function(output) { + AST.StatementWithBody.DEFMETHOD("_do_print_body", function(output) { force_statement(this.body, output); }); - DEFPRINT(AST_Statement, function(self, output) { + DEFPRINT(AST.Statement, function(self, output) { self.body.print(output); output.semicolon(); }); - DEFPRINT(AST_Toplevel, function(self, output) { + DEFPRINT(AST.Toplevel, function(self, output) { display_body(self.body, true, output, true); output.print(""); }); - DEFPRINT(AST_LabeledStatement, function(self, output) { + DEFPRINT(AST.LabeledStatement, function(self, output) { self.label.print(output); output.colon(); self.body.print(output); }); - DEFPRINT(AST_SimpleStatement, function(self, output) { + DEFPRINT(AST.SimpleStatement, function(self, output) { self.body.print(output); output.semicolon(); }); @@ -991,13 +931,13 @@ function OutputStream(options) { }); } else print_braced_empty(self, output); } - DEFPRINT(AST_BlockStatement, function(self, output) { + DEFPRINT(AST.BlockStatement, function(self, output) { print_braced(self, output); }); - DEFPRINT(AST_EmptyStatement, function(self, output) { + DEFPRINT(AST.EmptyStatement, function(self, output) { output.semicolon(); }); - DEFPRINT(AST_Do, function(self, output) { + DEFPRINT(AST.Do, function(self, output) { output.print("do"); output.space(); make_block(self.body, output); @@ -1009,7 +949,7 @@ function OutputStream(options) { }); output.semicolon(); }); - DEFPRINT(AST_While, function(self, output) { + DEFPRINT(AST.While, function(self, output) { output.print("while"); output.space(); output.with_parens(function() { @@ -1018,12 +958,12 @@ function OutputStream(options) { output.space(); self._do_print_body(output); }); - DEFPRINT(AST_For, function(self, output) { + DEFPRINT(AST.For, function(self, output) { output.print("for"); output.space(); output.with_parens(function() { if (self.init) { - if (self.init instanceof AST_Definitions) { + if (self.init instanceof AST.Definitions) { self.init.print(output); } else { parenthesize_for_noin(self.init, output, true); @@ -1047,7 +987,7 @@ function OutputStream(options) { output.space(); self._do_print_body(output); }); - DEFPRINT(AST_ForIn, function(self, output) { + DEFPRINT(AST.ForIn, function(self, output) { output.print("for"); output.space(); output.with_parens(function() { @@ -1060,7 +1000,7 @@ function OutputStream(options) { output.space(); self._do_print_body(output); }); - DEFPRINT(AST_With, function(self, output) { + DEFPRINT(AST.With, function(self, output) { output.print("with"); output.space(); output.with_parens(function() { @@ -1071,7 +1011,7 @@ function OutputStream(options) { }); /* -----[ functions ]----- */ - AST_Lambda.DEFMETHOD("_do_print", function(output, nokeyword) { + AST.Lambda.DEFMETHOD("_do_print", function(output, nokeyword) { var self = this; if (!nokeyword) { output.print("function"); @@ -1089,7 +1029,7 @@ function OutputStream(options) { output.space(); print_braced(self, output, true); }); - DEFPRINT(AST_Lambda, function(self, output) { + DEFPRINT(AST.Lambda, function(self, output) { self._do_print(output); }); @@ -1103,16 +1043,16 @@ function OutputStream(options) { output.semicolon(); } - DEFPRINT(AST_Return, function(self, output) { + DEFPRINT(AST.Return, function(self, output) { print_jump(output, "return", self.value); }); - DEFPRINT(AST_Throw, function(self, output) { + DEFPRINT(AST.Throw, function(self, output) { print_jump(output, "throw", self.value); }); - DEFPRINT(AST_Break, function(self, output) { + DEFPRINT(AST.Break, function(self, output) { print_jump(output, "break", self.label); }); - DEFPRINT(AST_Continue, function(self, output) { + DEFPRINT(AST.Continue, function(self, output) { print_jump(output, "continue", self.label); }); @@ -1120,7 +1060,7 @@ function OutputStream(options) { function make_then(self, output) { var b = self.body; if (output.option("braces") - || output.option("ie8") && b instanceof AST_Do) + || output.option("ie8") && b instanceof AST.Do) return make_block(b, output); // The squeezer replaces "block"-s that contain only a single // statement with the statement itself; technically, the AST @@ -1131,21 +1071,21 @@ function OutputStream(options) { // adds the block braces if needed. if (!b) return output.force_semicolon(); while (true) { - if (b instanceof AST_If) { + if (b instanceof AST.If) { if (!b.alternative) { make_block(self.body, output); return; } b = b.alternative; } - else if (b instanceof AST_StatementWithBody) { + else if (b instanceof AST.StatementWithBody) { b = b.body; } else break; } force_statement(self.body, output); } - DEFPRINT(AST_If, function(self, output) { + DEFPRINT(AST.If, function(self, output) { output.print("if"); output.space(); output.with_parens(function() { @@ -1157,7 +1097,7 @@ function OutputStream(options) { output.space(); output.print("else"); output.space(); - if (self.alternative instanceof AST_If) + if (self.alternative instanceof AST.If) self.alternative.print(output); else force_statement(self.alternative, output); @@ -1167,7 +1107,7 @@ function OutputStream(options) { }); /* -----[ switch ]----- */ - DEFPRINT(AST_Switch, function(self, output) { + DEFPRINT(AST.Switch, function(self, output) { output.print("switch"); output.space(); output.with_parens(function() { @@ -1185,7 +1125,7 @@ function OutputStream(options) { }); }); }); - AST_SwitchBranch.DEFMETHOD("_do_print_body", function(output) { + AST.SwitchBranch.DEFMETHOD("_do_print_body", function(output) { output.newline(); this.body.forEach(function(stmt) { output.indent(); @@ -1193,11 +1133,11 @@ function OutputStream(options) { output.newline(); }); }); - DEFPRINT(AST_Default, function(self, output) { + DEFPRINT(AST.Default, function(self, output) { output.print("default:"); self._do_print_body(output); }); - DEFPRINT(AST_Case, function(self, output) { + DEFPRINT(AST.Case, function(self, output) { output.print("case"); output.space(); self.expression.print(output); @@ -1206,7 +1146,7 @@ function OutputStream(options) { }); /* -----[ exceptions ]----- */ - DEFPRINT(AST_Try, function(self, output) { + DEFPRINT(AST.Try, function(self, output) { output.print("try"); output.space(); print_braced(self, output); @@ -1219,7 +1159,7 @@ function OutputStream(options) { self.bfinally.print(output); } }); - DEFPRINT(AST_Catch, function(self, output) { + DEFPRINT(AST.Catch, function(self, output) { output.print("catch"); output.space(); output.with_parens(function() { @@ -1228,13 +1168,13 @@ function OutputStream(options) { output.space(); print_braced(self, output); }); - DEFPRINT(AST_Finally, function(self, output) { + DEFPRINT(AST.Finally, function(self, output) { output.print("finally"); output.space(); print_braced(self, output); }); - DEFPRINT(AST_Var, function(self, output) { + DEFPRINT(AST.Var, function(self, output) { output.print("var"); output.space(); self.definitions.forEach(function(def, i) { @@ -1242,7 +1182,7 @@ function OutputStream(options) { def.print(output); }); var p = output.parent(); - if (p.init !== self || !(p instanceof AST_For || p instanceof AST_ForIn)) output.semicolon(); + if (p.init !== self || !(p instanceof AST.For || p instanceof AST.ForIn)) output.semicolon(); }); function parenthesize_for_noin(node, output, noin) { @@ -1250,8 +1190,8 @@ function OutputStream(options) { // need to take some precautions here: // https://github.com/mishoo/UglifyJS2/issues/60 if (noin) node.walk(new TreeWalker(function(node) { - if (parens || node instanceof AST_Scope) return true; - if (node instanceof AST_Binary && node.operator == "in") { + if (parens || node instanceof AST.Scope) return true; + if (node instanceof AST.Binary && node.operator == "in") { parens = true; return true; } @@ -1259,24 +1199,24 @@ function OutputStream(options) { node.print(output, parens); } - DEFPRINT(AST_VarDef, function(self, output) { + DEFPRINT(AST.VarDef, function(self, output) { self.name.print(output); if (self.value) { output.space(); output.print("="); output.space(); var p = output.parent(1); - var noin = p instanceof AST_For || p instanceof AST_ForIn; + var noin = p instanceof AST.For || p instanceof AST.ForIn; parenthesize_for_noin(self.value, output, noin); } }); /* -----[ other expressions ]----- */ - DEFPRINT(AST_Call, function(self, output) { + DEFPRINT(AST.Call, function(self, output) { self.expression.print(output); - if (self instanceof AST_New && !need_constructor_parens(self, output)) + if (self instanceof AST.New && !need_constructor_parens(self, output)) return; - if (self.expression instanceof AST_Call || self.expression instanceof AST_Lambda) { + if (self.expression instanceof AST.Call || self.expression instanceof AST.Lambda) { output.add_mapping(self.start); } output.with_parens(function() { @@ -1286,12 +1226,12 @@ function OutputStream(options) { }); }); }); - DEFPRINT(AST_New, function(self, output) { + DEFPRINT(AST.New, function(self, output) { output.print("new"); output.space(); - AST_Call.prototype._codegen(self, output); + AST.Call.prototype._codegen(self, output); }); - DEFPRINT(AST_Sequence, function(self, output) { + DEFPRINT(AST.Sequence, function(self, output) { self.expressions.forEach(function(node, index) { if (index > 0) { output.comma(); @@ -1303,7 +1243,7 @@ function OutputStream(options) { node.print(output); }); }); - DEFPRINT(AST_Dot, function(self, output) { + DEFPRINT(AST.Dot, function(self, output) { var expr = self.expression; expr.print(output); var prop = self.property; @@ -1313,7 +1253,7 @@ function OutputStream(options) { output.print_string(prop); output.print("]"); } else { - if (expr instanceof AST_Number && expr.getValue() >= 0) { + if (expr instanceof AST.Number && expr.getValue() >= 0) { if (!/[xa-f.)]/i.test(output.last())) { output.print("."); } @@ -1324,32 +1264,32 @@ function OutputStream(options) { output.print_name(prop); } }); - DEFPRINT(AST_Sub, function(self, output) { + DEFPRINT(AST.Sub, function(self, output) { self.expression.print(output); output.print("["); self.property.print(output); output.print("]"); }); - DEFPRINT(AST_UnaryPrefix, function(self, output) { + DEFPRINT(AST.UnaryPrefix, function(self, output) { var op = self.operator; output.print(op); if (/^[a-z]/i.test(op) || (/[+-]$/.test(op) - && self.expression instanceof AST_UnaryPrefix + && self.expression instanceof AST.UnaryPrefix && /^[+-]/.test(self.expression.operator))) { output.space(); } self.expression.print(output); }); - DEFPRINT(AST_UnaryPostfix, function(self, output) { + DEFPRINT(AST.UnaryPostfix, function(self, output) { self.expression.print(output); output.print(self.operator); }); - DEFPRINT(AST_Binary, function(self, output) { + DEFPRINT(AST.Binary, function(self, output) { var op = self.operator; self.left.print(output); if (op[0] == ">" /* ">>" ">>>" ">" ">=" */ - && self.left instanceof AST_UnaryPostfix + && self.left instanceof AST.UnaryPostfix && self.left.operator == "--") { // space is mandatory to avoid outputting --> output.print(" "); @@ -1359,9 +1299,9 @@ function OutputStream(options) { } output.print(op); if ((op == "<" || op == "<<") - && self.right instanceof AST_UnaryPrefix + && self.right instanceof AST.UnaryPrefix && self.right.operator == "!" - && self.right.expression instanceof AST_UnaryPrefix + && self.right.expression instanceof AST.UnaryPrefix && self.right.expression.operator == "--") { // space is mandatory to avoid outputting