| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101 | 
							- /***********************************************************************
 
-   A JavaScript tokenizer / parser / beautifier / compressor.
 
-   https://github.com/mishoo/UglifyJS2
 
-   -------------------------------- (C) ---------------------------------
 
-                            Author: Mihai Bazon
 
-                          <mihai.bazon@gmail.com>
 
-                        http://mihai.bazon.net/blog
 
-   Distributed under the BSD license:
 
-     Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
 
-     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 Compressor(options, false_by_default) {
 
-     if (!(this instanceof Compressor))
 
-         return new Compressor(options, false_by_default);
 
-     TreeTransformer.call(this, this.before, this.after);
 
-     this.options = defaults(options, {
 
-         angular       : false,
 
-         booleans      : !false_by_default,
 
-         cascade       : !false_by_default,
 
-         collapse_vars : !false_by_default,
 
-         comparisons   : !false_by_default,
 
-         conditionals  : !false_by_default,
 
-         dead_code     : !false_by_default,
 
-         drop_console  : false,
 
-         drop_debugger : !false_by_default,
 
-         evaluate      : !false_by_default,
 
-         expression    : false,
 
-         global_defs   : {},
 
-         hoist_funs    : !false_by_default,
 
-         hoist_vars    : false,
 
-         if_return     : !false_by_default,
 
-         join_vars     : !false_by_default,
 
-         keep_fargs    : true,
 
-         keep_fnames   : false,
 
-         keep_infinity : false,
 
-         loops         : !false_by_default,
 
-         negate_iife   : !false_by_default,
 
-         passes        : 1,
 
-         properties    : !false_by_default,
 
-         pure_getters  : !false_by_default && "strict",
 
-         pure_funcs    : null,
 
-         reduce_vars   : !false_by_default,
 
-         screw_ie8     : true,
 
-         sequences     : !false_by_default,
 
-         side_effects  : !false_by_default,
 
-         switches      : !false_by_default,
 
-         top_retain    : null,
 
-         toplevel      : !!(options && options["top_retain"]),
 
-         unsafe        : false,
 
-         unsafe_comps  : false,
 
-         unsafe_math   : false,
 
-         unsafe_proto  : false,
 
-         unsafe_regexp : false,
 
-         unused        : !false_by_default,
 
-         warnings      : true,
 
-     }, true);
 
-     var pure_funcs = this.options["pure_funcs"];
 
-     if (typeof pure_funcs == "function") {
 
-         this.pure_funcs = pure_funcs;
 
-     } else {
 
-         this.pure_funcs = pure_funcs ? function(node) {
 
-             return pure_funcs.indexOf(node.expression.print_to_string()) < 0;
 
-         } : return_true;
 
-     }
 
-     var top_retain = this.options["top_retain"];
 
-     if (top_retain instanceof RegExp) {
 
-         this.top_retain = function(def) {
 
-             return top_retain.test(def.name);
 
-         };
 
-     } else if (typeof top_retain == "function") {
 
-         this.top_retain = top_retain;
 
-     } else if (top_retain) {
 
-         if (typeof top_retain == "string") {
 
-             top_retain = top_retain.split(/,/);
 
-         }
 
-         this.top_retain = function(def) {
 
-             return top_retain.indexOf(def.name) >= 0;
 
-         };
 
-     }
 
-     var sequences = this.options["sequences"];
 
-     this.sequences_limit = sequences == 1 ? 200 : sequences | 0;
 
-     this.warnings_produced = {};
 
- };
 
- Compressor.prototype = new TreeTransformer;
 
- merge(Compressor.prototype, {
 
-     option: function(key) { return this.options[key] },
 
-     compress: function(node) {
 
-         if (this.option("expression")) {
 
-             node = node.process_expression(true);
 
-         }
 
-         var passes = +this.options.passes || 1;
 
-         for (var pass = 0; pass < passes && pass < 3; ++pass) {
 
-             if (pass > 0 || this.option("reduce_vars"))
 
-                 node.reset_opt_flags(this, true);
 
-             node = node.transform(this);
 
-         }
 
-         if (this.option("expression")) {
 
-             node = node.process_expression(false);
 
-         }
 
-         return node;
 
-     },
 
-     info: function() {
 
-         if (this.options.warnings == "verbose") {
 
-             AST_Node.warn.apply(AST_Node, arguments);
 
-         }
 
-     },
 
-     warn: function(text, props) {
 
-         if (this.options.warnings) {
 
-             // only emit unique warnings
 
-             var message = string_template(text, props);
 
-             if (!(message in this.warnings_produced)) {
 
-                 this.warnings_produced[message] = true;
 
-                 AST_Node.warn.apply(AST_Node, arguments);
 
-             }
 
-         }
 
-     },
 
-     clear_warnings: function() {
 
-         this.warnings_produced = {};
 
-     },
 
-     before: function(node, descend, in_list) {
 
-         if (node._squeezed) return node;
 
-         var was_scope = false;
 
-         if (node instanceof AST_Scope) {
 
-             node = node.hoist_declarations(this);
 
-             was_scope = true;
 
-         }
 
-         // 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
 
-         // thus gives a consistent AST snapshot.
 
-         descend(node, this);
 
-         // 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);
 
-         var opt = node.optimize(this);
 
-         if (was_scope && opt instanceof AST_Scope) {
 
-             opt.drop_unused(this);
 
-             descend(opt, this);
 
-         }
 
-         if (opt === node) opt._squeezed = true;
 
-         return opt;
 
-     }
 
- });
 
- (function(){
 
-     function OPT(node, optimizer) {
 
-         node.DEFMETHOD("optimize", function(compressor){
 
-             var self = this;
 
-             if (self._optimized) return self;
 
-             if (compressor.has_directive("use asm")) return self;
 
-             var opt = optimizer(self, compressor);
 
-             opt._optimized = true;
 
-             return opt;
 
-         });
 
-     };
 
-     OPT(AST_Node, function(self, compressor){
 
-         return self;
 
-     });
 
-     AST_Node.DEFMETHOD("equivalent_to", function(node){
 
-         return this.TYPE == node.TYPE && this.print_to_string() == node.print_to_string();
 
-     });
 
-     AST_Node.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, {
 
-                     value: node.body
 
-                 });
 
-             }
 
-             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, {
 
-                         body: value
 
-                     }) : make_node(AST_EmptyStatement, node);
 
-                 }
 
-                 return make_node(AST_SimpleStatement, node, {
 
-                     body: node.value || make_node(AST_UnaryPrefix, node, {
 
-                         operator: "void",
 
-                         expression: make_node(AST_Number, node, {
 
-                             value: 0
 
-                         })
 
-                     })
 
-                 });
 
-             }
 
-             if (node instanceof AST_Lambda && node !== self) {
 
-                 return node;
 
-             }
 
-             if (node instanceof AST_Block) {
 
-                 var index = node.body.length - 1;
 
-                 if (index >= 0) {
 
-                     node.body[index] = node.body[index].transform(tt);
 
-                 }
 
-             }
 
-             if (node instanceof AST_If) {
 
-                 node.body = node.body.transform(tt);
 
-                 if (node.alternative) {
 
-                     node.alternative = node.alternative.transform(tt);
 
-                 }
 
-             }
 
-             if (node instanceof AST_With) {
 
-                 node.body = node.body.transform(tt);
 
-             }
 
-             return node;
 
-         });
 
-         return self.transform(tt);
 
-     });
 
-     AST_Node.DEFMETHOD("reset_opt_flags", function(compressor, rescan){
 
-         var reduce_vars = rescan && compressor.option("reduce_vars");
 
-         var toplevel = compressor.option("toplevel");
 
-         var safe_ids = Object.create(null);
 
-         var suppressor = new TreeWalker(function(node) {
 
-             if (node instanceof AST_Symbol) {
 
-                 var d = node.definition();
 
-                 if (node instanceof AST_SymbolRef) d.references.push(node);
 
-                 d.fixed = false;
 
-             }
 
-         });
 
-         var tw = new TreeWalker(function(node, descend){
 
-             node._squeezed = false;
 
-             node._optimized = false;
 
-             if (reduce_vars) {
 
-                 if (node instanceof AST_Toplevel) node.globals.each(reset_def);
 
-                 if (node instanceof AST_Scope) node.variables.each(reset_def);
 
-                 if (node instanceof AST_SymbolRef) {
 
-                     var d = node.definition();
 
-                     d.references.push(node);
 
-                     if (d.fixed === undefined || !is_safe(d)
 
-                         || is_modified(node, 0, node.fixed_value() instanceof AST_Lambda)) {
 
-                         d.fixed = false;
 
-                     } else {
 
-                         var parent = tw.parent();
 
-                         if (parent instanceof AST_Assign && parent.operator == "=" && node === parent.right
 
-                             || parent instanceof AST_Call && node !== parent.expression
 
-                             || parent instanceof AST_Return && node === parent.value && node.scope !== d.scope
 
-                             || parent instanceof AST_VarDef && node === parent.value) {
 
-                             d.escaped = true;
 
-                         }
 
-                     }
 
-                 }
 
-                 if (node instanceof AST_SymbolCatch) {
 
-                     node.definition().fixed = false;
 
-                 }
 
-                 if (node instanceof AST_VarDef) {
 
-                     var d = node.name.definition();
 
-                     if (d.fixed == null) {
 
-                         if (node.value) {
 
-                             d.fixed = function() {
 
-                                 return node.value;
 
-                             };
 
-                             mark(d, false);
 
-                             descend();
 
-                         } else {
 
-                             d.fixed = null;
 
-                         }
 
-                         mark(d, true);
 
-                         return true;
 
-                     } else if (node.value) {
 
-                         d.fixed = false;
 
-                     }
 
-                 }
 
-                 if (node instanceof AST_Defun) {
 
-                     var d = node.name.definition();
 
-                     if (!toplevel && d.global || is_safe(d)) {
 
-                         d.fixed = false;
 
-                     } else {
 
-                         d.fixed = node;
 
-                         mark(d, true);
 
-                     }
 
-                     var save_ids = safe_ids;
 
-                     safe_ids = Object.create(null);
 
-                     descend();
 
-                     safe_ids = save_ids;
 
-                     return true;
 
-                 }
 
-                 if (node instanceof AST_Function) {
 
-                     push();
 
-                     var iife;
 
-                     if (!node.name
 
-                         && (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; ...})()
 
-                         // So existing transformation rules can work on them.
 
-                         node.argnames.forEach(function(arg, i) {
 
-                             var d = arg.definition();
 
-                             if (!node.uses_arguments && d.fixed === undefined) {
 
-                                 d.fixed = function() {
 
-                                     return iife.args[i] || make_node(AST_Undefined, iife);
 
-                                 };
 
-                                 mark(d, true);
 
-                             } else {
 
-                                 d.fixed = false;
 
-                             }
 
-                         });
 
-                     }
 
-                     descend();
 
-                     pop();
 
-                     return true;
 
-                 }
 
-                 if (node instanceof AST_Accessor) {
 
-                     var save_ids = safe_ids;
 
-                     safe_ids = Object.create(null);
 
-                     descend();
 
-                     safe_ids = save_ids;
 
-                     return true;
 
-                 }
 
-                 if (node instanceof AST_Binary
 
-                     && (node.operator == "&&" || node.operator == "||")) {
 
-                     node.left.walk(tw);
 
-                     push();
 
-                     node.right.walk(tw);
 
-                     pop();
 
-                     return true;
 
-                 }
 
-                 if (node instanceof AST_Conditional) {
 
-                     node.condition.walk(tw);
 
-                     push();
 
-                     node.consequent.walk(tw);
 
-                     pop();
 
-                     push();
 
-                     node.alternative.walk(tw);
 
-                     pop();
 
-                     return true;
 
-                 }
 
-                 if (node instanceof AST_If || node instanceof AST_DWLoop) {
 
-                     node.condition.walk(tw);
 
-                     push();
 
-                     node.body.walk(tw);
 
-                     pop();
 
-                     if (node.alternative) {
 
-                         push();
 
-                         node.alternative.walk(tw);
 
-                         pop();
 
-                     }
 
-                     return true;
 
-                 }
 
-                 if (node instanceof AST_LabeledStatement) {
 
-                     push();
 
-                     node.body.walk(tw);
 
-                     pop();
 
-                     return true;
 
-                 }
 
-                 if (node instanceof AST_For) {
 
-                     if (node.init) node.init.walk(tw);
 
-                     push();
 
-                     if (node.condition) node.condition.walk(tw);
 
-                     node.body.walk(tw);
 
-                     if (node.step) node.step.walk(tw);
 
-                     pop();
 
-                     return true;
 
-                 }
 
-                 if (node instanceof AST_ForIn) {
 
-                     node.init.walk(suppressor);
 
-                     node.object.walk(tw);
 
-                     push();
 
-                     node.body.walk(tw);
 
-                     pop();
 
-                     return true;
 
-                 }
 
-                 if (node instanceof AST_Try) {
 
-                     push();
 
-                     walk_body(node, tw);
 
-                     pop();
 
-                     if (node.bcatch) {
 
-                         push();
 
-                         node.bcatch.walk(tw);
 
-                         pop();
 
-                     }
 
-                     if (node.bfinally) node.bfinally.walk(tw);
 
-                     return true;
 
-                 }
 
-                 if (node instanceof AST_SwitchBranch) {
 
-                     push();
 
-                     descend();
 
-                     pop();
 
-                     return true;
 
-                 }
 
-             }
 
-         });
 
-         this.walk(tw);
 
-         function mark(def, safe) {
 
-             safe_ids[def.id] = safe;
 
-         }
 
-         function is_safe(def) {
 
-             if (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);
 
-                 }
 
-                 return true;
 
-             }
 
-         }
 
-         function push() {
 
-             safe_ids = Object.create(safe_ids);
 
-         }
 
-         function pop() {
 
-             safe_ids = Object.getPrototypeOf(safe_ids);
 
-         }
 
-         function reset_def(def) {
 
-             def.escaped = false;
 
-             if (def.scope.uses_eval) {
 
-                 def.fixed = false;
 
-             } else if (toplevel || !def.global || def.orig[0] instanceof AST_SymbolConst) {
 
-                 def.fixed = undefined;
 
-             } else {
 
-                 def.fixed = false;
 
-             }
 
-             def.references = [];
 
-             def.should_replace = undefined;
 
-         }
 
-         function is_modified(node, level, func) {
 
-             var parent = tw.parent(level);
 
-             if (is_lhs(node, parent)
 
-                 || !func && parent instanceof AST_Call && parent.expression === node) {
 
-                 return true;
 
-             } else if (parent instanceof AST_PropAccess && parent.expression === node) {
 
-                 return !func && is_modified(parent, level + 1);
 
-             }
 
-         }
 
-     });
 
-     AST_SymbolRef.DEFMETHOD("fixed_value", function() {
 
-         var fixed = this.definition().fixed;
 
-         if (!fixed || fixed instanceof AST_Node) return fixed;
 
-         return fixed();
 
-     });
 
-     function is_reference_const(ref) {
 
-         if (!(ref instanceof AST_SymbolRef)) return false;
 
-         var orig = ref.definition().orig;
 
-         for (var i = orig.length; --i >= 0;) {
 
-             if (orig[i] instanceof AST_SymbolConst) return true;
 
-         }
 
-     }
 
-     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) {
 
-                 scope = scope.argname.definition().scope;
 
-                 break;
 
-             }
 
-         }
 
-         return scope.find_variable(name);
 
-     }
 
-     function make_node(ctor, orig, props) {
 
-         if (!props) props = {};
 
-         if (orig) {
 
-             if (!props.start) props.start = orig.start;
 
-             if (!props.end) props.end = orig.end;
 
-         }
 
-         return new ctor(props);
 
-     };
 
-     function make_node_from_constant(val, orig) {
 
-         switch (typeof val) {
 
-           case "string":
 
-             return make_node(AST_String, orig, {
 
-                 value: val
 
-             });
 
-           case "number":
 
-             if (isNaN(val)) return make_node(AST_NaN, orig);
 
-             if (isFinite(val)) {
 
-                 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 });
 
-             }
 
-             return val < 0 ? make_node(AST_UnaryPrefix, orig, {
 
-                 operator: "-",
 
-                 expression: make_node(AST_Infinity, orig)
 
-             }) : make_node(AST_Infinity, orig);
 
-           case "boolean":
 
-             return make_node(val ? AST_True : AST_False, orig);
 
-           case "undefined":
 
-             return make_node(AST_Undefined, orig);
 
-           default:
 
-             if (val === null) {
 
-                 return make_node(AST_Null, orig, { value: null });
 
-             }
 
-             if (val instanceof RegExp) {
 
-                 return make_node(AST_RegExp, orig, { value: val });
 
-             }
 
-             throw new Error(string_template("Can't handle constant of type: {type}", {
 
-                 type: typeof val
 
-             }));
 
-         }
 
-     };
 
-     // we shouldn't compress (1,func)(something) to
 
-     // func(something) because that changes the meaning of
 
-     // the func (becomes lexical instead of global).
 
-     function maintain_this_binding(parent, orig, val) {
 
-         if (parent instanceof AST_UnaryPrefix && parent.operator == "delete"
 
-             || parent instanceof AST_Call && parent.expression === orig
 
-                 && (val instanceof AST_PropAccess || val instanceof AST_SymbolRef && val.name == "eval")) {
 
-             return make_node(AST_Seq, orig, {
 
-                 car: make_node(AST_Number, orig, {
 
-                     value: 0
 
-                 }),
 
-                 cdr: val
 
-             });
 
-         }
 
-         return val;
 
-     }
 
-     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 ];
 
-         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;
 
-         return false;
 
-     };
 
-     function loop_body(x) {
 
-         if (x instanceof AST_Switch) return x;
 
-         if (x instanceof AST_For || x instanceof AST_ForIn || x instanceof AST_DWLoop) {
 
-             return (x.body instanceof AST_BlockStatement ? x.body : x);
 
-         }
 
-         return x;
 
-     };
 
-     function is_iife_call(node) {
 
-         if (node instanceof AST_Call && !(node instanceof AST_New)) {
 
-             return node.expression instanceof AST_Function || is_iife_call(node.expression);
 
-         }
 
-         return false;
 
-     }
 
-     function tighten_body(statements, compressor) {
 
-         var CHANGED, max_iter = 10;
 
-         do {
 
-             CHANGED = false;
 
-             if (compressor.option("angular")) {
 
-                 statements = process_for_angular(statements);
 
-             }
 
-             statements = eliminate_spurious_blocks(statements);
 
-             if (compressor.option("dead_code")) {
 
-                 statements = eliminate_dead_code(statements, compressor);
 
-             }
 
-             if (compressor.option("if_return")) {
 
-                 statements = handle_if_return(statements, compressor);
 
-             }
 
-             if (compressor.sequences_limit > 0) {
 
-                 statements = sequencesize(statements, compressor);
 
-             }
 
-             if (compressor.option("join_vars")) {
 
-                 statements = join_consecutive_vars(statements, compressor);
 
-             }
 
-             if (compressor.option("collapse_vars")) {
 
-                 statements = collapse_single_use_vars(statements, compressor);
 
-             }
 
-         } while (CHANGED && max_iter-- > 0);
 
-         return statements;
 
-         function collapse_single_use_vars(statements, compressor) {
 
-             // Iterate statements backwards looking for a statement with a var/const
 
-             // declaration immediately preceding it. Grab the rightmost var definition
 
-             // and if it has exactly one reference then attempt to replace its reference
 
-             // in the statement with the var value and then erase the var definition.
 
-             var self = compressor.self();
 
-             var var_defs_removed = false;
 
-             var toplevel = compressor.option("toplevel");
 
-             for (var stat_index = statements.length; --stat_index >= 0;) {
 
-                 var stat = statements[stat_index];
 
-                 if (stat instanceof AST_Definitions) continue;
 
-                 // Process child blocks of statement if present.
 
-                 [stat, stat.body, stat.alternative, stat.bcatch, stat.bfinally].forEach(function(node) {
 
-                     node && node.body && collapse_single_use_vars(node.body, compressor);
 
-                 });
 
-                 // The variable definition must precede a statement.
 
-                 if (stat_index <= 0) break;
 
-                 var prev_stat_index = stat_index - 1;
 
-                 var prev_stat = statements[prev_stat_index];
 
-                 if (!(prev_stat instanceof AST_Definitions)) continue;
 
-                 var var_defs = prev_stat.definitions;
 
-                 if (var_defs == null) continue;
 
-                 var var_names_seen = {};
 
-                 var side_effects_encountered = false;
 
-                 var lvalues_encountered = false;
 
-                 var lvalues = {};
 
-                 // Scan variable definitions from right to left.
 
-                 for (var var_defs_index = var_defs.length; --var_defs_index >= 0;) {
 
-                     // Obtain var declaration and var name with basic sanity check.
 
-                     var var_decl = var_defs[var_defs_index];
 
-                     if (var_decl.value == null) break;
 
-                     var var_name = var_decl.name.name;
 
-                     if (!var_name || !var_name.length) break;
 
-                     // Bail if we've seen a var definition of same name before.
 
-                     if (var_name in var_names_seen) break;
 
-                     var_names_seen[var_name] = true;
 
-                     // Only interested in cases with just one reference to the variable.
 
-                     var def = self.find_variable && self.find_variable(var_name);
 
-                     if (!def || !def.references || def.references.length !== 1
 
-                         || var_name == "arguments" || (!toplevel && def.global)) {
 
-                         side_effects_encountered = true;
 
-                         continue;
 
-                     }
 
-                     var ref = def.references[0];
 
-                     // Don't replace ref if eval() or with statement in scope.
 
-                     if (ref.scope.uses_eval || ref.scope.uses_with) break;
 
-                     // Constant single use vars can be replaced in any scope.
 
-                     if (var_decl.value.is_constant()) {
 
-                         var ctt = new TreeTransformer(function(node) {
 
-                             var parent = ctt.parent();
 
-                             if (parent instanceof AST_IterationStatement
 
-                                 && (parent.condition === node || parent.init === node)) {
 
-                                 return node;
 
-                             }
 
-                             if (node === ref)
 
-                                 return replace_var(node, parent, true);
 
-                         });
 
-                         stat.transform(ctt);
 
-                         continue;
 
-                     }
 
-                     // Restrict var replacement to constants if side effects encountered.
 
-                     if (side_effects_encountered |= lvalues_encountered) continue;
 
-                     var value_has_side_effects = var_decl.value.has_side_effects(compressor);
 
-                     // Non-constant single use vars can only be replaced in same scope.
 
-                     if (ref.scope !== self) {
 
-                         side_effects_encountered |= value_has_side_effects;
 
-                         continue;
 
-                     }
 
-                     // Detect lvalues in var value.
 
-                     var tw = new TreeWalker(function(node){
 
-                         if (node instanceof AST_SymbolRef && is_lvalue(node, tw.parent())) {
 
-                             lvalues[node.name] = lvalues_encountered = true;
 
-                         }
 
-                     });
 
-                     var_decl.value.walk(tw);
 
-                     // Replace the non-constant single use var in statement if side effect free.
 
-                     var unwind = false;
 
-                     var tt = new TreeTransformer(
 
-                         function preorder(node) {
 
-                             if (unwind) return node;
 
-                             var parent = tt.parent();
 
-                             if (node instanceof AST_Lambda
 
-                                 || node instanceof AST_Try
 
-                                 || node instanceof AST_With
 
-                                 || node instanceof AST_Case
 
-                                 || node instanceof AST_IterationStatement
 
-                                 || (parent instanceof AST_If          && node !== parent.condition)
 
-                                 || (parent instanceof AST_Conditional && node !== parent.condition)
 
-                                 || (node instanceof AST_SymbolRef
 
-                                     && value_has_side_effects
 
-                                     && !are_references_in_scope(node.definition(), self))
 
-                                 || (parent instanceof AST_Binary
 
-                                     && (parent.operator == "&&" || parent.operator == "||")
 
-                                     && node === parent.right)
 
-                                 || (parent instanceof AST_Switch && node !== parent.expression)) {
 
-                                 return side_effects_encountered = unwind = true, node;
 
-                             }
 
-                             function are_references_in_scope(def, scope) {
 
-                                 if (def.orig.length === 1
 
-                                     && def.orig[0] instanceof AST_SymbolDefun) return true;
 
-                                 if (def.scope !== scope) return false;
 
-                                 var refs = def.references;
 
-                                 for (var i = 0, len = refs.length; i < len; i++) {
 
-                                     if (refs[i].scope !== scope) return false;
 
-                                 }
 
-                                 return true;
 
-                             }
 
-                         },
 
-                         function postorder(node) {
 
-                             if (unwind) return node;
 
-                             if (node === ref)
 
-                                 return unwind = true, replace_var(node, tt.parent(), false);
 
-                             if (side_effects_encountered |= node.has_side_effects(compressor))
 
-                                 return unwind = true, node;
 
-                             if (lvalues_encountered && node instanceof AST_SymbolRef && node.name in lvalues) {
 
-                                 side_effects_encountered = true;
 
-                                 return unwind = true, node;
 
-                             }
 
-                         }
 
-                     );
 
-                     stat.transform(tt);
 
-                 }
 
-             }
 
-             // Remove extraneous empty statments in block after removing var definitions.
 
-             // Leave at least one statement in `statements`.
 
-             if (var_defs_removed) for (var i = statements.length; --i >= 0;) {
 
-                 if (statements.length > 1 && statements[i] instanceof AST_EmptyStatement)
 
-                     statements.splice(i, 1);
 
-             }
 
-             return statements;
 
-             function is_lvalue(node, parent) {
 
-                 return node instanceof AST_SymbolRef && is_lhs(node, parent);
 
-             }
 
-             function replace_var(node, parent, is_constant) {
 
-                 if (is_lvalue(node, parent)) return node;
 
-                 // Remove var definition and return its value to the TreeTransformer to replace.
 
-                 var value = maintain_this_binding(parent, node, var_decl.value);
 
-                 var_decl.value = null;
 
-                 var_defs.splice(var_defs_index, 1);
 
-                 if (var_defs.length === 0) {
 
-                     statements[prev_stat_index] = make_node(AST_EmptyStatement, self);
 
-                     var_defs_removed = true;
 
-                 }
 
-                 // Further optimize statement after substitution.
 
-                 stat.reset_opt_flags(compressor);
 
-                 compressor.info("Collapsing " + (is_constant ? "constant" : "variable") +
 
-                     " " + var_name + " [{file}:{line},{col}]", node.start);
 
-                 CHANGED = true;
 
-                 return value;
 
-             }
 
-         }
 
-         function process_for_angular(statements) {
 
-             function has_inject(comment) {
 
-                 return /@ngInject/.test(comment.value);
 
-             }
 
-             function make_arguments_names_list(func) {
 
-                 return func.argnames.map(function(sym){
 
-                     return make_node(AST_String, sym, { value: sym.name });
 
-                 });
 
-             }
 
-             function make_array(orig, elements) {
 
-                 return make_node(AST_Array, orig, { elements: elements });
 
-             }
 
-             function make_injector(func, name) {
 
-                 return make_node(AST_SimpleStatement, func, {
 
-                     body: make_node(AST_Assign, func, {
 
-                         operator: "=",
 
-                         left: make_node(AST_Dot, name, {
 
-                             expression: make_node(AST_SymbolRef, name, name),
 
-                             property: "$inject"
 
-                         }),
 
-                         right: make_array(func, make_arguments_names_list(func))
 
-                     })
 
-                 });
 
-             }
 
-             function check_expression(body) {
 
-                 if (body && body.args) {
 
-                     // if this is a function call check all of arguments passed
 
-                     body.args.forEach(function(argument, index, array) {
 
-                         var comments = argument.start.comments_before;
 
-                         // if the argument is function preceded by @ngInject
 
-                         if (argument instanceof AST_Lambda && comments.length && has_inject(comments[0])) {
 
-                             // replace the function with an array of names of its parameters and function at the end
 
-                             array[index] = make_array(argument, make_arguments_names_list(argument).concat(argument));
 
-                         }
 
-                     });
 
-                     // if this is chained call check previous one recursively
 
-                     if (body.expression && body.expression.expression) {
 
-                         check_expression(body.expression.expression);
 
-                     }
 
-                 }
 
-             }
 
-             return statements.reduce(function(a, stat){
 
-                 a.push(stat);
 
-                 if (stat.body && stat.body.args) {
 
-                     check_expression(stat.body);
 
-                 } else {
 
-                     var token = stat.start;
 
-                     var comments = token.comments_before;
 
-                     if (comments && comments.length > 0) {
 
-                         var last = comments.pop();
 
-                         if (has_inject(last)) {
 
-                             // case 1: defun
 
-                             if (stat instanceof AST_Defun) {
 
-                                 a.push(make_injector(stat, stat.name));
 
-                             }
 
-                             else if (stat instanceof AST_Definitions) {
 
-                                 stat.definitions.forEach(function(def) {
 
-                                     if (def.value && def.value instanceof AST_Lambda) {
 
-                                         a.push(make_injector(def.value, def.name));
 
-                                     }
 
-                                 });
 
-                             }
 
-                             else {
 
-                                 compressor.warn("Unknown statement marked with @ngInject [{file}:{line},{col}]", token);
 
-                             }
 
-                         }
 
-                     }
 
-                 }
 
-                 return a;
 
-             }, []);
 
-         }
 
-         function eliminate_spurious_blocks(statements) {
 
-             var seen_dirs = [];
 
-             return statements.reduce(function(a, stat){
 
-                 if (stat instanceof AST_BlockStatement) {
 
-                     CHANGED = true;
 
-                     a.push.apply(a, eliminate_spurious_blocks(stat.body));
 
-                 } else if (stat instanceof AST_EmptyStatement) {
 
-                     CHANGED = true;
 
-                 } else if (stat instanceof AST_Directive) {
 
-                     if (seen_dirs.indexOf(stat.value) < 0) {
 
-                         a.push(stat);
 
-                         seen_dirs.push(stat.value);
 
-                     } else {
 
-                         CHANGED = true;
 
-                     }
 
-                 } else {
 
-                     a.push(stat);
 
-                 }
 
-                 return a;
 
-             }, []);
 
-         };
 
-         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 ret = []; // Optimized statements, build from tail to front
 
-             loop: for (var i = statements.length; --i >= 0;) {
 
-                 var stat = statements[i];
 
-                 switch (true) {
 
-                   case (in_lambda && stat instanceof AST_Return && !stat.value && ret.length == 0):
 
-                     CHANGED = true;
 
-                     // note, ret.length is probably always zero
 
-                     // because we drop unreachable code before this
 
-                     // step.  nevertheless, it's good to check.
 
-                     continue loop;
 
-                   case stat instanceof AST_If:
 
-                     if (stat.body instanceof AST_Return) {
 
-                         //---
 
-                         // pretty silly case, but:
 
-                         // if (foo()) return; return; ==> foo(); return;
 
-                         if (((in_lambda && ret.length == 0)
 
-                              || (ret[0] instanceof AST_Return && !ret[0].value))
 
-                             && !stat.body.value && !stat.alternative) {
 
-                             CHANGED = true;
 
-                             var cond = make_node(AST_SimpleStatement, stat.condition, {
 
-                                 body: stat.condition
 
-                             });
 
-                             ret.unshift(cond);
 
-                             continue loop;
 
-                         }
 
-                         //---
 
-                         // if (foo()) return x; return y; ==> return foo() ? x : y;
 
-                         if (ret[0] instanceof AST_Return && stat.body.value && ret[0].value && !stat.alternative) {
 
-                             CHANGED = true;
 
-                             stat = stat.clone();
 
-                             stat.alternative = ret[0];
 
-                             ret[0] = stat.transform(compressor);
 
-                             continue loop;
 
-                         }
 
-                         //---
 
-                         // if (foo()) return x; [ return ; ] ==> return foo() ? x : undefined;
 
-                         if (multiple_if_returns && (ret.length == 0 || ret[0] instanceof AST_Return)
 
-                             && stat.body.value && !stat.alternative && in_lambda) {
 
-                             CHANGED = true;
 
-                             stat = stat.clone();
 
-                             stat.alternative = ret[0] || make_node(AST_Return, stat, {
 
-                                 value: null
 
-                             });
 
-                             ret[0] = stat.transform(compressor);
 
-                             continue loop;
 
-                         }
 
-                         //---
 
-                         // if (foo()) return; [ else x... ]; y... ==> if (!foo()) { x...; y... }
 
-                         if (!stat.body.value && in_lambda) {
 
-                             CHANGED = true;
 
-                             stat = stat.clone();
 
-                             stat.condition = stat.condition.negate(compressor);
 
-                             var body = as_statement_array(stat.alternative).concat(ret);
 
-                             var funs = extract_functions_from_statement_array(body);
 
-                             stat.body = make_node(AST_BlockStatement, stat, {
 
-                                 body: body
 
-                             });
 
-                             stat.alternative = null;
 
-                             ret = funs.concat([ stat.transform(compressor) ]);
 
-                             continue loop;
 
-                         }
 
-                         //---
 
-                         // if (a) return b; if (c) return d; e; ==> return a ? b : c ? d : void e;
 
-                         //
 
-                         // if sequences is not enabled, this can lead to an endless loop (issue #866).
 
-                         // however, with sequences on this helps producing slightly better output for
 
-                         // the example code.
 
-                         if (compressor.option("sequences")
 
-                             && i > 0 && statements[i - 1] instanceof AST_If && statements[i - 1].body instanceof AST_Return
 
-                             && ret.length == 1 && in_lambda && ret[0] instanceof AST_SimpleStatement
 
-                             && !stat.alternative) {
 
-                             CHANGED = true;
 
-                             ret.push(make_node(AST_Return, ret[0], {
 
-                                 value: null
 
-                             }).transform(compressor));
 
-                             ret.unshift(stat);
 
-                             continue loop;
 
-                         }
 
-                     }
 
-                     var ab = aborts(stat.body);
 
-                     var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab) : null;
 
-                     if (ab && ((ab instanceof AST_Return && !ab.value && in_lambda)
 
-                                || (ab instanceof AST_Continue && self === loop_body(lct))
 
-                                || (ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct))) {
 
-                         if (ab.label) {
 
-                             remove(ab.label.thedef.references, ab);
 
-                         }
 
-                         CHANGED = true;
 
-                         var body = as_statement_array(stat.body).slice(0, -1);
 
-                         stat = stat.clone();
 
-                         stat.condition = stat.condition.negate(compressor);
 
-                         stat.body = make_node(AST_BlockStatement, stat, {
 
-                             body: as_statement_array(stat.alternative).concat(ret)
 
-                         });
 
-                         stat.alternative = make_node(AST_BlockStatement, stat, {
 
-                             body: body
 
-                         });
 
-                         ret = [ stat.transform(compressor) ];
 
-                         continue loop;
 
-                     }
 
-                     var ab = aborts(stat.alternative);
 
-                     var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab) : null;
 
-                     if (ab && ((ab instanceof AST_Return && !ab.value && in_lambda)
 
-                                || (ab instanceof AST_Continue && self === loop_body(lct))
 
-                                || (ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct))) {
 
-                         if (ab.label) {
 
-                             remove(ab.label.thedef.references, ab);
 
-                         }
 
-                         CHANGED = true;
 
-                         stat = stat.clone();
 
-                         stat.body = make_node(AST_BlockStatement, stat.body, {
 
-                             body: as_statement_array(stat.body).concat(ret)
 
-                         });
 
-                         stat.alternative = make_node(AST_BlockStatement, stat.alternative, {
 
-                             body: as_statement_array(stat.alternative).slice(0, -1)
 
-                         });
 
-                         ret = [ stat.transform(compressor) ];
 
-                         continue loop;
 
-                     }
 
-                     ret.unshift(stat);
 
-                     break;
 
-                   default:
 
-                     ret.unshift(stat);
 
-                     break;
 
-                 }
 
-             }
 
-             return ret;
 
-             function has_multiple_if_returns(statements) {
 
-                 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 (++n > 1) return true;
 
-                     }
 
-                 }
 
-                 return false;
 
-             }
 
-         };
 
-         function eliminate_dead_code(statements, compressor) {
 
-             var has_quit = false;
 
-             var orig = statements.length;
 
-             var self = compressor.self();
 
-             statements = statements.reduce(function(a, stat){
 
-                 if (has_quit) {
 
-                     extract_declarations_from_unreachable_code(compressor, stat, a);
 
-                 } else {
 
-                     if (stat instanceof AST_LoopControl) {
 
-                         var lct = compressor.loopcontrol_target(stat);
 
-                         if ((stat instanceof AST_Break
 
-                              && !(lct instanceof AST_IterationStatement)
 
-                              && loop_body(lct) === self) || (stat instanceof AST_Continue
 
-                                                              && loop_body(lct) === self)) {
 
-                             if (stat.label) {
 
-                                 remove(stat.label.thedef.references, stat);
 
-                             }
 
-                         } else {
 
-                             a.push(stat);
 
-                         }
 
-                     } else {
 
-                         a.push(stat);
 
-                     }
 
-                     if (aborts(stat)) has_quit = true;
 
-                 }
 
-                 return a;
 
-             }, []);
 
-             CHANGED = statements.length != orig;
 
-             return statements;
 
-         };
 
-         function sequencesize(statements, compressor) {
 
-             if (statements.length < 2) return statements;
 
-             var seq = [], ret = [];
 
-             function push_seq() {
 
-                 seq = AST_Seq.from_array(seq);
 
-                 if (seq) ret.push(make_node(AST_SimpleStatement, seq, {
 
-                     body: seq
 
-                 }));
 
-                 seq = [];
 
-             };
 
-             statements.forEach(function(stat){
 
-                 if (stat instanceof AST_SimpleStatement) {
 
-                     if (seqLength(seq) >= compressor.sequences_limit) push_seq();
 
-                     var body = stat.body;
 
-                     if (seq.length > 0) body = body.drop_side_effect_free(compressor);
 
-                     if (body) seq.push(body);
 
-                 } else {
 
-                     push_seq();
 
-                     ret.push(stat);
 
-                 }
 
-             });
 
-             push_seq();
 
-             ret = sequencesize_2(ret, compressor);
 
-             CHANGED = ret.length != statements.length;
 
-             return ret;
 
-         };
 
-         function seqLength(a) {
 
-             for (var len = 0, i = 0; i < a.length; ++i) {
 
-                 var stat = a[i];
 
-                 if (stat instanceof AST_Seq) {
 
-                     len += stat.len();
 
-                 } else {
 
-                     len++;
 
-                 }
 
-             }
 
-             return len;
 
-         };
 
-         function sequencesize_2(statements, compressor) {
 
-             function cons_seq(right) {
 
-                 ret.pop();
 
-                 var left = prev.body;
 
-                 if (left instanceof AST_Seq) {
 
-                     left.add(right);
 
-                 } else {
 
-                     left = AST_Seq.cons(left, right);
 
-                 }
 
-                 return left.transform(compressor);
 
-             };
 
-             var ret = [], prev = null;
 
-             statements.forEach(function(stat){
 
-                 if (prev) {
 
-                     if (stat instanceof AST_For) {
 
-                         var opera = {};
 
-                         try {
 
-                             prev.body.walk(new TreeWalker(function(node){
 
-                                 if (node instanceof AST_Binary && node.operator == "in")
 
-                                     throw opera;
 
-                             }));
 
-                             if (stat.init && !(stat.init instanceof AST_Definitions)) {
 
-                                 stat.init = cons_seq(stat.init);
 
-                             }
 
-                             else if (!stat.init) {
 
-                                 stat.init = prev.body.drop_side_effect_free(compressor);
 
-                                 ret.pop();
 
-                             }
 
-                         } catch(ex) {
 
-                             if (ex !== opera) throw ex;
 
-                         }
 
-                     }
 
-                     else if (stat instanceof AST_If) {
 
-                         stat.condition = cons_seq(stat.condition);
 
-                     }
 
-                     else if (stat instanceof AST_With) {
 
-                         stat.expression = cons_seq(stat.expression);
 
-                     }
 
-                     else if (stat instanceof AST_Exit && stat.value) {
 
-                         stat.value = cons_seq(stat.value);
 
-                     }
 
-                     else if (stat instanceof AST_Exit) {
 
-                         stat.value = cons_seq(make_node(AST_Undefined, stat).transform(compressor));
 
-                     }
 
-                     else if (stat instanceof AST_Switch) {
 
-                         stat.expression = cons_seq(stat.expression);
 
-                     }
 
-                 }
 
-                 ret.push(stat);
 
-                 prev = stat instanceof AST_SimpleStatement ? stat : null;
 
-             });
 
-             return ret;
 
-         };
 
-         function join_consecutive_vars(statements, compressor) {
 
-             var prev = null;
 
-             return statements.reduce(function(a, stat){
 
-                 if (stat instanceof AST_Definitions && prev && prev.TYPE == stat.TYPE) {
 
-                     prev.definitions = prev.definitions.concat(stat.definitions);
 
-                     CHANGED = true;
 
-                 }
 
-                 else if (stat instanceof AST_For
 
-                          && prev instanceof AST_Var
 
-                          && (!stat.init || stat.init.TYPE == prev.TYPE)) {
 
-                     CHANGED = true;
 
-                     a.pop();
 
-                     if (stat.init) {
 
-                         stat.init.definitions = prev.definitions.concat(stat.init.definitions);
 
-                     } else {
 
-                         stat.init = prev;
 
-                     }
 
-                     a.push(stat);
 
-                     prev = stat;
 
-                 }
 
-                 else {
 
-                     prev = stat;
 
-                     a.push(stat);
 
-                 }
 
-                 return a;
 
-             }, []);
 
-         };
 
-     };
 
-     function extract_functions_from_statement_array(statements) {
 
-         var funs = [];
 
-         for (var i = statements.length - 1; i >= 0; --i) {
 
-             var stat = statements[i];
 
-             if (stat instanceof AST_Defun) {
 
-                 statements.splice(i, 1);
 
-                 funs.unshift(stat);
 
-             }
 
-         }
 
-         return funs;
 
-     }
 
-     function extract_declarations_from_unreachable_code(compressor, stat, target) {
 
-         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) {
 
-                 compressor.warn("Declarations in unreachable code! [{file}:{line},{col}]", node.start);
 
-                 node.remove_initializers();
 
-                 target.push(node);
 
-                 return true;
 
-             }
 
-             if (node instanceof AST_Defun) {
 
-                 target.push(node);
 
-                 return true;
 
-             }
 
-             if (node instanceof AST_Scope) {
 
-                 return true;
 
-             }
 
-         }));
 
-     };
 
-     function is_undefined(node, compressor) {
 
-         return node.is_undefined
 
-             || node instanceof AST_Undefined
 
-             || node instanceof AST_UnaryPrefix
 
-                 && node.operator == "void"
 
-                 && !node.expression.has_side_effects(compressor);
 
-     }
 
-     // may_throw_on_access()
 
-     // returns true if this node may be null, undefined or contain `AST_Accessor`
 
-     (function(def) {
 
-         AST_Node.DEFMETHOD("may_throw_on_access", function(compressor) {
 
-             var pure_getters = compressor.option("pure_getters");
 
-             return !pure_getters || this._throw_on_access(pure_getters);
 
-         });
 
-         function is_strict(pure_getters) {
 
-             return /strict/.test(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(pure_getters) {
 
-             if (!is_strict(pure_getters)) return false;
 
-             for (var i = this.properties.length; --i >=0;)
 
-                 if (this.properties[i].value instanceof AST_Accessor) return true;
 
-             return false;
 
-         });
 
-         def(AST_Function, return_false);
 
-         def(AST_UnaryPostfix, return_false);
 
-         def(AST_UnaryPrefix, function() {
 
-             return this.operator == "void";
 
-         });
 
-         def(AST_Binary, function(pure_getters) {
 
-             switch (this.operator) {
 
-               case "&&":
 
-                 return this.left._throw_on_access(pure_getters);
 
-               case "||":
 
-                 return this.left._throw_on_access(pure_getters)
 
-                     && this.right._throw_on_access(pure_getters);
 
-               default:
 
-                 return false;
 
-             }
 
-         })
 
-         def(AST_Assign, function(pure_getters) {
 
-             return this.operator == "="
 
-                 && this.right._throw_on_access(pure_getters);
 
-         })
 
-         def(AST_Conditional, function(pure_getters) {
 
-             return this.consequent._throw_on_access(pure_getters)
 
-                 || this.alternative._throw_on_access(pure_getters);
 
-         })
 
-         def(AST_Seq, function(pure_getters) {
 
-             return this.cdr._throw_on_access(pure_getters);
 
-         });
 
-         def(AST_SymbolRef, function(pure_getters) {
 
-             if (this.is_undefined) return true;
 
-             if (!is_strict(pure_getters)) return false;
 
-             var fixed = this.fixed_value();
 
-             return !fixed || fixed._throw_on_access(pure_getters);
 
-         });
 
-     })(function(node, func) {
 
-         node.DEFMETHOD("_throw_on_access", func);
 
-     });
 
-     /* -----[ boolean/negation helpers ]----- */
 
-     // methods to determine whether an expression has a boolean result type
 
-     (function (def){
 
-         var unary_bool = [ "!", "delete" ];
 
-         var binary_bool = [ "in", "instanceof", "==", "!=", "===", "!==", "<", "<=", ">=", ">" ];
 
-         def(AST_Node, return_false);
 
-         def(AST_UnaryPrefix, function(){
 
-             return member(this.operator, unary_bool);
 
-         });
 
-         def(AST_Binary, function(){
 
-             return member(this.operator, binary_bool) ||
 
-                 ( (this.operator == "&&" || this.operator == "||") &&
 
-                   this.left.is_boolean() && this.right.is_boolean() );
 
-         });
 
-         def(AST_Conditional, function(){
 
-             return this.consequent.is_boolean() && this.alternative.is_boolean();
 
-         });
 
-         def(AST_Assign, function(){
 
-             return this.operator == "=" && this.right.is_boolean();
 
-         });
 
-         def(AST_Seq, function(){
 
-             return this.cdr.is_boolean();
 
-         });
 
-         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);
 
-         var unary = makePredicate("+ - ~ ++ --");
 
-         def(AST_Unary, function(){
 
-             return unary(this.operator);
 
-         });
 
-         var binary = makePredicate("- * / % & | ^ << >> >>>");
 
-         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){
 
-             return binary(this.operator.slice(0, -1))
 
-                 || this.operator == "=" && this.right.is_number(compressor);
 
-         });
 
-         def(AST_Seq, function(compressor){
 
-             return this.cdr.is_number(compressor);
 
-         });
 
-         def(AST_Conditional, function(compressor){
 
-             return this.consequent.is_number(compressor) && this.alternative.is_number(compressor);
 
-         });
 
-     })(function(node, func){
 
-         node.DEFMETHOD("is_number", func);
 
-     });
 
-     // 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(){
 
-             return this.operator == "typeof";
 
-         });
 
-         def(AST_Binary, function(compressor){
 
-             return this.operator == "+" &&
 
-                 (this.left.is_string(compressor) || this.right.is_string(compressor));
 
-         });
 
-         def(AST_Assign, function(compressor){
 
-             return (this.operator == "=" || this.operator == "+=") && this.right.is_string(compressor);
 
-         });
 
-         def(AST_Seq, function(compressor){
 
-             return this.cdr.is_string(compressor);
 
-         });
 
-         def(AST_Conditional, function(compressor){
 
-             return this.consequent.is_string(compressor) && this.alternative.is_string(compressor);
 
-         });
 
-     })(function(node, func){
 
-         node.DEFMETHOD("is_string", func);
 
-     });
 
-     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;
 
-     }
 
-     (function (def){
 
-         AST_Node.DEFMETHOD("resolve_defines", function(compressor) {
 
-             if (!compressor.option("global_defs")) return;
 
-             var def = this._find_defs(compressor, "");
 
-             if (def) {
 
-                 var node, parent = this, level = 0;
 
-                 do {
 
-                     node = parent;
 
-                     parent = compressor.parent(level++);
 
-                 } 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 {
 
-                     return def;
 
-                 }
 
-             }
 
-         });
 
-         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, {
 
-                 elements: value.map(function(value) {
 
-                     return to_node(value, orig);
 
-                 })
 
-             });
 
-             if (value && typeof value == "object") {
 
-                 var props = [];
 
-                 for (var key in value) {
 
-                     props.push(make_node(AST_ObjectKeyVal, orig, {
 
-                         key: key,
 
-                         value: to_node(value[key], 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){
 
-             return this.expression._find_defs(compressor, "." + this.property + 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);
 
-                 node.walk(new TreeWalker(function(node) {
 
-                     if (node instanceof AST_SymbolRef) {
 
-                         node.scope = top;
 
-                         node.thedef = top.def_global(node);
 
-                     }
 
-                 }));
 
-                 return node;
 
-             }
 
-         });
 
-     })(function(node, func){
 
-         node.DEFMETHOD("_find_defs", func);
 
-     });
 
-     function best_of_expression(ast1, ast2) {
 
-         return ast1.print_to_string().length >
 
-             ast2.print_to_string().length
 
-             ? ast2 : ast1;
 
-     }
 
-     function best_of_statement(ast1, ast2) {
 
-         return best_of_expression(make_node(AST_SimpleStatement, ast1, {
 
-             body: ast1
 
-         }), make_node(AST_SimpleStatement, ast2, {
 
-             body: ast2
 
-         })).body;
 
-     }
 
-     function best_of(compressor, ast1, ast2) {
 
-         return (first_in_statement(compressor) ? best_of_statement : best_of_expression)(ast1, ast2);
 
-     }
 
-     // methods to evaluate a constant expression
 
-     (function (def){
 
-         // If the node has been successfully reduced to a constant,
 
-         // 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){
 
-             if (!compressor.option("evaluate")) return this;
 
-             try {
 
-                 var val = this._eval(compressor);
 
-                 return !val || val instanceof RegExp || typeof val != "object" ? val : this;
 
-             } catch(ex) {
 
-                 if (ex !== def) throw ex;
 
-                 return this;
 
-             }
 
-         });
 
-         var unaryPrefix = makePredicate("! ~ - + void");
 
-         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);
 
-             } else {
 
-                 return this instanceof AST_UnaryPrefix
 
-                     && this.expression instanceof AST_Constant
 
-                     && unaryPrefix(this.operator);
 
-             }
 
-         });
 
-         // Obtain the constant value of an expression already known to be constant.
 
-         // Result only valid iff this.is_constant() is true.
 
-         AST_Node.DEFMETHOD("constant_value", function(compressor){
 
-             // Accomodate when option evaluate=false.
 
-             if (this instanceof AST_Constant && !(this instanceof AST_RegExp)) {
 
-                 return this.value;
 
-             }
 
-             // Accomodate the common constant expressions !0 and -1 when option evaluate=false.
 
-             if (this instanceof AST_UnaryPrefix
 
-                 && this.expression instanceof AST_Constant) switch (this.operator) {
 
-               case "!":
 
-                 return !this.expression.value;
 
-               case "~":
 
-                 return ~this.expression.value;
 
-               case "-":
 
-                 return -this.expression.value;
 
-               case "+":
 
-                 return +this.expression.value;
 
-               default:
 
-                 throw new Error(string_template("Cannot evaluate unary expression {value}", {
 
-                     value: this.print_to_string()
 
-                 }));
 
-             }
 
-             var result = this.evaluate(compressor);
 
-             if (result !== this) {
 
-                 return result;
 
-             }
 
-             throw new Error(string_template("Cannot evaluate constant [{file}:{line},{col}]", this.start));
 
-         });
 
-         def(AST_Statement, function(){
 
-             throw new Error(string_template("Cannot evaluate a statement [{file}:{line},{col}]", this.start));
 
-         });
 
-         def(AST_Lambda, function(){
 
-             throw def;
 
-         });
 
-         function ev(node, compressor) {
 
-             if (!compressor) throw new Error("Compressor must be passed");
 
-             return node._eval(compressor);
 
-         };
 
-         def(AST_Node, function(){
 
-             throw def;          // not constant
 
-         });
 
-         def(AST_Constant, function(){
 
-             return this.getValue();
 
-         });
 
-         def(AST_Array, function(compressor){
 
-             if (compressor.option("unsafe")) {
 
-                 return this.elements.map(function(element) {
 
-                     return ev(element, compressor);
 
-                 });
 
-             }
 
-             throw def;
 
-         });
 
-         def(AST_Object, function(compressor){
 
-             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) {
 
-                         key = key.name;
 
-                     } else if (key instanceof AST_Node) {
 
-                         key = ev(key, compressor);
 
-                     }
 
-                     if (typeof Object.prototype[key] === 'function') {
 
-                         throw def;
 
-                     }
 
-                     val[key] = ev(prop.value, compressor);
 
-                 }
 
-                 return val;
 
-             }
 
-             throw def;
 
-         });
 
-         def(AST_UnaryPrefix, function(compressor){
 
-             var e = this.expression;
 
-             switch (this.operator) {
 
-               case "!": return !ev(e, compressor);
 
-               case "typeof":
 
-                 // Function would be evaluated to an array and so typeof would
 
-                 // incorrectly return 'object'. Hence making is a special case.
 
-                 if (e instanceof AST_Function) return typeof function(){};
 
-                 e = ev(e, compressor);
 
-                 // typeof <RegExp> returns "object" or "function" on different platforms
 
-                 // so cannot evaluate reliably
 
-                 if (e instanceof RegExp) throw def;
 
-                 return typeof e;
 
-               case "void": return void ev(e, compressor);
 
-               case "~": return ~ev(e, compressor);
 
-               case "-": return -ev(e, compressor);
 
-               case "+": return +ev(e, compressor);
 
-             }
 
-             throw def;
 
-         });
 
-         def(AST_Binary, function(c){
 
-             var left = this.left, right = this.right, result;
 
-             switch (this.operator) {
 
-               case "&&"  : result = ev(left, c) &&  ev(right, c); break;
 
-               case "||"  : result = ev(left, c) ||  ev(right, c); break;
 
-               case "|"   : result = ev(left, c) |   ev(right, c); break;
 
-               case "&"   : result = ev(left, c) &   ev(right, c); break;
 
-               case "^"   : result = ev(left, c) ^   ev(right, c); break;
 
-               case "+"   : result = ev(left, c) +   ev(right, c); break;
 
-               case "*"   : result = ev(left, c) *   ev(right, c); break;
 
-               case "/"   : result = ev(left, c) /   ev(right, c); break;
 
-               case "%"   : result = ev(left, c) %   ev(right, c); break;
 
-               case "-"   : result = ev(left, c) -   ev(right, c); break;
 
-               case "<<"  : result = ev(left, c) <<  ev(right, c); break;
 
-               case ">>"  : result = ev(left, c) >>  ev(right, c); break;
 
-               case ">>>" : result = ev(left, c) >>> ev(right, c); break;
 
-               case "=="  : result = ev(left, c) ==  ev(right, c); break;
 
-               case "===" : result = ev(left, c) === ev(right, c); break;
 
-               case "!="  : result = ev(left, c) !=  ev(right, c); break;
 
-               case "!==" : result = ev(left, c) !== ev(right, c); break;
 
-               case "<"   : result = ev(left, c) <   ev(right, c); break;
 
-               case "<="  : result = ev(left, c) <=  ev(right, c); break;
 
-               case ">"   : result = ev(left, c) >   ev(right, c); break;
 
-               case ">="  : result = ev(left, c) >=  ev(right, c); break;
 
-               default:
 
-                   throw def;
 
-             }
 
-             if (isNaN(result) && c.find_parent(AST_With)) {
 
-                 // leave original expression as is
 
-                 throw def;
 
-             }
 
-             return result;
 
-         });
 
-         def(AST_Conditional, function(compressor){
 
-             return ev(this.condition, compressor)
 
-                 ? ev(this.consequent, compressor)
 
-                 : ev(this.alternative, compressor);
 
-         });
 
-         def(AST_SymbolRef, function(compressor){
 
-             if (!compressor.option("reduce_vars") || this._evaluating) throw def;
 
-             this._evaluating = true;
 
-             try {
 
-                 var fixed = this.fixed_value();
 
-                 if (!fixed) throw def;
 
-                 var value = ev(fixed, compressor);
 
-                 if (!HOP(fixed, "_eval")) fixed._eval = function() {
 
-                     return value;
 
-                 };
 
-                 if (value && typeof value == "object" && this.definition().escaped) throw def;
 
-                 return value;
 
-             } finally {
 
-                 this._evaluating = false;
 
-             }
 
-         });
 
-         def(AST_PropAccess, function(compressor){
 
-             if (compressor.option("unsafe")) {
 
-                 var key = this.property;
 
-                 if (key instanceof AST_Node) {
 
-                     key = ev(key, compressor);
 
-                 }
 
-                 var val = ev(this.expression, compressor);
 
-                 if (val && HOP(val, key)) {
 
-                     return val[key];
 
-                 }
 
-             }
 
-             throw def;
 
-         });
 
-     })(function(node, func){
 
-         node.DEFMETHOD("_eval", func);
 
-     });
 
-     // method to negate an expression
 
-     (function(def){
 
-         function basic_negation(exp) {
 
-             return make_node(AST_UnaryPrefix, exp, {
 
-                 operator: "!",
 
-                 expression: exp
 
-             });
 
-         }
 
-         function best(orig, alt, first_in_statement) {
 
-             var negated = basic_negation(orig);
 
-             if (first_in_statement) {
 
-                 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(){
 
-             return basic_negation(this);
 
-         });
 
-         def(AST_Statement, function(){
 
-             throw new Error("Cannot negate a statement");
 
-         });
 
-         def(AST_Function, function(){
 
-             return basic_negation(this);
 
-         });
 
-         def(AST_UnaryPrefix, function(){
 
-             if (this.operator == "!")
 
-                 return this.expression;
 
-             return basic_negation(this);
 
-         });
 
-         def(AST_Seq, function(compressor){
 
-             var self = this.clone();
 
-             self.cdr = self.cdr.negate(compressor);
 
-             return self;
 
-         });
 
-         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){
 
-             var self = this.clone(), op = this.operator;
 
-             if (compressor.option("unsafe_comps")) {
 
-                 switch (op) {
 
-                   case "<=" : self.operator = ">"  ; return self;
 
-                   case "<"  : self.operator = ">=" ; return self;
 
-                   case ">=" : self.operator = "<"  ; return self;
 
-                   case ">"  : self.operator = "<=" ; return self;
 
-                 }
 
-             }
 
-             switch (op) {
 
-               case "==" : self.operator = "!="; return self;
 
-               case "!=" : self.operator = "=="; return self;
 
-               case "===": self.operator = "!=="; return self;
 
-               case "!==": self.operator = "==="; return self;
 
-               case "&&":
 
-                 self.operator = "||";
 
-                 self.left = self.left.negate(compressor, first_in_statement);
 
-                 self.right = self.right.negate(compressor);
 
-                 return best(this, self, first_in_statement);
 
-               case "||":
 
-                 self.operator = "&&";
 
-                 self.left = self.left.negate(compressor, first_in_statement);
 
-                 self.right = self.right.negate(compressor);
 
-                 return best(this, self, first_in_statement);
 
-             }
 
-             return basic_negation(this);
 
-         });
 
-     })(function(node, func){
 
-         node.DEFMETHOD("negate", function(compressor, first_in_statement){
 
-             return func.call(this, compressor, first_in_statement);
 
-         });
 
-     });
 
-     AST_Call.DEFMETHOD("has_pure_annotation", function(compressor) {
 
-         if (!compressor.option("side_effects")) return false;
 
-         if (this.pure !== undefined) return this.pure;
 
-         var pure = false;
 
-         var comments, last_comment;
 
-         if (this.start
 
-             && (comments = this.start.comments_before)
 
-             && comments.length
 
-             && /[@#]__PURE__/.test((last_comment = comments[comments.length - 1]).value)) {
 
-             pure = last_comment;
 
-         }
 
-         return this.pure = pure;
 
-     });
 
-     // determine if expression has side effects
 
-     (function(def){
 
-         def(AST_Node, return_true);
 
-         def(AST_EmptyStatement, return_false);
 
-         def(AST_Constant, return_false);
 
-         def(AST_This, return_false);
 
-         def(AST_Call, function(compressor){
 
-             if (!this.has_pure_annotation(compressor) && compressor.pure_funcs(this)) return true;
 
-             for (var i = this.args.length; --i >= 0;) {
 
-                 if (this.args[i].has_side_effects(compressor))
 
-                     return true;
 
-             }
 
-             return false;
 
-         });
 
-         function any(list, compressor) {
 
-             for (var i = list.length; --i >= 0;)
 
-                 if (list[i].has_side_effects(compressor))
 
-                     return true;
 
-             return false;
 
-         }
 
-         def(AST_Block, function(compressor){
 
-             return any(this.body, compressor);
 
-         });
 
-         def(AST_Switch, function(compressor){
 
-             return this.expression.has_side_effects(compressor)
 
-                 || any(this.body, compressor);
 
-         });
 
-         def(AST_Case, function(compressor){
 
-             return this.expression.has_side_effects(compressor)
 
-                 || any(this.body, 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){
 
-             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){
 
-             return this.body.has_side_effects(compressor);
 
-         });
 
-         def(AST_SimpleStatement, function(compressor){
 
-             return this.body.has_side_effects(compressor);
 
-         });
 
-         def(AST_Defun, return_true);
 
-         def(AST_Function, 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){
 
-             return this.condition.has_side_effects(compressor)
 
-                 || this.consequent.has_side_effects(compressor)
 
-                 || this.alternative.has_side_effects(compressor);
 
-         });
 
-         def(AST_Unary, function(compressor){
 
-             return unary_side_effects(this.operator)
 
-                 || this.expression.has_side_effects(compressor);
 
-         });
 
-         def(AST_SymbolRef, function(compressor){
 
-             return this.undeclared();
 
-         });
 
-         def(AST_Object, function(compressor){
 
-             return any(this.properties, compressor);
 
-         });
 
-         def(AST_ObjectProperty, function(compressor){
 
-             return this.value.has_side_effects(compressor);
 
-         });
 
-         def(AST_Array, function(compressor){
 
-             return any(this.elements, 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){
 
-             return this.expression.may_throw_on_access(compressor)
 
-                 || this.expression.has_side_effects(compressor)
 
-                 || this.property.has_side_effects(compressor);
 
-         });
 
-         def(AST_Seq, function(compressor){
 
-             return this.car.has_side_effects(compressor)
 
-                 || this.cdr.has_side_effects(compressor);
 
-         });
 
-     })(function(node, func){
 
-         node.DEFMETHOD("has_side_effects", func);
 
-     });
 
-     // tell me if a statement aborts
 
-     function aborts(thing) {
 
-         return thing && thing.aborts();
 
-     };
 
-     (function(def){
 
-         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(){
 
-             return this.alternative && aborts(this.body) && aborts(this.alternative) && this;
 
-         });
 
-     })(function(node, func){
 
-         node.DEFMETHOD("aborts", func);
 
-     });
 
-     /* -----[ optimizers ]----- */
 
-     OPT(AST_Directive, function(self, compressor){
 
-         if (compressor.has_directive(self.value) !== self) {
 
-             return make_node(AST_EmptyStatement, self);
 
-         }
 
-         return self;
 
-     });
 
-     OPT(AST_Debugger, function(self, compressor){
 
-         if (compressor.option("drop_debugger"))
 
-             return make_node(AST_EmptyStatement, self);
 
-         return self;
 
-     });
 
-     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 self.label.references.length == 0 ? self.body : self;
 
-     });
 
-     OPT(AST_Block, function(self, compressor){
 
-         self.body = tighten_body(self.body, compressor);
 
-         return self;
 
-     });
 
-     OPT(AST_BlockStatement, function(self, compressor){
 
-         self.body = tighten_body(self.body, compressor);
 
-         switch (self.body.length) {
 
-           case 1: return self.body[0];
 
-           case 0: return make_node(AST_EmptyStatement, self);
 
-         }
 
-         return self;
 
-     });
 
-     AST_Scope.DEFMETHOD("drop_unused", function(compressor){
 
-         var self = this;
 
-         if (compressor.has_directive("use asm")) return self;
 
-         var toplevel = compressor.option("toplevel");
 
-         if (compressor.option("unused")
 
-             && (!(self instanceof AST_Toplevel) || toplevel)
 
-             && !self.uses_eval
 
-             && !self.uses_with) {
 
-             var assign_as_unused = !/keep_assign/.test(compressor.option("unused"));
 
-             var drop_funcs = /funcs/.test(toplevel);
 
-             var drop_vars = /vars/.test(toplevel);
 
-             if (!(self instanceof AST_Toplevel) || toplevel == true) {
 
-                 drop_funcs = drop_vars = true;
 
-             }
 
-             var in_use = [];
 
-             var in_use_ids = Object.create(null); // avoid expensive linear scans of in_use
 
-             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;
 
-                         in_use.push(def);
 
-                     }
 
-                 });
 
-             }
 
-             var initializations = new Dictionary();
 
-             // pass 1: find out which symbols are directly used in
 
-             // this scope (not in nested scopes).
 
-             var scope = this;
 
-             var tw = new TreeWalker(function(node, descend){
 
-                 if (node !== self) {
 
-                     if (node instanceof AST_Defun) {
 
-                         if (!drop_funcs && scope === self) {
 
-                             var node_def = node.name.definition();
 
-                             if (!(node_def.id in in_use_ids)) {
 
-                                 in_use_ids[node_def.id] = true;
 
-                                 in_use.push(node_def);
 
-                             }
 
-                         }
 
-                         initializations.add(node.name.name, node);
 
-                         return true; // don't go in nested scopes
 
-                     }
 
-                     if (node instanceof AST_Definitions && scope === self) {
 
-                         node.definitions.forEach(function(def){
 
-                             if (!drop_vars) {
 
-                                 var node_def = def.name.definition();
 
-                                 if (!(node_def.id in in_use_ids)) {
 
-                                     in_use_ids[node_def.id] = true;
 
-                                     in_use.push(node_def);
 
-                                 }
 
-                             }
 
-                             if (def.value) {
 
-                                 initializations.add(def.name.name, def.value);
 
-                                 if (def.value.has_side_effects(compressor)) {
 
-                                     def.value.walk(tw);
 
-                                 }
 
-                             }
 
-                         });
 
-                         return true;
 
-                     }
 
-                     if (assign_as_unused
 
-                         && node instanceof AST_Assign
 
-                         && node.operator == "="
 
-                         && node.left instanceof AST_SymbolRef
 
-                         && !is_reference_const(node.left)
 
-                         && scope === self) {
 
-                         node.right.walk(tw);
 
-                         return true;
 
-                     }
 
-                     if (node instanceof AST_SymbolRef) {
 
-                         var node_def = node.definition();
 
-                         if (!(node_def.id in in_use_ids)) {
 
-                             in_use_ids[node_def.id] = true;
 
-                             in_use.push(node_def);
 
-                         }
 
-                         return true;
 
-                     }
 
-                     if (node instanceof AST_Scope) {
 
-                         var save_scope = scope;
 
-                         scope = node;
 
-                         descend();
 
-                         scope = save_scope;
 
-                         return true;
 
-                     }
 
-                 }
 
-             });
 
-             self.walk(tw);
 
-             // pass 2: for every used symbol we need to walk its
 
-             // initialization code to figure out if it uses other
 
-             // symbols (that may not be in_use).
 
-             for (var i = 0; i < in_use.length; ++i) {
 
-                 in_use[i].orig.forEach(function(decl){
 
-                     // undeclared globals will be instanceof AST_SymbolRef
 
-                     var init = initializations.get(decl.name);
 
-                     if (init) init.forEach(function(init){
 
-                         var tw = new TreeWalker(function(node){
 
-                             if (node instanceof AST_SymbolRef) {
 
-                                 var node_def = node.definition();
 
-                                 if (!(node_def.id in in_use_ids)) {
 
-                                     in_use_ids[node_def.id] = true;
 
-                                     in_use.push(node_def);
 
-                                 }
 
-                             }
 
-                         });
 
-                         init.walk(tw);
 
-                     });
 
-                 });
 
-             }
 
-             // pass 3: we should drop declarations not in_use
 
-             var tt = new TreeTransformer(
 
-                 function before(node, descend, in_list) {
 
-                     if (node instanceof AST_Function
 
-                         && node.name
 
-                         && !compressor.option("keep_fnames")) {
 
-                         var def = node.name.definition();
 
-                         // any declarations with same name will overshadow
 
-                         // name of this anonymous function and can therefore
 
-                         // never be used anywhere
 
-                         if (!(def.id in in_use_ids) || def.orig.length > 1)
 
-                             node.name = null;
 
-                     }
 
-                     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];
 
-                             if (!(sym.definition().id in in_use_ids)) {
 
-                                 sym.__unused = true;
 
-                                 if (trim) {
 
-                                     a.pop();
 
-                                     compressor[sym.unreferenced() ? "warn" : "info"]("Dropping unused function argument {name} [{file}:{line},{col}]", {
 
-                                         name : sym.name,
 
-                                         file : sym.start.file,
 
-                                         line : sym.start.line,
 
-                                         col  : sym.start.col
 
-                                     });
 
-                                 }
 
-                             }
 
-                             else {
 
-                                 trim = false;
 
-                             }
 
-                         }
 
-                     }
 
-                     if (drop_funcs && node instanceof AST_Defun && node !== self) {
 
-                         if (!(node.name.definition().id in in_use_ids)) {
 
-                             compressor[node.name.unreferenced() ? "warn" : "info"]("Dropping unused function {name} [{file}:{line},{col}]", {
 
-                                 name : node.name.name,
 
-                                 file : node.name.start.file,
 
-                                 line : node.name.start.line,
 
-                                 col  : node.name.start.col
 
-                             });
 
-                             return make_node(AST_EmptyStatement, node);
 
-                         }
 
-                         return node;
 
-                     }
 
-                     if (drop_vars && node instanceof AST_Definitions && !(tt.parent() instanceof AST_ForIn && tt.parent().init === node)) {
 
-                         var def = node.definitions.filter(function(def){
 
-                             if (def.value) def.value = def.value.transform(tt);
 
-                             var sym = def.name.definition();
 
-                             if (sym.id in in_use_ids) return true;
 
-                             if (sym.orig[0] instanceof AST_SymbolCatch) {
 
-                                 def.value = def.value && def.value.drop_side_effect_free(compressor);
 
-                                 return true;
 
-                             }
 
-                             var w = {
 
-                                 name : def.name.name,
 
-                                 file : def.name.start.file,
 
-                                 line : def.name.start.line,
 
-                                 col  : def.name.start.col
 
-                             };
 
-                             if (def.value && (def._unused_side_effects = def.value.drop_side_effect_free(compressor))) {
 
-                                 compressor.warn("Side effects in initialization of unused variable {name} [{file}:{line},{col}]", w);
 
-                                 return true;
 
-                             }
 
-                             compressor[def.name.unreferenced() ? "warn" : "info"]("Dropping unused variable {name} [{file}:{line},{col}]", w);
 
-                             return false;
 
-                         });
 
-                         // place uninitialized names at the start
 
-                         def = mergeSort(def, function(a, b){
 
-                             if (!a.value && b.value) return -1;
 
-                             if (!b.value && a.value) return 1;
 
-                             return 0;
 
-                         });
 
-                         // for unused names whose initialization has
 
-                         // side effects, we can cascade the init. code
 
-                         // into the next one, or next statement.
 
-                         var side_effects = [];
 
-                         for (var i = 0; i < def.length;) {
 
-                             var x = def[i];
 
-                             if (x._unused_side_effects) {
 
-                                 side_effects.push(x._unused_side_effects);
 
-                                 def.splice(i, 1);
 
-                             } else {
 
-                                 if (side_effects.length > 0) {
 
-                                     side_effects.push(x.value);
 
-                                     x.value = AST_Seq.from_array(side_effects);
 
-                                     side_effects = [];
 
-                                 }
 
-                                 ++i;
 
-                             }
 
-                         }
 
-                         if (side_effects.length > 0) {
 
-                             side_effects = make_node(AST_BlockStatement, node, {
 
-                                 body: [ make_node(AST_SimpleStatement, node, {
 
-                                     body: AST_Seq.from_array(side_effects)
 
-                                 }) ]
 
-                             });
 
-                         } else {
 
-                             side_effects = null;
 
-                         }
 
-                         if (def.length == 0 && !side_effects) {
 
-                             return make_node(AST_EmptyStatement, node);
 
-                         }
 
-                         if (def.length == 0) {
 
-                             return in_list ? MAP.splice(side_effects.body) : side_effects;
 
-                         }
 
-                         node.definitions = def;
 
-                         if (side_effects) {
 
-                             side_effects.body.unshift(node);
 
-                             return in_list ? MAP.splice(side_effects.body) : side_effects;
 
-                         }
 
-                         return node;
 
-                     }
 
-                     if (drop_vars && assign_as_unused
 
-                         && node instanceof AST_Assign
 
-                         && node.operator == "="
 
-                         && node.left instanceof AST_SymbolRef) {
 
-                         var def = node.left.definition();
 
-                         if (!(def.id in in_use_ids)
 
-                             && self.variables.get(def.name) === def) {
 
-                             return maintain_this_binding(tt.parent(), node, node.right.transform(tt));
 
-                         }
 
-                     }
 
-                     // certain combination of unused name + side effect leads to:
 
-                     //    https://github.com/mishoo/UglifyJS2/issues/44
 
-                     //    https://github.com/mishoo/UglifyJS2/issues/1830
 
-                     // that's an invalid AST.
 
-                     // We fix it at this stage by moving the `var` outside the `for`.
 
-                     if (node instanceof AST_For) {
 
-                         descend(node, this);
 
-                         if (node.init instanceof AST_BlockStatement) {
 
-                             var block = node.init;
 
-                             node.init = block.body.pop();
 
-                             block.body.push(node);
 
-                             return in_list ? MAP.splice(block.body) : block;
 
-                         } else if (is_empty(node.init)) {
 
-                             node.init = null;
 
-                         }
 
-                         return node;
 
-                     }
 
-                     if (node instanceof AST_LabeledStatement && node.body instanceof AST_For) {
 
-                         descend(node, this);
 
-                         if (node.body instanceof AST_BlockStatement) {
 
-                             var block = node.body;
 
-                             node.body = block.body.pop();
 
-                             block.body.push(node);
 
-                             return in_list ? MAP.splice(block.body) : block;
 
-                         }
 
-                         return node;
 
-                     }
 
-                     if (node instanceof AST_Scope && node !== self)
 
-                         return node;
 
-                 }
 
-             );
 
-             self.transform(tt);
 
-         }
 
-     });
 
-     AST_Scope.DEFMETHOD("hoist_declarations", function(compressor){
 
-         var self = this;
 
-         if (compressor.has_directive("use asm")) return self;
 
-         var hoist_funs = compressor.option("hoist_funs");
 
-         var hoist_vars = compressor.option("hoist_vars");
 
-         if (hoist_funs || hoist_vars) {
 
-             var dirs = [];
 
-             var hoisted = [];
 
-             var vars = new Dictionary(), vars_found = 0, var_decl = 0;
 
-             // let's count var_decl first, we seem to waste a lot of
 
-             // space if we hoist `var` when there's only one.
 
-             self.walk(new TreeWalker(function(node){
 
-                 if (node instanceof AST_Scope && node !== self)
 
-                     return true;
 
-                 if (node instanceof AST_Var) {
 
-                     ++var_decl;
 
-                     return true;
 
-                 }
 
-             }));
 
-             hoist_vars = hoist_vars && var_decl > 1;
 
-             var tt = new TreeTransformer(
 
-                 function before(node) {
 
-                     if (node !== self) {
 
-                         if (node instanceof AST_Directive) {
 
-                             dirs.push(node);
 
-                             return make_node(AST_EmptyStatement, node);
 
-                         }
 
-                         if (node instanceof AST_Defun && hoist_funs) {
 
-                             hoisted.push(node);
 
-                             return make_node(AST_EmptyStatement, node);
 
-                         }
 
-                         if (node instanceof AST_Var && hoist_vars) {
 
-                             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 (seq == null) {
 
-                                     var def = node.definitions[0].name;
 
-                                     return make_node(AST_SymbolRef, def, def);
 
-                                 }
 
-                                 return seq;
 
-                             }
 
-                             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; // to avoid descending in nested scopes
 
-                     }
 
-                 }
 
-             );
 
-             self = 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
 
-                         && find_if(function(x){ return x.name == def.name.name },
 
-                                    self.argnames)) {
 
-                         vars.del(name);
 
-                     } else {
 
-                         def = def.clone();
 
-                         def.value = null;
 
-                         defs.push(def);
 
-                         vars.set(name, def);
 
-                     }
 
-                 });
 
-                 if (defs.length > 0) {
 
-                     // try to merge in assignments
 
-                     for (var i = 0; i < self.body.length;) {
 
-                         if (self.body[i] instanceof AST_SimpleStatement) {
 
-                             var expr = self.body[i].body, sym, assign;
 
-                             if (expr instanceof AST_Assign
 
-                                 && expr.operator == "="
 
-                                 && (sym = expr.left) instanceof AST_Symbol
 
-                                 && vars.has(sym.name))
 
-                             {
 
-                                 var def = vars.get(sym.name);
 
-                                 if (def.value) break;
 
-                                 def.value = expr.right;
 
-                                 remove(defs, def);
 
-                                 defs.push(def);
 
-                                 self.body.splice(i, 1);
 
-                                 continue;
 
-                             }
 
-                             if (expr instanceof AST_Seq
 
-                                 && (assign = expr.car) instanceof AST_Assign
 
-                                 && assign.operator == "="
 
-                                 && (sym = assign.left) instanceof AST_Symbol
 
-                                 && vars.has(sym.name))
 
-                             {
 
-                                 var def = vars.get(sym.name);
 
-                                 if (def.value) break;
 
-                                 def.value = assign.right;
 
-                                 remove(defs, def);
 
-                                 defs.push(def);
 
-                                 self.body[i].body = expr.cdr;
 
-                                 continue;
 
-                             }
 
-                         }
 
-                         if (self.body[i] instanceof AST_EmptyStatement) {
 
-                             self.body.splice(i, 1);
 
-                             continue;
 
-                         }
 
-                         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, {
 
-                         definitions: defs
 
-                     });
 
-                     hoisted.push(defs);
 
-                 };
 
-             }
 
-             self.body = dirs.concat(hoisted, self.body);
 
-         }
 
-         return self;
 
-     });
 
-     // drop_side_effect_free()
 
-     // remove side-effect-free parts which only affects return value
 
-     (function(def){
 
-         // Drop side-effect-free elements from an array of expressions.
 
-         // Returns an array of expressions with side-effects or null
 
-         // if all elements were dropped. Note: original array may be
 
-         // returned if nothing changed.
 
-         function trim(nodes, compressor, first_in_statement) {
 
-             var ret = [], changed = false;
 
-             for (var i = 0, len = nodes.length; i < len; i++) {
 
-                 var node = nodes[i].drop_side_effect_free(compressor, first_in_statement);
 
-                 changed |= node !== nodes[i];
 
-                 if (node) {
 
-                     ret.push(node);
 
-                     first_in_statement = false;
 
-                 }
 
-             }
 
-             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){
 
-             if (!this.has_pure_annotation(compressor) && compressor.pure_funcs(this)) {
 
-                 if (this.expression instanceof AST_Function
 
-                     && (!this.expression.name || !this.expression.name.definition().references.length)) {
 
-                     var node = this.clone();
 
-                     node.expression = node.expression.process_expression(false, compressor);
 
-                     return node;
 
-                 }
 
-                 return this;
 
-             }
 
-             if (this.pure) {
 
-                 compressor.warn("Dropping __PURE__ call [{file}:{line},{col}]", this.start);
 
-                 this.pure.value = this.pure.value.replace(/[@#]__PURE__/g, ' ');
 
-             }
 
-             var args = trim(this.args, compressor, first_in_statement);
 
-             return args && AST_Seq.from_array(args);
 
-         });
 
-         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);
 
-             switch (this.operator) {
 
-               case "&&":
 
-               case "||":
 
-                 if (right === this.right) return this;
 
-                 var node = this.clone();
 
-                 node.right = right;
 
-                 return node;
 
-               default:
 
-                 var left = this.left.drop_side_effect_free(compressor, first_in_statement);
 
-                 if (!left) return this.right.drop_side_effect_free(compressor, first_in_statement);
 
-                 return make_node(AST_Seq, this, {
 
-                     car: left,
 
-                     cdr: right
 
-                 });
 
-             }
 
-         });
 
-         def(AST_Assign, return_this);
 
-         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, {
 
-                 operator: "||",
 
-                 left: this.condition,
 
-                 right: alternative
 
-             }) : this.condition.drop_side_effect_free(compressor);
 
-             if (!alternative) return make_node(AST_Binary, this, {
 
-                 operator: "&&",
 
-                 left: this.condition,
 
-                 right: consequent
 
-             });
 
-             var node = this.clone();
 
-             node.consequent = consequent;
 
-             node.alternative = alternative;
 
-             return node;
 
-         });
 
-         def(AST_Unary, function(compressor, first_in_statement){
 
-             if (unary_side_effects(this.operator)) return this;
 
-             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
 
-                 && this instanceof AST_UnaryPrefix
 
-                 && is_iife_call(expression)) {
 
-                 if (expression === this.expression && this.operator.length === 1) return this;
 
-                 return make_node(AST_UnaryPrefix, this, {
 
-                     operator: this.operator.length === 1 ? this.operator : "!",
 
-                     expression: expression
 
-                 });
 
-             }
 
-             return expression;
 
-         });
 
-         def(AST_SymbolRef, function() {
 
-             return this.undeclared() ? this : null;
 
-         });
 
-         def(AST_Object, function(compressor, first_in_statement){
 
-             var values = trim(this.properties, compressor, first_in_statement);
 
-             return values && AST_Seq.from_array(values);
 
-         });
 
-         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){
 
-             var values = trim(this.elements, compressor, first_in_statement);
 
-             return values && AST_Seq.from_array(values);
 
-         });
 
-         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){
 
-             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);
 
-             var property = this.property.drop_side_effect_free(compressor);
 
-             if (!property) return expression;
 
-             return make_node(AST_Seq, this, {
 
-                 car: expression,
 
-                 cdr: property
 
-             });
 
-         });
 
-         def(AST_Seq, function(compressor){
 
-             var cdr = this.cdr.drop_side_effect_free(compressor);
 
-             if (cdr === this.cdr) return this;
 
-             if (!cdr) return this.car;
 
-             return make_node(AST_Seq, this, {
 
-                 car: this.car,
 
-                 cdr: cdr
 
-             });
 
-         });
 
-     })(function(node, func){
 
-         node.DEFMETHOD("drop_side_effect_free", func);
 
-     });
 
-     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);
 
-             }
 
-             if (node !== body) {
 
-                 return make_node(AST_SimpleStatement, self, { body: node });
 
-             }
 
-         }
 
-         return self;
 
-     });
 
-     OPT(AST_DWLoop, function(self, compressor){
 
-         if (!compressor.option("loops")) return self;
 
-         var cond = self.condition.evaluate(compressor);
 
-         if (cond !== self.condition) {
 
-             if (cond) {
 
-                 return make_node(AST_For, self, {
 
-                     body: self.body
 
-                 });
 
-             }
 
-             if (compressor.option("dead_code") && self instanceof AST_While) {
 
-                 var a = [];
 
-                 extract_declarations_from_unreachable_code(compressor, self.body, a);
 
-                 return make_node(AST_BlockStatement, self, { body: a }).optimize(compressor);
 
-             }
 
-             if (self instanceof AST_Do) {
 
-                 var has_loop_control = false;
 
-                 var tw = new TreeWalker(function(node) {
 
-                     if (node instanceof AST_Scope || has_loop_control) return true;
 
-                     if (node instanceof AST_LoopControl && tw.loopcontrol_target(node) === self)
 
-                         return has_loop_control = true;
 
-                 });
 
-                 var parent = compressor.parent();
 
-                 (parent instanceof AST_LabeledStatement ? parent : self).walk(tw);
 
-                 if (!has_loop_control) return self.body;
 
-             }
 
-         }
 
-         if (self instanceof AST_While) {
 
-             return make_node(AST_For, self, self).optimize(compressor);
 
-         }
 
-         return self;
 
-     });
 
-     function if_break_in_loop(self, compressor) {
 
-         function drop_it(rest) {
 
-             rest = as_statement_array(rest);
 
-             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, {
 
-                     body: rest
 
-                 }).transform(compressor);
 
-             }
 
-             if_break_in_loop(self, compressor);
 
-         }
 
-         var first = self.body instanceof AST_BlockStatement ? self.body.body[0] : self.body;
 
-         if (first instanceof AST_If) {
 
-             if (first.body instanceof AST_Break
 
-                 && compressor.loopcontrol_target(first.body) === compressor.self()) {
 
-                 if (self.condition) {
 
-                     self.condition = make_node(AST_Binary, self.condition, {
 
-                         left: self.condition,
 
-                         operator: "&&",
 
-                         right: first.condition.negate(compressor),
 
-                     });
 
-                 } else {
 
-                     self.condition = first.condition.negate(compressor);
 
-                 }
 
-                 drop_it(first.alternative);
 
-             }
 
-             else if (first.alternative instanceof AST_Break
 
-                      && compressor.loopcontrol_target(first.alternative) === compressor.self()) {
 
-                 if (self.condition) {
 
-                     self.condition = make_node(AST_Binary, self.condition, {
 
-                         left: self.condition,
 
-                         operator: "&&",
 
-                         right: first.condition,
 
-                     });
 
-                 } else {
 
-                     self.condition = first.condition;
 
-                 }
 
-                 drop_it(first.body);
 
-             }
 
-         }
 
-     };
 
-     OPT(AST_For, function(self, compressor){
 
-         if (!compressor.option("loops")) return self;
 
-         if (self.condition) {
 
-             var cond = self.condition.evaluate(compressor);
 
-             if (compressor.option("dead_code") && !cond) {
 
-                 var a = [];
 
-                 if (self.init instanceof AST_Statement) {
 
-                     a.push(self.init);
 
-                 }
 
-                 else if (self.init) {
 
-                     a.push(make_node(AST_SimpleStatement, self.init, {
 
-                         body: self.init
 
-                     }));
 
-                 }
 
-                 extract_declarations_from_unreachable_code(compressor, self.body, a);
 
-                 return make_node(AST_BlockStatement, self, { body: a }).optimize(compressor);
 
-             }
 
-             if (cond !== self.condition) {
 
-                 cond = make_node_from_constant(cond, self.condition).transform(compressor);
 
-                 self.condition = best_of_expression(cond, self.condition);
 
-             }
 
-         }
 
-         if_break_in_loop(self, compressor);
 
-         return self;
 
-     });
 
-     OPT(AST_If, function(self, compressor){
 
-         if (is_empty(self.alternative)) self.alternative = null;
 
-         if (!compressor.option("conditionals")) return self;
 
-         // if condition can be statically determined, warn and drop
 
-         // one of the blocks.  note, statically determined implies
 
-         // “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 (cond !== self.condition) {
 
-             if (cond) {
 
-                 compressor.warn("Condition always true [{file}:{line},{col}]", self.condition.start);
 
-                 if (compressor.option("dead_code")) {
 
-                     var a = [];
 
-                     if (self.alternative) {
 
-                         extract_declarations_from_unreachable_code(compressor, self.alternative, a);
 
-                     }
 
-                     a.push(self.body);
 
-                     return make_node(AST_BlockStatement, self, { body: a }).optimize(compressor);
 
-                 }
 
-             } else {
 
-                 compressor.warn("Condition always false [{file}:{line},{col}]", self.condition.start);
 
-                 if (compressor.option("dead_code")) {
 
-                     var a = [];
 
-                     extract_declarations_from_unreachable_code(compressor, self.body, a);
 
-                     if (self.alternative) a.push(self.alternative);
 
-                     return make_node(AST_BlockStatement, self, { body: a }).optimize(compressor);
 
-                 }
 
-             }
 
-             cond = make_node_from_constant(cond, self.condition).transform(compressor);
 
-             self.condition = best_of_expression(cond, self.condition);
 
-         }
 
-         var negated = self.condition.negate(compressor);
 
-         var self_condition_length = self.condition.print_to_string().length;
 
-         var negated_length = negated.print_to_string().length;
 
-         var negated_is_best = negated_length < self_condition_length;
 
-         if (self.alternative && negated_is_best) {
 
-             negated_is_best = false; // because we already do the switch here.
 
-             // no need to swap values of self_condition_length and negated_length
 
-             // 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.alternative = tmp;
 
-         }
 
-         if (is_empty(self.body) && is_empty(self.alternative)) {
 
-             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, {
 
-                     condition   : self.condition,
 
-                     consequent  : self.body.body,
 
-                     alternative : self.alternative.body
 
-                 })
 
-             }).optimize(compressor);
 
-         }
 
-         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 == "||") {
 
-                 // 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, {
 
-                     operator : "||",
 
-                     left     : negated,
 
-                     right    : self.body.body
 
-                 })
 
-             }).optimize(compressor);
 
-             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, {
 
-                     operator : "||",
 
-                     left     : self.condition,
 
-                     right    : self.alternative.body
 
-                 })
 
-             }).optimize(compressor);
 
-         }
 
-         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, {
 
-                     condition   : self.condition,
 
-                     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
 
-             && !self.body.alternative
 
-             && !self.alternative) {
 
-             self = make_node(AST_If, self, {
 
-                 condition: make_node(AST_Binary, self.condition, {
 
-                     operator: "&&",
 
-                     left: self.condition,
 
-                     right: self.body.condition
 
-                 }),
 
-                 body: self.body.body,
 
-                 alternative: null
 
-             });
 
-         }
 
-         if (aborts(self.body)) {
 
-             if (self.alternative) {
 
-                 var alt = self.alternative;
 
-                 self.alternative = null;
 
-                 return make_node(AST_BlockStatement, self, {
 
-                     body: [ self, alt ]
 
-                 }).optimize(compressor);
 
-             }
 
-         }
 
-         if (aborts(self.alternative)) {
 
-             var body = self.body;
 
-             self.body = self.alternative;
 
-             self.condition = negated_is_best ? negated : self.condition.negate(compressor);
 
-             self.alternative = null;
 
-             return make_node(AST_BlockStatement, self, {
 
-                 body: [ self, body ]
 
-             }).optimize(compressor);
 
-         }
 
-         return self;
 
-     });
 
-     OPT(AST_Switch, function(self, compressor){
 
-         if (!compressor.option("switches")) return self;
 
-         var branch;
 
-         var value = self.expression.evaluate(compressor);
 
-         if (value !== self.expression) {
 
-             var expression = make_node_from_constant(value, self.expression).transform(compressor);
 
-             self.expression = best_of_expression(expression, self.expression);
 
-         }
 
-         if (!compressor.option("dead_code")) return self;
 
-         var decl = [];
 
-         var body = [];
 
-         var default_branch;
 
-         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 (!default_branch) {
 
-                     default_branch = branch;
 
-                 } else {
 
-                     eliminate_branch(branch, body[body.length - 1]);
 
-                 }
 
-             } else if (value !== self.expression) {
 
-                 var exp = branch.expression.evaluate(compressor);
 
-                 if (exp === value) {
 
-                     exact_match = branch;
 
-                     if (default_branch) {
 
-                         var default_index = body.indexOf(default_branch);
 
-                         body.splice(default_index, 1);
 
-                         eliminate_branch(default_branch, body[default_index - 1]);
 
-                         default_branch = null;
 
-                     }
 
-                 } else if (exp !== branch.expression) {
 
-                     eliminate_branch(branch, body[body.length - 1]);
 
-                     continue;
 
-                 }
 
-             }
 
-             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))) {
 
-                     prev.body = [];
 
-                 }
 
-             }
 
-             body.push(branch);
 
-         }
 
-         while (i < len) eliminate_branch(self.body[i++], body[body.length - 1]);
 
-         if (body.length > 0) {
 
-             body[0].body = decl.concat(body[0].body);
 
-         }
 
-         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)
 
-                 branch.body.pop();
 
-             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, {
 
-                     body: self.expression
 
-                 }))
 
-             }).optimize(compressor);
 
-         }
 
-         if (body.length == 1 && (body[0] === exact_match || body[0] === default_branch)) {
 
-             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)
 
-                     has_break = true;
 
-             });
 
-             self.walk(tw);
 
-             if (!has_break) {
 
-                 body = body[0].body.slice();
 
-                 body.unshift(make_node(AST_SimpleStatement, self.expression, {
 
-                     body: self.expression
 
-                 }));
 
-                 return make_node(AST_BlockStatement, self, {
 
-                     body: body
 
-                 }).optimize(compressor);
 
-             }
 
-         }
 
-         return self;
 
-         function eliminate_branch(branch, prev) {
 
-             if (prev && !aborts(prev)) {
 
-                 prev.body = prev.body.concat(branch.body);
 
-             } else {
 
-                 extract_declarations_from_unreachable_code(compressor, branch, decl);
 
-             }
 
-         }
 
-     });
 
-     OPT(AST_Try, function(self, compressor){
 
-         self.body = tighten_body(self.body, compressor);
 
-         if (self.bcatch && self.bfinally && all(self.bfinally.body, is_empty)) self.bfinally = null;
 
-         if (all(self.body, is_empty)) {
 
-             var body = [];
 
-             if (self.bcatch) extract_declarations_from_unreachable_code(compressor, self.bcatch, body);
 
-             if (self.bfinally) body = body.concat(self.bfinally.body);
 
-             return make_node(AST_BlockStatement, self, {
 
-                 body: body
 
-             }).optimize(compressor);
 
-         }
 
-         return self;
 
-     });
 
-     AST_Definitions.DEFMETHOD("remove_initializers", function(){
 
-         this.definitions.forEach(function(def){ def.value = null });
 
-     });
 
-     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, {
 
-                     operator : "=",
 
-                     left     : name,
 
-                     right    : def.value
 
-                 }));
 
-                 if (reduce_vars) name.definition().fixed = false;
 
-             }
 
-             return a;
 
-         }, []);
 
-         if (assignments.length == 0) return null;
 
-         return AST_Seq.from_array(assignments);
 
-     });
 
-     OPT(AST_Definitions, function(self, compressor){
 
-         if (self.definitions.length == 0)
 
-             return make_node(AST_EmptyStatement, self);
 
-         return self;
 
-     });
 
-     OPT(AST_Call, function(self, compressor){
 
-         var exp = self.expression;
 
-         if (compressor.option("reduce_vars")
 
-             && exp instanceof AST_SymbolRef) {
 
-             var def = exp.definition();
 
-             var fixed = exp.fixed_value();
 
-             if (fixed instanceof AST_Defun) {
 
-                 def.fixed = fixed = make_node(AST_Function, fixed, fixed).clone(true);
 
-             }
 
-             if (fixed instanceof AST_Function) {
 
-                 exp = fixed;
 
-                 if (compressor.option("unused")
 
-                     && def.references.length == 1
 
-                     && !(def.scope.uses_arguments
 
-                         && def.orig[0] instanceof AST_SymbolFunarg)
 
-                     && !def.scope.uses_eval
 
-                     && compressor.find_parent(AST_Scope) === def.scope) {
 
-                     self.expression = exp;
 
-                 }
 
-             }
 
-         }
 
-         if (compressor.option("unused")
 
-             && exp instanceof AST_Function
 
-             && !exp.uses_arguments
 
-             && !exp.uses_eval) {
 
-             var pos = 0, last = 0;
 
-             for (var i = 0, len = self.args.length; i < len; i++) {
 
-                 var trim = i >= exp.argnames.length;
 
-                 if (trim || exp.argnames[i].__unused) {
 
-                     var node = self.args[i].drop_side_effect_free(compressor);
 
-                     if (node) {
 
-                         self.args[pos++] = node;
 
-                     } else if (!trim) {
 
-                         self.args[pos++] = make_node(AST_Number, self.args[i], {
 
-                             value: 0
 
-                         });
 
-                         continue;
 
-                     }
 
-                 } else {
 
-                     self.args[pos++] = self.args[i];
 
-                 }
 
-                 last = pos;
 
-             }
 
-             self.args.length = last;
 
-         }
 
-         if (compressor.option("unsafe")) {
 
-             if (exp instanceof AST_SymbolRef && exp.undeclared()) {
 
-                 switch (exp.name) {
 
-                   case "Array":
 
-                     if (self.args.length != 1) {
 
-                         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, {
 
-                             properties: []
 
-                         });
 
-                     }
 
-                     break;
 
-                   case "String":
 
-                     if (self.args.length == 0) return make_node(AST_String, self, {
 
-                         value: ""
 
-                     });
 
-                     if (self.args.length <= 1) return make_node(AST_Binary, self, {
 
-                         left: self.args[0],
 
-                         operator: "+",
 
-                         right: make_node(AST_String, self, { value: "" })
 
-                     }).optimize(compressor);
 
-                     break;
 
-                   case "Number":
 
-                     if (self.args.length == 0) return make_node(AST_Number, self, {
 
-                         value: 0
 
-                     });
 
-                     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, {
 
-                             expression: self.args[0],
 
-                             operator: "!"
 
-                         }),
 
-                         operator: "!"
 
-                     }).optimize(compressor);
 
-                     break;
 
-                   case "Function":
 
-                     // new Function() => function(){}
 
-                     if (self.args.length == 0) return make_node(AST_Function, self, {
 
-                         argnames: [],
 
-                         body: []
 
-                     });
 
-                     if (all(self.args, function(x){ return x instanceof AST_String })) {
 
-                         // quite a corner-case, but we can handle it:
 
-                         //   https://github.com/mishoo/UglifyJS2/issues/203
 
-                         // if the code argument is a constant, then we can minify it.
 
-                         try {
 
-                             var code = "(function(" + self.args.slice(0, -1).map(function(arg){
 
-                                 return arg.value;
 
-                             }).join(",") + "){" + self.args[self.args.length - 1].value + "})()";
 
-                             var ast = parse(code);
 
-                             ast.figure_out_scope({ screw_ie8: compressor.option("screw_ie8") });
 
-                             var comp = new Compressor(compressor.options);
 
-                             ast = ast.transform(comp);
 
-                             ast.figure_out_scope({ screw_ie8: compressor.option("screw_ie8") });
 
-                             ast.mangle_names();
 
-                             var fun;
 
-                             try {
 
-                                 ast.walk(new TreeWalker(function(node){
 
-                                     if (node instanceof AST_Lambda) {
 
-                                         fun = node;
 
-                                         throw ast;
 
-                                     }
 
-                                 }));
 
-                             } catch(ex) {
 
-                                 if (ex !== ast) throw ex;
 
-                             };
 
-                             if (!fun) return self;
 
-                             var args = fun.argnames.map(function(arg, i){
 
-                                 return make_node(AST_String, self.args[i], {
 
-                                     value: arg.print_to_string()
 
-                                 });
 
-                             });
 
-                             var code = OutputStream();
 
-                             AST_BlockStatement.prototype._codegen.call(fun, fun, code);
 
-                             code = code.toString().replace(/^\{|\}$/g, "");
 
-                             args.push(make_node(AST_String, self.args[self.args.length - 1], {
 
-                                 value: code
 
-                             }));
 
-                             self.args = args;
 
-                             return self;
 
-                         } catch(ex) {
 
-                             if (ex instanceof JS_Parse_Error) {
 
-                                 compressor.warn("Error parsing code passed to new Function [{file}:{line},{col}]", self.args[self.args.length - 1].start);
 
-                                 compressor.warn(ex.toString());
 
-                             } else {
 
-                                 console.log(ex);
 
-                                 throw ex;
 
-                             }
 
-                         }
 
-                     }
 
-                     break;
 
-                 }
 
-             }
 
-             else if (exp instanceof AST_Dot && exp.property == "toString" && self.args.length == 0) {
 
-                 return make_node(AST_Binary, self, {
 
-                     left: make_node(AST_String, self, { value: "" }),
 
-                     operator: "+",
 
-                     right: exp.expression
 
-                 }).optimize(compressor);
 
-             }
 
-             else if (exp instanceof AST_Dot && exp.expression instanceof AST_Array && exp.property == "join") EXIT: {
 
-                 var separator;
 
-                 if (self.args.length > 0) {
 
-                     separator = self.args[0].evaluate(compressor);
 
-                     if (separator === self.args[0]) break EXIT; // not a constant
 
-                 }
 
-                 var elements = [];
 
-                 var consts = [];
 
-                 exp.expression.elements.forEach(function(el) {
 
-                     var value = el.evaluate(compressor);
 
-                     if (value !== el) {
 
-                         consts.push(value);
 
-                     } else {
 
-                         if (consts.length > 0) {
 
-                             elements.push(make_node(AST_String, self, {
 
-                                 value: consts.join(separator)
 
-                             }));
 
-                             consts.length = 0;
 
-                         }
 
-                         elements.push(el);
 
-                     }
 
-                 });
 
-                 if (consts.length > 0) {
 
-                     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 == 1) {
 
-                     if (elements[0].is_string(compressor)) {
 
-                         return elements[0];
 
-                     }
 
-                     return make_node(AST_Binary, elements[0], {
 
-                         operator : "+",
 
-                         left     : make_node(AST_String, self, { value: "" }),
 
-                         right    : elements[0]
 
-                     });
 
-                 }
 
-                 if (separator == "") {
 
-                     var first;
 
-                     if (elements[0].is_string(compressor)
 
-                         || elements[1].is_string(compressor)) {
 
-                         first = elements.shift();
 
-                     } else {
 
-                         first = make_node(AST_String, self, { value: "" });
 
-                     }
 
-                     return elements.reduce(function(prev, el){
 
-                         return make_node(AST_Binary, el, {
 
-                             operator : "+",
 
-                             left     : prev,
 
-                             right    : el
 
-                         });
 
-                     }, first).optimize(compressor);
 
-                 }
 
-                 // need this awkward cloning to not affect original element
 
-                 // best_of will decide which one to get through.
 
-                 var node = self.clone();
 
-                 node.expression = node.expression.clone();
 
-                 node.expression.expression = node.expression.expression.clone();
 
-                 node.expression.expression.elements = elements;
 
-                 return best_of(compressor, self, node);
 
-             }
 
-             else if (exp instanceof AST_Dot && exp.expression.is_string(compressor) && exp.property == "charAt") {
 
-                 var arg = self.args[0];
 
-                 var index = arg ? arg.evaluate(compressor) : 0;
 
-                 if (index !== arg) {
 
-                     return make_node(AST_Sub, exp, {
 
-                         expression: exp.expression,
 
-                         property: make_node_from_constant(index | 0, arg || exp)
 
-                     }).optimize(compressor);
 
-                 }
 
-             }
 
-         }
 
-         if (exp instanceof AST_Function) {
 
-             if (exp.body[0] instanceof AST_Return) {
 
-                 var value = exp.body[0].value;
 
-                 if (!value || value.is_constant()) {
 
-                     var args = self.args.concat(value || make_node(AST_Undefined, self));
 
-                     return AST_Seq.from_array(args).transform(compressor);
 
-                 }
 
-             }
 
-             if (compressor.option("side_effects") && all(exp.body, is_empty)) {
 
-                 var args = self.args.concat(make_node(AST_Undefined, self));
 
-                 return AST_Seq.from_array(args).transform(compressor);
 
-             }
 
-         }
 
-         if (compressor.option("drop_console")) {
 
-             if (exp instanceof AST_PropAccess) {
 
-                 var name = exp.expression;
 
-                 while (name.expression) {
 
-                     name = name.expression;
 
-                 }
 
-                 if (name instanceof AST_SymbolRef
 
-                     && name.name == "console"
 
-                     && name.undeclared()) {
 
-                     return make_node(AST_Undefined, self).optimize(compressor);
 
-                 }
 
-             }
 
-         }
 
-         if (compressor.option("negate_iife")
 
-             && compressor.parent() instanceof AST_SimpleStatement
 
-             && is_iife_call(self)) {
 
-             return self.negate(compressor, true);
 
-         }
 
-         return self;
 
-     });
 
-     OPT(AST_New, function(self, compressor){
 
-         if (compressor.option("unsafe")) {
 
-             var exp = self.expression;
 
-             if (exp instanceof AST_SymbolRef && exp.undeclared()) {
 
-                 switch (exp.name) {
 
-                   case "Object":
 
-                   case "RegExp":
 
-                   case "Function":
 
-                   case "Error":
 
-                   case "Array":
 
-                     return make_node(AST_Call, self, self).transform(compressor);
 
-                 }
 
-             }
 
-         }
 
-         return self;
 
-     });
 
-     OPT(AST_Seq, function(self, compressor){
 
-         if (!compressor.option("side_effects"))
 
-             return self;
 
-         self.car = self.car.drop_side_effect_free(compressor, first_in_statement(compressor));
 
-         if (!self.car) return maintain_this_binding(compressor.parent(), self, self.cdr);
 
-         if (compressor.option("cascade")) {
 
-             var left;
 
-             if (self.car instanceof AST_Assign
 
-                 && !self.car.left.has_side_effects(compressor)) {
 
-                 left = self.car.left;
 
-             } else if (self.car instanceof AST_Unary
 
-                 && (self.car.operator == "++" || self.car.operator == "--")) {
 
-                 left = self.car.expression;
 
-             }
 
-             if (left
 
-                 && !(left instanceof AST_SymbolRef
 
-                     && (left.definition().orig[0] instanceof AST_SymbolLambda
 
-                         || is_reference_const(left)))) {
 
-                 var parent, field;
 
-                 var cdr = self.cdr;
 
-                 while (true) {
 
-                     if (cdr.equivalent_to(left)) {
 
-                         var car = self.car instanceof AST_UnaryPostfix ? make_node(AST_UnaryPrefix, self.car, {
 
-                             operator: self.car.operator,
 
-                             expression: left
 
-                         }) : self.car;
 
-                         if (parent) {
 
-                             parent[field] = car;
 
-                             return self.cdr;
 
-                         }
 
-                         return car;
 
-                     }
 
-                     if (cdr instanceof AST_Binary && !(cdr instanceof AST_Assign)) {
 
-                         if (cdr.left.is_constant()) {
 
-                             if (cdr.operator == "||" || cdr.operator == "&&") break;
 
-                             field = "right";
 
-                         } else {
 
-                             field = "left";
 
-                         }
 
-                     } else if (cdr instanceof AST_Call
 
-                         || cdr instanceof AST_Unary && !unary_side_effects(cdr.operator)) {
 
-                         field = "expression";
 
-                     } else break;
 
-                     parent = cdr;
 
-                     cdr = cdr[field];
 
-                 }
 
-             }
 
-         }
 
-         if (is_undefined(self.cdr, compressor)) {
 
-             return make_node(AST_UnaryPrefix, self, {
 
-                 operator   : "void",
 
-                 expression : self.car
 
-             });
 
-         }
 
-         return self;
 
-     });
 
-     AST_Unary.DEFMETHOD("lift_sequences", function(compressor){
 
-         if (compressor.option("sequences")) {
 
-             if (this.expression instanceof AST_Seq) {
 
-                 var seq = this.expression;
 
-                 var x = seq.to_array();
 
-                 var e = this.clone();
 
-                 e.expression = x.pop();
 
-                 x.push(e);
 
-                 seq = AST_Seq.from_array(x).transform(compressor);
 
-                 return seq;
 
-             }
 
-         }
 
-         return this;
 
-     });
 
-     OPT(AST_UnaryPostfix, function(self, compressor){
 
-         return self.lift_sequences(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_NaN
 
-                 || e instanceof AST_Infinity
 
-                 || e instanceof AST_Undefined)) {
 
-             if (e instanceof AST_Seq) {
 
-                 e = e.to_array();
 
-                 e.push(make_node(AST_True, self));
 
-                 return AST_Seq.from_array(e).optimize(compressor);
 
-             }
 
-             return make_node(AST_Seq, self, {
 
-                 car: e,
 
-                 cdr: make_node(AST_True, self)
 
-             }).optimize(compressor);
 
-         }
 
-         var seq = self.lift_sequences(compressor);
 
-         if (seq !== self) {
 
-             return seq;
 
-         }
 
-         if (compressor.option("side_effects") && self.operator == "void") {
 
-             e = e.drop_side_effect_free(compressor);
 
-             if (e) {
 
-                 self.expression = e;
 
-                 return self;
 
-             } else {
 
-                 return make_node(AST_Undefined, self).optimize(compressor);
 
-             }
 
-         }
 
-         if (compressor.option("booleans") && compressor.in_boolean_context()) {
 
-             switch (self.operator) {
 
-               case "!":
 
-                 if (e instanceof AST_UnaryPrefix && e.operator == "!") {
 
-                     // !!foo ==> foo, if we're in boolean context
 
-                     return e.expression;
 
-                 }
 
-                 if (e instanceof AST_Binary) {
 
-                     self = best_of(compressor, self, e.negate(compressor, first_in_statement(compressor)));
 
-                 }
 
-                 break;
 
-               case "typeof":
 
-                 // 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_node(AST_Seq, self, {
 
-                     car: e,
 
-                     cdr: make_node(AST_True, self)
 
-                 })).optimize(compressor);
 
-             }
 
-         }
 
-         if (self.operator == "-" && e instanceof AST_Infinity) {
 
-             e = e.transform(compressor);
 
-         }
 
-         if (e instanceof AST_Binary
 
-             && (self.operator == "+" || self.operator == "-")
 
-             && (e.operator == "*" || e.operator == "/" || e.operator == "%")) {
 
-             return make_node(AST_Binary, self, {
 
-                 operator: e.operator,
 
-                 left: make_node(AST_UnaryPrefix, e.left, {
 
-                     operator: self.operator,
 
-                     expression: e.left
 
-                 }),
 
-                 right: e.right
 
-             });
 
-         }
 
-         // avoids infinite recursion of numerals
 
-         if (self.operator != "-"
 
-             || !(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);
 
-                 return best_of(compressor, ev, self);
 
-             }
 
-         }
 
-         return self;
 
-     });
 
-     AST_Binary.DEFMETHOD("lift_sequences", function(compressor){
 
-         if (compressor.option("sequences")) {
 
-             if (this.left instanceof AST_Seq) {
 
-                 var seq = this.left;
 
-                 var x = seq.to_array();
 
-                 var e = this.clone();
 
-                 e.left = x.pop();
 
-                 x.push(e);
 
-                 return AST_Seq.from_array(x).optimize(compressor);
 
-             }
 
-             if (this.right instanceof AST_Seq && !this.left.has_side_effects(compressor)) {
 
-                 var assign = this.operator == "=" && this.left instanceof AST_SymbolRef;
 
-                 var root = this.right.clone();
 
-                 var cursor, seq = root;
 
-                 while (assign || !seq.car.has_side_effects(compressor)) {
 
-                     cursor = seq;
 
-                     if (seq.cdr instanceof AST_Seq) {
 
-                         seq = seq.cdr = seq.cdr.clone();
 
-                     } else break;
 
-                 }
 
-                 if (cursor) {
 
-                     var e = this.clone();
 
-                     e.right = cursor.cdr;
 
-                     cursor.cdr = e;
 
-                     return root.optimize(compressor);
 
-                 }
 
-             }
 
-         }
 
-         return this;
 
-     });
 
-     var commutativeOperators = makePredicate("== === != !== * & | ^");
 
-     OPT(AST_Binary, function(self, compressor){
 
-         function reversible() {
 
-             return self.left.is_constant()
 
-                 || self.right.is_constant()
 
-                 || !self.left.has_side_effects(compressor)
 
-                     && !self.right.has_side_effects(compressor);
 
-         }
 
-         function reverse(op) {
 
-             if (reversible()) {
 
-                 if (op) self.operator = op;
 
-                 var tmp = self.left;
 
-                 self.left = self.right;
 
-                 self.right = tmp;
 
-             }
 
-         }
 
-         if (commutativeOperators(self.operator)) {
 
-             if (self.right.is_constant()
 
-                 && !self.left.is_constant()) {
 
-                 // if right is a constant, whatever side effects the
 
-                 // left side might have could not influence the
 
-                 // result.  hence, force switch.
 
-                 if (!(self.left instanceof AST_Binary
 
-                       && PRECEDENCE[self.left.operator] >= PRECEDENCE[self.operator])) {
 
-                     reverse();
 
-                 }
 
-             }
 
-         }
 
-         self = self.lift_sequences(compressor);
 
-         if (compressor.option("comparisons")) switch (self.operator) {
 
-           case "===":
 
-           case "!==":
 
-             if ((self.left.is_string(compressor) && self.right.is_string(compressor)) ||
 
-                 (self.left.is_number(compressor) && self.right.is_number(compressor)) ||
 
-                 (self.left.is_boolean() && self.right.is_boolean())) {
 
-                 self.operator = self.operator.substr(0, 2);
 
-             }
 
-             // XXX: intentionally falling down to the next case
 
-           case "==":
 
-           case "!=":
 
-             // "undefined" == typeof x => undefined === x
 
-             if (self.left instanceof AST_String
 
-                 && self.left.value == "undefined"
 
-                 && self.right instanceof AST_UnaryPrefix
 
-                 && self.right.operator == "typeof") {
 
-                 var expr = self.right.expression;
 
-                 if (expr instanceof AST_SymbolRef ? !expr.undeclared()
 
-                     : !(expr instanceof AST_PropAccess) || compressor.option("screw_ie8")) {
 
-                     self.right = expr;
 
-                     self.left = make_node(AST_Undefined, self.left).optimize(compressor);
 
-                     if (self.operator.length == 2) self.operator += "=";
 
-                 }
 
-             }
 
-             break;
 
-         }
 
-         if (compressor.option("booleans") && self.operator == "+" && compressor.in_boolean_context()) {
 
-             var ll = self.left.evaluate(compressor);
 
-             var rr = self.right.evaluate(compressor);
 
-             if (ll && typeof ll == "string") {
 
-                 compressor.warn("+ in boolean context always true [{file}:{line},{col}]", self.start);
 
-                 return make_node(AST_Seq, self, {
 
-                     car: self.right,
 
-                     cdr: 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_node(AST_Seq, self, {
 
-                     car: self.left,
 
-                     cdr: 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, {
 
-                     operator: "!",
 
-                     expression: self.negate(compressor, first_in_statement(compressor))
 
-                 });
 
-                 self = best_of(compressor, self, negated);
 
-             }
 
-             if (compressor.option("unsafe_comps")) {
 
-                 switch (self.operator) {
 
-                   case "<": reverse(">"); break;
 
-                   case "<=": reverse(">="); break;
 
-                 }
 
-             }
 
-         }
 
-         if (self.operator == "+") {
 
-             if (self.right instanceof AST_String
 
-                 && self.right.getValue() == ""
 
-                 && self.left.is_string(compressor)) {
 
-                 return self.left;
 
-             }
 
-             if (self.left instanceof AST_String
 
-                 && self.left.getValue() == ""
 
-                 && self.right.is_string(compressor)) {
 
-                 return self.right;
 
-             }
 
-             if (self.left instanceof AST_Binary
 
-                 && self.left.operator == "+"
 
-                 && self.left.left instanceof AST_String
 
-                 && self.left.left.getValue() == ""
 
-                 && self.right.is_string(compressor)) {
 
-                 self.left = self.left.right;
 
-                 return self.transform(compressor);
 
-             }
 
-         }
 
-         if (compressor.option("evaluate")) {
 
-             switch (self.operator) {
 
-               case "&&":
 
-                 var ll = self.left.evaluate(compressor);
 
-                 if (!ll) {
 
-                     compressor.warn("Condition left of && always false [{file}:{line},{col}]", self.start);
 
-                     return maintain_this_binding(compressor.parent(), self, self.left).optimize(compressor);
 
-                 } else if (ll !== self.left) {
 
-                     compressor.warn("Condition left of && always true [{file}:{line},{col}]", self.start);
 
-                     return maintain_this_binding(compressor.parent(), self, self.right).optimize(compressor);
 
-                 }
 
-                 if (compressor.option("booleans") && compressor.in_boolean_context()) {
 
-                     var rr = self.right.evaluate(compressor);
 
-                     if (!rr) {
 
-                         compressor.warn("Boolean && always false [{file}:{line},{col}]", self.start);
 
-                         return make_node(AST_Seq, self, {
 
-                             car: self.left,
 
-                             cdr: make_node(AST_False, self)
 
-                         }).optimize(compressor);
 
-                     } else if (rr !== self.right) {
 
-                         compressor.warn("Dropping side-effect-free && in boolean context [{file}:{line},{col}]", self.start);
 
-                         return self.left.optimize(compressor);
 
-                     }
 
-                 }
 
-                 break;
 
-               case "||":
 
-                 var ll = self.left.evaluate(compressor);
 
-                 if (!ll) {
 
-                     compressor.warn("Condition left of || always false [{file}:{line},{col}]", self.start);
 
-                     return maintain_this_binding(compressor.parent(), self, self.right).optimize(compressor);
 
-                 } else if (ll !== self.left) {
 
-                     compressor.warn("Condition left of || always true [{file}:{line},{col}]", self.start);
 
-                     return maintain_this_binding(compressor.parent(), self, self.left).optimize(compressor);
 
-                 }
 
-                 if (compressor.option("booleans") && compressor.in_boolean_context()) {
 
-                     var rr = self.right.evaluate(compressor);
 
-                     if (!rr) {
 
-                         compressor.warn("Dropping side-effect-free || in boolean context [{file}:{line},{col}]", self.start);
 
-                         return self.left.optimize(compressor);
 
-                     } else if (rr !== self.right) {
 
-                         compressor.warn("Boolean || always true [{file}:{line},{col}]", self.start);
 
-                         return make_node(AST_Seq, self, {
 
-                             car: self.left,
 
-                             cdr: make_node(AST_True, self)
 
-                         }).optimize(compressor);
 
-                     }
 
-                 }
 
-                 break;
 
-             }
 
-             var associative = true;
 
-             switch (self.operator) {
 
-               case "+":
 
-                 // "foo" + ("bar" + x) => "foobar" + x
 
-                 if (self.left instanceof AST_Constant
 
-                     && self.right instanceof AST_Binary
 
-                     && self.right.operator == "+"
 
-                     && self.right.left instanceof AST_Constant
 
-                     && self.right.is_string(compressor)) {
 
-                     self = make_node(AST_Binary, self, {
 
-                         operator: "+",
 
-                         left: make_node(AST_String, self.left, {
 
-                             value: "" + self.left.getValue() + self.right.left.getValue(),
 
-                             start: self.left.start,
 
-                             end: self.right.left.end
 
-                         }),
 
-                         right: self.right.right
 
-                     });
 
-                 }
 
-                 // (x + "foo") + "bar" => x + "foobar"
 
-                 if (self.right instanceof AST_Constant
 
-                     && self.left instanceof AST_Binary
 
-                     && self.left.operator == "+"
 
-                     && self.left.right instanceof AST_Constant
 
-                     && self.left.is_string(compressor)) {
 
-                     self = make_node(AST_Binary, self, {
 
-                         operator: "+",
 
-                         left: self.left.left,
 
-                         right: make_node(AST_String, self.right, {
 
-                             value: "" + self.left.right.getValue() + self.right.getValue(),
 
-                             start: self.left.right.start,
 
-                             end: self.right.end
 
-                         })
 
-                     });
 
-                 }
 
-                 // (x + "foo") + ("bar" + y) => (x + "foobar") + y
 
-                 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.right.operator == "+"
 
-                     && self.right.left instanceof AST_Constant
 
-                     && self.right.is_string(compressor)) {
 
-                     self = make_node(AST_Binary, self, {
 
-                         operator: "+",
 
-                         left: make_node(AST_Binary, self.left, {
 
-                             operator: "+",
 
-                             left: self.left.left,
 
-                             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
 
-                             })
 
-                         }),
 
-                         right: self.right.right
 
-                     });
 
-                 }
 
-                 // a + -b => a - b
 
-                 if (self.right instanceof AST_UnaryPrefix
 
-                     && self.right.operator == "-"
 
-                     && self.left.is_number(compressor)) {
 
-                     self = make_node(AST_Binary, self, {
 
-                         operator: "-",
 
-                         left: self.left,
 
-                         right: self.right.expression
 
-                     });
 
-                     break;
 
-                 }
 
-                 // -a + b => b - a
 
-                 if (self.left instanceof AST_UnaryPrefix
 
-                     && self.left.operator == "-"
 
-                     && reversible()
 
-                     && self.right.is_number(compressor)) {
 
-                     self = make_node(AST_Binary, self, {
 
-                         operator: "-",
 
-                         left: self.right,
 
-                         right: self.left.expression
 
-                     });
 
-                     break;
 
-                 }
 
-               case "*":
 
-                 associative = compressor.option("unsafe_math");
 
-               case "&":
 
-               case "|":
 
-               case "^":
 
-                 // a + +b => +b + a
 
-                 if (self.left.is_number(compressor)
 
-                     && self.right.is_number(compressor)
 
-                     && reversible()
 
-                     && !(self.left instanceof AST_Binary
 
-                         && self.left.operator != self.operator
 
-                         && PRECEDENCE[self.left.operator] >= PRECEDENCE[self.operator])) {
 
-                     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)) {
 
-                         self = best_of(compressor, reversed, self);
 
-                     } else {
 
-                         self = best_of(compressor, self, reversed);
 
-                     }
 
-                 }
 
-                 if (associative && self.is_number(compressor)) {
 
-                     // a + (b + c) => (a + b) + c
 
-                     if (self.right instanceof AST_Binary
 
-                         && self.right.operator == self.operator) {
 
-                         self = make_node(AST_Binary, self, {
 
-                             operator: self.operator,
 
-                             left: make_node(AST_Binary, self.left, {
 
-                                 operator: self.operator,
 
-                                 left: self.left,
 
-                                 right: self.right.left,
 
-                                 start: self.left.start,
 
-                                 end: self.right.left.end
 
-                             }),
 
-                             right: self.right.right
 
-                         });
 
-                     }
 
-                     // (n + 2) + 3 => 5 + n
 
-                     // (2 * n) * 3 => 6 + n
 
-                     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, {
 
-                                 operator: self.operator,
 
-                                 left: make_node(AST_Binary, self.left, {
 
-                                     operator: self.operator,
 
-                                     left: self.left.left,
 
-                                     right: self.right,
 
-                                     start: self.left.left.start,
 
-                                     end: self.right.end
 
-                                 }),
 
-                                 right: self.left.right
 
-                             });
 
-                         } else if (self.left.right instanceof AST_Constant) {
 
-                             self = make_node(AST_Binary, self, {
 
-                                 operator: self.operator,
 
-                                 left: make_node(AST_Binary, self.left, {
 
-                                     operator: self.operator,
 
-                                     left: self.left.right,
 
-                                     right: self.right,
 
-                                     start: self.left.right.start,
 
-                                     end: self.right.end
 
-                                 }),
 
-                                 right: self.left.left
 
-                             });
 
-                         }
 
-                     }
 
-                     // (a | 1) | (2 | d) => (3 | a) | b
 
-                     if (self.left instanceof AST_Binary
 
-                         && self.left.operator == self.operator
 
-                         && 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, {
 
-                             operator: self.operator,
 
-                             left: make_node(AST_Binary, self.left, {
 
-                                 operator: self.operator,
 
-                                 left: make_node(AST_Binary, self.left.left, {
 
-                                     operator: self.operator,
 
-                                     left: self.left.right,
 
-                                     right: self.right.left,
 
-                                     start: self.left.right.start,
 
-                                     end: self.right.left.end
 
-                                 }),
 
-                                 right: self.left.left
 
-                             }),
 
-                             right: self.right.right
 
-                         });
 
-                     }
 
-                 }
 
-             }
 
-         }
 
-         // x && (y && z)  ==>  x && y && z
 
-         // x || (y || z)  ==>  x || y || z
 
-         // x + ("y" + z)  ==>  x + "y" + z
 
-         // "x" + (y + "z")==>  "x" + y + "z"
 
-         if (self.right instanceof AST_Binary
 
-             && self.right.operator == self.operator
 
-             && (self.operator == "&&"
 
-                 || self.operator == "||"
 
-                 || (self.operator == "+"
 
-                     && (self.right.left.is_string(compressor)
 
-                         || (self.left.is_string(compressor)
 
-                             && self.right.right.is_string(compressor))))))
 
-         {
 
-             self.left = make_node(AST_Binary, self.left, {
 
-                 operator : self.operator,
 
-                 left     : self.left,
 
-                 right    : self.right.left
 
-             });
 
-             self.right = self.right.right;
 
-             return self.transform(compressor);
 
-         }
 
-         var ev = self.evaluate(compressor);
 
-         if (ev !== self) {
 
-             ev = make_node_from_constant(ev, self).optimize(compressor);
 
-             return best_of(compressor, ev, self);
 
-         }
 
-         return self;
 
-     });
 
-     OPT(AST_SymbolRef, function(self, compressor){
 
-         var def = self.resolve_defines(compressor);
 
-         if (def) {
 
-             return def.optimize(compressor);
 
-         }
 
-         // testing against !self.scope.uses_with first is an optimization
 
-         if (compressor.option("screw_ie8")
 
-             && self.undeclared()
 
-             && (!self.scope.uses_with || !compressor.find_parent(AST_With))) {
 
-             switch (self.name) {
 
-               case "undefined":
 
-                 return make_node(AST_Undefined, self).optimize(compressor);
 
-               case "NaN":
 
-                 return make_node(AST_NaN, self).optimize(compressor);
 
-               case "Infinity":
 
-                 return make_node(AST_Infinity, self).optimize(compressor);
 
-             }
 
-         }
 
-         if (compressor.option("evaluate")
 
-             && compressor.option("reduce_vars")
 
-             && is_lhs(self, compressor.parent()) !== self) {
 
-             var d = self.definition();
 
-             var fixed = self.fixed_value();
 
-             if (fixed) {
 
-                 if (d.should_replace === undefined) {
 
-                     var init = fixed.evaluate(compressor);
 
-                     if (init !== fixed && (compressor.option("unsafe_regexp") || !(init instanceof RegExp))) {
 
-                         init = make_node_from_constant(init, fixed);
 
-                         var value = init.optimize(compressor).print_to_string().length;
 
-                         var fn;
 
-                         if (has_symbol_ref(fixed)) {
 
-                             fn = function() {
 
-                                 var result = init.optimize(compressor);
 
-                                 return result === init ? result.clone(true) : result;
 
-                             };
 
-                         } else {
 
-                             value = Math.min(value, fixed.print_to_string().length);
 
-                             fn = function() {
 
-                                 var result = best_of_expression(init.optimize(compressor), fixed);
 
-                                 return result === init || result === fixed ? result.clone(true) : result;
 
-                             };
 
-                         }
 
-                         var name = d.name.length;
 
-                         var overhead = 0;
 
-                         if (compressor.option("unused") && (!d.global || compressor.option("toplevel"))) {
 
-                             overhead = (name + 2 + value) / d.references.length;
 
-                         }
 
-                         d.should_replace = value <= name + overhead ? fn : false;
 
-                     } else {
 
-                         d.should_replace = false;
 
-                     }
 
-                 }
 
-                 if (d.should_replace) {
 
-                     return d.should_replace();
 
-                 }
 
-             }
 
-         }
 
-         return self;
 
-         function has_symbol_ref(value) {
 
-             var found;
 
-             value.walk(new TreeWalker(function(node) {
 
-                 if (node instanceof AST_SymbolRef) found = true;
 
-                 if (found) return true;
 
-             }));
 
-             return found;
 
-         }
 
-     });
 
-     function is_atomic(lhs, self) {
 
-         return lhs instanceof AST_SymbolRef || lhs.TYPE === self.TYPE;
 
-     }
 
-     OPT(AST_Undefined, function(self, compressor){
 
-         if (compressor.option("unsafe")) {
 
-             var undef = find_variable(compressor, "undefined");
 
-             if (undef) {
 
-                 var ref = make_node(AST_SymbolRef, self, {
 
-                     name   : "undefined",
 
-                     scope  : undef.scope,
 
-                     thedef : undef
 
-                 });
 
-                 ref.is_undefined = true;
 
-                 return ref;
 
-             }
 
-         }
 
-         var lhs = is_lhs(compressor.self(), compressor.parent());
 
-         if (lhs && is_atomic(lhs, self)) return self;
 
-         return make_node(AST_UnaryPrefix, self, {
 
-             operator: "void",
 
-             expression: make_node(AST_Number, self, {
 
-                 value: 0
 
-             })
 
-         });
 
-     });
 
-     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, {
 
-             operator: "/",
 
-             left: make_node(AST_Number, self, {
 
-                 value: 1
 
-             }),
 
-             right: make_node(AST_Number, self, {
 
-                 value: 0
 
-             })
 
-         });
 
-     });
 
-     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, {
 
-                 operator: "/",
 
-                 left: make_node(AST_Number, self, {
 
-                     value: 0
 
-                 }),
 
-                 right: make_node(AST_Number, self, {
 
-                     value: 0
 
-                 })
 
-             });
 
-         }
 
-         return self;
 
-     });
 
-     var ASSIGN_OPS = [ '+', '-', '/', '*', '%', '>>', '<<', '>>>', '|', '^', '&' ];
 
-     var ASSIGN_OPS_COMMUTATIVE = [ '*', '|', '^', '&' ];
 
-     OPT(AST_Assign, function(self, compressor){
 
-         self = self.lift_sequences(compressor);
 
-         if (self.operator == "=" && self.left instanceof AST_SymbolRef && self.right instanceof AST_Binary) {
 
-             // x = expr1 OP expr2
 
-             if (self.right.left instanceof AST_SymbolRef
 
-                 && self.right.left.name == self.left.name
 
-                 && member(self.right.operator, ASSIGN_OPS)) {
 
-                 // x = x - 2  --->  x -= 2
 
-                 self.operator = self.right.operator + "=";
 
-                 self.right = self.right.right;
 
-             }
 
-             else if (self.right.right instanceof AST_SymbolRef
 
-                 && self.right.right.name == self.left.name
 
-                 && member(self.right.operator, ASSIGN_OPS_COMMUTATIVE)
 
-                 && !self.right.left.has_side_effects(compressor)) {
 
-                 // x = 2 & x  --->  x &= 2
 
-                 self.operator = self.right.operator + "=";
 
-                 self.right = self.right.left;
 
-             }
 
-         }
 
-         return self;
 
-     });
 
-     OPT(AST_Conditional, function(self, compressor){
 
-         if (!compressor.option("conditionals")) return self;
 
-         if (self.condition instanceof AST_Seq) {
 
-             var car = self.condition.car;
 
-             self.condition = self.condition.cdr;
 
-             return AST_Seq.cons(car, self);
 
-         }
 
-         var cond = self.condition.evaluate(compressor);
 
-         if (cond !== self.condition) {
 
-             if (cond) {
 
-                 compressor.warn("Condition always true [{file}:{line},{col}]", self.start);
 
-                 return maintain_this_binding(compressor.parent(), self, self.consequent);
 
-             } else {
 
-                 compressor.warn("Condition always false [{file}:{line},{col}]", self.start);
 
-                 return maintain_this_binding(compressor.parent(), self, self.alternative);
 
-             }
 
-         }
 
-         var negated = cond.negate(compressor, first_in_statement(compressor));
 
-         if (best_of(compressor, cond, negated) === negated) {
 
-             self = make_node(AST_Conditional, self, {
 
-                 condition: negated,
 
-                 consequent: self.alternative,
 
-                 alternative: self.consequent
 
-             });
 
-         }
 
-         var condition = self.condition;
 
-         var consequent = self.consequent;
 
-         var alternative = self.alternative;
 
-         // x?x:y --> x||y
 
-         if (condition instanceof AST_SymbolRef
 
-             && consequent instanceof AST_SymbolRef
 
-             && condition.definition() === consequent.definition()) {
 
-             return make_node(AST_Binary, self, {
 
-                 operator: "||",
 
-                 left: condition,
 
-                 right: alternative
 
-             });
 
-         }
 
-         // if (foo) exp = something; else exp = something_else;
 
-         //                   |
 
-         //                   v
 
-         // exp = foo ? something : something_else;
 
-         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, {
 
-                 operator: consequent.operator,
 
-                 left: consequent.left,
 
-                 right: make_node(AST_Conditional, self, {
 
-                     condition: self.condition,
 
-                     consequent: consequent.right,
 
-                     alternative: alternative.right
 
-                 })
 
-             });
 
-         }
 
-         // x ? y(a) : y(b) --> y(x ? a : b)
 
-         if (consequent instanceof AST_Call
 
-             && alternative.TYPE === consequent.TYPE
 
-             && consequent.args.length == 1
 
-             && alternative.args.length == 1
 
-             && consequent.expression.equivalent_to(alternative.expression)
 
-             && !consequent.expression.has_side_effects(compressor)) {
 
-             consequent.args[0] = make_node(AST_Conditional, self, {
 
-                 condition: self.condition,
 
-                 consequent: consequent.args[0],
 
-                 alternative: alternative.args[0]
 
-             });
 
-             return consequent;
 
-         }
 
-         // x?y?z:a:a --> x&&y?z:a
 
-         if (consequent instanceof AST_Conditional
 
-             && consequent.alternative.equivalent_to(alternative)) {
 
-             return make_node(AST_Conditional, self, {
 
-                 condition: make_node(AST_Binary, self, {
 
-                     left: self.condition,
 
-                     operator: "&&",
 
-                     right: consequent.condition
 
-                 }),
 
-                 consequent: consequent.consequent,
 
-                 alternative: alternative
 
-             });
 
-         }
 
-         // x ? y : y --> x, y
 
-         if (consequent.equivalent_to(alternative)) {
 
-             return make_node(AST_Seq, self, {
 
-                 car: self.condition,
 
-                 cdr: consequent
 
-             }).optimize(compressor);
 
-         }
 
-         if (is_true(self.consequent)) {
 
-             if (is_false(self.alternative)) {
 
-                 // c ? true : false ---> !!c
 
-                 return booleanize(self.condition);
 
-             }
 
-             // c ? true : x ---> !!c || x
 
-             return make_node(AST_Binary, self, {
 
-                 operator: "||",
 
-                 left: booleanize(self.condition),
 
-                 right: self.alternative
 
-             });
 
-         }
 
-         if (is_false(self.consequent)) {
 
-             if (is_true(self.alternative)) {
 
-                 // c ? false : true ---> !c
 
-                 return booleanize(self.condition.negate(compressor));
 
-             }
 
-             // c ? false : x ---> !c && x
 
-             return make_node(AST_Binary, self, {
 
-                 operator: "&&",
 
-                 left: booleanize(self.condition.negate(compressor)),
 
-                 right: self.alternative
 
-             });
 
-         }
 
-         if (is_true(self.alternative)) {
 
-             // c ? x : true ---> !c || x
 
-             return make_node(AST_Binary, self, {
 
-                 operator: "||",
 
-                 left: booleanize(self.condition.negate(compressor)),
 
-                 right: self.consequent
 
-             });
 
-         }
 
-         if (is_false(self.alternative)) {
 
-             // c ? x : false ---> !!c && x
 
-             return make_node(AST_Binary, self, {
 
-                 operator: "&&",
 
-                 left: booleanize(self.condition),
 
-                 right: self.consequent
 
-             });
 
-         }
 
-         return self;
 
-         function booleanize(node) {
 
-             if (node.is_boolean()) return node;
 
-             // !!expression
 
-             return make_node(AST_UnaryPrefix, node, {
 
-                 operator: "!",
 
-                 expression: node.negate(compressor)
 
-             });
 
-         }
 
-         // AST_True or !0
 
-         function is_true(node) {
 
-             return node instanceof AST_True
 
-                 || (node instanceof AST_UnaryPrefix
 
-                     && node.operator == "!"
 
-                     && node.expression instanceof AST_Constant
 
-                     && !node.expression.value);
 
-         }
 
-         // AST_False or !1
 
-         function is_false(node) {
 
-             return node instanceof AST_False
 
-                 || (node instanceof AST_UnaryPrefix
 
-                     && node.operator == "!"
 
-                     && node.expression instanceof AST_Constant
 
-                     && !!node.expression.value);
 
-         }
 
-     });
 
-     OPT(AST_Boolean, function(self, compressor){
 
-         if (compressor.option("booleans")) {
 
-             var p = compressor.parent();
 
-             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,
 
-                     file     : p.start.file,
 
-                     line     : p.start.line,
 
-                     col      : p.start.col,
 
-                 });
 
-                 return make_node(AST_Number, self, {
 
-                     value: +self.value
 
-                 });
 
-             }
 
-             return make_node(AST_UnaryPrefix, self, {
 
-                 operator: "!",
 
-                 expression: make_node(AST_Number, self, {
 
-                     value: 1 - self.value
 
-                 })
 
-             });
 
-         }
 
-         return self;
 
-     });
 
-     OPT(AST_Sub, function(self, compressor){
 
-         var prop = self.property;
 
-         if (prop instanceof AST_String && compressor.option("properties")) {
 
-             prop = prop.getValue();
 
-             if (RESERVED_WORDS(prop) ? compressor.option("screw_ie8") : is_identifier_string(prop)) {
 
-                 return make_node(AST_Dot, self, {
 
-                     expression : self.expression,
 
-                     property   : prop
 
-                 }).optimize(compressor);
 
-             }
 
-             var v = parseFloat(prop);
 
-             if (!isNaN(v) && v.toString() == prop) {
 
-                 self.property = make_node(AST_Number, self.property, {
 
-                     value: v
 
-                 });
 
-             }
 
-         }
 
-         var ev = self.evaluate(compressor);
 
-         if (ev !== self) {
 
-             ev = make_node_from_constant(ev, self).optimize(compressor);
 
-             return best_of(compressor, ev, self);
 
-         }
 
-         return self;
 
-     });
 
-     OPT(AST_Dot, function(self, compressor){
 
-         var def = self.resolve_defines(compressor);
 
-         if (def) {
 
-             return def.optimize(compressor);
 
-         }
 
-         var prop = self.property;
 
-         if (RESERVED_WORDS(prop) && !compressor.option("screw_ie8")) {
 
-             return make_node(AST_Sub, self, {
 
-                 expression : self.expression,
 
-                 property   : make_node(AST_String, self, {
 
-                     value: prop
 
-                 })
 
-             }).optimize(compressor);
 
-         }
 
-         if (compressor.option("unsafe_proto")
 
-             && self.expression instanceof AST_Dot
 
-             && self.expression.property == "prototype") {
 
-             var exp = self.expression.expression;
 
-             if (exp instanceof AST_SymbolRef && exp.undeclared()) switch (exp.name) {
 
-               case "Array":
 
-                 self.expression = make_node(AST_Array, self.expression, {
 
-                     elements: []
 
-                 });
 
-                 break;
 
-               case "Object":
 
-                 self.expression = make_node(AST_Object, self.expression, {
 
-                     properties: []
 
-                 });
 
-                 break;
 
-               case "String":
 
-                 self.expression = make_node(AST_String, self.expression, {
 
-                     value: ""
 
-                 });
 
-                 break;
 
-             }
 
-         }
 
-         var ev = self.evaluate(compressor);
 
-         if (ev !== self) {
 
-             ev = make_node_from_constant(ev, self).optimize(compressor);
 
-             return best_of(compressor, ev, self);
 
-         }
 
-         return self;
 
-     });
 
-     function literals_in_boolean_context(self, compressor) {
 
-         if (compressor.option("booleans") && compressor.in_boolean_context()) {
 
-             return best_of(compressor, self, make_node(AST_Seq, self, {
 
-                 car: self,
 
-                 cdr: make_node(AST_True, self)
 
-             }).optimize(compressor));
 
-         }
 
-         return self;
 
-     };
 
-     OPT(AST_Array, literals_in_boolean_context);
 
-     OPT(AST_Object, literals_in_boolean_context);
 
-     OPT(AST_RegExp, literals_in_boolean_context);
 
-     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){
 
-         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);
 
-         }
 
-         return self;
 
-     });
 
- })();
 
 
  |