react / react-0.13.3 / examples / basic-commonjs / node_modules / browserify / node_modules / umd / node_modules / ruglify / node_modules / uglify-js / lib / output.js
81169 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,53inline_script : false,54width : 80,55max_line_len : 32000,56ie_proof : true,57beautify : false,58source_map : null,59bracketize : false,60semicolons : true,61comments : false,62preserve_line : false63}, true);6465var indentation = 0;66var current_col = 0;67var current_line = 1;68var current_pos = 0;69var OUTPUT = "";7071function to_ascii(str) {72return str.replace(/[\u0080-\uffff]/g, function(ch) {73var code = ch.charCodeAt(0).toString(16);74while (code.length < 4) code = "0" + code;75return "\\u" + code;76});77};7879function make_string(str) {80var dq = 0, sq = 0;81str = str.replace(/[\\\b\f\n\r\t\x22\x27\u2028\u2029\0]/g, function(s){82switch (s) {83case "\\": return "\\\\";84case "\b": return "\\b";85case "\f": return "\\f";86case "\n": return "\\n";87case "\r": return "\\r";88case "\u2028": return "\\u2028";89case "\u2029": return "\\u2029";90case '"': ++dq; return '"';91case "'": ++sq; return "'";92case "\0": return "\\0";93}94return s;95});96if (options.ascii_only) str = to_ascii(str);97if (dq > sq) return "'" + str.replace(/\x27/g, "\\'") + "'";98else return '"' + str.replace(/\x22/g, '\\"') + '"';99};100101function encode_string(str) {102var ret = make_string(str);103if (options.inline_script)104ret = ret.replace(/<\x2fscript([>\/\t\n\f\r ])/gi, "<\\/script$1");105return ret;106};107108function make_name(name) {109name = name.toString();110if (options.ascii_only)111name = to_ascii(name);112return name;113};114115function make_indent(back) {116return repeat_string(" ", options.indent_start + indentation - back * options.indent_level);117};118119/* -----[ beautification/minification ]----- */120121var might_need_space = false;122var might_need_semicolon = false;123var last = null;124125function last_char() {126return last.charAt(last.length - 1);127};128129function maybe_newline() {130if (options.max_line_len && current_col > options.max_line_len)131print("\n");132};133134var requireSemicolonChars = makePredicate("( [ + * / - , .");135136function print(str) {137str = String(str);138var ch = str.charAt(0);139if (might_need_semicolon) {140if ((!ch || ";}".indexOf(ch) < 0) && !/[;]$/.test(last)) {141if (options.semicolons || requireSemicolonChars(ch)) {142OUTPUT += ";";143current_col++;144current_pos++;145} else {146OUTPUT += "\n";147current_pos++;148current_line++;149current_col = 0;150}151if (!options.beautify)152might_need_space = false;153}154might_need_semicolon = false;155maybe_newline();156}157158if (!options.beautify && options.preserve_line && stack[stack.length - 1]) {159var target_line = stack[stack.length - 1].start.line;160while (current_line < target_line) {161OUTPUT += "\n";162current_pos++;163current_line++;164current_col = 0;165might_need_space = false;166}167}168169if (might_need_space) {170var prev = last_char();171if ((is_identifier_char(prev)172&& (is_identifier_char(ch) || ch == "\\"))173|| (/^[\+\-\/]$/.test(ch) && ch == prev))174{175OUTPUT += " ";176current_col++;177current_pos++;178}179might_need_space = false;180}181var a = str.split(/\r?\n/), n = a.length - 1;182current_line += n;183if (n == 0) {184current_col += a[n].length;185} else {186current_col = a[n].length;187}188current_pos += str.length;189last = str;190OUTPUT += str;191};192193var space = options.beautify ? function() {194print(" ");195} : function() {196might_need_space = true;197};198199var indent = options.beautify ? function(half) {200if (options.beautify) {201print(make_indent(half ? 0.5 : 0));202}203} : noop;204205var with_indent = options.beautify ? function(col, cont) {206if (col === true) col = next_indent();207var save_indentation = indentation;208indentation = col;209var ret = cont();210indentation = save_indentation;211return ret;212} : function(col, cont) { return cont() };213214var newline = options.beautify ? function() {215print("\n");216} : noop;217218var semicolon = options.beautify ? function() {219print(";");220} : function() {221might_need_semicolon = true;222};223224function force_semicolon() {225might_need_semicolon = false;226print(";");227};228229function next_indent() {230return indentation + options.indent_level;231};232233function with_block(cont) {234var ret;235print("{");236newline();237with_indent(next_indent(), function(){238ret = cont();239});240indent();241print("}");242return ret;243};244245function with_parens(cont) {246print("(");247//XXX: still nice to have that for argument lists248//var ret = with_indent(current_col, cont);249var ret = cont();250print(")");251return ret;252};253254function with_square(cont) {255print("[");256//var ret = with_indent(current_col, cont);257var ret = cont();258print("]");259return ret;260};261262function comma() {263print(",");264space();265};266267function colon() {268print(":");269if (options.space_colon) space();270};271272var add_mapping = options.source_map ? function(token, name) {273try {274if (token) options.source_map.add(275token.file || "?",276current_line, current_col,277token.line, token.col,278(!name && token.type == "name") ? token.value : name279);280} catch(ex) {281AST_Node.warn("Couldn't figure out mapping for {file}:{line},{col} → {cline},{ccol} [{name}]", {282file: token.file,283line: token.line,284col: token.col,285cline: current_line,286ccol: current_col,287name: name || ""288})289}290} : noop;291292function get() {293return OUTPUT;294};295296var stack = [];297return {298get : get,299toString : get,300indent : indent,301indentation : function() { return indentation },302current_width : function() { return current_col - indentation },303should_break : function() { return options.width && this.current_width() >= options.width },304newline : newline,305print : print,306space : space,307comma : comma,308colon : colon,309last : function() { return last },310semicolon : semicolon,311force_semicolon : force_semicolon,312to_ascii : to_ascii,313print_name : function(name) { print(make_name(name)) },314print_string : function(str) { print(encode_string(str)) },315next_indent : next_indent,316with_indent : with_indent,317with_block : with_block,318with_parens : with_parens,319with_square : with_square,320add_mapping : add_mapping,321option : function(opt) { return options[opt] },322line : function() { return current_line },323col : function() { return current_col },324pos : function() { return current_pos },325push_node : function(node) { stack.push(node) },326pop_node : function() { return stack.pop() },327stack : function() { return stack },328parent : function(n) {329return stack[stack.length - 2 - (n || 0)];330}331};332333};334335/* -----[ code generators ]----- */336337(function(){338339/* -----[ utils ]----- */340341function DEFPRINT(nodetype, generator) {342nodetype.DEFMETHOD("_codegen", generator);343};344345AST_Node.DEFMETHOD("print", function(stream, force_parens){346var self = this, generator = self._codegen;347stream.push_node(self);348if (force_parens || self.needs_parens(stream)) {349stream.with_parens(function(){350self.add_comments(stream);351self.add_source_map(stream);352generator(self, stream);353});354} else {355self.add_comments(stream);356self.add_source_map(stream);357generator(self, stream);358}359stream.pop_node();360});361362AST_Node.DEFMETHOD("print_to_string", function(options){363var s = OutputStream(options);364this.print(s);365return s.get();366});367368/* -----[ comments ]----- */369370AST_Node.DEFMETHOD("add_comments", function(output){371var c = output.option("comments"), self = this;372if (c) {373var start = self.start;374if (start && !start._comments_dumped) {375start._comments_dumped = true;376var comments = start.comments_before;377378// XXX: ugly fix for https://github.com/mishoo/UglifyJS2/issues/112379// if this node is `return` or `throw`, we cannot allow comments before380// the returned or thrown value.381if (self instanceof AST_Exit &&382self.value && self.value.start.comments_before.length > 0) {383comments = (comments || []).concat(self.value.start.comments_before);384self.value.start.comments_before = [];385}386387if (c.test) {388comments = comments.filter(function(comment){389return c.test(comment.value);390});391} else if (typeof c == "function") {392comments = comments.filter(function(comment){393return c(self, comment);394});395}396comments.forEach(function(c){397if (c.type == "comment1") {398output.print("//" + c.value + "\n");399output.indent();400}401else if (c.type == "comment2") {402output.print("/*" + c.value + "*/");403if (start.nlb) {404output.print("\n");405output.indent();406} else {407output.space();408}409}410});411}412}413});414415/* -----[ PARENTHESES ]----- */416417function PARENS(nodetype, func) {418nodetype.DEFMETHOD("needs_parens", func);419};420421PARENS(AST_Node, function(){422return false;423});424425// a function expression needs parens around it when it's provably426// the first token to appear in a statement.427PARENS(AST_Function, function(output){428return first_in_statement(output);429});430431// same goes for an object literal, because otherwise it would be432// interpreted as a block of code.433PARENS(AST_Object, function(output){434return first_in_statement(output);435});436437PARENS(AST_Unary, function(output){438var p = output.parent();439return p instanceof AST_PropAccess && p.expression === this;440});441442PARENS(AST_Seq, function(output){443var p = output.parent();444return p instanceof AST_Call // (foo, bar)() or foo(1, (2, 3), 4)445|| p instanceof AST_Unary // !(foo, bar, baz)446|| p instanceof AST_Binary // 1 + (2, 3) + 4 ==> 8447|| p instanceof AST_VarDef // var a = (1, 2), b = a + a; ==> b == 4448|| p instanceof AST_Dot // (1, {foo:2}).foo ==> 2449|| p instanceof AST_Array // [ 1, (2, 3), 4 ] ==> [ 1, 3, 4 ]450|| p instanceof AST_ObjectProperty // { foo: (1, 2) }.foo ==> 2451|| p instanceof AST_Conditional /* (false, true) ? (a = 10, b = 20) : (c = 30)452* ==> 20 (side effect, set a := 10 and b := 20) */453;454});455456PARENS(AST_Binary, function(output){457var p = output.parent();458// (foo && bar)()459if (p instanceof AST_Call && p.expression === this)460return true;461// typeof (foo && bar)462if (p instanceof AST_Unary)463return true;464// (foo && bar)["prop"], (foo && bar).prop465if (p instanceof AST_PropAccess && p.expression === this)466return true;467// this deals with precedence: 3 * (2 + 1)468if (p instanceof AST_Binary) {469var po = p.operator, pp = PRECEDENCE[po];470var so = this.operator, sp = PRECEDENCE[so];471if (pp > sp472|| (pp == sp473&& this === p.right474&& !(so == po &&475(so == "*" ||476so == "&&" ||477so == "||")))) {478return true;479}480}481});482483PARENS(AST_PropAccess, function(output){484var p = output.parent();485if (p instanceof AST_New && p.expression === this) {486// i.e. new (foo.bar().baz)487//488// if there's one call into this subtree, then we need489// parens around it too, otherwise the call will be490// interpreted as passing the arguments to the upper New491// expression.492try {493this.walk(new TreeWalker(function(node){494if (node instanceof AST_Call) throw p;495}));496} catch(ex) {497if (ex !== p) throw ex;498return true;499}500}501});502503PARENS(AST_Call, function(output){504var p = output.parent();505return p instanceof AST_New && p.expression === this;506});507508PARENS(AST_New, function(output){509var p = output.parent();510if (no_constructor_parens(this, output)511&& (p instanceof AST_PropAccess // (new Date).getTime(), (new Date)["getTime"]()512|| p instanceof AST_Call && p.expression === this)) // (new foo)(bar)513return true;514});515516PARENS(AST_Number, function(output){517var p = output.parent();518if (this.getValue() < 0 && p instanceof AST_PropAccess && p.expression === this)519return true;520});521522PARENS(AST_NaN, function(output){523var p = output.parent();524if (p instanceof AST_PropAccess && p.expression === this)525return true;526});527528function assign_and_conditional_paren_rules(output) {529var p = output.parent();530// !(a = false) → true531if (p instanceof AST_Unary)532return true;533// 1 + (a = 2) + 3 → 6, side effect setting a = 2534if (p instanceof AST_Binary && !(p instanceof AST_Assign))535return true;536// (a = func)() —or— new (a = Object)()537if (p instanceof AST_Call && p.expression === this)538return true;539// (a = foo) ? bar : baz540if (p instanceof AST_Conditional && p.condition === this)541return true;542// (a = foo)["prop"] —or— (a = foo).prop543if (p instanceof AST_PropAccess && p.expression === this)544return true;545};546547PARENS(AST_Assign, assign_and_conditional_paren_rules);548PARENS(AST_Conditional, assign_and_conditional_paren_rules);549550/* -----[ PRINTERS ]----- */551552DEFPRINT(AST_Directive, function(self, output){553output.print_string(self.value);554output.semicolon();555});556DEFPRINT(AST_Debugger, function(self, output){557output.print("debugger");558output.semicolon();559});560561/* -----[ statements ]----- */562563function display_body(body, is_toplevel, output) {564var last = body.length - 1;565body.forEach(function(stmt, i){566if (!(stmt instanceof AST_EmptyStatement)) {567output.indent();568stmt.print(output);569if (!(i == last && is_toplevel)) {570output.newline();571if (is_toplevel) output.newline();572}573}574});575};576577AST_StatementWithBody.DEFMETHOD("_do_print_body", function(output){578force_statement(this.body, output);579});580581DEFPRINT(AST_Statement, function(self, output){582self.body.print(output);583output.semicolon();584});585DEFPRINT(AST_Toplevel, function(self, output){586display_body(self.body, true, output);587output.print("");588});589DEFPRINT(AST_LabeledStatement, function(self, output){590self.label.print(output);591output.colon();592self.body.print(output);593});594DEFPRINT(AST_SimpleStatement, function(self, output){595self.body.print(output);596output.semicolon();597});598function print_bracketed(body, output) {599if (body.length > 0) output.with_block(function(){600display_body(body, false, output);601});602else output.print("{}");603};604DEFPRINT(AST_BlockStatement, function(self, output){605print_bracketed(self.body, output);606});607DEFPRINT(AST_EmptyStatement, function(self, output){608output.semicolon();609});610DEFPRINT(AST_Do, function(self, output){611output.print("do");612output.space();613self._do_print_body(output);614output.space();615output.print("while");616output.space();617output.with_parens(function(){618self.condition.print(output);619});620output.semicolon();621});622DEFPRINT(AST_While, function(self, output){623output.print("while");624output.space();625output.with_parens(function(){626self.condition.print(output);627});628output.space();629self._do_print_body(output);630});631DEFPRINT(AST_For, function(self, output){632output.print("for");633output.space();634output.with_parens(function(){635if (self.init) {636if (self.init instanceof AST_Definitions) {637self.init.print(output);638} else {639parenthesize_for_noin(self.init, output, true);640}641output.print(";");642output.space();643} else {644output.print(";");645}646if (self.condition) {647self.condition.print(output);648output.print(";");649output.space();650} else {651output.print(";");652}653if (self.step) {654self.step.print(output);655}656});657output.space();658self._do_print_body(output);659});660DEFPRINT(AST_ForIn, function(self, output){661output.print("for");662output.space();663output.with_parens(function(){664self.init.print(output);665output.space();666output.print("in");667output.space();668self.object.print(output);669});670output.space();671self._do_print_body(output);672});673DEFPRINT(AST_With, function(self, output){674output.print("with");675output.space();676output.with_parens(function(){677self.expression.print(output);678});679output.space();680self._do_print_body(output);681});682683/* -----[ functions ]----- */684AST_Lambda.DEFMETHOD("_do_print", function(output, nokeyword){685var self = this;686if (!nokeyword) {687output.print("function");688}689if (self.name) {690output.space();691self.name.print(output);692}693output.with_parens(function(){694self.argnames.forEach(function(arg, i){695if (i) output.comma();696arg.print(output);697});698});699output.space();700print_bracketed(self.body, output);701});702DEFPRINT(AST_Lambda, function(self, output){703self._do_print(output);704});705706/* -----[ exits ]----- */707AST_Exit.DEFMETHOD("_do_print", function(output, kind){708output.print(kind);709if (this.value) {710output.space();711this.value.print(output);712}713output.semicolon();714});715DEFPRINT(AST_Return, function(self, output){716self._do_print(output, "return");717});718DEFPRINT(AST_Throw, function(self, output){719self._do_print(output, "throw");720});721722/* -----[ loop control ]----- */723AST_LoopControl.DEFMETHOD("_do_print", function(output, kind){724output.print(kind);725if (this.label) {726output.space();727this.label.print(output);728}729output.semicolon();730});731DEFPRINT(AST_Break, function(self, output){732self._do_print(output, "break");733});734DEFPRINT(AST_Continue, function(self, output){735self._do_print(output, "continue");736});737738/* -----[ if ]----- */739function make_then(self, output) {740if (output.option("bracketize")) {741make_block(self.body, output);742return;743}744// The squeezer replaces "block"-s that contain only a single745// statement with the statement itself; technically, the AST746// is correct, but this can create problems when we output an747// IF having an ELSE clause where the THEN clause ends in an748// IF *without* an ELSE block (then the outer ELSE would refer749// to the inner IF). This function checks for this case and750// adds the block brackets if needed.751if (!self.body)752return output.force_semicolon();753if (self.body instanceof AST_Do754&& output.option("ie_proof")) {755// https://github.com/mishoo/UglifyJS/issues/#issue/57 IE756// croaks with "syntax error" on code like this: if (foo)757// do ... while(cond); else ... we need block brackets758// around do/while759make_block(self.body, output);760return;761}762var b = self.body;763while (true) {764if (b instanceof AST_If) {765if (!b.alternative) {766make_block(self.body, output);767return;768}769b = b.alternative;770}771else if (b instanceof AST_StatementWithBody) {772b = b.body;773}774else break;775}776force_statement(self.body, output);777};778DEFPRINT(AST_If, function(self, output){779output.print("if");780output.space();781output.with_parens(function(){782self.condition.print(output);783});784output.space();785if (self.alternative) {786make_then(self, output);787output.space();788output.print("else");789output.space();790force_statement(self.alternative, output);791} else {792self._do_print_body(output);793}794});795796/* -----[ switch ]----- */797DEFPRINT(AST_Switch, function(self, output){798output.print("switch");799output.space();800output.with_parens(function(){801self.expression.print(output);802});803output.space();804if (self.body.length > 0) output.with_block(function(){805self.body.forEach(function(stmt, i){806if (i) output.newline();807output.indent(true);808stmt.print(output);809});810});811else output.print("{}");812});813AST_SwitchBranch.DEFMETHOD("_do_print_body", function(output){814if (this.body.length > 0) {815output.newline();816this.body.forEach(function(stmt){817output.indent();818stmt.print(output);819output.newline();820});821}822});823DEFPRINT(AST_Default, function(self, output){824output.print("default:");825self._do_print_body(output);826});827DEFPRINT(AST_Case, function(self, output){828output.print("case");829output.space();830self.expression.print(output);831output.print(":");832self._do_print_body(output);833});834835/* -----[ exceptions ]----- */836DEFPRINT(AST_Try, function(self, output){837output.print("try");838output.space();839print_bracketed(self.body, output);840if (self.bcatch) {841output.space();842self.bcatch.print(output);843}844if (self.bfinally) {845output.space();846self.bfinally.print(output);847}848});849DEFPRINT(AST_Catch, function(self, output){850output.print("catch");851output.space();852output.with_parens(function(){853self.argname.print(output);854});855output.space();856print_bracketed(self.body, output);857});858DEFPRINT(AST_Finally, function(self, output){859output.print("finally");860output.space();861print_bracketed(self.body, output);862});863864/* -----[ var/const ]----- */865AST_Definitions.DEFMETHOD("_do_print", function(output, kind){866output.print(kind);867output.space();868this.definitions.forEach(function(def, i){869if (i) output.comma();870def.print(output);871});872var p = output.parent();873var in_for = p instanceof AST_For || p instanceof AST_ForIn;874var avoid_semicolon = in_for && p.init === this;875if (!avoid_semicolon)876output.semicolon();877});878DEFPRINT(AST_Var, function(self, output){879self._do_print(output, "var");880});881DEFPRINT(AST_Const, function(self, output){882self._do_print(output, "const");883});884885function parenthesize_for_noin(node, output, noin) {886if (!noin) node.print(output);887else try {888// need to take some precautions here:889// https://github.com/mishoo/UglifyJS2/issues/60890node.walk(new TreeWalker(function(node){891if (node instanceof AST_Binary && node.operator == "in")892throw output;893}));894node.print(output);895} catch(ex) {896if (ex !== output) throw ex;897node.print(output, true);898}899};900901DEFPRINT(AST_VarDef, function(self, output){902self.name.print(output);903if (self.value) {904output.space();905output.print("=");906output.space();907var p = output.parent(1);908var noin = p instanceof AST_For || p instanceof AST_ForIn;909parenthesize_for_noin(self.value, output, noin);910}911});912913/* -----[ other expressions ]----- */914DEFPRINT(AST_Call, function(self, output){915self.expression.print(output);916if (self instanceof AST_New && no_constructor_parens(self, output))917return;918output.with_parens(function(){919self.args.forEach(function(expr, i){920if (i) output.comma();921expr.print(output);922});923});924});925DEFPRINT(AST_New, function(self, output){926output.print("new");927output.space();928AST_Call.prototype._codegen(self, output);929});930931AST_Seq.DEFMETHOD("_do_print", function(output){932this.car.print(output);933if (this.cdr) {934output.comma();935if (output.should_break()) {936output.newline();937output.indent();938}939this.cdr.print(output);940}941});942DEFPRINT(AST_Seq, function(self, output){943self._do_print(output);944// var p = output.parent();945// if (p instanceof AST_Statement) {946// output.with_indent(output.next_indent(), function(){947// self._do_print(output);948// });949// } else {950// self._do_print(output);951// }952});953DEFPRINT(AST_Dot, function(self, output){954var expr = self.expression;955expr.print(output);956if (expr instanceof AST_Number && expr.getValue() >= 0) {957if (!/[xa-f.]/i.test(output.last())) {958output.print(".");959}960}961output.print(".");962// the name after dot would be mapped about here.963output.add_mapping(self.end);964output.print_name(self.property);965});966DEFPRINT(AST_Sub, function(self, output){967self.expression.print(output);968output.print("[");969self.property.print(output);970output.print("]");971});972DEFPRINT(AST_UnaryPrefix, function(self, output){973var op = self.operator;974output.print(op);975if (/^[a-z]/i.test(op))976output.space();977self.expression.print(output);978});979DEFPRINT(AST_UnaryPostfix, function(self, output){980self.expression.print(output);981output.print(self.operator);982});983DEFPRINT(AST_Binary, function(self, output){984self.left.print(output);985output.space();986output.print(self.operator);987output.space();988self.right.print(output);989});990DEFPRINT(AST_Conditional, function(self, output){991self.condition.print(output);992output.space();993output.print("?");994output.space();995self.consequent.print(output);996output.space();997output.colon();998self.alternative.print(output);999});10001001/* -----[ literals ]----- */1002DEFPRINT(AST_Array, function(self, output){1003output.with_square(function(){1004var a = self.elements, len = a.length;1005if (len > 0) output.space();1006a.forEach(function(exp, i){1007if (i) output.comma();1008exp.print(output);1009});1010if (len > 0) output.space();1011});1012});1013DEFPRINT(AST_Object, function(self, output){1014if (self.properties.length > 0) output.with_block(function(){1015self.properties.forEach(function(prop, i){1016if (i) {1017output.print(",");1018output.newline();1019}1020output.indent();1021prop.print(output);1022});1023output.newline();1024});1025else output.print("{}");1026});1027DEFPRINT(AST_ObjectKeyVal, function(self, output){1028var key = self.key;1029if (output.option("quote_keys")) {1030output.print_string(key);1031} else if ((typeof key == "number"1032|| !output.option("beautify")1033&& +key + "" == key)1034&& parseFloat(key) >= 0) {1035output.print(make_num(key));1036} else if (!is_identifier(key)) {1037output.print_string(key);1038} else {1039output.print_name(key);1040}1041output.colon();1042self.value.print(output);1043});1044DEFPRINT(AST_ObjectSetter, function(self, output){1045output.print("set");1046self.value._do_print(output, true);1047});1048DEFPRINT(AST_ObjectGetter, function(self, output){1049output.print("get");1050self.value._do_print(output, true);1051});1052DEFPRINT(AST_Symbol, function(self, output){1053var def = self.definition();1054output.print_name(def ? def.mangled_name || def.name : self.name);1055});1056DEFPRINT(AST_Undefined, function(self, output){1057output.print("void 0");1058});1059DEFPRINT(AST_Hole, noop);1060DEFPRINT(AST_Infinity, function(self, output){1061output.print("1/0");1062});1063DEFPRINT(AST_NaN, function(self, output){1064output.print("0/0");1065});1066DEFPRINT(AST_This, function(self, output){1067output.print("this");1068});1069DEFPRINT(AST_Constant, function(self, output){1070output.print(self.getValue());1071});1072DEFPRINT(AST_String, function(self, output){1073output.print_string(self.getValue());1074});1075DEFPRINT(AST_Number, function(self, output){1076output.print(make_num(self.getValue()));1077});1078DEFPRINT(AST_RegExp, function(self, output){1079var str = self.getValue().toString();1080if (output.option("ascii_only"))1081str = output.to_ascii(str);1082output.print(str);1083var p = output.parent();1084if (p instanceof AST_Binary && /^in/.test(p.operator) && p.left === self)1085output.print(" ");1086});10871088function force_statement(stat, output) {1089if (output.option("bracketize")) {1090if (!stat || stat instanceof AST_EmptyStatement)1091output.print("{}");1092else if (stat instanceof AST_BlockStatement)1093stat.print(output);1094else output.with_block(function(){1095output.indent();1096stat.print(output);1097output.newline();1098});1099} else {1100if (!stat || stat instanceof AST_EmptyStatement)1101output.force_semicolon();1102else1103stat.print(output);1104}1105};11061107// return true if the node at the top of the stack (that means the1108// innermost node in the current output) is lexically the first in1109// a statement.1110function first_in_statement(output) {1111var a = output.stack(), i = a.length, node = a[--i], p = a[--i];1112while (i > 0) {1113if (p instanceof AST_Statement && p.body === node)1114return true;1115if ((p instanceof AST_Seq && p.car === node ) ||1116(p instanceof AST_Call && p.expression === node ) ||1117(p instanceof AST_Dot && p.expression === node ) ||1118(p instanceof AST_Sub && p.expression === node ) ||1119(p instanceof AST_Conditional && p.condition === node ) ||1120(p instanceof AST_Binary && p.left === node ) ||1121(p instanceof AST_UnaryPostfix && p.expression === node ))1122{1123node = p;1124p = a[--i];1125} else {1126return false;1127}1128}1129};11301131// self should be AST_New. decide if we want to show parens or not.1132function no_constructor_parens(self, output) {1133return self.args.length == 0 && !output.option("beautify");1134};11351136function best_of(a) {1137var best = a[0], len = best.length;1138for (var i = 1; i < a.length; ++i) {1139if (a[i].length < len) {1140best = a[i];1141len = best.length;1142}1143}1144return best;1145};11461147function make_num(num) {1148var str = num.toString(10), a = [ str.replace(/^0\./, ".").replace('e+', 'e') ], m;1149if (Math.floor(num) === num) {1150if (num >= 0) {1151a.push("0x" + num.toString(16).toLowerCase(), // probably pointless1152"0" + num.toString(8)); // same.1153} else {1154a.push("-0x" + (-num).toString(16).toLowerCase(), // probably pointless1155"-0" + (-num).toString(8)); // same.1156}1157if ((m = /^(.*?)(0+)$/.exec(num))) {1158a.push(m[1] + "e" + m[2].length);1159}1160} else if ((m = /^0?\.(0+)(.*)$/.exec(num))) {1161a.push(m[2] + "e-" + (m[1].length + m[2].length),1162str.substr(str.indexOf(".")));1163}1164return best_of(a);1165};11661167function make_block(stmt, output) {1168if (stmt instanceof AST_BlockStatement) {1169stmt.print(output);1170return;1171}1172output.with_block(function(){1173output.indent();1174stmt.print(output);1175output.newline();1176});1177};11781179/* -----[ source map generators ]----- */11801181function DEFMAP(nodetype, generator) {1182nodetype.DEFMETHOD("add_source_map", function(stream){1183generator(this, stream);1184});1185};11861187// We could easily add info for ALL nodes, but it seems to me that1188// would be quite wasteful, hence this noop in the base class.1189DEFMAP(AST_Node, noop);11901191function basic_sourcemap_gen(self, output) {1192output.add_mapping(self.start);1193};11941195// XXX: I'm not exactly sure if we need it for all of these nodes,1196// or if we should add even more.11971198DEFMAP(AST_Directive, basic_sourcemap_gen);1199DEFMAP(AST_Debugger, basic_sourcemap_gen);1200DEFMAP(AST_Symbol, basic_sourcemap_gen);1201DEFMAP(AST_Jump, basic_sourcemap_gen);1202DEFMAP(AST_StatementWithBody, basic_sourcemap_gen);1203DEFMAP(AST_LabeledStatement, noop); // since the label symbol will mark it1204DEFMAP(AST_Lambda, basic_sourcemap_gen);1205DEFMAP(AST_Switch, basic_sourcemap_gen);1206DEFMAP(AST_SwitchBranch, basic_sourcemap_gen);1207DEFMAP(AST_BlockStatement, basic_sourcemap_gen);1208DEFMAP(AST_Toplevel, noop);1209DEFMAP(AST_New, basic_sourcemap_gen);1210DEFMAP(AST_Try, basic_sourcemap_gen);1211DEFMAP(AST_Catch, basic_sourcemap_gen);1212DEFMAP(AST_Finally, basic_sourcemap_gen);1213DEFMAP(AST_Definitions, basic_sourcemap_gen);1214DEFMAP(AST_Constant, basic_sourcemap_gen);1215DEFMAP(AST_ObjectProperty, function(self, output){1216output.add_mapping(self.start, self.key);1217});12181219})();122012211222