react / react-0.13.3 / examples / basic-commonjs / node_modules / browserify / node_modules / umd / node_modules / uglify-js / lib / output.js
80743 views/***********************************************************************12A JavaScript tokenizer / parser / beautifier / compressor.3https://github.com/mishoo/UglifyJS245-------------------------------- (C) ---------------------------------67Author: Mihai Bazon8<[email protected]>9http://mihai.bazon.net/blog1011Distributed under the BSD license:1213Copyright 2012 (c) Mihai Bazon <[email protected]>1415Redistribution and use in source and binary forms, with or without16modification, are permitted provided that the following conditions17are met:1819* Redistributions of source code must retain the above20copyright notice, this list of conditions and the following21disclaimer.2223* Redistributions in binary form must reproduce the above24copyright notice, this list of conditions and the following25disclaimer in the documentation and/or other materials26provided with the distribution.2728THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY29EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE30IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR31PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE32LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,33OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,34PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR35PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY36THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR37TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF38THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF39SUCH DAMAGE.4041***********************************************************************/4243"use strict";4445function OutputStream(options) {4647options = defaults(options, {48indent_start : 0,49indent_level : 4,50quote_keys : false,51space_colon : true,52ascii_only : false,53unescape_regexps : false,54inline_script : false,55width : 80,56max_line_len : 32000,57beautify : false,58source_map : null,59bracketize : false,60semicolons : true,61comments : false,62preserve_line : false,63screw_ie8 : false,64preamble : null,65quote_style : 066}, true);6768var indentation = 0;69var current_col = 0;70var current_line = 1;71var current_pos = 0;72var OUTPUT = "";7374function to_ascii(str, identifier) {75return str.replace(/[\u0080-\uffff]/g, function(ch) {76var code = ch.charCodeAt(0).toString(16);77if (code.length <= 2 && !identifier) {78while (code.length < 2) code = "0" + code;79return "\\x" + code;80} else {81while (code.length < 4) code = "0" + code;82return "\\u" + code;83}84});85};8687function make_string(str, quote) {88var dq = 0, sq = 0;89str = str.replace(/[\\\b\f\n\r\t\x22\x27\u2028\u2029\0\ufeff]/g, function(s){90switch (s) {91case "\\": return "\\\\";92case "\b": return "\\b";93case "\f": return "\\f";94case "\n": return "\\n";95case "\r": return "\\r";96case "\u2028": return "\\u2028";97case "\u2029": return "\\u2029";98case '"': ++dq; return '"';99case "'": ++sq; return "'";100case "\0": return "\\x00";101case "\ufeff": return "\\ufeff";102}103return s;104});105function quote_single() {106return "'" + str.replace(/\x27/g, "\\'") + "'";107}108function quote_double() {109return '"' + str.replace(/\x22/g, '\\"') + '"';110}111if (options.ascii_only) str = to_ascii(str);112switch (options.quote_style) {113case 1:114return quote_single();115case 2:116return quote_double();117case 3:118return quote == "'" ? quote_single() : quote_double();119default:120return dq > sq ? quote_single() : quote_double();121}122};123124function encode_string(str, quote) {125var ret = make_string(str, quote);126if (options.inline_script)127ret = ret.replace(/<\x2fscript([>\/\t\n\f\r ])/gi, "<\\/script$1");128return ret;129};130131function make_name(name) {132name = name.toString();133if (options.ascii_only)134name = to_ascii(name, true);135return name;136};137138function make_indent(back) {139return repeat_string(" ", options.indent_start + indentation - back * options.indent_level);140};141142/* -----[ beautification/minification ]----- */143144var might_need_space = false;145var might_need_semicolon = false;146var last = null;147148function last_char() {149return last.charAt(last.length - 1);150};151152function maybe_newline() {153if (options.max_line_len && current_col > options.max_line_len)154print("\n");155};156157var requireSemicolonChars = makePredicate("( [ + * / - , .");158159function print(str) {160str = String(str);161var ch = str.charAt(0);162if (might_need_semicolon) {163if ((!ch || ";}".indexOf(ch) < 0) && !/[;]$/.test(last)) {164if (options.semicolons || requireSemicolonChars(ch)) {165OUTPUT += ";";166current_col++;167current_pos++;168} else {169OUTPUT += "\n";170current_pos++;171current_line++;172current_col = 0;173}174if (!options.beautify)175might_need_space = false;176}177might_need_semicolon = false;178}179180if (!options.beautify && options.preserve_line && stack[stack.length - 1]) {181var target_line = stack[stack.length - 1].start.line;182while (current_line < target_line) {183OUTPUT += "\n";184current_pos++;185current_line++;186current_col = 0;187might_need_space = false;188}189}190191if (might_need_space) {192var prev = last_char();193if ((is_identifier_char(prev)194&& (is_identifier_char(ch) || ch == "\\"))195|| (/^[\+\-\/]$/.test(ch) && ch == prev))196{197OUTPUT += " ";198current_col++;199current_pos++;200}201might_need_space = false;202}203var a = str.split(/\r?\n/), n = a.length - 1;204current_line += n;205if (n == 0) {206current_col += a[n].length;207} else {208current_col = a[n].length;209}210current_pos += str.length;211last = str;212OUTPUT += str;213};214215var space = options.beautify ? function() {216print(" ");217} : function() {218might_need_space = true;219};220221var indent = options.beautify ? function(half) {222if (options.beautify) {223print(make_indent(half ? 0.5 : 0));224}225} : noop;226227var with_indent = options.beautify ? function(col, cont) {228if (col === true) col = next_indent();229var save_indentation = indentation;230indentation = col;231var ret = cont();232indentation = save_indentation;233return ret;234} : function(col, cont) { return cont() };235236var newline = options.beautify ? function() {237print("\n");238} : maybe_newline;239240var semicolon = options.beautify ? function() {241print(";");242} : function() {243might_need_semicolon = true;244};245246function force_semicolon() {247might_need_semicolon = false;248print(";");249};250251function next_indent() {252return indentation + options.indent_level;253};254255function with_block(cont) {256var ret;257print("{");258newline();259with_indent(next_indent(), function(){260ret = cont();261});262indent();263print("}");264return ret;265};266267function with_parens(cont) {268print("(");269//XXX: still nice to have that for argument lists270//var ret = with_indent(current_col, cont);271var ret = cont();272print(")");273return ret;274};275276function with_square(cont) {277print("[");278//var ret = with_indent(current_col, cont);279var ret = cont();280print("]");281return ret;282};283284function comma() {285print(",");286space();287};288289function colon() {290print(":");291if (options.space_colon) space();292};293294var add_mapping = options.source_map ? function(token, name) {295try {296if (token) options.source_map.add(297token.file || "?",298current_line, current_col,299token.line, token.col,300(!name && token.type == "name") ? token.value : name301);302} catch(ex) {303AST_Node.warn("Couldn't figure out mapping for {file}:{line},{col} → {cline},{ccol} [{name}]", {304file: token.file,305line: token.line,306col: token.col,307cline: current_line,308ccol: current_col,309name: name || ""310})311}312} : noop;313314function get() {315return OUTPUT;316};317318if (options.preamble) {319print(options.preamble.replace(/\r\n?|[\n\u2028\u2029]|\s*$/g, "\n"));320}321322var stack = [];323return {324get : get,325toString : get,326indent : indent,327indentation : function() { return indentation },328current_width : function() { return current_col - indentation },329should_break : function() { return options.width && this.current_width() >= options.width },330newline : newline,331print : print,332space : space,333comma : comma,334colon : colon,335last : function() { return last },336semicolon : semicolon,337force_semicolon : force_semicolon,338to_ascii : to_ascii,339print_name : function(name) { print(make_name(name)) },340print_string : function(str, quote) { print(encode_string(str, quote)) },341next_indent : next_indent,342with_indent : with_indent,343with_block : with_block,344with_parens : with_parens,345with_square : with_square,346add_mapping : add_mapping,347option : function(opt) { return options[opt] },348line : function() { return current_line },349col : function() { return current_col },350pos : function() { return current_pos },351push_node : function(node) { stack.push(node) },352pop_node : function() { return stack.pop() },353stack : function() { return stack },354parent : function(n) {355return stack[stack.length - 2 - (n || 0)];356}357};358359};360361/* -----[ code generators ]----- */362363(function(){364365/* -----[ utils ]----- */366367function DEFPRINT(nodetype, generator) {368nodetype.DEFMETHOD("_codegen", generator);369};370371AST_Node.DEFMETHOD("print", function(stream, force_parens){372var self = this, generator = self._codegen;373function doit() {374self.add_comments(stream);375self.add_source_map(stream);376generator(self, stream);377}378stream.push_node(self);379if (force_parens || self.needs_parens(stream)) {380stream.with_parens(doit);381} else {382doit();383}384stream.pop_node();385});386387AST_Node.DEFMETHOD("print_to_string", function(options){388var s = OutputStream(options);389this.print(s);390return s.get();391});392393/* -----[ comments ]----- */394395AST_Node.DEFMETHOD("add_comments", function(output){396var c = output.option("comments"), self = this;397if (c) {398var start = self.start;399if (start && !start._comments_dumped) {400start._comments_dumped = true;401var comments = start.comments_before || [];402403// XXX: ugly fix for https://github.com/mishoo/UglifyJS2/issues/112404// and https://github.com/mishoo/UglifyJS2/issues/372405if (self instanceof AST_Exit && self.value) {406self.value.walk(new TreeWalker(function(node){407if (node.start && node.start.comments_before) {408comments = comments.concat(node.start.comments_before);409node.start.comments_before = [];410}411if (node instanceof AST_Function ||412node instanceof AST_Array ||413node instanceof AST_Object)414{415return true; // don't go inside.416}417}));418}419420if (c.test) {421comments = comments.filter(function(comment){422return c.test(comment.value);423});424} else if (typeof c == "function") {425comments = comments.filter(function(comment){426return c(self, comment);427});428}429430// Keep single line comments after nlb, after nlb431if (!output.option("beautify") && comments.length > 0 &&432/comment[134]/.test(comments[0].type) &&433output.col() !== 0 && comments[0].nlb)434{435output.print("\n");436}437438comments.forEach(function(c){439if (/comment[134]/.test(c.type)) {440output.print("//" + c.value + "\n");441output.indent();442}443else if (c.type == "comment2") {444output.print("/*" + c.value + "*/");445if (start.nlb) {446output.print("\n");447output.indent();448} else {449output.space();450}451}452});453}454}455});456457/* -----[ PARENTHESES ]----- */458459function PARENS(nodetype, func) {460if (Array.isArray(nodetype)) {461nodetype.forEach(function(nodetype){462PARENS(nodetype, func);463});464} else {465nodetype.DEFMETHOD("needs_parens", func);466}467};468469PARENS(AST_Node, function(){470return false;471});472473// a function expression needs parens around it when it's provably474// the first token to appear in a statement.475PARENS(AST_Function, function(output){476return first_in_statement(output);477});478479// same goes for an object literal, because otherwise it would be480// interpreted as a block of code.481PARENS(AST_Object, function(output){482return first_in_statement(output);483});484485PARENS([ AST_Unary, AST_Undefined ], function(output){486var p = output.parent();487return p instanceof AST_PropAccess && p.expression === this;488});489490PARENS(AST_Seq, function(output){491var p = output.parent();492return p instanceof AST_Call // (foo, bar)() or foo(1, (2, 3), 4)493|| p instanceof AST_Unary // !(foo, bar, baz)494|| p instanceof AST_Binary // 1 + (2, 3) + 4 ==> 8495|| p instanceof AST_VarDef // var a = (1, 2), b = a + a; ==> b == 4496|| p instanceof AST_PropAccess // (1, {foo:2}).foo or (1, {foo:2})["foo"] ==> 2497|| p instanceof AST_Array // [ 1, (2, 3), 4 ] ==> [ 1, 3, 4 ]498|| p instanceof AST_ObjectProperty // { foo: (1, 2) }.foo ==> 2499|| p instanceof AST_Conditional /* (false, true) ? (a = 10, b = 20) : (c = 30)500* ==> 20 (side effect, set a := 10 and b := 20) */501;502});503504PARENS(AST_Binary, function(output){505var p = output.parent();506// (foo && bar)()507if (p instanceof AST_Call && p.expression === this)508return true;509// typeof (foo && bar)510if (p instanceof AST_Unary)511return true;512// (foo && bar)["prop"], (foo && bar).prop513if (p instanceof AST_PropAccess && p.expression === this)514return true;515// this deals with precedence: 3 * (2 + 1)516if (p instanceof AST_Binary) {517var po = p.operator, pp = PRECEDENCE[po];518var so = this.operator, sp = PRECEDENCE[so];519if (pp > sp520|| (pp == sp521&& this === p.right)) {522return true;523}524}525});526527PARENS(AST_PropAccess, function(output){528var p = output.parent();529if (p instanceof AST_New && p.expression === this) {530// i.e. new (foo.bar().baz)531//532// if there's one call into this subtree, then we need533// parens around it too, otherwise the call will be534// interpreted as passing the arguments to the upper New535// expression.536try {537this.walk(new TreeWalker(function(node){538if (node instanceof AST_Call) throw p;539}));540} catch(ex) {541if (ex !== p) throw ex;542return true;543}544}545});546547PARENS(AST_Call, function(output){548var p = output.parent(), p1;549if (p instanceof AST_New && p.expression === this)550return true;551552// workaround for Safari bug.553// https://bugs.webkit.org/show_bug.cgi?id=123506554return this.expression instanceof AST_Function555&& p instanceof AST_PropAccess556&& p.expression === this557&& (p1 = output.parent(1)) instanceof AST_Assign558&& p1.left === p;559});560561PARENS(AST_New, function(output){562var p = output.parent();563if (no_constructor_parens(this, output)564&& (p instanceof AST_PropAccess // (new Date).getTime(), (new Date)["getTime"]()565|| p instanceof AST_Call && p.expression === this)) // (new foo)(bar)566return true;567});568569PARENS(AST_Number, function(output){570var p = output.parent();571if (this.getValue() < 0 && p instanceof AST_PropAccess && p.expression === this)572return true;573});574575PARENS([ AST_Assign, AST_Conditional ], function (output){576var p = output.parent();577// !(a = false) → true578if (p instanceof AST_Unary)579return true;580// 1 + (a = 2) + 3 → 6, side effect setting a = 2581if (p instanceof AST_Binary && !(p instanceof AST_Assign))582return true;583// (a = func)() —or— new (a = Object)()584if (p instanceof AST_Call && p.expression === this)585return true;586// (a = foo) ? bar : baz587if (p instanceof AST_Conditional && p.condition === this)588return true;589// (a = foo)["prop"] —or— (a = foo).prop590if (p instanceof AST_PropAccess && p.expression === this)591return true;592});593594/* -----[ PRINTERS ]----- */595596DEFPRINT(AST_Directive, function(self, output){597output.print_string(self.value, self.quote);598output.semicolon();599});600DEFPRINT(AST_Debugger, function(self, output){601output.print("debugger");602output.semicolon();603});604605/* -----[ statements ]----- */606607function display_body(body, is_toplevel, output) {608var last = body.length - 1;609body.forEach(function(stmt, i){610if (!(stmt instanceof AST_EmptyStatement)) {611output.indent();612stmt.print(output);613if (!(i == last && is_toplevel)) {614output.newline();615if (is_toplevel) output.newline();616}617}618});619};620621AST_StatementWithBody.DEFMETHOD("_do_print_body", function(output){622force_statement(this.body, output);623});624625DEFPRINT(AST_Statement, function(self, output){626self.body.print(output);627output.semicolon();628});629DEFPRINT(AST_Toplevel, function(self, output){630display_body(self.body, true, output);631output.print("");632});633DEFPRINT(AST_LabeledStatement, function(self, output){634self.label.print(output);635output.colon();636self.body.print(output);637});638DEFPRINT(AST_SimpleStatement, function(self, output){639self.body.print(output);640output.semicolon();641});642function print_bracketed(body, output) {643if (body.length > 0) output.with_block(function(){644display_body(body, false, output);645});646else output.print("{}");647};648DEFPRINT(AST_BlockStatement, function(self, output){649print_bracketed(self.body, output);650});651DEFPRINT(AST_EmptyStatement, function(self, output){652output.semicolon();653});654DEFPRINT(AST_Do, function(self, output){655output.print("do");656output.space();657self._do_print_body(output);658output.space();659output.print("while");660output.space();661output.with_parens(function(){662self.condition.print(output);663});664output.semicolon();665});666DEFPRINT(AST_While, function(self, output){667output.print("while");668output.space();669output.with_parens(function(){670self.condition.print(output);671});672output.space();673self._do_print_body(output);674});675DEFPRINT(AST_For, function(self, output){676output.print("for");677output.space();678output.with_parens(function(){679if (self.init && !(self.init instanceof AST_EmptyStatement)) {680if (self.init instanceof AST_Definitions) {681self.init.print(output);682} else {683parenthesize_for_noin(self.init, output, true);684}685output.print(";");686output.space();687} else {688output.print(";");689}690if (self.condition) {691self.condition.print(output);692output.print(";");693output.space();694} else {695output.print(";");696}697if (self.step) {698self.step.print(output);699}700});701output.space();702self._do_print_body(output);703});704DEFPRINT(AST_ForIn, function(self, output){705output.print("for");706output.space();707output.with_parens(function(){708self.init.print(output);709output.space();710output.print("in");711output.space();712self.object.print(output);713});714output.space();715self._do_print_body(output);716});717DEFPRINT(AST_With, function(self, output){718output.print("with");719output.space();720output.with_parens(function(){721self.expression.print(output);722});723output.space();724self._do_print_body(output);725});726727/* -----[ functions ]----- */728AST_Lambda.DEFMETHOD("_do_print", function(output, nokeyword){729var self = this;730if (!nokeyword) {731output.print("function");732}733if (self.name) {734output.space();735self.name.print(output);736}737output.with_parens(function(){738self.argnames.forEach(function(arg, i){739if (i) output.comma();740arg.print(output);741});742});743output.space();744print_bracketed(self.body, output);745});746DEFPRINT(AST_Lambda, function(self, output){747self._do_print(output);748});749750/* -----[ exits ]----- */751AST_Exit.DEFMETHOD("_do_print", function(output, kind){752output.print(kind);753if (this.value) {754output.space();755this.value.print(output);756}757output.semicolon();758});759DEFPRINT(AST_Return, function(self, output){760self._do_print(output, "return");761});762DEFPRINT(AST_Throw, function(self, output){763self._do_print(output, "throw");764});765766/* -----[ loop control ]----- */767AST_LoopControl.DEFMETHOD("_do_print", function(output, kind){768output.print(kind);769if (this.label) {770output.space();771this.label.print(output);772}773output.semicolon();774});775DEFPRINT(AST_Break, function(self, output){776self._do_print(output, "break");777});778DEFPRINT(AST_Continue, function(self, output){779self._do_print(output, "continue");780});781782/* -----[ if ]----- */783function make_then(self, output) {784if (output.option("bracketize")) {785make_block(self.body, output);786return;787}788// The squeezer replaces "block"-s that contain only a single789// statement with the statement itself; technically, the AST790// is correct, but this can create problems when we output an791// IF having an ELSE clause where the THEN clause ends in an792// IF *without* an ELSE block (then the outer ELSE would refer793// to the inner IF). This function checks for this case and794// adds the block brackets if needed.795if (!self.body)796return output.force_semicolon();797if (self.body instanceof AST_Do798&& !output.option("screw_ie8")) {799// https://github.com/mishoo/UglifyJS/issues/#issue/57 IE800// croaks with "syntax error" on code like this: if (foo)801// do ... while(cond); else ... we need block brackets802// around do/while803make_block(self.body, output);804return;805}806var b = self.body;807while (true) {808if (b instanceof AST_If) {809if (!b.alternative) {810make_block(self.body, output);811return;812}813b = b.alternative;814}815else if (b instanceof AST_StatementWithBody) {816b = b.body;817}818else break;819}820force_statement(self.body, output);821};822DEFPRINT(AST_If, function(self, output){823output.print("if");824output.space();825output.with_parens(function(){826self.condition.print(output);827});828output.space();829if (self.alternative) {830make_then(self, output);831output.space();832output.print("else");833output.space();834force_statement(self.alternative, output);835} else {836self._do_print_body(output);837}838});839840/* -----[ switch ]----- */841DEFPRINT(AST_Switch, function(self, output){842output.print("switch");843output.space();844output.with_parens(function(){845self.expression.print(output);846});847output.space();848if (self.body.length > 0) output.with_block(function(){849self.body.forEach(function(stmt, i){850if (i) output.newline();851output.indent(true);852stmt.print(output);853});854});855else output.print("{}");856});857AST_SwitchBranch.DEFMETHOD("_do_print_body", function(output){858if (this.body.length > 0) {859output.newline();860this.body.forEach(function(stmt){861output.indent();862stmt.print(output);863output.newline();864});865}866});867DEFPRINT(AST_Default, function(self, output){868output.print("default:");869self._do_print_body(output);870});871DEFPRINT(AST_Case, function(self, output){872output.print("case");873output.space();874self.expression.print(output);875output.print(":");876self._do_print_body(output);877});878879/* -----[ exceptions ]----- */880DEFPRINT(AST_Try, function(self, output){881output.print("try");882output.space();883print_bracketed(self.body, output);884if (self.bcatch) {885output.space();886self.bcatch.print(output);887}888if (self.bfinally) {889output.space();890self.bfinally.print(output);891}892});893DEFPRINT(AST_Catch, function(self, output){894output.print("catch");895output.space();896output.with_parens(function(){897self.argname.print(output);898});899output.space();900print_bracketed(self.body, output);901});902DEFPRINT(AST_Finally, function(self, output){903output.print("finally");904output.space();905print_bracketed(self.body, output);906});907908/* -----[ var/const ]----- */909AST_Definitions.DEFMETHOD("_do_print", function(output, kind){910output.print(kind);911output.space();912this.definitions.forEach(function(def, i){913if (i) output.comma();914def.print(output);915});916var p = output.parent();917var in_for = p instanceof AST_For || p instanceof AST_ForIn;918var avoid_semicolon = in_for && p.init === this;919if (!avoid_semicolon)920output.semicolon();921});922DEFPRINT(AST_Var, function(self, output){923self._do_print(output, "var");924});925DEFPRINT(AST_Const, function(self, output){926self._do_print(output, "const");927});928929function parenthesize_for_noin(node, output, noin) {930if (!noin) node.print(output);931else try {932// need to take some precautions here:933// https://github.com/mishoo/UglifyJS2/issues/60934node.walk(new TreeWalker(function(node){935if (node instanceof AST_Binary && node.operator == "in")936throw output;937}));938node.print(output);939} catch(ex) {940if (ex !== output) throw ex;941node.print(output, true);942}943};944945DEFPRINT(AST_VarDef, function(self, output){946self.name.print(output);947if (self.value) {948output.space();949output.print("=");950output.space();951var p = output.parent(1);952var noin = p instanceof AST_For || p instanceof AST_ForIn;953parenthesize_for_noin(self.value, output, noin);954}955});956957/* -----[ other expressions ]----- */958DEFPRINT(AST_Call, function(self, output){959self.expression.print(output);960if (self instanceof AST_New && no_constructor_parens(self, output))961return;962output.with_parens(function(){963self.args.forEach(function(expr, i){964if (i) output.comma();965expr.print(output);966});967});968});969DEFPRINT(AST_New, function(self, output){970output.print("new");971output.space();972AST_Call.prototype._codegen(self, output);973});974975AST_Seq.DEFMETHOD("_do_print", function(output){976this.car.print(output);977if (this.cdr) {978output.comma();979if (output.should_break()) {980output.newline();981output.indent();982}983this.cdr.print(output);984}985});986DEFPRINT(AST_Seq, function(self, output){987self._do_print(output);988// var p = output.parent();989// if (p instanceof AST_Statement) {990// output.with_indent(output.next_indent(), function(){991// self._do_print(output);992// });993// } else {994// self._do_print(output);995// }996});997DEFPRINT(AST_Dot, function(self, output){998var expr = self.expression;999expr.print(output);1000if (expr instanceof AST_Number && expr.getValue() >= 0) {1001if (!/[xa-f.]/i.test(output.last())) {1002output.print(".");1003}1004}1005output.print(".");1006// the name after dot would be mapped about here.1007output.add_mapping(self.end);1008output.print_name(self.property);1009});1010DEFPRINT(AST_Sub, function(self, output){1011self.expression.print(output);1012output.print("[");1013self.property.print(output);1014output.print("]");1015});1016DEFPRINT(AST_UnaryPrefix, function(self, output){1017var op = self.operator;1018output.print(op);1019if (/^[a-z]/i.test(op)1020|| (/[+-]$/.test(op)1021&& self.expression instanceof AST_UnaryPrefix1022&& /^[+-]/.test(self.expression.operator))) {1023output.space();1024}1025self.expression.print(output);1026});1027DEFPRINT(AST_UnaryPostfix, function(self, output){1028self.expression.print(output);1029output.print(self.operator);1030});1031DEFPRINT(AST_Binary, function(self, output){1032self.left.print(output);1033output.space();1034output.print(self.operator);1035if (self.operator == "<"1036&& self.right instanceof AST_UnaryPrefix1037&& self.right.operator == "!"1038&& self.right.expression instanceof AST_UnaryPrefix1039&& self.right.expression.operator == "--") {1040// space is mandatory to avoid outputting <!--1041// http://javascript.spec.whatwg.org/#comment-syntax1042output.print(" ");1043} else {1044// the space is optional depending on "beautify"1045output.space();1046}1047self.right.print(output);1048});1049DEFPRINT(AST_Conditional, function(self, output){1050self.condition.print(output);1051output.space();1052output.print("?");1053output.space();1054self.consequent.print(output);1055output.space();1056output.colon();1057self.alternative.print(output);1058});10591060/* -----[ literals ]----- */1061DEFPRINT(AST_Array, function(self, output){1062output.with_square(function(){1063var a = self.elements, len = a.length;1064if (len > 0) output.space();1065a.forEach(function(exp, i){1066if (i) output.comma();1067exp.print(output);1068// If the final element is a hole, we need to make sure it1069// doesn't look like a trailing comma, by inserting an actual1070// trailing comma.1071if (i === len - 1 && exp instanceof AST_Hole)1072output.comma();1073});1074if (len > 0) output.space();1075});1076});1077DEFPRINT(AST_Object, function(self, output){1078if (self.properties.length > 0) output.with_block(function(){1079self.properties.forEach(function(prop, i){1080if (i) {1081output.print(",");1082output.newline();1083}1084output.indent();1085prop.print(output);1086});1087output.newline();1088});1089else output.print("{}");1090});1091DEFPRINT(AST_ObjectKeyVal, function(self, output){1092var key = self.key;1093var quote = self.quote;1094if (output.option("quote_keys")) {1095output.print_string(key + "");1096} else if ((typeof key == "number"1097|| !output.option("beautify")1098&& +key + "" == key)1099&& parseFloat(key) >= 0) {1100output.print(make_num(key));1101} else if (RESERVED_WORDS(key) ? output.option("screw_ie8") : is_identifier_string(key)) {1102output.print_name(key);1103} else {1104output.print_string(key, quote);1105}1106output.colon();1107self.value.print(output);1108});1109DEFPRINT(AST_ObjectSetter, function(self, output){1110output.print("set");1111output.space();1112self.key.print(output);1113self.value._do_print(output, true);1114});1115DEFPRINT(AST_ObjectGetter, function(self, output){1116output.print("get");1117output.space();1118self.key.print(output);1119self.value._do_print(output, true);1120});1121DEFPRINT(AST_Symbol, function(self, output){1122var def = self.definition();1123output.print_name(def ? def.mangled_name || def.name : self.name);1124});1125DEFPRINT(AST_Undefined, function(self, output){1126output.print("void 0");1127});1128DEFPRINT(AST_Hole, noop);1129DEFPRINT(AST_Infinity, function(self, output){1130output.print("Infinity");1131});1132DEFPRINT(AST_NaN, function(self, output){1133output.print("NaN");1134});1135DEFPRINT(AST_This, function(self, output){1136output.print("this");1137});1138DEFPRINT(AST_Constant, function(self, output){1139output.print(self.getValue());1140});1141DEFPRINT(AST_String, function(self, output){1142output.print_string(self.getValue(), self.quote);1143});1144DEFPRINT(AST_Number, function(self, output){1145output.print(make_num(self.getValue()));1146});11471148function regexp_safe_literal(code) {1149return [11500x5c , // \11510x2f , // /11520x2e , // .11530x2b , // +11540x2a , // *11550x3f , // ?11560x28 , // (11570x29 , // )11580x5b , // [11590x5d , // ]11600x7b , // {11610x7d , // }11620x24 , // $11630x5e , // ^11640x3a , // :11650x7c , // |11660x21 , // !11670x0a , // \n11680x0d , // \r11690x00 , // \011700xfeff , // Unicode BOM11710x2028 , // unicode "line separator"11720x2029 , // unicode "paragraph separator"1173].indexOf(code) < 0;1174};11751176DEFPRINT(AST_RegExp, function(self, output){1177var str = self.getValue().toString();1178if (output.option("ascii_only")) {1179str = output.to_ascii(str);1180} else if (output.option("unescape_regexps")) {1181str = str.split("\\\\").map(function(str){1182return str.replace(/\\u[0-9a-fA-F]{4}|\\x[0-9a-fA-F]{2}/g, function(s){1183var code = parseInt(s.substr(2), 16);1184return regexp_safe_literal(code) ? String.fromCharCode(code) : s;1185});1186}).join("\\\\");1187}1188output.print(str);1189var p = output.parent();1190if (p instanceof AST_Binary && /^in/.test(p.operator) && p.left === self)1191output.print(" ");1192});11931194function force_statement(stat, output) {1195if (output.option("bracketize")) {1196if (!stat || stat instanceof AST_EmptyStatement)1197output.print("{}");1198else if (stat instanceof AST_BlockStatement)1199stat.print(output);1200else output.with_block(function(){1201output.indent();1202stat.print(output);1203output.newline();1204});1205} else {1206if (!stat || stat instanceof AST_EmptyStatement)1207output.force_semicolon();1208else1209stat.print(output);1210}1211};12121213// return true if the node at the top of the stack (that means the1214// innermost node in the current output) is lexically the first in1215// a statement.1216function first_in_statement(output) {1217var a = output.stack(), i = a.length, node = a[--i], p = a[--i];1218while (i > 0) {1219if (p instanceof AST_Statement && p.body === node)1220return true;1221if ((p instanceof AST_Seq && p.car === node ) ||1222(p instanceof AST_Call && p.expression === node && !(p instanceof AST_New) ) ||1223(p instanceof AST_Dot && p.expression === node ) ||1224(p instanceof AST_Sub && p.expression === node ) ||1225(p instanceof AST_Conditional && p.condition === node ) ||1226(p instanceof AST_Binary && p.left === node ) ||1227(p instanceof AST_UnaryPostfix && p.expression === node ))1228{1229node = p;1230p = a[--i];1231} else {1232return false;1233}1234}1235};12361237// self should be AST_New. decide if we want to show parens or not.1238function no_constructor_parens(self, output) {1239return self.args.length == 0 && !output.option("beautify");1240};12411242function best_of(a) {1243var best = a[0], len = best.length;1244for (var i = 1; i < a.length; ++i) {1245if (a[i].length < len) {1246best = a[i];1247len = best.length;1248}1249}1250return best;1251};12521253function make_num(num) {1254var str = num.toString(10), a = [ str.replace(/^0\./, ".").replace('e+', 'e') ], m;1255if (Math.floor(num) === num) {1256if (num >= 0) {1257a.push("0x" + num.toString(16).toLowerCase(), // probably pointless1258"0" + num.toString(8)); // same.1259} else {1260a.push("-0x" + (-num).toString(16).toLowerCase(), // probably pointless1261"-0" + (-num).toString(8)); // same.1262}1263if ((m = /^(.*?)(0+)$/.exec(num))) {1264a.push(m[1] + "e" + m[2].length);1265}1266} else if ((m = /^0?\.(0+)(.*)$/.exec(num))) {1267a.push(m[2] + "e-" + (m[1].length + m[2].length),1268str.substr(str.indexOf(".")));1269}1270return best_of(a);1271};12721273function make_block(stmt, output) {1274if (stmt instanceof AST_BlockStatement) {1275stmt.print(output);1276return;1277}1278output.with_block(function(){1279output.indent();1280stmt.print(output);1281output.newline();1282});1283};12841285/* -----[ source map generators ]----- */12861287function DEFMAP(nodetype, generator) {1288nodetype.DEFMETHOD("add_source_map", function(stream){1289generator(this, stream);1290});1291};12921293// We could easily add info for ALL nodes, but it seems to me that1294// would be quite wasteful, hence this noop in the base class.1295DEFMAP(AST_Node, noop);12961297function basic_sourcemap_gen(self, output) {1298output.add_mapping(self.start);1299};13001301// XXX: I'm not exactly sure if we need it for all of these nodes,1302// or if we should add even more.13031304DEFMAP(AST_Directive, basic_sourcemap_gen);1305DEFMAP(AST_Debugger, basic_sourcemap_gen);1306DEFMAP(AST_Symbol, basic_sourcemap_gen);1307DEFMAP(AST_Jump, basic_sourcemap_gen);1308DEFMAP(AST_StatementWithBody, basic_sourcemap_gen);1309DEFMAP(AST_LabeledStatement, noop); // since the label symbol will mark it1310DEFMAP(AST_Lambda, basic_sourcemap_gen);1311DEFMAP(AST_Switch, basic_sourcemap_gen);1312DEFMAP(AST_SwitchBranch, basic_sourcemap_gen);1313DEFMAP(AST_BlockStatement, basic_sourcemap_gen);1314DEFMAP(AST_Toplevel, noop);1315DEFMAP(AST_New, basic_sourcemap_gen);1316DEFMAP(AST_Try, basic_sourcemap_gen);1317DEFMAP(AST_Catch, basic_sourcemap_gen);1318DEFMAP(AST_Finally, basic_sourcemap_gen);1319DEFMAP(AST_Definitions, basic_sourcemap_gen);1320DEFMAP(AST_Constant, basic_sourcemap_gen);1321DEFMAP(AST_ObjectProperty, function(self, output){1322output.add_mapping(self.start, self.key);1323});13241325})();132613271328