| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075 |
- define(function(require, exports, module) {
- // 2.1.9
- require = null;
- require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({
- 9:[function (req,module,exports){
- ["log", "info", "warn", "error",
- "time","timeEnd", "trace", "dir", "assert"
- ].forEach(function(x) {exports[x] = nop;});
- function nop() {}
- },{}],
- 1:[function(req,module,exports){
- // Underscore.js 1.4.4
- // http://underscorejs.org
- // (c) 2009-2013 Jeremy Ashkenas, DocumentCloud Inc.
- // Underscore may be freely distributed under the MIT license.
- (function() {
- // Baseline setup
- // --------------
- // Establish the root object, `window` in the browser, or `global` on the server.
- var root = this;
- // Save the previous value of the `_` variable.
- var previousUnderscore = root._;
- // Establish the object that gets returned to break out of a loop iteration.
- var breaker = {};
- // Save bytes in the minified (but not gzipped) version:
- var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
- // Create quick reference variables for speed access to core prototypes.
- var push = ArrayProto.push,
- slice = ArrayProto.slice,
- concat = ArrayProto.concat,
- toString = ObjProto.toString,
- hasOwnProperty = ObjProto.hasOwnProperty;
- // All **ECMAScript 5** native function implementations that we hope to use
- // are declared here.
- var
- nativeForEach = ArrayProto.forEach,
- nativeMap = ArrayProto.map,
- nativeReduce = ArrayProto.reduce,
- nativeReduceRight = ArrayProto.reduceRight,
- nativeFilter = ArrayProto.filter,
- nativeEvery = ArrayProto.every,
- nativeSome = ArrayProto.some,
- nativeIndexOf = ArrayProto.indexOf,
- nativeLastIndexOf = ArrayProto.lastIndexOf,
- nativeIsArray = Array.isArray,
- nativeKeys = Object.keys,
- nativeBind = FuncProto.bind;
- // Create a safe reference to the Underscore object for use below.
- var _ = function(obj) {
- if (obj instanceof _) return obj;
- if (!(this instanceof _)) return new _(obj);
- this._wrapped = obj;
- };
- // Export the Underscore object for **Node.js**, with
- // backwards-compatibility for the old `require()` API. If we're in
- // the browser, add `_` as a global object via a string identifier,
- // for Closure Compiler "advanced" mode.
- if (typeof exports !== 'undefined') {
- if (typeof module !== 'undefined' && module.exports) {
- exports = module.exports = _;
- }
- exports._ = _;
- } else {
- root._ = _;
- }
- // Current version.
- _.VERSION = '1.4.4';
- // Collection Functions
- // --------------------
- // The cornerstone, an `each` implementation, aka `forEach`.
- // Handles objects with the built-in `forEach`, arrays, and raw objects.
- // Delegates to **ECMAScript 5**'s native `forEach` if available.
- var each = _.each = _.forEach = function(obj, iterator, context) {
- if (obj == null) return;
- if (nativeForEach && obj.forEach === nativeForEach) {
- obj.forEach(iterator, context);
- } else if (obj.length === +obj.length) {
- for (var i = 0, l = obj.length; i < l; i++) {
- if (iterator.call(context, obj[i], i, obj) === breaker) return;
- }
- } else {
- for (var key in obj) {
- if (_.has(obj, key)) {
- if (iterator.call(context, obj[key], key, obj) === breaker) return;
- }
- }
- }
- };
- // Return the results of applying the iterator to each element.
- // Delegates to **ECMAScript 5**'s native `map` if available.
- _.map = _.collect = function(obj, iterator, context) {
- var results = [];
- if (obj == null) return results;
- if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
- each(obj, function(value, index, list) {
- results[results.length] = iterator.call(context, value, index, list);
- });
- return results;
- };
- var reduceError = 'Reduce of empty array with no initial value';
- // **Reduce** builds up a single result from a list of values, aka `inject`,
- // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.
- _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
- var initial = arguments.length > 2;
- if (obj == null) obj = [];
- if (nativeReduce && obj.reduce === nativeReduce) {
- if (context) iterator = _.bind(iterator, context);
- return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
- }
- each(obj, function(value, index, list) {
- if (!initial) {
- memo = value;
- initial = true;
- } else {
- memo = iterator.call(context, memo, value, index, list);
- }
- });
- if (!initial) throw new TypeError(reduceError);
- return memo;
- };
- // The right-associative version of reduce, also known as `foldr`.
- // Delegates to **ECMAScript 5**'s native `reduceRight` if available.
- _.reduceRight = _.foldr = function(obj, iterator, memo, context) {
- var initial = arguments.length > 2;
- if (obj == null) obj = [];
- if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
- if (context) iterator = _.bind(iterator, context);
- return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
- }
- var length = obj.length;
- if (length !== +length) {
- var keys = _.keys(obj);
- length = keys.length;
- }
- each(obj, function(value, index, list) {
- index = keys ? keys[--length] : --length;
- if (!initial) {
- memo = obj[index];
- initial = true;
- } else {
- memo = iterator.call(context, memo, obj[index], index, list);
- }
- });
- if (!initial) throw new TypeError(reduceError);
- return memo;
- };
- // Return the first value which passes a truth test. Aliased as `detect`.
- _.find = _.detect = function(obj, iterator, context) {
- var result;
- any(obj, function(value, index, list) {
- if (iterator.call(context, value, index, list)) {
- result = value;
- return true;
- }
- });
- return result;
- };
- // Return all the elements that pass a truth test.
- // Delegates to **ECMAScript 5**'s native `filter` if available.
- // Aliased as `select`.
- _.filter = _.select = function(obj, iterator, context) {
- var results = [];
- if (obj == null) return results;
- if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
- each(obj, function(value, index, list) {
- if (iterator.call(context, value, index, list)) results[results.length] = value;
- });
- return results;
- };
- // Return all the elements for which a truth test fails.
- _.reject = function(obj, iterator, context) {
- return _.filter(obj, function(value, index, list) {
- return !iterator.call(context, value, index, list);
- }, context);
- };
- // Determine whether all of the elements match a truth test.
- // Delegates to **ECMAScript 5**'s native `every` if available.
- // Aliased as `all`.
- _.every = _.all = function(obj, iterator, context) {
- iterator || (iterator = _.identity);
- var result = true;
- if (obj == null) return result;
- if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
- each(obj, function(value, index, list) {
- if (!(result = result && iterator.call(context, value, index, list))) return breaker;
- });
- return !!result;
- };
- // Determine if at least one element in the object matches a truth test.
- // Delegates to **ECMAScript 5**'s native `some` if available.
- // Aliased as `any`.
- var any = _.some = _.any = function(obj, iterator, context) {
- iterator || (iterator = _.identity);
- var result = false;
- if (obj == null) return result;
- if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
- each(obj, function(value, index, list) {
- if (result || (result = iterator.call(context, value, index, list))) return breaker;
- });
- return !!result;
- };
- // Determine if the array or object contains a given value (using `===`).
- // Aliased as `include`.
- _.contains = _.include = function(obj, target) {
- if (obj == null) return false;
- if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
- return any(obj, function(value) {
- return value === target;
- });
- };
- // Invoke a method (with arguments) on every item in a collection.
- _.invoke = function(obj, method) {
- var args = slice.call(arguments, 2);
- var isFunc = _.isFunction(method);
- return _.map(obj, function(value) {
- return (isFunc ? method : value[method]).apply(value, args);
- });
- };
- // Convenience version of a common use case of `map`: fetching a property.
- _.pluck = function(obj, key) {
- return _.map(obj, function(value){ return value[key]; });
- };
- // Convenience version of a common use case of `filter`: selecting only objects
- // containing specific `key:value` pairs.
- _.where = function(obj, attrs, first) {
- if (_.isEmpty(attrs)) return first ? null : [];
- return _[first ? 'find' : 'filter'](obj, function(value) {
- for (var key in attrs) {
- if (attrs[key] !== value[key]) return false;
- }
- return true;
- });
- };
- // Convenience version of a common use case of `find`: getting the first object
- // containing specific `key:value` pairs.
- _.findWhere = function(obj, attrs) {
- return _.where(obj, attrs, true);
- };
- // Return the maximum element or (element-based computation).
- // Can't optimize arrays of integers longer than 65,535 elements.
- // See: https://bugs.webkit.org/show_bug.cgi?id=80797
- _.max = function(obj, iterator, context) {
- if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
- return Math.max.apply(Math, obj);
- }
- if (!iterator && _.isEmpty(obj)) return -Infinity;
- var result = {computed : -Infinity, value: -Infinity};
- each(obj, function(value, index, list) {
- var computed = iterator ? iterator.call(context, value, index, list) : value;
- computed >= result.computed && (result = {value : value, computed : computed});
- });
- return result.value;
- };
- // Return the minimum element (or element-based computation).
- _.min = function(obj, iterator, context) {
- if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
- return Math.min.apply(Math, obj);
- }
- if (!iterator && _.isEmpty(obj)) return Infinity;
- var result = {computed : Infinity, value: Infinity};
- each(obj, function(value, index, list) {
- var computed = iterator ? iterator.call(context, value, index, list) : value;
- computed < result.computed && (result = {value : value, computed : computed});
- });
- return result.value;
- };
- // Shuffle an array.
- _.shuffle = function(obj) {
- var rand;
- var index = 0;
- var shuffled = [];
- each(obj, function(value) {
- rand = _.random(index++);
- shuffled[index - 1] = shuffled[rand];
- shuffled[rand] = value;
- });
- return shuffled;
- };
- // An internal function to generate lookup iterators.
- var lookupIterator = function(value) {
- return _.isFunction(value) ? value : function(obj){ return obj[value]; };
- };
- // Sort the object's values by a criterion produced by an iterator.
- _.sortBy = function(obj, value, context) {
- var iterator = lookupIterator(value);
- return _.pluck(_.map(obj, function(value, index, list) {
- return {
- value : value,
- index : index,
- criteria : iterator.call(context, value, index, list)
- };
- }).sort(function(left, right) {
- var a = left.criteria;
- var b = right.criteria;
- if (a !== b) {
- if (a > b || a === void 0) return 1;
- if (a < b || b === void 0) return -1;
- }
- return left.index < right.index ? -1 : 1;
- }), 'value');
- };
- // An internal function used for aggregate "group by" operations.
- var group = function(obj, value, context, behavior) {
- var result = {};
- var iterator = lookupIterator(value || _.identity);
- each(obj, function(value, index) {
- var key = iterator.call(context, value, index, obj);
- behavior(result, key, value);
- });
- return result;
- };
- // Groups the object's values by a criterion. Pass either a string attribute
- // to group by, or a function that returns the criterion.
- _.groupBy = function(obj, value, context) {
- return group(obj, value, context, function(result, key, value) {
- (_.has(result, key) ? result[key] : (result[key] = [])).push(value);
- });
- };
- // Counts instances of an object that group by a certain criterion. Pass
- // either a string attribute to count by, or a function that returns the
- // criterion.
- _.countBy = function(obj, value, context) {
- return group(obj, value, context, function(result, key) {
- if (!_.has(result, key)) result[key] = 0;
- result[key]++;
- });
- };
- // Use a comparator function to figure out the smallest index at which
- // an object should be inserted so as to maintain order. Uses binary search.
- _.sortedIndex = function(array, obj, iterator, context) {
- iterator = iterator == null ? _.identity : lookupIterator(iterator);
- var value = iterator.call(context, obj);
- var low = 0, high = array.length;
- while (low < high) {
- var mid = (low + high) >>> 1;
- iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid;
- }
- return low;
- };
- // Safely convert anything iterable into a real, live array.
- _.toArray = function(obj) {
- if (!obj) return [];
- if (_.isArray(obj)) return slice.call(obj);
- if (obj.length === +obj.length) return _.map(obj, _.identity);
- return _.values(obj);
- };
- // Return the number of elements in an object.
- _.size = function(obj) {
- if (obj == null) return 0;
- return (obj.length === +obj.length) ? obj.length : _.keys(obj).length;
- };
- // Array Functions
- // ---------------
- // Get the first element of an array. Passing **n** will return the first N
- // values in the array. Aliased as `head` and `take`. The **guard** check
- // allows it to work with `_.map`.
- _.first = _.head = _.take = function(array, n, guard) {
- if (array == null) return void 0;
- return (n != null) && !guard ? slice.call(array, 0, n) : array[0];
- };
- // Returns everything but the last entry of the array. Especially useful on
- // the arguments object. Passing **n** will return all the values in
- // the array, excluding the last N. The **guard** check allows it to work with
- // `_.map`.
- _.initial = function(array, n, guard) {
- return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n));
- };
- // Get the last element of an array. Passing **n** will return the last N
- // values in the array. The **guard** check allows it to work with `_.map`.
- _.last = function(array, n, guard) {
- if (array == null) return void 0;
- if ((n != null) && !guard) {
- return slice.call(array, Math.max(array.length - n, 0));
- } else {
- return array[array.length - 1];
- }
- };
- // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
- // Especially useful on the arguments object. Passing an **n** will return
- // the rest N values in the array. The **guard**
- // check allows it to work with `_.map`.
- _.rest = _.tail = _.drop = function(array, n, guard) {
- return slice.call(array, (n == null) || guard ? 1 : n);
- };
- // Trim out all falsy values from an array.
- _.compact = function(array) {
- return _.filter(array, _.identity);
- };
- // Internal implementation of a recursive `flatten` function.
- var flatten = function(input, shallow, output) {
- each(input, function(value) {
- if (_.isArray(value)) {
- shallow ? push.apply(output, value) : flatten(value, shallow, output);
- } else {
- output.push(value);
- }
- });
- return output;
- };
- // Return a completely flattened version of an array.
- _.flatten = function(array, shallow) {
- return flatten(array, shallow, []);
- };
- // Return a version of the array that does not contain the specified value(s).
- _.without = function(array) {
- return _.difference(array, slice.call(arguments, 1));
- };
- // Produce a duplicate-free version of the array. If the array has already
- // been sorted, you have the option of using a faster algorithm.
- // Aliased as `unique`.
- _.uniq = _.unique = function(array, isSorted, iterator, context) {
- if (_.isFunction(isSorted)) {
- context = iterator;
- iterator = isSorted;
- isSorted = false;
- }
- var initial = iterator ? _.map(array, iterator, context) : array;
- var results = [];
- var seen = [];
- each(initial, function(value, index) {
- if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) {
- seen.push(value);
- results.push(array[index]);
- }
- });
- return results;
- };
- // Produce an array that contains the union: each distinct element from all of
- // the passed-in arrays.
- _.union = function() {
- return _.uniq(concat.apply(ArrayProto, arguments));
- };
- // Produce an array that contains every item shared between all the
- // passed-in arrays.
- _.intersection = function(array) {
- var rest = slice.call(arguments, 1);
- return _.filter(_.uniq(array), function(item) {
- return _.every(rest, function(other) {
- return _.indexOf(other, item) >= 0;
- });
- });
- };
- // Take the difference between one array and a number of other arrays.
- // Only the elements present in just the first array will remain.
- _.difference = function(array) {
- var rest = concat.apply(ArrayProto, slice.call(arguments, 1));
- return _.filter(array, function(value){ return !_.contains(rest, value); });
- };
- // Zip together multiple lists into a single array -- elements that share
- // an index go together.
- _.zip = function() {
- var args = slice.call(arguments);
- var length = _.max(_.pluck(args, 'length'));
- var results = new Array(length);
- for (var i = 0; i < length; i++) {
- results[i] = _.pluck(args, "" + i);
- }
- return results;
- };
- // Converts lists into objects. Pass either a single array of `[key, value]`
- // pairs, or two parallel arrays of the same length -- one of keys, and one of
- // the corresponding values.
- _.object = function(list, values) {
- if (list == null) return {};
- var result = {};
- for (var i = 0, l = list.length; i < l; i++) {
- if (values) {
- result[list[i]] = values[i];
- } else {
- result[list[i][0]] = list[i][1];
- }
- }
- return result;
- };
- // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),
- // we need this function. Return the position of the first occurrence of an
- // item in an array, or -1 if the item is not included in the array.
- // Delegates to **ECMAScript 5**'s native `indexOf` if available.
- // If the array is large and already in sort order, pass `true`
- // for **isSorted** to use binary search.
- _.indexOf = function(array, item, isSorted) {
- if (array == null) return -1;
- var i = 0, l = array.length;
- if (isSorted) {
- if (typeof isSorted == 'number') {
- i = (isSorted < 0 ? Math.max(0, l + isSorted) : isSorted);
- } else {
- i = _.sortedIndex(array, item);
- return array[i] === item ? i : -1;
- }
- }
- if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted);
- for (; i < l; i++) if (array[i] === item) return i;
- return -1;
- };
- // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
- _.lastIndexOf = function(array, item, from) {
- if (array == null) return -1;
- var hasIndex = from != null;
- if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) {
- return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item);
- }
- var i = (hasIndex ? from : array.length);
- while (i--) if (array[i] === item) return i;
- return -1;
- };
- // Generate an integer Array containing an arithmetic progression. A port of
- // the native Python `range()` function. See
- // [the Python documentation](http://docs.python.org/library/functions.html#range).
- _.range = function(start, stop, step) {
- if (arguments.length <= 1) {
- stop = start || 0;
- start = 0;
- }
- step = arguments[2] || 1;
- var len = Math.max(Math.ceil((stop - start) / step), 0);
- var idx = 0;
- var range = new Array(len);
- while(idx < len) {
- range[idx++] = start;
- start += step;
- }
- return range;
- };
- // Function (ahem) Functions
- // ------------------
- // Create a function bound to a given object (assigning `this`, and arguments,
- // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if
- // available.
- _.bind = function(func, context) {
- if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
- var args = slice.call(arguments, 2);
- return function() {
- return func.apply(context, args.concat(slice.call(arguments)));
- };
- };
- // Partially apply a function by creating a version that has had some of its
- // arguments pre-filled, without changing its dynamic `this` context.
- _.partial = function(func) {
- var args = slice.call(arguments, 1);
- return function() {
- return func.apply(this, args.concat(slice.call(arguments)));
- };
- };
- // Bind all of an object's methods to that object. Useful for ensuring that
- // all callbacks defined on an object belong to it.
- _.bindAll = function(obj) {
- var funcs = slice.call(arguments, 1);
- if (funcs.length === 0) funcs = _.functions(obj);
- each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
- return obj;
- };
- // Memoize an expensive function by storing its results.
- _.memoize = function(func, hasher) {
- var memo = {};
- hasher || (hasher = _.identity);
- return function() {
- var key = hasher.apply(this, arguments);
- return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
- };
- };
- // Delays a function for the given number of milliseconds, and then calls
- // it with the arguments supplied.
- _.delay = function(func, wait) {
- var args = slice.call(arguments, 2);
- return setTimeout(function(){ return func.apply(null, args); }, wait);
- };
- // Defers a function, scheduling it to run after the current call stack has
- // cleared.
- _.defer = function(func) {
- return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
- };
- // Returns a function, that, when invoked, will only be triggered at most once
- // during a given window of time.
- _.throttle = function(func, wait) {
- var context, args, timeout, result;
- var previous = 0;
- var later = function() {
- previous = new Date;
- timeout = null;
- result = func.apply(context, args);
- };
- return function() {
- var now = new Date;
- var remaining = wait - (now - previous);
- context = this;
- args = arguments;
- if (remaining <= 0) {
- clearTimeout(timeout);
- timeout = null;
- previous = now;
- result = func.apply(context, args);
- } else if (!timeout) {
- timeout = setTimeout(later, remaining);
- }
- return result;
- };
- };
- // Returns a function, that, as long as it continues to be invoked, will not
- // be triggered. The function will be called after it stops being called for
- // N milliseconds. If `immediate` is passed, trigger the function on the
- // leading edge, instead of the trailing.
- _.debounce = function(func, wait, immediate) {
- var timeout, result;
- return function() {
- var context = this, args = arguments;
- var later = function() {
- timeout = null;
- if (!immediate) result = func.apply(context, args);
- };
- var callNow = immediate && !timeout;
- clearTimeout(timeout);
- timeout = setTimeout(later, wait);
- if (callNow) result = func.apply(context, args);
- return result;
- };
- };
- // Returns a function that will be executed at most one time, no matter how
- // often you call it. Useful for lazy initialization.
- _.once = function(func) {
- var ran = false, memo;
- return function() {
- if (ran) return memo;
- ran = true;
- memo = func.apply(this, arguments);
- func = null;
- return memo;
- };
- };
- // Returns the first function passed as an argument to the second,
- // allowing you to adjust arguments, run code before and after, and
- // conditionally execute the original function.
- _.wrap = function(func, wrapper) {
- return function() {
- var args = [func];
- push.apply(args, arguments);
- return wrapper.apply(this, args);
- };
- };
- // Returns a function that is the composition of a list of functions, each
- // consuming the return value of the function that follows.
- _.compose = function() {
- var funcs = arguments;
- return function() {
- var args = arguments;
- for (var i = funcs.length - 1; i >= 0; i--) {
- args = [funcs[i].apply(this, args)];
- }
- return args[0];
- };
- };
- // Returns a function that will only be executed after being called N times.
- _.after = function(times, func) {
- if (times <= 0) return func();
- return function() {
- if (--times < 1) {
- return func.apply(this, arguments);
- }
- };
- };
- // Object Functions
- // ----------------
- // Retrieve the names of an object's properties.
- // Delegates to **ECMAScript 5**'s native `Object.keys`
- _.keys = nativeKeys || function(obj) {
- if (obj !== Object(obj)) throw new TypeError('Invalid object');
- var keys = [];
- for (var key in obj) if (_.has(obj, key)) keys[keys.length] = key;
- return keys;
- };
- // Retrieve the values of an object's properties.
- _.values = function(obj) {
- var values = [];
- for (var key in obj) if (_.has(obj, key)) values.push(obj[key]);
- return values;
- };
- // Convert an object into a list of `[key, value]` pairs.
- _.pairs = function(obj) {
- var pairs = [];
- for (var key in obj) if (_.has(obj, key)) pairs.push([key, obj[key]]);
- return pairs;
- };
- // Invert the keys and values of an object. The values must be serializable.
- _.invert = function(obj) {
- var result = {};
- for (var key in obj) if (_.has(obj, key)) result[obj[key]] = key;
- return result;
- };
- // Return a sorted list of the function names available on the object.
- // Aliased as `methods`
- _.functions = _.methods = function(obj) {
- var names = [];
- for (var key in obj) {
- if (_.isFunction(obj[key])) names.push(key);
- }
- return names.sort();
- };
- // Extend a given object with all the properties in passed-in object(s).
- _.extend = function(obj) {
- each(slice.call(arguments, 1), function(source) {
- if (source) {
- for (var prop in source) {
- obj[prop] = source[prop];
- }
- }
- });
- return obj;
- };
- // Return a copy of the object only containing the whitelisted properties.
- _.pick = function(obj) {
- var copy = {};
- var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
- each(keys, function(key) {
- if (key in obj) copy[key] = obj[key];
- });
- return copy;
- };
- // Return a copy of the object without the blacklisted properties.
- _.omit = function(obj) {
- var copy = {};
- var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
- for (var key in obj) {
- if (!_.contains(keys, key)) copy[key] = obj[key];
- }
- return copy;
- };
- // Fill in a given object with default properties.
- _.defaults = function(obj) {
- each(slice.call(arguments, 1), function(source) {
- if (source) {
- for (var prop in source) {
- if (obj[prop] == null) obj[prop] = source[prop];
- }
- }
- });
- return obj;
- };
- // Create a (shallow-cloned) duplicate of an object.
- _.clone = function(obj) {
- if (!_.isObject(obj)) return obj;
- return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
- };
- // Invokes interceptor with the obj, and then returns obj.
- // The primary purpose of this method is to "tap into" a method chain, in
- // order to perform operations on intermediate results within the chain.
- _.tap = function(obj, interceptor) {
- interceptor(obj);
- return obj;
- };
- // Internal recursive comparison function for `isEqual`.
- var eq = function(a, b, aStack, bStack) {
- // Identical objects are equal. `0 === -0`, but they aren't identical.
- // See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal.
- if (a === b) return a !== 0 || 1 / a == 1 / b;
- // A strict comparison is necessary because `null == undefined`.
- if (a == null || b == null) return a === b;
- // Unwrap any wrapped objects.
- if (a instanceof _) a = a._wrapped;
- if (b instanceof _) b = b._wrapped;
- // Compare `[[Class]]` names.
- var className = toString.call(a);
- if (className != toString.call(b)) return false;
- switch (className) {
- // Strings, numbers, dates, and booleans are compared by value.
- case '[object String]':
- // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
- // equivalent to `new String("5")`.
- return a == String(b);
- case '[object Number]':
- // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for
- // other numeric values.
- return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b);
- case '[object Date]':
- case '[object Boolean]':
- // Coerce dates and booleans to numeric primitive values. Dates are compared by their
- // millisecond representations. Note that invalid dates with millisecond representations
- // of `NaN` are not equivalent.
- return +a == +b;
- // RegExps are compared by their source patterns and flags.
- case '[object RegExp]':
- return a.source == b.source &&
- a.global == b.global &&
- a.multiline == b.multiline &&
- a.ignoreCase == b.ignoreCase;
- }
- if (typeof a != 'object' || typeof b != 'object') return false;
- // Assume equality for cyclic structures. The algorithm for detecting cyclic
- // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
- var length = aStack.length;
- while (length--) {
- // Linear search. Performance is inversely proportional to the number of
- // unique nested structures.
- if (aStack[length] == a) return bStack[length] == b;
- }
- // Add the first object to the stack of traversed objects.
- aStack.push(a);
- bStack.push(b);
- var size = 0, result = true;
- // Recursively compare objects and arrays.
- if (className == '[object Array]') {
- // Compare array lengths to determine if a deep comparison is necessary.
- size = a.length;
- result = size == b.length;
- if (result) {
- // Deep compare the contents, ignoring non-numeric properties.
- while (size--) {
- if (!(result = eq(a[size], b[size], aStack, bStack))) break;
- }
- }
- } else {
- // Objects with different constructors are not equivalent, but `Object`s
- // from different frames are.
- var aCtor = a.constructor, bCtor = b.constructor;
- if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) &&
- _.isFunction(bCtor) && (bCtor instanceof bCtor))) {
- return false;
- }
- // Deep compare objects.
- for (var key in a) {
- if (_.has(a, key)) {
- // Count the expected number of properties.
- size++;
- // Deep compare each member.
- if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break;
- }
- }
- // Ensure that both objects contain the same number of properties.
- if (result) {
- for (key in b) {
- if (_.has(b, key) && !(size--)) break;
- }
- result = !size;
- }
- }
- // Remove the first object from the stack of traversed objects.
- aStack.pop();
- bStack.pop();
- return result;
- };
- // Perform a deep comparison to check if two objects are equal.
- _.isEqual = function(a, b) {
- return eq(a, b, [], []);
- };
- // Is a given array, string, or object empty?
- // An "empty" object has no enumerable own-properties.
- _.isEmpty = function(obj) {
- if (obj == null) return true;
- if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
- for (var key in obj) if (_.has(obj, key)) return false;
- return true;
- };
- // Is a given value a DOM element?
- _.isElement = function(obj) {
- return !!(obj && obj.nodeType === 1);
- };
- // Is a given value an array?
- // Delegates to ECMA5's native Array.isArray
- _.isArray = nativeIsArray || function(obj) {
- return toString.call(obj) == '[object Array]';
- };
- // Is a given variable an object?
- _.isObject = function(obj) {
- return obj === Object(obj);
- };
- // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp.
- each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) {
- _['is' + name] = function(obj) {
- return toString.call(obj) == '[object ' + name + ']';
- };
- });
- // Define a fallback version of the method in browsers (ahem, IE), where
- // there isn't any inspectable "Arguments" type.
- if (!_.isArguments(arguments)) {
- _.isArguments = function(obj) {
- return !!(obj && _.has(obj, 'callee'));
- };
- }
- // Optimize `isFunction` if appropriate.
- if (typeof (/./) !== 'function') {
- _.isFunction = function(obj) {
- return typeof obj === 'function';
- };
- }
- // Is a given object a finite number?
- _.isFinite = function(obj) {
- return isFinite(obj) && !isNaN(parseFloat(obj));
- };
- // Is the given value `NaN`? (NaN is the only number which does not equal itself).
- _.isNaN = function(obj) {
- return _.isNumber(obj) && obj != +obj;
- };
- // Is a given value a boolean?
- _.isBoolean = function(obj) {
- return obj === true || obj === false || toString.call(obj) == '[object Boolean]';
- };
- // Is a given value equal to null?
- _.isNull = function(obj) {
- return obj === null;
- };
- // Is a given variable undefined?
- _.isUndefined = function(obj) {
- return obj === void 0;
- };
- // Shortcut function for checking if an object has a given property directly
- // on itself (in other words, not on a prototype).
- _.has = function(obj, key) {
- return hasOwnProperty.call(obj, key);
- };
- // Utility Functions
- // -----------------
- // Run Underscore.js in *noConflict* mode, returning the `_` variable to its
- // previous owner. Returns a reference to the Underscore object.
- _.noConflict = function() {
- root._ = previousUnderscore;
- return this;
- };
- // Keep the identity function around for default iterators.
- _.identity = function(value) {
- return value;
- };
- // Run a function **n** times.
- _.times = function(n, iterator, context) {
- var accum = Array(n);
- for (var i = 0; i < n; i++) accum[i] = iterator.call(context, i);
- return accum;
- };
- // Return a random integer between min and max (inclusive).
- _.random = function(min, max) {
- if (max == null) {
- max = min;
- min = 0;
- }
- return min + Math.floor(Math.random() * (max - min + 1));
- };
- // List of HTML entities for escaping.
- var entityMap = {
- escape: {
- '&': '&',
- '<': '<',
- '>': '>',
- '"': '"',
- "'": ''',
- '/': '/'
- }
- };
- entityMap.unescape = _.invert(entityMap.escape);
- // Regexes containing the keys and values listed immediately above.
- var entityRegexes = {
- escape: new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'),
- unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g')
- };
- // Functions for escaping and unescaping strings to/from HTML interpolation.
- _.each(['escape', 'unescape'], function(method) {
- _[method] = function(string) {
- if (string == null) return '';
- return ('' + string).replace(entityRegexes[method], function(match) {
- return entityMap[method][match];
- });
- };
- });
- // If the value of the named property is a function then invoke it;
- // otherwise, return it.
- _.result = function(object, property) {
- if (object == null) return null;
- var value = object[property];
- return _.isFunction(value) ? value.call(object) : value;
- };
- // Add your own custom functions to the Underscore object.
- _.mixin = function(obj) {
- each(_.functions(obj), function(name){
- var func = _[name] = obj[name];
- _.prototype[name] = function() {
- var args = [this._wrapped];
- push.apply(args, arguments);
- return result.call(this, func.apply(_, args));
- };
- });
- };
- // Generate a unique integer id (unique within the entire client session).
- // Useful for temporary DOM ids.
- var idCounter = 0;
- _.uniqueId = function(prefix) {
- var id = ++idCounter + '';
- return prefix ? prefix + id : id;
- };
- // By default, Underscore uses ERB-style template delimiters, change the
- // following template settings to use alternative delimiters.
- _.templateSettings = {
- evaluate : /<%([\s\S]+?)%>/g,
- interpolate : /<%=([\s\S]+?)%>/g,
- escape : /<%-([\s\S]+?)%>/g
- };
- // When customizing `templateSettings`, if you don't want to define an
- // interpolation, evaluation or escaping regex, we need one that is
- // guaranteed not to match.
- var noMatch = /(.)^/;
- // Certain characters need to be escaped so that they can be put into a
- // string literal.
- var escapes = {
- "'": "'",
- '\\': '\\',
- '\r': 'r',
- '\n': 'n',
- '\t': 't',
- '\u2028': 'u2028',
- '\u2029': 'u2029'
- };
- var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
- // JavaScript micro-templating, similar to John Resig's implementation.
- // Underscore templating handles arbitrary delimiters, preserves whitespace,
- // and correctly escapes quotes within interpolated code.
- _.template = function(text, data, settings) {
- var render;
- settings = _.defaults({}, settings, _.templateSettings);
- // Combine delimiters into one regular expression via alternation.
- var matcher = new RegExp([
- (settings.escape || noMatch).source,
- (settings.interpolate || noMatch).source,
- (settings.evaluate || noMatch).source
- ].join('|') + '|$', 'g');
- // Compile the template source, escaping string literals appropriately.
- var index = 0;
- var source = "__p+='";
- text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
- source += text.slice(index, offset)
- .replace(escaper, function(match) { return '\\' + escapes[match]; });
- if (escape) {
- source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
- }
- if (interpolate) {
- source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
- }
- if (evaluate) {
- source += "';\n" + evaluate + "\n__p+='";
- }
- index = offset + match.length;
- return match;
- });
- source += "';\n";
- // If a variable is not specified, place data values in local scope.
- if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
- source = "var __t,__p='',__j=Array.prototype.join," +
- "print=function(){__p+=__j.call(arguments,'');};\n" +
- source + "return __p;\n";
- try {
- render = new Function(settings.variable || 'obj', '_', source);
- } catch (e) {
- e.source = source;
- throw e;
- }
- if (data) return render(data, _);
- var template = function(data) {
- return render.call(this, data, _);
- };
- // Provide the compiled function source as a convenience for precompilation.
- template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}';
- return template;
- };
- // Add a "chain" function, which will delegate to the wrapper.
- _.chain = function(obj) {
- return _(obj).chain();
- };
- // OOP
- // ---------------
- // If Underscore is called as a function, it returns a wrapped object that
- // can be used OO-style. This wrapper holds altered versions of all the
- // underscore functions. Wrapped objects may be chained.
- // Helper function to continue chaining intermediate results.
- var result = function(obj) {
- return this._chain ? _(obj).chain() : obj;
- };
- // Add all of the Underscore functions to the wrapper object.
- _.mixin(_);
- // Add all mutator Array functions to the wrapper.
- each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
- var method = ArrayProto[name];
- _.prototype[name] = function() {
- var obj = this._wrapped;
- method.apply(obj, arguments);
- if ((name == 'shift' || name == 'splice') && obj.length === 0) delete obj[0];
- return result.call(this, obj);
- };
- });
- // Add all accessor Array functions to the wrapper.
- each(['concat', 'join', 'slice'], function(name) {
- var method = ArrayProto[name];
- _.prototype[name] = function() {
- return result.call(this, method.apply(this._wrapped, arguments));
- };
- });
- _.extend(_.prototype, {
- // Start chaining a wrapped Underscore object.
- chain: function() {
- this._chain = true;
- return this;
- },
- // Extracts the result from a wrapped and chained object.
- value: function() {
- return this._wrapped;
- }
- });
- }).call(this);
- },
- {}],
- 2:[function(req,module,exports){
- "use strict";
- var _ = req("underscore");
- var errors = {
- // JSHint options
- E001: "Bad option: '{a}'.",
- E002: "Bad option value.",
- // JSHint input
- E003: "Expected a JSON value.",
- E004: "Input is neither a string nor an array of strings.",
- E005: "Input is empty.",
- E006: "Unexpected early end of program.",
- // Strict mode
- E007: "Missing \"use strict\" statement.",
- E008: "Strict violation.",
- E009: "Option 'validthis' can't be used in a global scope.",
- E010: "'with' is not allowed in strict mode.",
- // Constants
- E011: "const '{a}' has already been declared.",
- E012: "const '{a}' is initialized to 'undefined'.",
- E013: "Attempting to override '{a}' which is a constant.",
- // Regular expressions
- E014: "A regular expression literal can be confused with '/='.",
- E015: "Unclosed regular expression.",
- E016: "Invalid regular expression.",
- // Tokens
- E017: "Unclosed comment.",
- E018: "Unbegun comment.",
- E019: "Unmatched '{a}'.",
- E020: "Expected '{a}' to match '{b}' from line {c} and instead saw '{d}'.",
- E021: "Expected '{a}' and instead saw '{b}'.",
- E022: "Line breaking error '{a}'.",
- E023: "Missing '{a}'.",
- E024: "Unexpected '{a}'.",
- E025: "Missing ':' on a case clause.",
- E026: "Missing '}' to match '{' from line {a}.",
- E027: "Missing ']' to match '[' form line {a}.",
- E028: "Illegal comma.",
- E029: "Unclosed string.",
- // Everything else
- E030: "Expected an identifier and instead saw '{a}'.",
- E031: "Bad assignment.", // FIXME: Rephrase
- E032: "Expected a small integer or 'false' and instead saw '{a}'.",
- E033: "Expected an operator and instead saw '{a}'.",
- E034: "get/set are ES5 features.",
- E035: "Missing property name.",
- E036: "Expected to see a statement and instead saw a block.",
- E037: null, // Vacant
- E038: null, // Vacant
- E039: "Function declarations are not invocable. Wrap the whole function invocation in parens.",
- E040: "Each value should have its own case label.",
- E041: "Unrecoverable syntax error.",
- E042: "Stopping.",
- E043: "Too many errors.",
- E044: "'{a}' is already defined and can't be redefined.",
- E045: "Invalid for each loop.",
- E046: "A yield statement shall be within a generator function (with syntax: `function*`)",
- E047: "A generator function shall contain a yield statement.",
- E048: "Let declaration not directly within block.",
- E049: "A {a} cannot be named '{b}'.",
- E050: "Mozilla requires the yield expression to be parenthesized here.",
- E051: "Regular parameters cannot come after default parameters."
- };
- var warnings = {
- W001: "'hasOwnProperty' is a really bad name.",
- W002: "Value of '{a}' may be overwritten in IE 8 and earlier.",
- W003: "'{a}' was used before it was defined.",
- W004: "'{a}' is already defined.",
- W005: "A dot following a number can be confused with a decimal point.",
- W006: "Confusing minuses.",
- W007: "Confusing pluses.",
- W008: "A leading decimal point can be confused with a dot: '{a}'.",
- W009: "The array literal notation [] is preferrable.",
- W010: "The object literal notation {} is preferrable.",
- W011: "Unexpected space after '{a}'.",
- W012: "Unexpected space before '{a}'.",
- W013: "Missing space after '{a}'.",
- W014: "Bad line breaking before '{a}'.",
- W015: "Expected '{a}' to have an indentation at {b} instead at {c}.",
- W016: "Unexpected use of '{a}'.",
- W017: "Bad operand.",
- W018: "Confusing use of '{a}'.",
- W019: "Use the isNaN function to compare with NaN.",
- W020: "Read only.",
- W021: "'{a}' is a function.",
- W022: "Do not assign to the exception parameter.",
- W023: "Expected an identifier in an assignment and instead saw a function invocation.",
- W024: "Expected an identifier and instead saw '{a}' (a reserved word).",
- W025: "Missing name in function declaration.",
- W026: "Inner functions should be listed at the top of the outer function.",
- W027: "Unreachable '{a}' after '{b}'.",
- W028: "Label '{a}' on {b} statement.",
- W030: "Expected an assignment or function call and instead saw an expression.",
- W031: "Do not use 'new' for side effects.",
- W032: "Unnecessary semicolon.",
- W033: "Missing semicolon.",
- W034: "Unnecessary directive \"{a}\".",
- W035: "Empty block.",
- W036: "Unexpected /*member '{a}'.",
- W037: "'{a}' is a statement label.",
- W038: "'{a}' used out of scope.",
- W039: "'{a}' is not allowed.",
- W040: "Possible strict violation.",
- W041: "Use '{a}' to compare with '{b}'.",
- W042: "Avoid EOL escaping.",
- W043: "Bad escaping of EOL. Use option multistr if needed.",
- W044: "Bad or unnecessary escaping.",
- W045: "Bad number '{a}'.",
- W046: "Don't use extra leading zeros '{a}'.",
- W047: "A trailing decimal point can be confused with a dot: '{a}'.",
- W048: "Unexpected control character in regular expression.",
- W049: "Unexpected escaped character '{a}' in regular expression.",
- W050: "JavaScript URL.",
- W051: "Variables should not be deleted.",
- W052: "Unexpected '{a}'.",
- W053: "Do not use {a} as a constructor.",
- W054: "The Function constructor is a form of eval.",
- W055: "A constructor name should start with an uppercase letter.",
- W056: "Bad constructor.",
- W057: "Weird construction. Is 'new' unnecessary?",
- W058: "Missing '()' invoking a constructor.",
- W059: "Avoid arguments.{a}.",
- W060: "document.write can be a form of eval.",
- W061: "eval can be harmful.",
- W062: "Wrap an immediate function invocation in parens " +
- "to assist the reader in understanding that the expression " +
- "is the result of a function, and not the function itself.",
- W063: "Math is not a function.",
- W064: "Missing 'new' prefix when invoking a constructor.",
- W065: "Missing radix parameter.",
- W066: "Implied eval. Consider passing a function instead of a string.",
- W067: "Bad invocation.",
- W068: "Wrapping non-IIFE function literals in parens is unnecessary.",
- W069: "['{a}'] is better written in dot notation.",
- W070: "Extra comma. (it breaks older versions of IE)",
- W071: "This function has too many statements. ({a})",
- W072: "This function has too many parameters. ({a})",
- W073: "Blocks are nested too deeply. ({a})",
- W074: "This function's cyclomatic complexity is too high. ({a})",
- W075: "Duplicate key '{a}'.",
- W076: "Unexpected parameter '{a}' in get {b} function.",
- W077: "Expected a single parameter in set {a} function.",
- W078: "Setter is defined without getter.",
- W079: "Redefinition of '{a}'.",
- W080: "It's not necessary to initialize '{a}' to 'undefined'.",
- W081: "Too many var statements.",
- W082: "Function declarations should not be placed in blocks. " +
- "Use a function expression or move the statement to the top of " +
- "the outer function.",
- W083: "Don't make functions within a loop.",
- W084: "Assignment in conditional expression",
- W085: "Don't use 'with'.",
- W086: "Expected a 'break' statement before '{a}'.",
- W087: "Forgotten 'debugger' statement?",
- W088: "Creating global 'for' variable. Should be 'for (var {a} ...'.",
- W089: "The body of a for in should be wrapped in an if statement to filter " +
- "unwanted properties from the prototype.",
- W090: "'{a}' is not a statement label.",
- W091: "'{a}' is out of scope.",
- W092: "Wrap the /regexp/ literal in parens to disambiguate the slash operator.",
- W093: "Did you mean to return a conditional instead of an assignment?",
- W094: "Unexpected comma.",
- W095: "Expected a string and instead saw {a}.",
- W096: "The '{a}' key may produce unexpected results.",
- W097: "Use the function form of \"use strict\".",
- W098: "'{a}' is defined but never used.",
- W099: "Mixed spaces and tabs.",
- W100: "This character may get silently deleted by one or more browsers.",
- W101: "Line is too long.",
- W102: "Trailing whitespace.",
- W103: "The '{a}' property is deprecated.",
- W104: "'{a}' is only available in JavaScript 1.7.",
- W105: "Unexpected {a} in '{b}'.",
- W106: "Identifier '{a}' is not in camel case.",
- W107: "Script URL.",
- W108: "Strings must use doublequote.",
- W109: "Strings must use singlequote.",
- W110: "Mixed double and single quotes.",
- W112: "Unclosed string.",
- W113: "Control character in string: {a}.",
- W114: "Avoid {a}.",
- W115: "Octal literals are not allowed in strict mode.",
- W116: "Expected '{a}' and instead saw '{b}'.",
- W117: "'{a}' is not defined.",
- W118: "'{a}' is only available in Mozilla JavaScript extensions (use moz option).",
- W119: "'{a}' is only available in ES6 (use esnext option).",
- W120: "You might be leaking a variable ({a}) here."
- };
- var info = {
- I001: "Comma warnings can be turned off with 'laxcomma'.",
- I002: "Reserved words as properties can be used under the 'es5' option.",
- I003: "ES5 option is now set per default"
- };
- exports.errors = {};
- exports.warnings = {};
- exports.info = {};
- _.each(errors, function (desc, code) {
- exports.errors[code] = { code: code, desc: desc };
- });
- _.each(warnings, function (desc, code) {
- exports.warnings[code] = { code: code, desc: desc };
- });
- _.each(info, function (desc, code) {
- exports.info[code] = { code: code, desc: desc };
- });
- },
- {"underscore":1}],
- 3:[function(req,module,exports){
- // jshint -W001
- "use strict";
- // Identifiers provided by the ECMAScript standard.
- exports.reservedVars = {
- arguments : false,
- NaN : false
- };
- exports.ecmaIdentifiers = {
- Array : false,
- Boolean : false,
- Date : false,
- decodeURI : false,
- decodeURIComponent : false,
- encodeURI : false,
- encodeURIComponent : false,
- Error : false,
- "eval" : false,
- EvalError : false,
- Function : false,
- hasOwnProperty : false,
- isFinite : false,
- isNaN : false,
- JSON : false,
- Math : false,
- Map : false,
- Number : false,
- Object : false,
- parseInt : false,
- parseFloat : false,
- RangeError : false,
- ReferenceError : false,
- RegExp : false,
- Set : false,
- String : false,
- SyntaxError : false,
- TypeError : false,
- URIError : false,
- WeakMap : false
- };
- // Global variables commonly provided by a web browser environment.
- exports.browser = {
- ArrayBuffer : false,
- ArrayBufferView : false,
- Audio : false,
- Blob : false,
- addEventListener : false,
- applicationCache : false,
- atob : false,
- blur : false,
- btoa : false,
- clearInterval : false,
- clearTimeout : false,
- close : false,
- closed : false,
- CustomEvent : false,
- DataView : false,
- DOMParser : false,
- defaultStatus : false,
- document : false,
- Element : false,
- ElementTimeControl : false,
- event : false,
- FileReader : false,
- Float32Array : false,
- Float64Array : false,
- FormData : false,
- focus : false,
- frames : false,
- getComputedStyle : false,
- HTMLElement : false,
- HTMLAnchorElement : false,
- HTMLBaseElement : false,
- HTMLBlockquoteElement: false,
- HTMLBodyElement : false,
- HTMLBRElement : false,
- HTMLButtonElement : false,
- HTMLCanvasElement : false,
- HTMLDirectoryElement : false,
- HTMLDivElement : false,
- HTMLDListElement : false,
- HTMLFieldSetElement : false,
- HTMLFontElement : false,
- HTMLFormElement : false,
- HTMLFrameElement : false,
- HTMLFrameSetElement : false,
- HTMLHeadElement : false,
- HTMLHeadingElement : false,
- HTMLHRElement : false,
- HTMLHtmlElement : false,
- HTMLIFrameElement : false,
- HTMLImageElement : false,
- HTMLInputElement : false,
- HTMLIsIndexElement : false,
- HTMLLabelElement : false,
- HTMLLayerElement : false,
- HTMLLegendElement : false,
- HTMLLIElement : false,
- HTMLLinkElement : false,
- HTMLMapElement : false,
- HTMLMenuElement : false,
- HTMLMetaElement : false,
- HTMLModElement : false,
- HTMLObjectElement : false,
- HTMLOListElement : false,
- HTMLOptGroupElement : false,
- HTMLOptionElement : false,
- HTMLParagraphElement : false,
- HTMLParamElement : false,
- HTMLPreElement : false,
- HTMLQuoteElement : false,
- HTMLScriptElement : false,
- HTMLSelectElement : false,
- HTMLStyleElement : false,
- HTMLTableCaptionElement: false,
- HTMLTableCellElement : false,
- HTMLTableColElement : false,
- HTMLTableElement : false,
- HTMLTableRowElement : false,
- HTMLTableSectionElement: false,
- HTMLTextAreaElement : false,
- HTMLTitleElement : false,
- HTMLUListElement : false,
- HTMLVideoElement : false,
- history : false,
- Int16Array : false,
- Int32Array : false,
- Int8Array : false,
- Image : false,
- length : false,
- localStorage : false,
- location : false,
- MessageChannel : false,
- MessageEvent : false,
- MessagePort : false,
- MouseEvent : false,
- moveBy : false,
- moveTo : false,
- MutationObserver : false,
- name : false,
- Node : false,
- NodeFilter : false,
- navigator : false,
- onbeforeunload : true,
- onblur : true,
- onerror : true,
- onfocus : true,
- onload : true,
- onresize : true,
- onunload : true,
- open : false,
- openDatabase : false,
- opener : false,
- Option : false,
- parent : false,
- print : false,
- removeEventListener : false,
- resizeBy : false,
- resizeTo : false,
- screen : false,
- scroll : false,
- scrollBy : false,
- scrollTo : false,
- sessionStorage : false,
- setInterval : false,
- setTimeout : false,
- SharedWorker : false,
- status : false,
- SVGAElement : false,
- SVGAltGlyphDefElement: false,
- SVGAltGlyphElement : false,
- SVGAltGlyphItemElement: false,
- SVGAngle : false,
- SVGAnimateColorElement: false,
- SVGAnimateElement : false,
- SVGAnimateMotionElement: false,
- SVGAnimateTransformElement: false,
- SVGAnimatedAngle : false,
- SVGAnimatedBoolean : false,
- SVGAnimatedEnumeration: false,
- SVGAnimatedInteger : false,
- SVGAnimatedLength : false,
- SVGAnimatedLengthList: false,
- SVGAnimatedNumber : false,
- SVGAnimatedNumberList: false,
- SVGAnimatedPathData : false,
- SVGAnimatedPoints : false,
- SVGAnimatedPreserveAspectRatio: false,
- SVGAnimatedRect : false,
- SVGAnimatedString : false,
- SVGAnimatedTransformList: false,
- SVGAnimationElement : false,
- SVGCSSRule : false,
- SVGCircleElement : false,
- SVGClipPathElement : false,
- SVGColor : false,
- SVGColorProfileElement: false,
- SVGColorProfileRule : false,
- SVGComponentTransferFunctionElement: false,
- SVGCursorElement : false,
- SVGDefsElement : false,
- SVGDescElement : false,
- SVGDocument : false,
- SVGElement : false,
- SVGElementInstance : false,
- SVGElementInstanceList: false,
- SVGEllipseElement : false,
- SVGExternalResourcesRequired: false,
- SVGFEBlendElement : false,
- SVGFEColorMatrixElement: false,
- SVGFEComponentTransferElement: false,
- SVGFECompositeElement: false,
- SVGFEConvolveMatrixElement: false,
- SVGFEDiffuseLightingElement: false,
- SVGFEDisplacementMapElement: false,
- SVGFEDistantLightElement: false,
- SVGFEFloodElement : false,
- SVGFEFuncAElement : false,
- SVGFEFuncBElement : false,
- SVGFEFuncGElement : false,
- SVGFEFuncRElement : false,
- SVGFEGaussianBlurElement: false,
- SVGFEImageElement : false,
- SVGFEMergeElement : false,
- SVGFEMergeNodeElement: false,
- SVGFEMorphologyElement: false,
- SVGFEOffsetElement : false,
- SVGFEPointLightElement: false,
- SVGFESpecularLightingElement: false,
- SVGFESpotLightElement: false,
- SVGFETileElement : false,
- SVGFETurbulenceElement: false,
- SVGFilterElement : false,
- SVGFilterPrimitiveStandardAttributes: false,
- SVGFitToViewBox : false,
- SVGFontElement : false,
- SVGFontFaceElement : false,
- SVGFontFaceFormatElement: false,
- SVGFontFaceNameElement: false,
- SVGFontFaceSrcElement: false,
- SVGFontFaceUriElement: false,
- SVGForeignObjectElement: false,
- SVGGElement : false,
- SVGGlyphElement : false,
- SVGGlyphRefElement : false,
- SVGGradientElement : false,
- SVGHKernElement : false,
- SVGICCColor : false,
- SVGImageElement : false,
- SVGLangSpace : false,
- SVGLength : false,
- SVGLengthList : false,
- SVGLineElement : false,
- SVGLinearGradientElement: false,
- SVGLocatable : false,
- SVGMPathElement : false,
- SVGMarkerElement : false,
- SVGMaskElement : false,
- SVGMatrix : false,
- SVGMetadataElement : false,
- SVGMissingGlyphElement: false,
- SVGNumber : false,
- SVGNumberList : false,
- SVGPaint : false,
- SVGPathElement : false,
- SVGPathSeg : false,
- SVGPathSegArcAbs : false,
- SVGPathSegArcRel : false,
- SVGPathSegClosePath : false,
- SVGPathSegCurvetoCubicAbs: false,
- SVGPathSegCurvetoCubicRel: false,
- SVGPathSegCurvetoCubicSmoothAbs: false,
- SVGPathSegCurvetoCubicSmoothRel: false,
- SVGPathSegCurvetoQuadraticAbs: false,
- SVGPathSegCurvetoQuadraticRel: false,
- SVGPathSegCurvetoQuadraticSmoothAbs: false,
- SVGPathSegCurvetoQuadraticSmoothRel: false,
- SVGPathSegLinetoAbs : false,
- SVGPathSegLinetoHorizontalAbs: false,
- SVGPathSegLinetoHorizontalRel: false,
- SVGPathSegLinetoRel : false,
- SVGPathSegLinetoVerticalAbs: false,
- SVGPathSegLinetoVerticalRel: false,
- SVGPathSegList : false,
- SVGPathSegMovetoAbs : false,
- SVGPathSegMovetoRel : false,
- SVGPatternElement : false,
- SVGPoint : false,
- SVGPointList : false,
- SVGPolygonElement : false,
- SVGPolylineElement : false,
- SVGPreserveAspectRatio: false,
- SVGRadialGradientElement: false,
- SVGRect : false,
- SVGRectElement : false,
- SVGRenderingIntent : false,
- SVGSVGElement : false,
- SVGScriptElement : false,
- SVGSetElement : false,
- SVGStopElement : false,
- SVGStringList : false,
- SVGStylable : false,
- SVGStyleElement : false,
- SVGSwitchElement : false,
- SVGSymbolElement : false,
- SVGTRefElement : false,
- SVGTSpanElement : false,
- SVGTests : false,
- SVGTextContentElement: false,
- SVGTextElement : false,
- SVGTextPathElement : false,
- SVGTextPositioningElement: false,
- SVGTitleElement : false,
- SVGTransform : false,
- SVGTransformList : false,
- SVGTransformable : false,
- SVGURIReference : false,
- SVGUnitTypes : false,
- SVGUseElement : false,
- SVGVKernElement : false,
- SVGViewElement : false,
- SVGViewSpec : false,
- SVGZoomAndPan : false,
- TimeEvent : false,
- top : false,
- Uint16Array : false,
- Uint32Array : false,
- Uint8Array : false,
- Uint8ClampedArray : false,
- WebSocket : false,
- window : false,
- Worker : false,
- XMLHttpRequest : false,
- XMLSerializer : false,
- XPathEvaluator : false,
- XPathException : false,
- XPathExpression : false,
- XPathNamespace : false,
- XPathNSResolver : false,
- XPathResult : false
- };
- exports.devel = {
- alert : false,
- confirm: false,
- console: false,
- Debug : false,
- opera : false,
- prompt : false
- };
- exports.worker = {
- importScripts: true,
- postMessage : true,
- self : true
- };
- // Widely adopted global names that are not part of ECMAScript standard
- exports.nonstandard = {
- escape : false,
- unescape: false
- };
- // Globals provided by popular JavaScript environments.
- exports.couch = {
- "require" : false,
- respond : false,
- getRow : false,
- emit : false,
- send : false,
- start : false,
- sum : false,
- log : false,
- exports : false,
- module : false,
- provides : false
- };
- exports.node = {
- __filename : false,
- __dirname : false,
- Buffer : false,
- DataView : false,
- console : false,
- exports : true, // In Node it is ok to exports = module.exports = foo();
- GLOBAL : false,
- global : false,
- module : false,
- process : false,
- require : false,
- setTimeout : false,
- clearTimeout : false,
- setInterval : false,
- clearInterval : false,
- setImmediate : false, // v0.9.1+
- clearImmediate: false // v0.9.1+
- };
- exports.phantom = {
- phantom : true,
- require : true,
- WebPage : true
- };
- exports.rhino = {
- defineClass : false,
- deserialize : false,
- gc : false,
- help : false,
- importPackage: false,
- "java" : false,
- load : false,
- loadClass : false,
- print : false,
- quit : false,
- readFile : false,
- readUrl : false,
- runCommand : false,
- seal : false,
- serialize : false,
- spawn : false,
- sync : false,
- toint32 : false,
- version : false
- };
- exports.shelljs = {
- target : false,
- echo : false,
- exit : false,
- cd : false,
- pwd : false,
- ls : false,
- find : false,
- cp : false,
- rm : false,
- mv : false,
- mkdir : false,
- test : false,
- cat : false,
- sed : false,
- grep : false,
- which : false,
- dirs : false,
- pushd : false,
- popd : false,
- env : false,
- exec : false,
- chmod : false,
- config : false,
- error : false,
- tempdir : false
- };
- exports.wsh = {
- ActiveXObject : true,
- Enumerator : true,
- GetObject : true,
- ScriptEngine : true,
- ScriptEngineBuildVersion : true,
- ScriptEngineMajorVersion : true,
- ScriptEngineMinorVersion : true,
- VBArray : true,
- WSH : true,
- WScript : true,
- XDomainRequest : true
- };
- // Globals provided by popular JavaScript libraries.
- exports.dojo = {
- dojo : false,
- dijit : false,
- dojox : false,
- define : false,
- "require": false
- };
- exports.jquery = {
- "$" : false,
- jQuery : false
- };
- exports.mootools = {
- "$" : false,
- "$$" : false,
- Asset : false,
- Browser : false,
- Chain : false,
- Class : false,
- Color : false,
- Cookie : false,
- Core : false,
- Document : false,
- DomReady : false,
- DOMEvent : false,
- DOMReady : false,
- Drag : false,
- Element : false,
- Elements : false,
- Event : false,
- Events : false,
- Fx : false,
- Group : false,
- Hash : false,
- HtmlTable : false,
- Iframe : false,
- IframeShim : false,
- InputValidator: false,
- instanceOf : false,
- Keyboard : false,
- Locale : false,
- Mask : false,
- MooTools : false,
- Native : false,
- Options : false,
- OverText : false,
- Request : false,
- Scroller : false,
- Slick : false,
- Slider : false,
- Sortables : false,
- Spinner : false,
- Swiff : false,
- Tips : false,
- Type : false,
- typeOf : false,
- URI : false,
- Window : false
- };
- exports.prototypejs = {
- "$" : false,
- "$$" : false,
- "$A" : false,
- "$F" : false,
- "$H" : false,
- "$R" : false,
- "$break" : false,
- "$continue" : false,
- "$w" : false,
- Abstract : false,
- Ajax : false,
- Class : false,
- Enumerable : false,
- Element : false,
- Event : false,
- Field : false,
- Form : false,
- Hash : false,
- Insertion : false,
- ObjectRange : false,
- PeriodicalExecuter: false,
- Position : false,
- Prototype : false,
- Selector : false,
- Template : false,
- Toggle : false,
- Try : false,
- Autocompleter : false,
- Builder : false,
- Control : false,
- Draggable : false,
- Draggables : false,
- Droppables : false,
- Effect : false,
- Sortable : false,
- SortableObserver : false,
- Sound : false,
- Scriptaculous : false
- };
- exports.yui = {
- YUI : false,
- Y : false,
- YUI_config: false
- };
- },
- {}],
- "n4bKNg":[function(req,module,exports){
- /*!
- * JSHint, by JSHint Community.
- *
- * This file (and this file only) is licensed under the same slightly modified
- * MIT license that JSLint is. It stops evil-doers everywhere:
- *
- * Copyright (c) 2002 Douglas Crockford (www.JSLint.com)
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom
- * the Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * The Software shall be used for Good, not Evil.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- */
- /*jshint quotmark:double */
- /*global console:true */
- /*exported console */
- var _ = req("underscore");
- var events = req("events");
- var vars = req("../shared/vars.js");
- var messages = req("../shared/messages.js");
- var Lexer = req("./lex.js").Lexer;
- var reg = req("./reg.js");
- var state = req("./state.js").state;
- var style = req("./style.js");
- // We need this module here because environments such as IE and Rhino
- // don't necessarilly expose the 'console' API and browserify uses
- // it to log things. It's a sad state of affair, really.
- var console = req("console-browserify");
- // We build the application inside a function so that we produce only a singleton
- // variable. That function will be invoked immediately, and its return value is
- // the JSHINT function itself.
- var JSHINT = (function () {
- "use strict";
- var anonname, // The guessed name for anonymous functions.
- api, // Extension API
- // These are operators that should not be used with the ! operator.
- bang = {
- "<" : true,
- "<=" : true,
- "==" : true,
- "===": true,
- "!==": true,
- "!=" : true,
- ">" : true,
- ">=" : true,
- "+" : true,
- "-" : true,
- "*" : true,
- "/" : true,
- "%" : true
- },
- // These are the JSHint boolean options.
- boolOptions = {
- asi : true, // if automatic semicolon insertion should be tolerated
- bitwise : true, // if bitwise operators should not be allowed
- boss : true, // if advanced usage of assignments should be allowed
- browser : true, // if the standard browser globals should be predefined
- camelcase : true, // if identifiers should be required in camel case
- couch : true, // if CouchDB globals should be predefined
- curly : true, // if curly braces around all blocks should be required
- debug : true, // if debugger statements should be allowed
- devel : true, // if logging globals should be predefined (console, alert, etc.)
- dojo : true, // if Dojo Toolkit globals should be predefined
- eqeqeq : true, // if === should be required
- eqnull : true, // if == null comparisons should be tolerated
- es3 : true, // if ES3 syntax should be allowed
- es5 : true, // if ES5 syntax should be allowed (is now set per default)
- esnext : true, // if es.next specific syntax should be allowed
- moz : true, // if mozilla specific syntax should be allowed
- evil : true, // if eval should be allowed
- expr : true, // if ExpressionStatement should be allowed as Programs
- forin : true, // if for in statements must filter
- funcscope : true, // if only function scope should be used for scope tests
- gcl : true, // if JSHint should be compatible with Google Closure Linter
- globalstrict: true, // if global "use strict"; should be allowed (also enables 'strict')
- immed : true, // if immediate invocations must be wrapped in parens
- iterator : true, // if the `__iterator__` property should be allowed
- jquery : true, // if jQuery globals should be predefined
- lastsemic : true, // if semicolons may be ommitted for the trailing
- // statements inside of a one-line blocks.
- laxbreak : true, // if line breaks should not be checked
- laxcomma : true, // if line breaks should not be checked around commas
- loopfunc : true, // if functions should be allowed to be defined within
- // loops
- mootools : true, // if MooTools globals should be predefined
- multistr : true, // allow multiline strings
- newcap : true, // if constructor names must be capitalized
- noarg : true, // if arguments.caller and arguments.callee should be
- // disallowed
- node : true, // if the Node.js environment globals should be
- // predefined
- noempty : true, // if empty blocks should be disallowed
- nonew : true, // if using `new` for side-effects should be disallowed
- nonstandard : true, // if non-standard (but widely adopted) globals should
- // be predefined
- nomen : true, // if names should be checked
- onevar : true, // if only one var statement per function should be
- // allowed
- passfail : true, // if the scan should stop on first error
- phantom : true, // if PhantomJS symbols should be allowed
- plusplus : true, // if increment/decrement should not be allowed
- proto : true, // if the `__proto__` property should be allowed
- prototypejs : true, // if Prototype and Scriptaculous globals should be
- // predefined
- rhino : true, // if the Rhino environment globals should be predefined
- shelljs : true, // if ShellJS globals should be predefined
- undef : true, // if variables should be declared before used
- scripturl : true, // if script-targeted URLs should be tolerated
- shadow : true, // if variable shadowing should be tolerated
- smarttabs : true, // if smarttabs should be tolerated
- // (http://www.emacswiki.org/emacs/SmartTabs)
- strict : true, // require the "use strict"; pragma
- sub : true, // if all forms of subscript notation are tolerated
- supernew : true, // if `new function () { ... };` and `new Object;`
- // should be tolerated
- trailing : true, // if trailing whitespace rules apply
- validthis : true, // if 'this' inside a non-constructor function is valid.
- // This is a function scoped option only.
- withstmt : true, // if with statements should be allowed
- white : true, // if strict whitespace rules apply
- worker : true, // if Web Worker script symbols should be allowed
- wsh : true, // if the Windows Scripting Host environment globals
- // should be predefined
- yui : true, // YUI variables should be predefined
- // Obsolete options
- onecase : true, // if one case switch statements should be allowed
- regexp : true, // if the . should not be allowed in regexp literals
- regexdash : true // if unescaped first/last dash (-) inside brackets
- // should be tolerated
- },
- // These are the JSHint options that can take any value
- // (we use this object to detect invalid options)
- valOptions = {
- maxlen : false,
- indent : false,
- maxerr : false,
- predef : false,
- quotmark : false, //'single'|'double'|true
- scope : false,
- maxstatements: false, // {int} max statements per function
- maxdepth : false, // {int} max nested block depth per function
- maxparams : false, // {int} max params per function
- maxcomplexity: false, // {int} max cyclomatic complexity per function
- unused : true, // warn if variables are unused. Available options:
- // false - don't check for unused variables
- // true - "vars" + check last function param
- // "vars" - skip checking unused function params
- // "strict" - "vars" + check all function params
- latedef : false // warn if the variable is used before its definition
- // false - don't emit any warnings
- // true - warn if any variable is used before its definition
- // "nofunc" - warn for any variable but function declarations
- },
- // These are JSHint boolean options which are shared with JSLint
- // where the definition in JSHint is opposite JSLint
- invertedOptions = {
- bitwise : true,
- forin : true,
- newcap : true,
- nomen : true,
- plusplus: true,
- regexp : true,
- undef : true,
- white : true,
- // Inverted and renamed, use JSHint name here
- eqeqeq : true,
- onevar : true,
- strict : true
- },
- // These are JSHint boolean options which are shared with JSLint
- // where the name has been changed but the effect is unchanged
- renamedOptions = {
- eqeq : "eqeqeq",
- vars : "onevar",
- windows: "wsh",
- sloppy : "strict"
- },
- declared, // Globals that were declared using /*global ... */ syntax.
- exported, // Variables that are used outside of the current file.
- functionicity = [
- "closure", "exception", "global", "label",
- "outer", "unused", "var"
- ],
- funct, // The current function
- functions, // All of the functions
- global, // The global scope
- implied, // Implied globals
- inblock,
- indent,
- lookahead,
- lex,
- member,
- membersOnly,
- noreach,
- predefined, // Global variables defined by option
- scope, // The current scope
- stack,
- unuseds,
- urls,
- warnings,
- extraModules = [],
- emitter = new events.EventEmitter();
- function checkOption(name, t) {
- name = name.trim();
- if (/^[+-]W\d{3}$/g.test(name)) {
- return true;
- }
- if (valOptions[name] === undefined && boolOptions[name] === undefined) {
- if (t.type !== "jslint") {
- error("E001", t, name);
- return false;
- }
- }
- return true;
- }
- function isString(obj) {
- return Object.prototype.toString.call(obj) === "[object String]";
- }
- function isIdentifier(tkn, value) {
- if (!tkn)
- return false;
- if (!tkn.identifier || tkn.value !== value)
- return false;
- return true;
- }
- function isReserved(token) {
- if (!token.reserved) {
- return false;
- }
- var meta = token.meta;
- if (meta && meta.isFutureReservedWord && state.option.inES5()) {
- // ES3 FutureReservedWord in an ES5 environment.
- if (!meta.es5) {
- return false;
- }
- // Some ES5 FutureReservedWord identifiers are active only
- // within a strict mode environment.
- if (meta.strictOnly) {
- if (!state.option.strict && !state.directive["use strict"]) {
- return false;
- }
- }
- if (token.isProperty) {
- return false;
- }
- }
- return true;
- }
- function supplant(str, data) {
- return str.replace(/\{([^{}]*)\}/g, function (a, b) {
- var r = data[b];
- return typeof r === "string" || typeof r === "number" ? r : a;
- });
- }
- function combine(t, o) {
- var n;
- for (n in o) {
- if (_.has(o, n) && !_.has(JSHINT.blacklist, n)) {
- t[n] = o[n];
- }
- }
- }
- function updatePredefined() {
- Object.keys(JSHINT.blacklist).forEach(function (key) {
- delete predefined[key];
- });
- }
- function assume() {
- if (state.option.couch) {
- combine(predefined, vars.couch);
- }
- if (state.option.rhino) {
- combine(predefined, vars.rhino);
- }
- if (state.option.shelljs) {
- combine(predefined, vars.shelljs);
- combine(predefined, vars.node);
- }
- if (state.option.phantom) {
- combine(predefined, vars.phantom);
- }
- if (state.option.prototypejs) {
- combine(predefined, vars.prototypejs);
- }
- if (state.option.node) {
- combine(predefined, vars.node);
- }
- if (state.option.devel) {
- combine(predefined, vars.devel);
- }
- if (state.option.dojo) {
- combine(predefined, vars.dojo);
- }
- if (state.option.browser) {
- combine(predefined, vars.browser);
- }
- if (state.option.nonstandard) {
- combine(predefined, vars.nonstandard);
- }
- if (state.option.jquery) {
- combine(predefined, vars.jquery);
- }
- if (state.option.mootools) {
- combine(predefined, vars.mootools);
- }
- if (state.option.worker) {
- combine(predefined, vars.worker);
- }
- if (state.option.wsh) {
- combine(predefined, vars.wsh);
- }
- if (state.option.globalstrict && state.option.strict !== false) {
- state.option.strict = true;
- }
- if (state.option.yui) {
- combine(predefined, vars.yui);
- }
- // Let's assume that chronologically ES3 < ES5 < ES6/ESNext < Moz
- state.option.inMoz = function (strict) {
- return state.option.moz;
- };
- state.option.inESNext = function (strict) {
- return state.option.moz || state.option.esnext;
- };
- state.option.inES5 = function (/* strict */) {
- return !state.option.es3;
- };
- state.option.inES3 = function (strict) {
- if (strict) {
- return !state.option.moz && !state.option.esnext && state.option.es3;
- }
- return state.option.es3;
- };
- }
- // Produce an error warning.
- function quit(code, line, chr) {
- var percentage = Math.floor((line / state.lines.length) * 100);
- var message = messages.errors[code].desc;
- throw {
- name: "JSHintError",
- line: line,
- character: chr,
- message: message + " (" + percentage + "% scanned).",
- raw: message,
- code: code
- };
- }
- function isundef(scope, code, token, a) {
- return JSHINT.undefs.push([scope, code, token, a]);
- }
- function warning(code, t, a, b, c, d) {
- var ch, l, w, msg;
- if (/^W\d{3}$/.test(code)) {
- if (state.ignored[code])
- return;
- msg = messages.warnings[code];
- } else if (/E\d{3}/.test(code)) {
- msg = messages.errors[code];
- } else if (/I\d{3}/.test(code)) {
- msg = messages.info[code];
- }
- t = t || state.tokens.next;
- if (t.id === "(end)") { // `~
- t = state.tokens.curr;
- }
- l = t.line || 0;
- ch = t.from || 0;
- w = {
- id: "(error)",
- raw: msg.desc,
- code: msg.code,
- evidence: state.lines[l - 1] || "",
- line: l,
- character: ch,
- scope: JSHINT.scope,
- a: a,
- b: b,
- c: c,
- d: d
- };
- w.reason = supplant(msg.desc, w);
- JSHINT.errors.push(w);
- if (state.option.passfail) {
- quit("E042", l, ch);
- }
- warnings += 1;
- if (warnings >= state.option.maxerr) {
- quit("E043", l, ch);
- }
- return w;
- }
- function warningAt(m, l, ch, a, b, c, d) {
- return warning(m, {
- line: l,
- from: ch
- }, a, b, c, d);
- }
- function error(m, t, a, b, c, d) {
- warning(m, t, a, b, c, d);
- }
- function errorAt(m, l, ch, a, b, c, d) {
- return error(m, {
- line: l,
- from: ch
- }, a, b, c, d);
- }
- // Tracking of "internal" scripts, like eval containing a static string
- function addInternalSrc(elem, src) {
- var i;
- i = {
- id: "(internal)",
- elem: elem,
- value: src
- };
- JSHINT.internals.push(i);
- return i;
- }
- function addlabel(t, type, tkn, islet) {
- // Define t in the current function in the current scope.
- if (type === "exception") {
- if (_.has(funct["(context)"], t)) {
- if (funct[t] !== true && !state.option.node) {
- warning("W002", state.tokens.next, t);
- }
- }
- }
- if (_.has(funct, t) && !funct["(global)"]) {
- if (funct[t] === true) {
- if (state.option.latedef) {
- if ((state.option.latedef === true && _.contains([funct[t], type], "unction")) ||
- !_.contains([funct[t], type], "unction")) {
- warning("W003", state.tokens.next, t);
- }
- }
- } else {
- if (!state.option.shadow && type !== "exception" ||
- (funct["(blockscope)"].getlabel(t))) {
- warning("W004", state.tokens.next, t);
- }
- }
- }
- // a double definition of a let variable in same block throws a TypeError
- if (funct["(blockscope)"] && funct["(blockscope)"].current.has(t)) {
- error("E044", state.tokens.next, t);
- }
- // if the identifier is from a let, adds it only to the current blockscope
- if (islet) {
- funct["(blockscope)"].current.add(t, type, state.tokens.curr);
- } else {
- funct[t] = type;
- if (tkn) {
- funct["(tokens)"][t] = tkn;
- }
- if (funct["(global)"]) {
- global[t] = funct;
- if (_.has(implied, t)) {
- if (state.option.latedef) {
- if ((state.option.latedef === true && _.contains([funct[t], type], "unction")) ||
- !_.contains([funct[t], type], "unction")) {
- warning("W003", state.tokens.next, t);
- }
- }
- delete implied[t];
- }
- } else {
- scope[t] = funct;
- }
- }
- }
- function doOption() {
- var nt = state.tokens.next;
- var body = nt.body.match(/(-\s+)?[^\s,]+(?:\s*:\s*(-\s+)?[^\s,]+)?/g);
- var predef = {};
- if (nt.type === "globals") {
- body.forEach(function (g) {
- g = g.split(":");
- var key = (g[0] || "").trim();
- var val = (g[1] || "").trim();
- if (key.charAt(0) === "-") {
- key = key.slice(1);
- val = false;
- JSHINT.blacklist[key] = key;
- updatePredefined();
- } else {
- predef[key] = (val === "true");
- }
- });
- combine(predefined, predef);
- for (var key in predef) {
- if (_.has(predef, key)) {
- declared[key] = nt;
- }
- }
- }
- if (nt.type === "exported") {
- body.forEach(function (e) {
- exported[e] = true;
- });
- }
- if (nt.type === "members") {
- membersOnly = membersOnly || {};
- body.forEach(function (m) {
- var ch1 = m.charAt(0);
- var ch2 = m.charAt(m.length - 1);
- if (ch1 === ch2 && (ch1 === "\"" || ch1 === "'")) {
- m = m
- .substr(1, m.length - 2)
- .replace("\\b", "\b")
- .replace("\\t", "\t")
- .replace("\\n", "\n")
- .replace("\\v", "\v")
- .replace("\\f", "\f")
- .replace("\\r", "\r")
- .replace("\\\\", "\\")
- .replace("\\\"", "\"");
- }
- membersOnly[m] = false;
- });
- }
- var numvals = [
- "maxstatements",
- "maxparams",
- "maxdepth",
- "maxcomplexity",
- "maxerr",
- "maxlen",
- "indent"
- ];
- if (nt.type === "jshint" || nt.type === "jslint") {
- body.forEach(function (g) {
- g = g.split(":");
- var key = (g[0] || "").trim();
- var val = (g[1] || "").trim();
- if (!checkOption(key, nt)) {
- return;
- }
- if (numvals.indexOf(key) >= 0) {
- // GH988 - numeric options can be disabled by setting them to `false`
- if (val !== "false") {
- val = +val;
- if (typeof val !== "number" || !isFinite(val) || val <= 0 || Math.floor(val) !== val) {
- error("E032", nt, g[1].trim());
- return;
- }
- if (key === "indent") {
- state.option["(explicitIndent)"] = true;
- }
- state.option[key] = val;
- } else {
- if (key === "indent") {
- state.option["(explicitIndent)"] = false;
- } else {
- state.option[key] = false;
- }
- }
- return;
- }
- if (key === "validthis") {
- // `validthis` is valid only within a function scope.
- if (funct["(global)"]) {
- error("E009");
- } else {
- if (val === "true" || val === "false") {
- state.option.validthis = (val === "true");
- } else {
- error("E002", nt);
- }
- }
- return;
- }
- if (key === "quotmark") {
- switch (val) {
- case "true":
- case "false":
- state.option.quotmark = (val === "true");
- break;
- case "double":
- case "single":
- state.option.quotmark = val;
- break;
- default:
- error("E002", nt);
- }
- return;
- }
- if (key === "unused") {
- switch (val) {
- case "true":
- state.option.unused = true;
- break;
- case "false":
- state.option.unused = false;
- break;
- case "vars":
- case "strict":
- state.option.unused = val;
- break;
- default:
- error("E002", nt);
- }
- return;
- }
- if (key === "latedef") {
- switch (val) {
- case "true":
- state.option.latedef = true;
- break;
- case "false":
- state.option.latedef = false;
- break;
- case "nofunc":
- state.option.latedef = "nofunc";
- break;
- default:
- error("E002", nt);
- }
- return;
- }
- var match = /^([+-])(W\d{3})$/g.exec(key);
- if (match) {
- // ignore for -W..., unignore for +W...
- state.ignored[match[2]] = (match[1] === "-");
- return;
- }
- var tn;
- if (val === "true" || val === "false") {
- if (nt.type === "jslint") {
- tn = renamedOptions[key] || key;
- state.option[tn] = (val === "true");
- if (invertedOptions[tn] !== undefined) {
- state.option[tn] = !state.option[tn];
- }
- } else {
- state.option[key] = (val === "true");
- }
- if (key === "newcap") {
- state.option["(explicitNewcap)"] = true;
- }
- return;
- }
- error("E002", nt);
- });
- assume();
- }
- }
- // We need a peek function. If it has an argument, it peeks that much farther
- // ahead. It is used to distinguish
- // for ( var i in ...
- // from
- // for ( var i = ...
- function peek(p) {
- var i = p || 0, j = 0, t;
- while (j <= i) {
- t = lookahead[j];
- if (!t) {
- t = lookahead[j] = lex.token();
- }
- j += 1;
- }
- return t;
- }
- // Produce the next token. It looks for programming errors.
- function advance(id, t) {
- switch (state.tokens.curr.id) {
- case "(number)":
- if (state.tokens.next.id === ".") {
- warning("W005", state.tokens.curr);
- }
- break;
- case "-":
- if (state.tokens.next.id === "-" || state.tokens.next.id === "--") {
- warning("W006");
- }
- break;
- case "+":
- if (state.tokens.next.id === "+" || state.tokens.next.id === "++") {
- warning("W007");
- }
- break;
- }
- if (state.tokens.curr.type === "(string)" || state.tokens.curr.identifier) {
- anonname = state.tokens.curr.value;
- }
- if (id && state.tokens.next.id !== id) {
- if (t) {
- if (state.tokens.next.id === "(end)") {
- error("E019", t, t.id);
- } else {
- error("E020", state.tokens.next, id, t.id, t.line, state.tokens.next.value);
- }
- } else if (state.tokens.next.type !== "(identifier)" || state.tokens.next.value !== id) {
- warning("W116", state.tokens.next, id, state.tokens.next.value);
- }
- }
- state.tokens.prev = state.tokens.curr;
- state.tokens.curr = state.tokens.next;
- for (;;) {
- state.tokens.next = lookahead.shift() || lex.token();
- if (!state.tokens.next) { // No more tokens left, give up
- quit("E041", state.tokens.curr.line);
- }
- if (state.tokens.next.id === "(end)" || state.tokens.next.id === "(error)") {
- return;
- }
- if (state.tokens.next.check) {
- state.tokens.next.check();
- }
- if (state.tokens.next.isSpecial) {
- doOption();
- } else {
- if (state.tokens.next.id !== "(endline)") {
- break;
- }
- }
- }
- }
- function isInfix(token) {
- return token.infix || (!token.identifier && !!token.led);
- }
- function isEndOfExpr() {
- var curr = state.tokens.curr;
- var next = state.tokens.next;
- if (next.id === ";" || next.id === "}" || next.id === ":") {
- return true;
- }
- if (isInfix(next) === isInfix(curr) || (curr.id === "yield" && state.option.inMoz(true))) {
- return curr.line !== next.line;
- }
- return false;
- }
- // This is the heart of JSHINT, the Pratt parser. In addition to parsing, it
- // is looking for ad hoc lint patterns. We add .fud to Pratt's model, which is
- // like .nud except that it is only used on the first token of a statement.
- // Having .fud makes it much easier to define statement-oriented languages like
- // JavaScript. I retained Pratt's nomenclature.
- // .nud Null denotation
- // .fud First null denotation
- // .led Left denotation
- // lbp Left binding power
- // rbp Right binding power
- // They are elements of the parsing method called Top Down Operator Precedence.
- function expression(rbp, initial) {
- var left, isArray = false, isObject = false, isLetExpr = false;
- // if current expression is a let expression
- if (!initial && state.tokens.next.value === "let" && peek(0).value === "(") {
- if (!state.option.inMoz(true)) {
- warning("W118", state.tokens.next, "let expressions");
- }
- isLetExpr = true;
- // create a new block scope we use only for the current expression
- funct["(blockscope)"].stack();
- advance("let");
- advance("(");
- state.syntax["let"].fud.call(state.syntax["let"].fud, false);
- advance(")");
- }
- if (state.tokens.next.id === "(end)")
- error("E006", state.tokens.curr);
- advance();
- if (initial) {
- anonname = "anonymous";
- funct["(verb)"] = state.tokens.curr.value;
- }
- if (initial === true && state.tokens.curr.fud) {
- left = state.tokens.curr.fud();
- } else {
- if (state.tokens.curr.nud) {
- left = state.tokens.curr.nud();
- } else {
- error("E030", state.tokens.curr, state.tokens.curr.id);
- }
- while (rbp < state.tokens.next.lbp && !isEndOfExpr()) {
- isArray = state.tokens.curr.value === "Array";
- isObject = state.tokens.curr.value === "Object";
- // #527, new Foo.Array(), Foo.Array(), new Foo.Object(), Foo.Object()
- // Line breaks in IfStatement heads exist to satisfy the checkJSHint
- // "Line too long." error.
- if (left && (left.value || (left.first && left.first.value))) {
- // If the left.value is not "new", or the left.first.value is a "."
- // then safely assume that this is not "new Array()" and possibly
- // not "new Object()"...
- if (left.value !== "new" ||
- (left.first && left.first.value && left.first.value === ".")) {
- isArray = false;
- // ...In the case of Object, if the left.value and state.tokens.curr.value
- // are not equal, then safely assume that this not "new Object()"
- if (left.value !== state.tokens.curr.value) {
- isObject = false;
- }
- }
- }
- advance();
- if (isArray && state.tokens.curr.id === "(" && state.tokens.next.id === ")") {
- warning("W009", state.tokens.curr);
- }
- if (isObject && state.tokens.curr.id === "(" && state.tokens.next.id === ")") {
- warning("W010", state.tokens.curr);
- }
- if (left && state.tokens.curr.led) {
- left = state.tokens.curr.led(left);
- } else {
- error("E033", state.tokens.curr, state.tokens.curr.id);
- }
- }
- }
- if (isLetExpr) {
- funct["(blockscope)"].unstack();
- }
- return left;
- }
- // Functions for conformance of style.
- function adjacent(left, right) {
- left = left || state.tokens.curr;
- right = right || state.tokens.next;
- if (state.option.white) {
- if (left.character !== right.from && left.line === right.line) {
- left.from += (left.character - left.from);
- warning("W011", left, left.value);
- }
- }
- }
- function nobreak(left, right) {
- left = left || state.tokens.curr;
- right = right || state.tokens.next;
- if (state.option.white && (left.character !== right.from || left.line !== right.line)) {
- warning("W012", right, right.value);
- }
- }
- function nospace(left, right) {
- left = left || state.tokens.curr;
- right = right || state.tokens.next;
- if (state.option.white && !left.comment) {
- if (left.line === right.line) {
- adjacent(left, right);
- }
- }
- }
- function nonadjacent(left, right) {
- if (state.option.white) {
- left = left || state.tokens.curr;
- right = right || state.tokens.next;
- if (left.value === ";" && right.value === ";") {
- return;
- }
- if (left.line === right.line && left.character === right.from) {
- left.from += (left.character - left.from);
- warning("W013", left, left.value);
- }
- }
- }
- function nobreaknonadjacent(left, right) {
- left = left || state.tokens.curr;
- right = right || state.tokens.next;
- if (!state.option.laxbreak && left.line !== right.line) {
- warning("W014", right, right.value);
- } else if (state.option.white) {
- left = left || state.tokens.curr;
- right = right || state.tokens.next;
- if (left.character === right.from) {
- left.from += (left.character - left.from);
- warning("W013", left, left.value);
- }
- }
- }
- function indentation(bias) {
- if (!state.option.white && !state.option["(explicitIndent)"]) {
- return;
- }
- if (state.tokens.next.id === "(end)") {
- return;
- }
- var i = indent + (bias || 0);
- if (state.tokens.next.from !== i) {
- warning("W015", state.tokens.next, state.tokens.next.value, i, state.tokens.next.from);
- }
- }
- function nolinebreak(t) {
- t = t || state.tokens.curr;
- if (t.line !== state.tokens.next.line) {
- warning("E022", t, t.value);
- }
- }
- function nobreakcomma(left, right) {
- if (left.line !== right.line) {
- if (!state.option.laxcomma) {
- if (comma.first) {
- warning("I001");
- comma.first = false;
- }
- warning("W014", left, right.value);
- }
- } else if (!left.comment && left.character !== right.from && state.option.white) {
- left.from += (left.character - left.from);
- warning("W011", left, left.value);
- }
- }
- function comma(opts) {
- opts = opts || {};
- if (!opts.peek) {
- nobreakcomma(state.tokens.curr, state.tokens.next);
- advance(",");
- } else {
- nobreakcomma(state.tokens.prev, state.tokens.curr);
- }
- // TODO: This is a temporary solution to fight against false-positives in
- // arrays and objects with trailing commas (see GH-363). The best solution
- // would be to extract all whitespace rules out of parser.
- if (state.tokens.next.value !== "]" && state.tokens.next.value !== "}") {
- nonadjacent(state.tokens.curr, state.tokens.next);
- }
- if (state.tokens.next.identifier && !(opts.property && state.option.inES5())) {
- // Keywords that cannot follow a comma operator.
- switch (state.tokens.next.value) {
- case "break":
- case "case":
- case "catch":
- case "continue":
- case "default":
- case "do":
- case "else":
- case "finally":
- case "for":
- case "if":
- case "in":
- case "instanceof":
- case "return":
- case "switch":
- case "throw":
- case "try":
- case "var":
- case "let":
- case "while":
- case "with":
- error("E024", state.tokens.next, state.tokens.next.value);
- return false;
- }
- }
- if (state.tokens.next.type === "(punctuator)") {
- switch (state.tokens.next.value) {
- case "}":
- case "]":
- case ",":
- if (opts.allowTrailing) {
- return true;
- }
- /* falls through */
- case ")":
- error("E024", state.tokens.next, state.tokens.next.value);
- return false;
- }
- }
- return true;
- }
- // Functional constructors for making the symbols that will be inherited by
- // tokens.
- function symbol(s, p) {
- var x = state.syntax[s];
- if (!x || typeof x !== "object") {
- state.syntax[s] = x = {
- id: s,
- lbp: p,
- value: s
- };
- }
- return x;
- }
- function delim(s) {
- return symbol(s, 0);
- }
- function stmt(s, f) {
- var x = delim(s);
- x.identifier = x.reserved = true;
- x.fud = f;
- return x;
- }
- function blockstmt(s, f) {
- var x = stmt(s, f);
- x.block = true;
- return x;
- }
- function reserveName(x) {
- var c = x.id.charAt(0);
- if ((c >= "a" && c <= "z") || (c >= "A" && c <= "Z")) {
- x.identifier = x.reserved = true;
- }
- return x;
- }
- function prefix(s, f) {
- var x = symbol(s, 150);
- reserveName(x);
- x.nud = (typeof f === "function") ? f : function () {
- this.right = expression(150);
- this.arity = "unary";
- if (this.id === "++" || this.id === "--") {
- if (state.option.plusplus) {
- warning("W016", this, this.id);
- } else if ((!this.right.identifier || isReserved(this.right)) &&
- this.right.id !== "." && this.right.id !== "[") {
- warning("W017", this);
- }
- }
- return this;
- };
- return x;
- }
- function type(s, f) {
- var x = delim(s);
- x.type = s;
- x.nud = f;
- return x;
- }
- function reserve(name, func) {
- var x = type(name, func);
- x.identifier = true;
- x.reserved = true;
- return x;
- }
- function FutureReservedWord(name, meta) {
- var x = type(name, (meta && meta.nud) || function () {
- return this;
- });
- meta = meta || {};
- meta.isFutureReservedWord = true;
- x.value = name;
- x.identifier = true;
- x.reserved = true;
- x.meta = meta;
- return x;
- }
- function reservevar(s, v) {
- return reserve(s, function () {
- if (typeof v === "function") {
- v(this);
- }
- return this;
- });
- }
- function infix(s, f, p, w) {
- var x = symbol(s, p);
- reserveName(x);
- x.infix = true;
- x.led = function (left) {
- if (!w) {
- nobreaknonadjacent(state.tokens.prev, state.tokens.curr);
- nonadjacent(state.tokens.curr, state.tokens.next);
- }
- if (s === "in" && left.id === "!") {
- warning("W018", left, "!");
- }
- if (typeof f === "function") {
- return f(left, this);
- } else {
- this.left = left;
- this.right = expression(p);
- return this;
- }
- };
- return x;
- }
- function application(s) {
- var x = symbol(s, 42);
- x.led = function (left) {
- if (!state.option.inESNext()) {
- warning("W104", state.tokens.curr, "arrow function syntax (=>)");
- }
- nobreaknonadjacent(state.tokens.prev, state.tokens.curr);
- nonadjacent(state.tokens.curr, state.tokens.next);
- this.left = left;
- this.right = doFunction(undefined, undefined, false, left);
- return this;
- };
- return x;
- }
- function relation(s, f) {
- var x = symbol(s, 100);
- x.led = function (left) {
- nobreaknonadjacent(state.tokens.prev, state.tokens.curr);
- nonadjacent(state.tokens.curr, state.tokens.next);
- var right = expression(100);
- if (isIdentifier(left, "NaN") || isIdentifier(right, "NaN")) {
- warning("W019", this);
- } else if (f) {
- f.apply(this, [left, right]);
- }
- if (!left || !right) {
- quit("E041", state.tokens.curr.line);
- }
- if (left.id === "!") {
- warning("W018", left, "!");
- }
- if (right.id === "!") {
- warning("W018", right, "!");
- }
- this.left = left;
- this.right = right;
- return this;
- };
- return x;
- }
- function isPoorRelation(node) {
- return node &&
- ((node.type === "(number)" && +node.value === 0) ||
- (node.type === "(string)" && node.value === "") ||
- (node.type === "null" && !state.option.eqnull) ||
- node.type === "true" ||
- node.type === "false" ||
- node.type === "undefined");
- }
- function assignop(s, f, p) {
- var x = infix(s, typeof f === "function" ? f : function (left, that) {
- that.left = left;
- if (left) {
- if (predefined[left.value] === false &&
- scope[left.value]["(global)"] === true) {
- warning("W020", left);
- } else if (left["function"]) {
- warning("W021", left, left.value);
- }
- if (funct[left.value] === "const") {
- error("E013", left, left.value);
- }
- if (left.id === ".") {
- if (!left.left) {
- warning("E031", that);
- } else if (left.left.value === "arguments" && !state.directive["use strict"]) {
- warning("E031", that);
- }
- that.right = expression(10);
- return that;
- } else if (left.id === "[") {
- if (state.tokens.curr.left.first) {
- state.tokens.curr.left.first.forEach(function (t) {
- if (funct[t.value] === "const") {
- error("E013", t, t.value);
- }
- });
- } else if (!left.left) {
- warning("E031", that);
- } else if (left.left.value === "arguments" && !state.directive["use strict"]) {
- warning("E031", that);
- }
- that.right = expression(10);
- return that;
- } else if (left.identifier && !isReserved(left)) {
- if (funct[left.value] === "exception") {
- warning("W022", left);
- }
- that.right = expression(10);
- return that;
- }
- if (left === state.syntax["function"]) {
- warning("W023", state.tokens.curr);
- }
- }
- error("E031", that);
- }, p);
- x.exps = true;
- x.assign = true;
- return x;
- }
- function bitwise(s, f, p) {
- var x = symbol(s, p);
- reserveName(x);
- x.led = (typeof f === "function") ? f : function (left) {
- if (state.option.bitwise) {
- warning("W016", this, this.id);
- }
- this.left = left;
- this.right = expression(p);
- return this;
- };
- return x;
- }
- function bitwiseassignop(s) {
- return assignop(s, function (left, that) {
- if (state.option.bitwise) {
- warning("W016", that, that.id);
- }
- nonadjacent(state.tokens.prev, state.tokens.curr);
- nonadjacent(state.tokens.curr, state.tokens.next);
- if (left) {
- if (left.id === "." || left.id === "[" ||
- (left.identifier && !isReserved(left))) {
- expression(10);
- return that;
- }
- if (left === state.syntax["function"]) {
- warning("W023", state.tokens.curr);
- }
- return that;
- }
- error("E031", that);
- }, 20);
- }
- function suffix(s) {
- var x = symbol(s, 150);
- x.led = function (left) {
- if (state.option.plusplus) {
- warning("W016", this, this.id);
- } else if ((!left.identifier || isReserved(left)) && left.id !== "." && left.id !== "[") {
- warning("W017", this);
- }
- this.left = left;
- return this;
- };
- return x;
- }
- // fnparam means that this identifier is being defined as a function
- // argument (see identifier())
- // prop means that this identifier is that of an object property
- function optionalidentifier(fnparam, prop) {
- if (!state.tokens.next.identifier) {
- return;
- }
- advance();
- var curr = state.tokens.curr;
- var val = state.tokens.curr.value;
- if (!isReserved(curr)) {
- return val;
- }
- if (prop) {
- if (state.option.inES5()) {
- return val;
- }
- }
- if (fnparam && val === "undefined") {
- return val;
- }
- // Display an info message about reserved words as properties
- // and ES5 but do it only once.
- if (prop && !api.getCache("displayed:I002")) {
- api.setCache("displayed:I002", true);
- warning("I002");
- }
- warning("W024", state.tokens.curr, state.tokens.curr.id);
- return val;
- }
- // fnparam means that this identifier is being defined as a function
- // argument
- // prop means that this identifier is that of an object property
- function identifier(fnparam, prop) {
- var i = optionalidentifier(fnparam, prop);
- if (i) {
- return i;
- }
- if (state.tokens.curr.id === "function" && state.tokens.next.id === "(") {
- warning("W025");
- } else {
- error("E030", state.tokens.next, state.tokens.next.value);
- }
- }
- function reachable(s) {
- var i = 0, t;
- if (state.tokens.next.id !== ";" || noreach) {
- return;
- }
- for (;;) {
- t = peek(i);
- if (t.reach) {
- return;
- }
- if (t.id !== "(endline)") {
- if (t.id === "function") {
- if (!state.option.latedef) {
- break;
- }
- warning("W026", t);
- break;
- }
- warning("W027", t, t.value, s);
- break;
- }
- i += 1;
- }
- }
- function statement(noindent) {
- var values;
- var i = indent, r, s = scope, t = state.tokens.next;
- if (t.id === ";") {
- advance(";");
- return;
- }
- // Is this a labelled statement?
- var res = isReserved(t);
- // We're being more tolerant here: if someone uses
- // a FutureReservedWord as a label, we warn but proceed
- // anyway.
- if (res && t.meta && t.meta.isFutureReservedWord && peek().id === ":") {
- warning("W024", t, t.id);
- res = false;
- }
- // detect a destructuring assignment
- if (_.has(["[", "{"], t.value)) {
- if (lookupBlockType().isDestAssign) {
- if (!state.option.inESNext()) {
- warning("W104", state.tokens.curr, "destructuring expression");
- }
- values = destructuringExpression();
- values.forEach(function (tok) {
- isundef(funct, "W117", tok.token, tok.id);
- });
- advance("=");
- destructuringExpressionMatch(values, expression(10, true));
- advance(";");
- return;
- }
- }
- if (t.identifier && !res && peek().id === ":") {
- advance();
- advance(":");
- scope = Object.create(s);
- addlabel(t.value, "label");
- if (!state.tokens.next.labelled && state.tokens.next.value !== "{") {
- warning("W028", state.tokens.next, t.value, state.tokens.next.value);
- }
- state.tokens.next.label = t.value;
- t = state.tokens.next;
- }
- // Is it a lonely block?
- if (t.id === "{") {
- block(true, true);
- return;
- }
- // Parse the statement.
- if (!noindent) {
- indentation();
- }
- r = expression(0, true);
- // Look for the final semicolon.
- if (!t.block) {
- if (!state.option.expr && (!r || !r.exps)) {
- warning("W030", state.tokens.curr);
- } else if (state.option.nonew && r && r.left && r.id === "(" && r.left.id === "new") {
- warning("W031", t);
- }
- if (state.tokens.next.id !== ";") {
- if (!state.option.asi) {
- // If this is the last statement in a block that ends on
- // the same line *and* option lastsemic is on, ignore the warning.
- // Otherwise, complain about missing semicolon.
- if (!state.option.lastsemic || state.tokens.next.id !== "}" ||
- state.tokens.next.line !== state.tokens.curr.line) {
- warningAt("W033", state.tokens.curr.line, state.tokens.curr.character);
- }
- }
- } else {
- adjacent(state.tokens.curr, state.tokens.next);
- advance(";");
- nonadjacent(state.tokens.curr, state.tokens.next);
- }
- }
- // Restore the indentation.
- indent = i;
- scope = s;
- return r;
- }
- function statements(startLine) {
- var a = [], p;
- while (!state.tokens.next.reach && state.tokens.next.id !== "(end)") {
- if (state.tokens.next.id === ";") {
- p = peek();
- if (!p || (p.id !== "(" && p.id !== "[")) {
- warning("W032");
- }
- advance(";");
- } else {
- a.push(statement(startLine === state.tokens.next.line));
- }
- }
- return a;
- }
- /*
- * read all directives
- * recognizes a simple form of asi, but always
- * warns, if it is used
- */
- function directives() {
- var i, p, pn;
- for (;;) {
- if (state.tokens.next.id === "(string)") {
- p = peek(0);
- if (p.id === "(endline)") {
- i = 1;
- do {
- pn = peek(i);
- i = i + 1;
- } while (pn.id === "(endline)");
- if (pn.id !== ";") {
- if (pn.id !== "(string)" && pn.id !== "(number)" &&
- pn.id !== "(regexp)" && pn.identifier !== true &&
- pn.id !== "}") {
- break;
- }
- warning("W033", state.tokens.next);
- } else {
- p = pn;
- }
- } else if (p.id === "}") {
- // Directive with no other statements, warn about missing semicolon
- warning("W033", p);
- } else if (p.id !== ";") {
- break;
- }
- indentation();
- advance();
- if (state.directive[state.tokens.curr.value]) {
- warning("W034", state.tokens.curr, state.tokens.curr.value);
- }
- if (state.tokens.curr.value === "use strict") {
- if (!state.option["(explicitNewcap)"])
- state.option.newcap = true;
- state.option.undef = true;
- }
- // there's no directive negation, so always set to true
- state.directive[state.tokens.curr.value] = true;
- if (p.id === ";") {
- advance(";");
- }
- continue;
- }
- break;
- }
- }
- /*
- * Parses a single block. A block is a sequence of statements wrapped in
- * braces.
- *
- * ordinary - true for everything but function bodies and try blocks.
- * stmt - true if block can be a single statement (e.g. in if/for/while).
- * isfunc - true if block is a function body
- */
- function block(ordinary, stmt, isfunc, isfatarrow) {
- var a,
- b = inblock,
- old_indent = indent,
- m,
- s = scope,
- t,
- line,
- d;
- inblock = ordinary;
- if (!ordinary || !state.option.funcscope)
- scope = Object.create(scope);
- nonadjacent(state.tokens.curr, state.tokens.next);
- t = state.tokens.next;
- var metrics = funct["(metrics)"];
- metrics.nestedBlockDepth += 1;
- metrics.verifyMaxNestedBlockDepthPerFunction();
- if (state.tokens.next.id === "{") {
- advance("{");
- // create a new block scope
- funct["(blockscope)"].stack();
- line = state.tokens.curr.line;
- if (state.tokens.next.id !== "}") {
- indent += state.option.indent;
- while (!ordinary && state.tokens.next.from > indent) {
- indent += state.option.indent;
- }
- if (isfunc) {
- m = {};
- for (d in state.directive) {
- if (_.has(state.directive, d)) {
- m[d] = state.directive[d];
- }
- }
- directives();
- if (state.option.strict && funct["(context)"]["(global)"]) {
- if (!m["use strict"] && !state.directive["use strict"]) {
- warning("E007");
- }
- }
- }
- a = statements(line);
- metrics.statementCount += a.length;
- if (isfunc) {
- state.directive = m;
- }
- indent -= state.option.indent;
- if (line !== state.tokens.next.line) {
- indentation();
- }
- } else if (line !== state.tokens.next.line) {
- indentation();
- }
- advance("}", t);
- funct["(blockscope)"].unstack();
- indent = old_indent;
- } else if (!ordinary) {
- if (isfunc) {
- m = {};
- if (stmt && !isfatarrow && !state.option.inMoz(true)) {
- error("W118", state.tokens.curr, "function closure expressions");
- }
- if (!stmt) {
- for (d in state.directive) {
- if (_.has(state.directive, d)) {
- m[d] = state.directive[d];
- }
- }
- }
- expression(10);
- if (state.option.strict && funct["(context)"]["(global)"]) {
- if (!m["use strict"] && !state.directive["use strict"]) {
- warning("E007");
- }
- }
- } else {
- error("E021", state.tokens.next, "{", state.tokens.next.value);
- }
- } else {
- // check to avoid let declaration not within a block
- funct["(nolet)"] = true;
- if (!stmt || state.option.curly) {
- warning("W116", state.tokens.next, "{", state.tokens.next.value);
- }
- noreach = true;
- indent += state.option.indent;
- // test indentation only if statement is in new line
- a = [statement(state.tokens.next.line === state.tokens.curr.line)];
- indent -= state.option.indent;
- noreach = false;
- delete funct["(nolet)"];
- }
- funct["(verb)"] = null;
- if (!ordinary || !state.option.funcscope) scope = s;
- inblock = b;
- if (ordinary && state.option.noempty && (!a || a.length === 0)) {
- warning("W035");
- }
- metrics.nestedBlockDepth -= 1;
- return a;
- }
- function countMember(m) {
- if (membersOnly && typeof membersOnly[m] !== "boolean") {
- warning("W036", state.tokens.curr, m);
- }
- if (typeof member[m] === "number") {
- member[m] += 1;
- } else {
- member[m] = 1;
- }
- }
- function note_implied(tkn) {
- var name = tkn.value, line = tkn.line, a = implied[name];
- if (typeof a === "function") {
- a = false;
- }
- if (!a) {
- a = [line];
- implied[name] = a;
- } else if (a[a.length - 1] !== line) {
- a.push(line);
- }
- }
- // Build the syntax table by declaring the syntactic elements of the language.
- type("(number)", function () {
- return this;
- });
- type("(string)", function () {
- return this;
- });
- state.syntax["(identifier)"] = {
- type: "(identifier)",
- lbp: 0,
- identifier: true,
- nud: function () {
- var v = this.value,
- s = scope[v],
- f;
- if (typeof s === "function") {
- // Protection against accidental inheritance.
- s = undefined;
- } else if (typeof s === "boolean") {
- f = funct;
- funct = functions[0];
- addlabel(v, "var");
- s = funct;
- funct = f;
- }
- var block;
- if (_.has(funct, "(blockscope)")) {
- block = funct["(blockscope)"].getlabel(v);
- }
- // The name is in scope and defined in the current function.
- if (funct === s || block) {
- // Change 'unused' to 'var', and reject labels.
- // the name is in a block scope
- switch (block ? block[v]["(type)"] : funct[v]) {
- case "unused":
- if (block) block[v]["(type)"] = "var";
- else funct[v] = "var";
- break;
- case "unction":
- if (block) block[v]["(type)"] = "function";
- else funct[v] = "function";
- this["function"] = true;
- break;
- case "function":
- this["function"] = true;
- break;
- case "label":
- warning("W037", state.tokens.curr, v);
- break;
- }
- } else if (funct["(global)"]) {
- // The name is not defined in the function. If we are in the global
- // scope, then we have an undefined variable.
- //
- // Operators typeof and delete do not raise runtime errors even if
- // the base object of a reference is null so no need to display warning
- // if we're inside of typeof or delete.
- if (typeof predefined[v] !== "boolean") {
- // Attempting to subscript a null reference will throw an
- // error, even within the typeof and delete operators
- if (!(anonname === "typeof" || anonname === "delete") ||
- (state.tokens.next && (state.tokens.next.value === "." ||
- state.tokens.next.value === "["))) {
- // if we're in a list comprehension, variables are declared
- // locally and used before being defined. So we check
- // the presence of the given variable in the comp array
- // before declaring it undefined.
- if (!funct["(comparray)"].check(v)) {
- isundef(funct, "W117", state.tokens.curr, v);
- }
- }
- }
- note_implied(state.tokens.curr);
- } else {
- // If the name is already defined in the current
- // function, but not as outer, then there is a scope error.
- switch (funct[v]) {
- case "closure":
- case "function":
- case "var":
- case "unused":
- warning("W038", state.tokens.curr, v);
- break;
- case "label":
- warning("W037", state.tokens.curr, v);
- break;
- case "outer":
- case "global":
- break;
- default:
- // If the name is defined in an outer function, make an outer entry,
- // and if it was unused, make it var.
- if (s === true) {
- funct[v] = true;
- } else if (s === null) {
- warning("W039", state.tokens.curr, v);
- note_implied(state.tokens.curr);
- } else if (typeof s !== "object") {
- // Operators typeof and delete do not raise runtime errors even
- // if the base object of a reference is null so no need to
- //
- // display warning if we're inside of typeof or delete.
- // Attempting to subscript a null reference will throw an
- // error, even within the typeof and delete operators
- if (!(anonname === "typeof" || anonname === "delete") ||
- (state.tokens.next &&
- (state.tokens.next.value === "." || state.tokens.next.value === "["))) {
- isundef(funct, "W117", state.tokens.curr, v);
- }
- funct[v] = true;
- note_implied(state.tokens.curr);
- } else {
- switch (s[v]) {
- case "function":
- case "unction":
- this["function"] = true;
- s[v] = "closure";
- funct[v] = s["(global)"] ? "global" : "outer";
- break;
- case "var":
- case "unused":
- s[v] = "closure";
- funct[v] = s["(global)"] ? "global" : "outer";
- break;
- case "closure":
- funct[v] = s["(global)"] ? "global" : "outer";
- break;
- case "label":
- warning("W037", state.tokens.curr, v);
- }
- }
- }
- }
- return this;
- },
- led: function () {
- error("E033", state.tokens.next, state.tokens.next.value);
- }
- };
- type("(regexp)", function () {
- return this;
- });
- // ECMAScript parser
- delim("(endline)");
- delim("(begin)");
- delim("(end)").reach = true;
- delim("(error)").reach = true;
- delim("}").reach = true;
- delim(")");
- delim("]");
- delim("\"").reach = true;
- delim("'").reach = true;
- delim(";");
- delim(":").reach = true;
- delim("#");
- reserve("else");
- reserve("case").reach = true;
- reserve("catch");
- reserve("default").reach = true;
- reserve("finally");
- reservevar("arguments", function (x) {
- if (state.directive["use strict"] && funct["(global)"]) {
- warning("E008", x);
- }
- });
- reservevar("eval");
- reservevar("false");
- reservevar("Infinity");
- reservevar("null");
- reservevar("this", function (x) {
- if (state.directive["use strict"] && !state.option.validthis && ((funct["(statement)"] &&
- funct["(name)"].charAt(0) > "Z") || funct["(global)"])) {
- warning("W040", x);
- }
- });
- reservevar("true");
- reservevar("undefined");
- assignop("=", "assign", 20);
- assignop("+=", "assignadd", 20);
- assignop("-=", "assignsub", 20);
- assignop("*=", "assignmult", 20);
- assignop("/=", "assigndiv", 20).nud = function () {
- error("E014");
- };
- assignop("%=", "assignmod", 20);
- bitwiseassignop("&=", "assignbitand", 20);
- bitwiseassignop("|=", "assignbitor", 20);
- bitwiseassignop("^=", "assignbitxor", 20);
- bitwiseassignop("<<=", "assignshiftleft", 20);
- bitwiseassignop(">>=", "assignshiftright", 20);
- bitwiseassignop(">>>=", "assignshiftrightunsigned", 20);
- infix(",", function (left, that) {
- var expr;
- that.exprs = [left];
- if (!comma({peek: true})) {
- return that;
- }
- while (true) {
- if (!(expr = expression(10))) {
- break;
- }
- that.exprs.push(expr);
- if (state.tokens.next.value !== "," || !comma()) {
- break;
- }
- }
- return that;
- }, 10, true);
- infix("?", function (left, that) {
- increaseComplexityCount();
- that.left = left;
- that.right = expression(10);
- advance(":");
- that["else"] = expression(10);
- return that;
- }, 30);
- var orPrecendence = 40;
- infix("||", function (left, that) {
- increaseComplexityCount();
- that.left = left;
- that.right = expression(orPrecendence);
- return that;
- }, orPrecendence);
- infix("&&", "and", 50);
- bitwise("|", "bitor", 70);
- bitwise("^", "bitxor", 80);
- bitwise("&", "bitand", 90);
- relation("==", function (left, right) {
- var eqnull = state.option.eqnull && (left.value === "null" || right.value === "null");
- if (!eqnull && state.option.eqeqeq)
- warning("W116", this, "===", "==");
- else if (isPoorRelation(left))
- warning("W041", this, "===", left.value);
- else if (isPoorRelation(right))
- warning("W041", this, "===", right.value);
- return this;
- });
- relation("===");
- relation("!=", function (left, right) {
- var eqnull = state.option.eqnull &&
- (left.value === "null" || right.value === "null");
- if (!eqnull && state.option.eqeqeq) {
- warning("W116", this, "!==", "!=");
- } else if (isPoorRelation(left)) {
- warning("W041", this, "!==", left.value);
- } else if (isPoorRelation(right)) {
- warning("W041", this, "!==", right.value);
- }
- return this;
- });
- relation("!==");
- relation("<");
- relation(">");
- relation("<=");
- relation(">=");
- bitwise("<<", "shiftleft", 120);
- bitwise(">>", "shiftright", 120);
- bitwise(">>>", "shiftrightunsigned", 120);
- infix("in", "in", 120);
- infix("instanceof", "instanceof", 120);
- infix("+", function (left, that) {
- var right = expression(130);
- if (left && right && left.id === "(string)" && right.id === "(string)") {
- left.value += right.value;
- left.character = right.character;
- if (!state.option.scripturl && reg.javascriptURL.test(left.value)) {
- warning("W050", left);
- }
- return left;
- }
- that.left = left;
- that.right = right;
- return that;
- }, 130);
- prefix("+", "num");
- prefix("+++", function () {
- warning("W007");
- this.right = expression(150);
- this.arity = "unary";
- return this;
- });
- infix("+++", function (left) {
- warning("W007");
- this.left = left;
- this.right = expression(130);
- return this;
- }, 130);
- infix("-", "sub", 130);
- prefix("-", "neg");
- prefix("---", function () {
- warning("W006");
- this.right = expression(150);
- this.arity = "unary";
- return this;
- });
- infix("---", function (left) {
- warning("W006");
- this.left = left;
- this.right = expression(130);
- return this;
- }, 130);
- infix("*", "mult", 140);
- infix("/", "div", 140);
- infix("%", "mod", 140);
- suffix("++", "postinc");
- prefix("++", "preinc");
- state.syntax["++"].exps = true;
- suffix("--", "postdec");
- prefix("--", "predec");
- state.syntax["--"].exps = true;
- prefix("delete", function () {
- var p = expression(10);
- if (!p || (p.id !== "." && p.id !== "[")) {
- warning("W051");
- }
- this.first = p;
- return this;
- }).exps = true;
- prefix("~", function () {
- if (state.option.bitwise) {
- warning("W052", this, "~");
- }
- expression(150);
- return this;
- });
- prefix("...", function () {
- if (!state.option.inESNext()) {
- warning("W104", this, "spread/rest operator");
- }
- if (!state.tokens.next.identifier) {
- error("E030", state.tokens.next, state.tokens.next.value);
- }
- expression(150);
- return this;
- });
- prefix("!", function () {
- this.right = expression(150);
- this.arity = "unary";
- if (!this.right) { // '!' followed by nothing? Give up.
- quit("E041", this.line || 0);
- }
- if (bang[this.right.id] === true) {
- warning("W018", this, "!");
- }
- return this;
- });
- prefix("typeof", "typeof");
- prefix("new", function () {
- var c = expression(155), i;
- if (c && c.id !== "function") {
- if (c.identifier) {
- c["new"] = true;
- switch (c.value) {
- case "Number":
- case "String":
- case "Boolean":
- case "Math":
- case "JSON":
- warning("W053", state.tokens.prev, c.value);
- break;
- case "Function":
- if (!state.option.evil) {
- warning("W054");
- }
- break;
- case "Date":
- case "RegExp":
- break;
- default:
- if (c.id !== "function") {
- i = c.value.substr(0, 1);
- if (state.option.newcap && (i < "A" || i > "Z") && !_.has(global, c.value)) {
- warning("W055", state.tokens.curr);
- }
- }
- }
- } else {
- if (c.id !== "." && c.id !== "[" && c.id !== "(") {
- warning("W056", state.tokens.curr);
- }
- }
- } else {
- if (!state.option.supernew)
- warning("W057", this);
- }
- adjacent(state.tokens.curr, state.tokens.next);
- if (state.tokens.next.id !== "(" && !state.option.supernew) {
- warning("W058", state.tokens.curr, state.tokens.curr.value);
- }
- this.first = c;
- return this;
- });
- state.syntax["new"].exps = true;
- prefix("void").exps = true;
- infix(".", function (left, that) {
- adjacent(state.tokens.prev, state.tokens.curr);
- nobreak();
- var m = identifier(false, true);
- if (typeof m === "string") {
- countMember(m);
- }
- that.left = left;
- that.right = m;
- if (m && m === "hasOwnProperty" && state.tokens.next.value === "=") {
- warning("W001");
- }
- if (left && left.value === "arguments" && (m === "callee" || m === "caller")) {
- if (state.option.noarg)
- warning("W059", left, m);
- else if (state.directive["use strict"])
- error("E008");
- } else if (!state.option.evil && left && left.value === "document" &&
- (m === "write" || m === "writeln")) {
- warning("W060", left);
- }
- if (!state.option.evil && (m === "eval" || m === "execScript")) {
- warning("W061");
- }
- return that;
- }, 160, true);
- infix("(", function (left, that) {
- if (state.tokens.prev.id !== "}" && state.tokens.prev.id !== ")") {
- nobreak(state.tokens.prev, state.tokens.curr);
- }
- nospace();
- if (state.option.immed && left && !left.immed && left.id === "function") {
- warning("W062");
- }
- var n = 0;
- var p = [];
- if (left) {
- if (left.type === "(identifier)") {
- if (left.value.match(/^[A-Z]([A-Z0-9_$]*[a-z][A-Za-z0-9_$]*)?$/)) {
- if ("Number String Boolean Date Object".indexOf(left.value) === -1) {
- if (left.value === "Math") {
- warning("W063", left);
- } else if (state.option.newcap) {
- warning("W064", left);
- }
- }
- }
- }
- }
- if (state.tokens.next.id !== ")") {
- for (;;) {
- p[p.length] = expression(10);
- n += 1;
- if (state.tokens.next.id !== ",") {
- break;
- }
- comma();
- }
- }
- advance(")");
- nospace(state.tokens.prev, state.tokens.curr);
- if (typeof left === "object") {
- if (left.value === "parseInt" && n === 1) {
- warning("W065", state.tokens.curr);
- }
- if (!state.option.evil) {
- if (left.value === "eval" || left.value === "Function" ||
- left.value === "execScript") {
- warning("W061", left);
- if (p[0] && [0].id === "(string)") {
- addInternalSrc(left, p[0].value);
- }
- } else if (p[0] && p[0].id === "(string)" &&
- (left.value === "setTimeout" ||
- left.value === "setInterval")) {
- warning("W066", left);
- addInternalSrc(left, p[0].value);
- // window.setTimeout/setInterval
- } else if (p[0] && p[0].id === "(string)" &&
- left.value === "." &&
- left.left.value === "window" &&
- (left.right === "setTimeout" ||
- left.right === "setInterval")) {
- warning("W066", left);
- addInternalSrc(left, p[0].value);
- }
- }
- if (!left.identifier && left.id !== "." && left.id !== "[" &&
- left.id !== "(" && left.id !== "&&" && left.id !== "||" &&
- left.id !== "?") {
- warning("W067", left);
- }
- }
- that.left = left;
- return that;
- }, 155, true).exps = true;
- prefix("(", function () {
- nospace();
- var bracket, brackets = [];
- var pn, pn1, i = 0;
- var ret;
- do {
- pn = peek(i);
- i += 1;
- pn1 = peek(i);
- i += 1;
- } while (pn.value !== ")" && pn1.value !== "=>" && pn1.value !== ";" && pn1.type !== "(end)");
- if (state.tokens.next.id === "function") {
- state.tokens.next.immed = true;
- }
- var exprs = [];
- if (state.tokens.next.id !== ")") {
- for (;;) {
- if (pn1.value === "=>" && state.tokens.next.value === "{") {
- bracket = state.tokens.next;
- bracket.left = destructuringExpression();
- brackets.push(bracket);
- for (var t in bracket.left) {
- exprs.push(bracket.left[t].token);
- }
- } else {
- exprs.push(expression(10));
- }
- if (state.tokens.next.id !== ",") {
- break;
- }
- comma();
- }
- }
- advance(")", this);
- nospace(state.tokens.prev, state.tokens.curr);
- if (state.option.immed && exprs[0] && exprs[0].id === "function") {
- if (state.tokens.next.id !== "(" &&
- (state.tokens.next.id !== "." || (peek().value !== "call" && peek().value !== "apply"))) {
- warning("W068", this);
- }
- }
- if (state.tokens.next.value === "=>") {
- return exprs;
- }
- if (!exprs.length) {
- return;
- }
- if (exprs.length > 1) {
- ret = Object.create(state.syntax[","]);
- ret.exprs = exprs;
- } else {
- ret = exprs[0];
- }
- if (ret) {
- ret.paren = true;
- }
- return ret;
- });
- application("=>");
- infix("[", function (left, that) {
- nobreak(state.tokens.prev, state.tokens.curr);
- nospace();
- var e = expression(10), s;
- if (e && e.type === "(string)") {
- if (!state.option.evil && (e.value === "eval" || e.value === "execScript")) {
- warning("W061", that);
- }
- countMember(e.value);
- if (!state.option.sub && reg.identifier.test(e.value)) {
- s = state.syntax[e.value];
- if (!s || !isReserved(s)) {
- warning("W069", state.tokens.prev, e.value);
- }
- }
- }
- advance("]", that);
- if (e && e.value === "hasOwnProperty" && state.tokens.next.value === "=") {
- warning("W001");
- }
- nospace(state.tokens.prev, state.tokens.curr);
- that.left = left;
- that.right = e;
- return that;
- }, 160, true);
- function comprehensiveArrayExpression() {
- var res = {};
- res.exps = true;
- funct["(comparray)"].stack();
- res.right = expression(10);
- advance("for");
- if (state.tokens.next.value === "each") {
- advance("each");
- if (!state.option.inMoz(true)) {
- warning("W118", state.tokens.curr, "for each");
- }
- }
- advance("(");
- funct["(comparray)"].setState("define");
- res.left = expression(10);
- advance(")");
- if (state.tokens.next.value === "if") {
- advance("if");
- advance("(");
- funct["(comparray)"].setState("filter");
- res.filter = expression(10);
- advance(")");
- }
- advance("]");
- funct["(comparray)"].unstack();
- return res;
- }
- prefix("[", function () {
- var blocktype = lookupBlockType(true);
- if (blocktype.isCompArray) {
- if (!state.option.inMoz(true)) {
- warning("W118", state.tokens.curr, "array comprehension");
- }
- return comprehensiveArrayExpression();
- } else if (blocktype.isDestAssign && !state.option.inESNext()) {
- warning("W104", state.tokens.curr, "destructuring assignment");
- }
- var b = state.tokens.curr.line !== state.tokens.next.line;
- this.first = [];
- if (b) {
- indent += state.option.indent;
- if (state.tokens.next.from === indent + state.option.indent) {
- indent += state.option.indent;
- }
- }
- while (state.tokens.next.id !== "(end)") {
- while (state.tokens.next.id === ",") {
- if (!state.option.inES5())
- warning("W070");
- advance(",");
- }
- if (state.tokens.next.id === "]") {
- break;
- }
- if (b && state.tokens.curr.line !== state.tokens.next.line) {
- indentation();
- }
- this.first.push(expression(10));
- if (state.tokens.next.id === ",") {
- comma({ allowTrailing: true });
- if (state.tokens.next.id === "]" && !state.option.inES5(true)) {
- warning("W070", state.tokens.curr);
- break;
- }
- } else {
- break;
- }
- }
- if (b) {
- indent -= state.option.indent;
- indentation();
- }
- advance("]", this);
- return this;
- }, 160);
- function property_name() {
- var id = optionalidentifier(false, true);
- if (!id) {
- if (state.tokens.next.id === "(string)") {
- id = state.tokens.next.value;
- advance();
- } else if (state.tokens.next.id === "(number)") {
- id = state.tokens.next.value.toString();
- advance();
- }
- }
- if (id === "hasOwnProperty") {
- warning("W001");
- }
- return id;
- }
- function functionparams(parsed) {
- var curr, next;
- var params = [];
- var ident;
- var tokens = [];
- var t;
- var pastDefault = false;
- if (parsed) {
- if (parsed instanceof Array) {
- for (var i in parsed) {
- curr = parsed[i];
- if (_.contains(["{", "["], curr.id)) {
- for (t in curr.left) {
- t = tokens[t];
- if (t.id) {
- params.push(t.id);
- addlabel(t.id, "unused", t.token);
- }
- }
- } else if (curr.value === "...") {
- if (!state.option.inESNext()) {
- warning("W104", curr, "spread/rest operator");
- }
- continue;
- } else {
- addlabel(curr.value, "unused", curr);
- }
- }
- return params;
- } else {
- if (parsed.identifier === true) {
- addlabel(parsed.value, "unused", parsed);
- return [parsed];
- }
- }
- }
- next = state.tokens.next;
- advance("(");
- nospace();
- if (state.tokens.next.id === ")") {
- advance(")");
- return;
- }
- for (;;) {
- if (_.contains(["{", "["], state.tokens.next.id)) {
- tokens = destructuringExpression();
- for (t in tokens) {
- t = tokens[t];
- if (t.id) {
- params.push(t.id);
- addlabel(t.id, "unused", t.token);
- }
- }
- } else if (state.tokens.next.value === "...") {
- if (!state.option.inESNext()) {
- warning("W104", state.tokens.next, "spread/rest operator");
- }
- advance("...");
- nospace();
- ident = identifier(true);
- params.push(ident);
- addlabel(ident, "unused", state.tokens.curr);
- } else {
- ident = identifier(true);
- params.push(ident);
- addlabel(ident, "unused", state.tokens.curr);
- }
- // it is a syntax error to have a regular argument after a default argument
- if (pastDefault) {
- if (state.tokens.next.id !== "=") {
- error("E051", state.tokens.current);
- }
- }
- if (state.tokens.next.id === "=") {
- if (!state.option.inESNext()) {
- warning("W119", state.tokens.next, "default parameters");
- }
- advance("=");
- pastDefault = true;
- expression(10);
- }
- if (state.tokens.next.id === ",") {
- comma();
- } else {
- advance(")", next);
- nospace(state.tokens.prev, state.tokens.curr);
- return params;
- }
- }
- }
- function doFunction(name, statement, generator, fatarrowparams) {
- var f;
- var oldOption = state.option;
- var oldIgnored = state.ignored;
- var oldScope = scope;
- state.option = Object.create(state.option);
- state.ignored = Object.create(state.ignored);
- scope = Object.create(scope);
- funct = {
- "(name)" : name || "\"" + anonname + "\"",
- "(line)" : state.tokens.next.line,
- "(character)" : state.tokens.next.character,
- "(context)" : funct,
- "(breakage)" : 0,
- "(loopage)" : 0,
- "(metrics)" : createMetrics(state.tokens.next),
- "(scope)" : scope,
- "(statement)" : statement,
- "(tokens)" : {},
- "(blockscope)": funct["(blockscope)"],
- "(comparray)" : funct["(comparray)"]
- };
- if (generator) {
- funct["(generator)"] = true;
- }
- f = funct;
- state.tokens.curr.funct = funct;
- functions.push(funct);
- if (name) {
- addlabel(name, "function");
- }
- funct["(params)"] = functionparams(fatarrowparams);
- funct["(metrics)"].verifyMaxParametersPerFunction(funct["(params)"]);
- block(false, true, true, fatarrowparams ? true:false);
- if (generator && funct["(generator)"] !== "yielded") {
- error("E047", state.tokens.curr);
- }
- funct["(metrics)"].verifyMaxStatementsPerFunction();
- funct["(metrics)"].verifyMaxComplexityPerFunction();
- funct["(unusedOption)"] = state.option.unused;
- scope = oldScope;
- state.option = oldOption;
- state.ignored = oldIgnored;
- funct["(last)"] = state.tokens.curr.line;
- funct["(lastcharacter)"] = state.tokens.curr.character;
- funct = funct["(context)"];
- return f;
- }
- function createMetrics(functionStartToken) {
- return {
- statementCount: 0,
- nestedBlockDepth: -1,
- ComplexityCount: 1,
- verifyMaxStatementsPerFunction: function () {
- if (state.option.maxstatements &&
- this.statementCount > state.option.maxstatements) {
- warning("W071", functionStartToken, this.statementCount);
- }
- },
- verifyMaxParametersPerFunction: function (params) {
- params = params || [];
- if (state.option.maxparams && params.length > state.option.maxparams) {
- warning("W072", functionStartToken, params.length);
- }
- },
- verifyMaxNestedBlockDepthPerFunction: function () {
- if (state.option.maxdepth &&
- this.nestedBlockDepth > 0 &&
- this.nestedBlockDepth === state.option.maxdepth + 1) {
- warning("W073", null, this.nestedBlockDepth);
- }
- },
- verifyMaxComplexityPerFunction: function () {
- var max = state.option.maxcomplexity;
- var cc = this.ComplexityCount;
- if (max && cc > max) {
- warning("W074", functionStartToken, cc);
- }
- }
- };
- }
- function increaseComplexityCount() {
- funct["(metrics)"].ComplexityCount += 1;
- }
- // Parse assignments that were found instead of conditionals.
- // For example: if (a = 1) { ... }
- function checkCondAssignment(expr) {
- var id, paren;
- if (expr) {
- id = expr.id;
- paren = expr.paren;
- if (id === "," && (expr = expr.exprs[expr.exprs.length - 1])) {
- id = expr.id;
- paren = paren || expr.paren;
- }
- }
- switch (id) {
- case "=":
- case "+=":
- case "-=":
- case "*=":
- case "%=":
- case "&=":
- case "|=":
- case "^=":
- case "/=":
- if (!paren && !state.option.boss) {
- warning("W084");
- }
- }
- }
- (function (x) {
- x.nud = function (isclassdef) {
- var b, f, i, p, t, g;
- var props = {}; // All properties, including accessors
- var tag = "";
- function saveProperty(name, tkn) {
- if (props[name] && _.has(props, name))
- warning("W075", state.tokens.next, i);
- else
- props[name] = {};
- props[name].basic = true;
- props[name].basictkn = tkn;
- }
- function saveSetter(name, tkn) {
- if (props[name] && _.has(props, name)) {
- if (props[name].basic || props[name].setter)
- warning("W075", state.tokens.next, i);
- } else {
- props[name] = {};
- }
- props[name].setter = true;
- props[name].setterToken = tkn;
- }
- function saveGetter(name) {
- if (props[name] && _.has(props, name)) {
- if (props[name].basic || props[name].getter)
- warning("W075", state.tokens.next, i);
- } else {
- props[name] = {};
- }
- props[name].getter = true;
- props[name].getterToken = state.tokens.curr;
- }
- b = state.tokens.curr.line !== state.tokens.next.line;
- if (b) {
- indent += state.option.indent;
- if (state.tokens.next.from === indent + state.option.indent) {
- indent += state.option.indent;
- }
- }
- for (;;) {
- if (state.tokens.next.id === "}") {
- break;
- }
- if (b) {
- indentation();
- }
- if (isclassdef && state.tokens.next.value === "static") {
- advance("static");
- tag = "static ";
- }
- if (state.tokens.next.value === "get" && peek().id !== ":") {
- advance("get");
- if (!state.option.inES5(!isclassdef)) {
- error("E034");
- }
- i = property_name();
- if (!i) {
- error("E035");
- }
- // It is a Syntax Error if PropName of MethodDefinition is
- // "constructor" and SpecialMethod of MethodDefinition is true.
- if (isclassdef && i === "constructor") {
- error("E049", state.tokens.next, "class getter method", i);
- }
- saveGetter(tag + i);
- t = state.tokens.next;
- adjacent(state.tokens.curr, state.tokens.next);
- f = doFunction();
- p = f["(params)"];
- if (p) {
- warning("W076", t, p[0], i);
- }
- adjacent(state.tokens.curr, state.tokens.next);
- } else if (state.tokens.next.value === "set" && peek().id !== ":") {
- advance("set");
- if (!state.option.inES5(!isclassdef)) {
- error("E034");
- }
- i = property_name();
- if (!i) {
- error("E035");
- }
- // It is a Syntax Error if PropName of MethodDefinition is
- // "constructor" and SpecialMethod of MethodDefinition is true.
- if (isclassdef && i === "constructor") {
- error("E049", state.tokens.next, "class setter method", i);
- }
- saveSetter(tag + i, state.tokens.next);
- t = state.tokens.next;
- adjacent(state.tokens.curr, state.tokens.next);
- f = doFunction();
- p = f["(params)"];
- if (!p || p.length !== 1) {
- warning("W077", t, i);
- }
- } else {
- g = false;
- if (state.tokens.next.value === "*" && state.tokens.next.type === "(punctuator)") {
- if (!state.option.inESNext()) {
- warning("W104", state.tokens.next, "generator functions");
- }
- advance("*");
- g = true;
- }
- i = property_name();
- saveProperty(tag + i, state.tokens.next);
- if (typeof i !== "string") {
- break;
- }
- if (state.tokens.next.value === "(") {
- if (!state.option.inESNext()) {
- warning("W104", state.tokens.curr, "concise methods");
- }
- doFunction(i, undefined, g);
- } else if (!isclassdef) {
- advance(":");
- nonadjacent(state.tokens.curr, state.tokens.next);
- expression(10);
- }
- }
- // It is a Syntax Error if PropName of MethodDefinition is "prototype".
- if (isclassdef && i === "prototype") {
- error("E049", state.tokens.next, "class method", i);
- }
- countMember(i);
- if (isclassdef) {
- tag = "";
- continue;
- }
- if (state.tokens.next.id === ",") {
- comma({ allowTrailing: true, property: true });
- if (state.tokens.next.id === ",") {
- warning("W070", state.tokens.curr);
- } else if (state.tokens.next.id === "}" && !state.option.inES5(true)) {
- warning("W070", state.tokens.curr);
- }
- } else {
- break;
- }
- }
- if (b) {
- indent -= state.option.indent;
- indentation();
- }
- advance("}", this);
- // Check for lonely setters if in the ES5 mode.
- if (state.option.inES5()) {
- for (var name in props) {
- if (_.has(props, name) && props[name].setter && !props[name].getter) {
- warning("W078", props[name].setterToken);
- }
- }
- }
- return this;
- };
- x.fud = function () {
- error("E036", state.tokens.curr);
- };
- }(delim("{")));
- function destructuringExpression() {
- var id, ids;
- var identifiers = [];
- if (!state.option.inESNext()) {
- warning("W104", state.tokens.curr, "destructuring expression");
- }
- var nextInnerDE = function () {
- var ident;
- if (_.contains(["[", "{"], state.tokens.next.value)) {
- ids = destructuringExpression();
- for (var id in ids) {
- id = ids[id];
- identifiers.push({ id: id.id, token: id.token });
- }
- } else if (state.tokens.next.value === ",") {
- identifiers.push({ id: null, token: state.tokens.curr });
- } else {
- ident = identifier();
- if (ident)
- identifiers.push({ id: ident, token: state.tokens.curr });
- }
- };
- if (state.tokens.next.value === "[") {
- advance("[");
- nextInnerDE();
- while (state.tokens.next.value !== "]") {
- advance(",");
- nextInnerDE();
- }
- advance("]");
- } else if (state.tokens.next.value === "{") {
- advance("{");
- id = identifier();
- if (state.tokens.next.value === ":") {
- advance(":");
- nextInnerDE();
- } else {
- identifiers.push({ id: id, token: state.tokens.curr });
- }
- while (state.tokens.next.value !== "}") {
- advance(",");
- id = identifier();
- if (state.tokens.next.value === ":") {
- advance(":");
- nextInnerDE();
- } else {
- identifiers.push({ id: id, token: state.tokens.curr });
- }
- }
- advance("}");
- }
- return identifiers;
- }
- function destructuringExpressionMatch(tokens, value) {
- if (value.first) {
- _.zip(tokens, value.first).forEach(function (val) {
- var token = val[0];
- var value = val[1];
- if (token && value) {
- token.first = value;
- } else if (token && token.first && !value) {
- warning("W080", token.first, token.first.value);
- } /* else {
- XXX value is discarded: wouldn't it need a warning ?
- } */
- });
- }
- }
- var conststatement = stmt("const", function (prefix) {
- var tokens, value;
- // state variable to know if it is a lone identifier, or a destructuring statement.
- var lone;
- if (!state.option.inESNext()) {
- warning("W104", state.tokens.curr, "const");
- }
- this.first = [];
- for (;;) {
- var names = [];
- nonadjacent(state.tokens.curr, state.tokens.next);
- if (_.contains(["{", "["], state.tokens.next.value)) {
- tokens = destructuringExpression();
- lone = false;
- } else {
- tokens = [ { id: identifier(), token: state.tokens.curr } ];
- lone = true;
- }
- for (var t in tokens) {
- t = tokens[t];
- if (funct[t.id] === "const") {
- warning("E011", null, t.id);
- }
- if (funct["(global)"] && predefined[t.id] === false) {
- warning("W079", t.token, t.id);
- }
- if (t.id) {
- addlabel(t.id, "const");
- names.push(t.token);
- }
- }
- if (prefix) {
- break;
- }
- this.first = this.first.concat(names);
- if (state.tokens.next.id !== "=") {
- warning("E012", state.tokens.curr, state.tokens.curr.value);
- }
- if (state.tokens.next.id === "=") {
- nonadjacent(state.tokens.curr, state.tokens.next);
- advance("=");
- nonadjacent(state.tokens.curr, state.tokens.next);
- if (state.tokens.next.id === "undefined") {
- warning("W080", state.tokens.prev, state.tokens.prev.value);
- }
- if (peek(0).id === "=" && state.tokens.next.identifier) {
- warning("W120", state.tokens.next, state.tokens.next.value);
- }
- value = expression(10);
- if (lone) {
- tokens[0].first = value;
- } else {
- destructuringExpressionMatch(names, value);
- }
- }
- if (state.tokens.next.id !== ",") {
- break;
- }
- comma();
- }
- return this;
- });
- conststatement.exps = true;
- var varstatement = stmt("var", function (prefix) {
- // JavaScript does not have block scope. It only has function scope. So,
- // declaring a variable in a block can have unexpected consequences.
- var tokens, lone, value;
- if (funct["(onevar)"] && state.option.onevar) {
- warning("W081");
- } else if (!funct["(global)"]) {
- funct["(onevar)"] = true;
- }
- this.first = [];
- for (;;) {
- var names = [];
- nonadjacent(state.tokens.curr, state.tokens.next);
- if (_.contains(["{", "["], state.tokens.next.value)) {
- tokens = destructuringExpression();
- lone = false;
- } else {
- tokens = [ { id: identifier(), token: state.tokens.curr } ];
- lone = true;
- }
- for (var t in tokens) {
- t = tokens[t];
- if (state.option.inESNext() && funct[t.id] === "const") {
- warning("E011", null, t.id);
- }
- if (funct["(global)"] && predefined[t.id] === false) {
- warning("W079", t.token, t.id);
- }
- if (t.id) {
- addlabel(t.id, "unused", t.token);
- names.push(t.token);
- }
- }
- if (prefix) {
- break;
- }
- this.first = this.first.concat(names);
- if (state.tokens.next.id === "=") {
- nonadjacent(state.tokens.curr, state.tokens.next);
- advance("=");
- nonadjacent(state.tokens.curr, state.tokens.next);
- if (state.tokens.next.id === "undefined") {
- warning("W080", state.tokens.prev, state.tokens.prev.value);
- }
- if (peek(0).id === "=" && state.tokens.next.identifier) {
- warning("W120", state.tokens.next, state.tokens.next.value);
- }
- value = expression(10);
- if (lone) {
- tokens[0].first = value;
- } else {
- destructuringExpressionMatch(names, value);
- }
- }
- if (state.tokens.next.id !== ",") {
- break;
- }
- comma();
- }
- return this;
- });
- varstatement.exps = true;
- var letstatement = stmt("let", function (prefix) {
- var tokens, lone, value, letblock;
- if (!state.option.inESNext()) {
- warning("W104", state.tokens.curr, "let");
- }
- if (state.tokens.next.value === "(") {
- if (!state.option.inMoz(true)) {
- warning("W118", state.tokens.next, "let block");
- }
- advance("(");
- funct["(blockscope)"].stack();
- letblock = true;
- } else if (funct["(nolet)"]) {
- error("E048", state.tokens.curr);
- }
- if (funct["(onevar)"] && state.option.onevar) {
- warning("W081");
- } else if (!funct["(global)"]) {
- funct["(onevar)"] = true;
- }
- this.first = [];
- for (;;) {
- var names = [];
- nonadjacent(state.tokens.curr, state.tokens.next);
- if (_.contains(["{", "["], state.tokens.next.value)) {
- tokens = destructuringExpression();
- lone = false;
- } else {
- tokens = [ { id: identifier(), token: state.tokens.curr.value } ];
- lone = true;
- }
- for (var t in tokens) {
- t = tokens[t];
- if (state.option.inESNext() && funct[t.id] === "const") {
- warning("E011", null, t.id);
- }
- if (funct["(global)"] && predefined[t.id] === false) {
- warning("W079", t.token, t.id);
- }
- if (t.id && !funct["(nolet)"]) {
- addlabel(t.id, "unused", t.token, true);
- names.push(t.token);
- }
- }
- if (prefix) {
- break;
- }
- this.first = this.first.concat(names);
- if (state.tokens.next.id === "=") {
- nonadjacent(state.tokens.curr, state.tokens.next);
- advance("=");
- nonadjacent(state.tokens.curr, state.tokens.next);
- if (state.tokens.next.id === "undefined") {
- warning("W080", state.tokens.prev, state.tokens.prev.value);
- }
- if (peek(0).id === "=" && state.tokens.next.identifier) {
- warning("W120", state.tokens.next, state.tokens.next.value);
- }
- value = expression(10);
- if (lone) {
- tokens[0].first = value;
- } else {
- destructuringExpressionMatch(names, value);
- }
- }
- if (state.tokens.next.id !== ",") {
- break;
- }
- comma();
- }
- if (letblock) {
- advance(")");
- block(true, true);
- this.block = true;
- funct["(blockscope)"].unstack();
- }
- return this;
- });
- letstatement.exps = true;
- blockstmt("class", function () {
- return classdef.call(this, true);
- });
- function classdef(stmt) {
- /*jshint validthis:true */
- if (!state.option.inESNext()) {
- warning("W104", state.tokens.curr, "class");
- }
- if (stmt) {
- // BindingIdentifier
- this.name = identifier();
- addlabel(this.name, "unused", state.tokens.curr);
- } else if (state.tokens.next.identifier && state.tokens.next.value !== "extends") {
- // BindingIdentifier(opt)
- this.name = identifier();
- }
- classtail(this);
- return this;
- }
- function classtail(c) {
- var strictness = state.directive["use strict"];
- // ClassHeritage(opt)
- if (state.tokens.next.value === "extends") {
- advance("extends");
- c.heritage = expression(10);
- }
- // A ClassBody is always strict code.
- state.directive["use strict"] = true;
- advance("{");
- // ClassBody(opt)
- c.body = state.syntax["{"].nud(true);
- state.directive["use strict"] = strictness;
- }
- blockstmt("function", function () {
- var generator = false;
- if (state.tokens.next.value === "*") {
- advance("*");
- if (state.option.inESNext(true)) {
- generator = true;
- } else {
- warning("W119", state.tokens.curr, "function*");
- }
- }
- if (inblock) {
- warning("W082", state.tokens.curr);
- }
- var i = identifier();
- if (funct[i] === "const") {
- warning("E011", null, i);
- }
- adjacent(state.tokens.curr, state.tokens.next);
- addlabel(i, "unction", state.tokens.curr);
- doFunction(i, { statement: true }, generator);
- if (state.tokens.next.id === "(" && state.tokens.next.line === state.tokens.curr.line) {
- error("E039");
- }
- return this;
- });
- prefix("function", function () {
- var generator = false;
- if (state.tokens.next.value === "*") {
- if (!state.option.inESNext()) {
- warning("W119", state.tokens.curr, "function*");
- }
- advance("*");
- generator = true;
- }
- var i = optionalidentifier();
- if (i || state.option.gcl) {
- adjacent(state.tokens.curr, state.tokens.next);
- } else {
- nonadjacent(state.tokens.curr, state.tokens.next);
- }
- doFunction(i, undefined, generator);
- if (!state.option.loopfunc && funct["(loopage)"]) {
- warning("W083");
- }
- return this;
- });
- blockstmt("if", function () {
- var t = state.tokens.next;
- increaseComplexityCount();
- state.condition = true;
- advance("(");
- nonadjacent(this, t);
- nospace();
- checkCondAssignment(expression(0));
- advance(")", t);
- state.condition = false;
- nospace(state.tokens.prev, state.tokens.curr);
- block(true, true);
- if (state.tokens.next.id === "else") {
- nonadjacent(state.tokens.curr, state.tokens.next);
- advance("else");
- if (state.tokens.next.id === "if" || state.tokens.next.id === "switch") {
- statement(true);
- } else {
- block(true, true);
- }
- }
- return this;
- });
- blockstmt("try", function () {
- var b;
- function doCatch() {
- var oldScope = scope;
- var e;
- advance("catch");
- nonadjacent(state.tokens.curr, state.tokens.next);
- advance("(");
- scope = Object.create(oldScope);
- e = state.tokens.next.value;
- if (state.tokens.next.type !== "(identifier)") {
- e = null;
- warning("E030", state.tokens.next, e);
- }
- advance();
- funct = {
- "(name)" : "(catch)",
- "(line)" : state.tokens.next.line,
- "(character)": state.tokens.next.character,
- "(context)" : funct,
- "(breakage)" : funct["(breakage)"],
- "(loopage)" : funct["(loopage)"],
- "(scope)" : scope,
- "(statement)": false,
- "(metrics)" : createMetrics(state.tokens.next),
- "(catch)" : true,
- "(tokens)" : {},
- "(blockscope)": funct["(blockscope)"],
- "(comparray)": funct["(comparray)"]
- };
- if (e) {
- addlabel(e, "exception");
- }
- if (state.tokens.next.value === "if") {
- if (!state.option.inMoz(true)) {
- warning("W118", state.tokens.curr, "catch filter");
- }
- advance("if");
- expression(0);
- }
- advance(")");
- state.tokens.curr.funct = funct;
- functions.push(funct);
- block(false);
- scope = oldScope;
- funct["(last)"] = state.tokens.curr.line;
- funct["(lastcharacter)"] = state.tokens.curr.character;
- funct = funct["(context)"];
- }
- block(false);
- while (state.tokens.next.id === "catch") {
- increaseComplexityCount();
- if (b && (!state.option.inMoz(true))) {
- warning("W118", state.tokens.next, "multiple catch blocks");
- }
- doCatch();
- b = true;
- }
- if (state.tokens.next.id === "finally") {
- advance("finally");
- block(false);
- return;
- }
- if (!b) {
- error("E021", state.tokens.next, "catch", state.tokens.next.value);
- }
- return this;
- });
- blockstmt("while", function () {
- var t = state.tokens.next;
- funct["(breakage)"] += 1;
- funct["(loopage)"] += 1;
- increaseComplexityCount();
- advance("(");
- nonadjacent(this, t);
- nospace();
- checkCondAssignment(expression(0));
- advance(")", t);
- nospace(state.tokens.prev, state.tokens.curr);
- block(true, true);
- funct["(breakage)"] -= 1;
- funct["(loopage)"] -= 1;
- return this;
- }).labelled = true;
- blockstmt("with", function () {
- var t = state.tokens.next;
- if (state.directive["use strict"]) {
- error("E010", state.tokens.curr);
- } else if (!state.option.withstmt) {
- warning("W085", state.tokens.curr);
- }
- advance("(");
- nonadjacent(this, t);
- nospace();
- expression(0);
- advance(")", t);
- nospace(state.tokens.prev, state.tokens.curr);
- block(true, true);
- return this;
- });
- blockstmt("switch", function () {
- var t = state.tokens.next,
- g = false;
- funct["(breakage)"] += 1;
- advance("(");
- nonadjacent(this, t);
- nospace();
- checkCondAssignment(expression(0));
- advance(")", t);
- nospace(state.tokens.prev, state.tokens.curr);
- nonadjacent(state.tokens.curr, state.tokens.next);
- t = state.tokens.next;
- advance("{");
- nonadjacent(state.tokens.curr, state.tokens.next);
- indent += state.option.indent;
- this.cases = [];
- for (;;) {
- switch (state.tokens.next.id) {
- case "case":
- switch (funct["(verb)"]) {
- case "yield":
- case "break":
- case "case":
- case "continue":
- case "return":
- case "switch":
- case "throw":
- break;
- default:
- // You can tell JSHint that you don't use break intentionally by
- // adding a comment /* falls through */ on a line just before
- // the next `case`.
- if (!reg.fallsThrough.test(state.lines[state.tokens.next.line - 2])) {
- warning("W086", state.tokens.curr, "case");
- }
- }
- indentation(-state.option.indent);
- advance("case");
- this.cases.push(expression(20));
- increaseComplexityCount();
- g = true;
- advance(":");
- funct["(verb)"] = "case";
- break;
- case "default":
- switch (funct["(verb)"]) {
- case "yield":
- case "break":
- case "continue":
- case "return":
- case "throw":
- break;
- default:
- // Do not display a warning if 'default' is the first statement or if
- // there is a special /* falls through */ comment.
- if (this.cases.length) {
- if (!reg.fallsThrough.test(state.lines[state.tokens.next.line - 2])) {
- warning("W086", state.tokens.curr, "default");
- }
- }
- }
- indentation(-state.option.indent);
- advance("default");
- g = true;
- advance(":");
- break;
- case "}":
- indent -= state.option.indent;
- indentation();
- advance("}", t);
- funct["(breakage)"] -= 1;
- funct["(verb)"] = undefined;
- return;
- case "(end)":
- error("E023", state.tokens.next, "}");
- return;
- default:
- if (g) {
- switch (state.tokens.curr.id) {
- case ",":
- error("E040");
- return;
- case ":":
- g = false;
- statements();
- break;
- default:
- error("E025", state.tokens.curr);
- return;
- }
- } else {
- if (state.tokens.curr.id === ":") {
- advance(":");
- error("E024", state.tokens.curr, ":");
- statements();
- } else {
- error("E021", state.tokens.next, "case", state.tokens.next.value);
- return;
- }
- }
- }
- }
- }).labelled = true;
- stmt("debugger", function () {
- if (!state.option.debug) {
- warning("W087");
- }
- return this;
- }).exps = true;
- (function () {
- var x = stmt("do", function () {
- funct["(breakage)"] += 1;
- funct["(loopage)"] += 1;
- increaseComplexityCount();
- this.first = block(true, true);
- advance("while");
- var t = state.tokens.next;
- nonadjacent(state.tokens.curr, t);
- advance("(");
- nospace();
- checkCondAssignment(expression(0));
- advance(")", t);
- nospace(state.tokens.prev, state.tokens.curr);
- funct["(breakage)"] -= 1;
- funct["(loopage)"] -= 1;
- return this;
- });
- x.labelled = true;
- x.exps = true;
- }());
- blockstmt("for", function () {
- var s, t = state.tokens.next;
- var letscope = false;
- var foreachtok = null;
- if (t.value === "each") {
- foreachtok = t;
- advance("each");
- if (!state.option.inMoz(true)) {
- warning("W118", state.tokens.curr, "for each");
- }
- }
- funct["(breakage)"] += 1;
- funct["(loopage)"] += 1;
- increaseComplexityCount();
- advance("(");
- nonadjacent(this, t);
- nospace();
- // what kind of for(…) statement it is? for(…of…)? for(…in…)? for(…;…;…)?
- var nextop; // contains the token of the "in" or "of" operator
- var i = 0;
- var inof = ["in", "of"];
- do {
- nextop = peek(i);
- ++i;
- } while (!_.contains(inof, nextop.value) && nextop.value !== ";" &&
- nextop.type !== "(end)");
- // if we're in a for (… in|of …) statement
- if (_.contains(inof, nextop.value)) {
- if (!state.option.inESNext() && nextop.value === "of") {
- error("W104", nextop, "for of");
- }
- if (state.tokens.next.id === "var") {
- advance("var");
- state.syntax["var"].fud.call(state.syntax["var"].fud, true);
- } else if (state.tokens.next.id === "let") {
- advance("let");
- // create a new block scope
- letscope = true;
- funct["(blockscope)"].stack();
- state.syntax["let"].fud.call(state.syntax["let"].fud, true);
- } else {
- switch (funct[state.tokens.next.value]) {
- case "unused":
- funct[state.tokens.next.value] = "var";
- break;
- case "var":
- break;
- default:
- if (!funct["(blockscope)"].getlabel(state.tokens.next.value))
- warning("W088", state.tokens.next, state.tokens.next.value);
- }
- advance();
- }
- advance(nextop.value);
- expression(20);
- advance(")", t);
- s = block(true, true);
- if (state.option.forin && s && (s.length > 1 || typeof s[0] !== "object" ||
- s[0].value !== "if")) {
- warning("W089", this);
- }
- funct["(breakage)"] -= 1;
- funct["(loopage)"] -= 1;
- } else {
- if (foreachtok) {
- error("E045", foreachtok);
- }
- if (state.tokens.next.id !== ";") {
- if (state.tokens.next.id === "var") {
- advance("var");
- state.syntax["var"].fud.call(state.syntax["var"].fud);
- } else if (state.tokens.next.id === "let") {
- advance("let");
- // create a new block scope
- letscope = true;
- funct["(blockscope)"].stack();
- state.syntax["let"].fud.call(state.syntax["let"].fud);
- } else {
- for (;;) {
- expression(0, "for");
- if (state.tokens.next.id !== ",") {
- break;
- }
- comma();
- }
- }
- }
- nolinebreak(state.tokens.curr);
- advance(";");
- if (state.tokens.next.id !== ";") {
- checkCondAssignment(expression(0));
- }
- nolinebreak(state.tokens.curr);
- advance(";");
- if (state.tokens.next.id === ";") {
- error("E021", state.tokens.next, ")", ";");
- }
- if (state.tokens.next.id !== ")") {
- for (;;) {
- expression(0, "for");
- if (state.tokens.next.id !== ",") {
- break;
- }
- comma();
- }
- }
- advance(")", t);
- nospace(state.tokens.prev, state.tokens.curr);
- block(true, true);
- funct["(breakage)"] -= 1;
- funct["(loopage)"] -= 1;
- }
- // unstack loop blockscope
- if (letscope) {
- funct["(blockscope)"].unstack();
- }
- return this;
- }).labelled = true;
- stmt("break", function () {
- var v = state.tokens.next.value;
- if (funct["(breakage)"] === 0)
- warning("W052", state.tokens.next, this.value);
- if (!state.option.asi)
- nolinebreak(this);
- if (state.tokens.next.id !== ";" && !state.tokens.next.reach) {
- if (state.tokens.curr.line === state.tokens.next.line) {
- if (funct[v] !== "label") {
- warning("W090", state.tokens.next, v);
- } else if (scope[v] !== funct) {
- warning("W091", state.tokens.next, v);
- }
- this.first = state.tokens.next;
- advance();
- }
- }
- reachable("break");
- return this;
- }).exps = true;
- stmt("continue", function () {
- var v = state.tokens.next.value;
- if (funct["(breakage)"] === 0)
- warning("W052", state.tokens.next, this.value);
- if (!state.option.asi)
- nolinebreak(this);
- if (state.tokens.next.id !== ";" && !state.tokens.next.reach) {
- if (state.tokens.curr.line === state.tokens.next.line) {
- if (funct[v] !== "label") {
- warning("W090", state.tokens.next, v);
- } else if (scope[v] !== funct) {
- warning("W091", state.tokens.next, v);
- }
- this.first = state.tokens.next;
- advance();
- }
- } else if (!funct["(loopage)"]) {
- warning("W052", state.tokens.next, this.value);
- }
- reachable("continue");
- return this;
- }).exps = true;
- stmt("return", function () {
- if (this.line === state.tokens.next.line) {
- if (state.tokens.next.id === "(regexp)")
- warning("W092");
- if (state.tokens.next.id !== ";" && !state.tokens.next.reach) {
- nonadjacent(state.tokens.curr, state.tokens.next);
- this.first = expression(0);
- if (this.first &&
- this.first.type === "(punctuator)" && this.first.value === "=" && !state.option.boss) {
- warningAt("W093", this.first.line, this.first.character);
- }
- }
- } else {
- if (state.tokens.next.type === "(punctuator)" &&
- ["[", "{", "+", "-"].indexOf(state.tokens.next.value) > -1) {
- nolinebreak(this); // always warn (Line breaking error)
- }
- }
- reachable("return");
- return this;
- }).exps = true;
- (function (x) {
- x.exps = true;
- x.lbp = 25;
- }(prefix("yield", function () {
- var prev = state.tokens.prev;
- if (state.option.inESNext(true) && !funct["(generator)"]) {
- error("E046", state.tokens.curr, "yield");
- } else if (!state.option.inESNext()) {
- warning("W104", state.tokens.curr, "yield");
- }
- funct["(generator)"] = "yielded";
- if (this.line === state.tokens.next.line || !state.option.inMoz(true)) {
- if (state.tokens.next.id === "(regexp)")
- warning("W092");
- if (state.tokens.next.id !== ";" && !state.tokens.next.reach && state.tokens.next.nud) {
- nobreaknonadjacent(state.tokens.curr, state.tokens.next);
- this.first = expression(10);
- if (this.first.type === "(punctuator)" && this.first.value === "=" && !state.option.boss) {
- warningAt("W093", this.first.line, this.first.character);
- }
- }
- if (state.option.inMoz(true) && state.tokens.next.id !== ")" &&
- (prev.lbp > 30 || (!prev.assign && !isEndOfExpr()) || prev.id === "yield")) {
- error("E050", this);
- }
- } else if (!state.option.asi) {
- nolinebreak(this); // always warn (Line breaking error)
- }
- return this;
- })));
- stmt("throw", function () {
- nolinebreak(this);
- nonadjacent(state.tokens.curr, state.tokens.next);
- this.first = expression(20);
- reachable("throw");
- return this;
- }).exps = true;
- stmt("import", function () {
- if (!state.option.inESNext()) {
- warning("W119", state.tokens.curr, "import");
- }
- if (state.tokens.next.identifier) {
- this.name = identifier();
- addlabel(this.name, "unused", state.tokens.curr);
- } else {
- advance("{");
- for (;;) {
- var importName;
- if (state.tokens.next.type === "default") {
- importName = "default";
- advance("default");
- } else {
- importName = identifier();
- }
- if (state.tokens.next.value === "as") {
- advance("as");
- importName = identifier();
- }
- addlabel(importName, "unused", state.tokens.curr);
- if (state.tokens.next.value === ",") {
- advance(",");
- } else if (state.tokens.next.value === "}") {
- advance("}");
- break;
- } else {
- error("E024", state.tokens.next, state.tokens.next.value);
- break;
- }
- }
- }
- advance("from");
- advance("(string)");
- return this;
- }).exps = true;
- stmt("export", function () {
- if (!state.option.inESNext()) {
- warning("W119", state.tokens.curr, "export");
- }
- if (state.tokens.next.type === "default") {
- advance("default");
- if (state.tokens.next.id === "function" || state.tokens.next.id === "class") {
- this.block = true;
- }
- this.exportee = expression(10);
- return this;
- }
- if (state.tokens.next.value === "{") {
- advance("{");
- for (;;) {
- identifier();
- if (state.tokens.next.value === ",") {
- advance(",");
- } else if (state.tokens.next.value === "}") {
- advance("}");
- break;
- } else {
- error("E024", state.tokens.next, state.tokens.next.value);
- break;
- }
- }
- return this;
- }
- if (state.tokens.next.id === "var") {
- advance("var");
- state.syntax["var"].fud.call(state.syntax["var"].fud);
- } else if (state.tokens.next.id === "let") {
- advance("let");
- state.syntax["let"].fud.call(state.syntax["let"].fud);
- } else if (state.tokens.next.id === "const") {
- advance("const");
- state.syntax["const"].fud.call(state.syntax["const"].fud);
- } else if (state.tokens.next.id === "function") {
- this.block = true;
- advance("function");
- state.syntax["function"].fud();
- } else if (state.tokens.next.id === "class") {
- this.block = true;
- advance("class");
- state.syntax["class"].fud();
- } else {
- error("E024", state.tokens.next, state.tokens.next.value);
- }
- return this;
- }).exps = true;
- // Future Reserved Words
- FutureReservedWord("abstract");
- FutureReservedWord("boolean");
- FutureReservedWord("byte");
- FutureReservedWord("char");
- FutureReservedWord("class", { es5: true, nud: classdef });
- FutureReservedWord("double");
- FutureReservedWord("enum", { es5: true });
- FutureReservedWord("export", { es5: true });
- FutureReservedWord("extends", { es5: true });
- FutureReservedWord("final");
- FutureReservedWord("float");
- FutureReservedWord("goto");
- FutureReservedWord("implements", { es5: true, strictOnly: true });
- FutureReservedWord("import", { es5: true });
- FutureReservedWord("int");
- FutureReservedWord("interface", { es5: true, strictOnly: true });
- FutureReservedWord("long");
- FutureReservedWord("native");
- FutureReservedWord("package", { es5: true, strictOnly: true });
- FutureReservedWord("private", { es5: true, strictOnly: true });
- FutureReservedWord("protected", { es5: true, strictOnly: true });
- FutureReservedWord("public", { es5: true, strictOnly: true });
- FutureReservedWord("short");
- FutureReservedWord("static", { es5: true, strictOnly: true });
- FutureReservedWord("super", { es5: true });
- FutureReservedWord("synchronized");
- FutureReservedWord("throws");
- FutureReservedWord("transient");
- FutureReservedWord("volatile");
- // this function is used to determine wether a squarebracket or a curlybracket
- // expression is a comprehension array, destructuring assignment or a json value.
- var lookupBlockType = function () {
- var pn, pn1;
- var i = 0;
- var bracketStack = 0;
- var ret = {};
- if (_.contains(["[", "{"], state.tokens.curr.value))
- bracketStack += 1;
- if (_.contains(["[", "{"], state.tokens.next.value))
- bracketStack += 1;
- if (_.contains(["]", "}"], state.tokens.next.value))
- bracketStack -= 1;
- do {
- pn = peek(i);
- pn1 = peek(i + 1);
- i = i + 1;
- if (_.contains(["[", "{"], pn.value)) {
- bracketStack += 1;
- } else if (_.contains(["]", "}"], pn.value)) {
- bracketStack -= 1;
- }
- if (pn.identifier && pn.value === "for" && bracketStack === 1) {
- ret.isCompArray = true;
- ret.notJson = true;
- break;
- }
- if (_.contains(["}", "]"], pn.value) && pn1.value === "=") {
- ret.isDestAssign = true;
- ret.notJson = true;
- break;
- }
- if (pn.value === ";") {
- ret.isBlock = true;
- ret.notJson = true;
- }
- } while (bracketStack > 0 && pn.id !== "(end)" && i < 15);
- return ret;
- };
- // Check whether this function has been reached for a destructuring assign with undeclared values
- function destructuringAssignOrJsonValue() {
- // lookup for the assignment (esnext only)
- // if it has semicolons, it is a block, so go parse it as a block
- // or it's not a block, but there are assignments, check for undeclared variables
- var block = lookupBlockType();
- if (block.notJson) {
- if (!state.option.inESNext() && block.isDestAssign) {
- warning("W104", state.tokens.curr, "destructuring assignment");
- }
- statements();
- // otherwise parse json value
- } else {
- state.option.laxbreak = true;
- state.jsonMode = true;
- jsonValue();
- }
- }
- // array comprehension parsing function
- // parses and defines the three states of the list comprehension in order
- // to avoid defining global variables, but keeping them to the list comprehension scope
- // only. The order of the states are as follows:
- // * "use" which will be the returned iterative part of the list comprehension
- // * "define" which will define the variables local to the list comprehension
- // * "filter" which will help filter out values
- var arrayComprehension = function () {
- var CompArray = function () {
- this.mode = "use";
- this.variables = [];
- };
- var _carrays = [];
- var _current;
- function declare(v) {
- var l = _current.variables.filter(function (elt) {
- // if it has, change its undef state
- if (elt.value === v) {
- elt.undef = false;
- return v;
- }
- }).length;
- return l !== 0;
- }
- function use(v) {
- var l = _current.variables.filter(function (elt) {
- // and if it has been defined
- if (elt.value === v && !elt.undef) {
- if (elt.unused === true) {
- elt.unused = false;
- }
- return v;
- }
- }).length;
- // otherwise we warn about it
- return (l === 0);
- }
- return {stack: function () {
- _current = new CompArray();
- _carrays.push(_current);
- },
- unstack: function () {
- _current.variables.filter(function (v) {
- if (v.unused)
- warning("W098", v.token, v.value);
- if (v.undef)
- isundef(v.funct, "W117", v.token, v.value);
- });
- _carrays.splice(_carrays[_carrays.length - 1], 1);
- _current = _carrays[_carrays.length - 1];
- },
- setState: function (s) {
- if (_.contains(["use", "define", "filter"], s))
- _current.mode = s;
- },
- check: function (v) {
- // When we are in "use" state of the list comp, we enqueue that var
- if (_current && _current.mode === "use") {
- _current.variables.push({funct: funct,
- token: state.tokens.curr,
- value: v,
- undef: true,
- unused: false});
- return true;
- // When we are in "define" state of the list comp,
- } else if (_current && _current.mode === "define") {
- // check if the variable has been used previously
- if (!declare(v)) {
- _current.variables.push({funct: funct,
- token: state.tokens.curr,
- value: v,
- undef: false,
- unused: true});
- }
- return true;
- // When we are in "filter" state,
- } else if (_current && _current.mode === "filter") {
- // we check whether current variable has been declared
- if (use(v)) {
- // if not we warn about it
- isundef(funct, "W117", state.tokens.curr, v);
- }
- return true;
- }
- return false;
- }
- };
- };
- // Parse JSON
- function jsonValue() {
- function jsonObject() {
- var o = {}, t = state.tokens.next;
- advance("{");
- if (state.tokens.next.id !== "}") {
- for (;;) {
- if (state.tokens.next.id === "(end)") {
- error("E026", state.tokens.next, t.line);
- } else if (state.tokens.next.id === "}") {
- warning("W094", state.tokens.curr);
- break;
- } else if (state.tokens.next.id === ",") {
- error("E028", state.tokens.next);
- } else if (state.tokens.next.id !== "(string)") {
- warning("W095", state.tokens.next, state.tokens.next.value);
- }
- if (o[state.tokens.next.value] === true) {
- warning("W075", state.tokens.next, state.tokens.next.value);
- } else if ((state.tokens.next.value === "__proto__" &&
- !state.option.proto) || (state.tokens.next.value === "__iterator__" &&
- !state.option.iterator)) {
- warning("W096", state.tokens.next, state.tokens.next.value);
- } else {
- o[state.tokens.next.value] = true;
- }
- advance();
- advance(":");
- jsonValue();
- if (state.tokens.next.id !== ",") {
- break;
- }
- advance(",");
- }
- }
- advance("}");
- }
- function jsonArray() {
- var t = state.tokens.next;
- advance("[");
- if (state.tokens.next.id !== "]") {
- for (;;) {
- if (state.tokens.next.id === "(end)") {
- error("E027", state.tokens.next, t.line);
- } else if (state.tokens.next.id === "]") {
- warning("W094", state.tokens.curr);
- break;
- } else if (state.tokens.next.id === ",") {
- error("E028", state.tokens.next);
- }
- jsonValue();
- if (state.tokens.next.id !== ",") {
- break;
- }
- advance(",");
- }
- }
- advance("]");
- }
- switch (state.tokens.next.id) {
- case "{":
- jsonObject();
- break;
- case "[":
- jsonArray();
- break;
- case "true":
- case "false":
- case "null":
- case "(number)":
- case "(string)":
- advance();
- break;
- case "-":
- advance("-");
- if (state.tokens.curr.character !== state.tokens.next.from) {
- warning("W011", state.tokens.curr);
- }
- adjacent(state.tokens.curr, state.tokens.next);
- advance("(number)");
- break;
- default:
- error("E003", state.tokens.next);
- }
- }
- var blockScope = function () {
- var _current = {};
- var _variables = [_current];
- function _checkBlockLabels() {
- for (var t in _current) {
- if (_current[t]["(type)"] === "unused") {
- if (state.option.unused) {
- var tkn = _current[t]["(token)"];
- var line = tkn.line;
- var chr = tkn.character;
- warningAt("W098", line, chr, t);
- }
- }
- }
- }
- return {
- stack: function () {
- _current = {};
- _variables.push(_current);
- },
- unstack: function () {
- _checkBlockLabels();
- _variables.splice(_variables.length - 1, 1);
- _current = _.last(_variables);
- },
- getlabel: function (l) {
- for (var i = _variables.length - 1 ; i >= 0; --i) {
- if (_.has(_variables[i], l)) {
- return _variables[i];
- }
- }
- },
- current: {
- has: function (t) {
- return _.has(_current, t);
- },
- add: function (t, type, tok) {
- _current[t] = { "(type)" : type,
- "(token)": tok };
- }
- }
- };
- };
- // The actual JSHINT function itself.
- var itself = function (s, o, g) {
- var i, k, x;
- var optionKeys;
- var newOptionObj = {};
- var newIgnoredObj = {};
- state.reset();
- if (o && o.scope) {
- JSHINT.scope = o.scope;
- } else {
- JSHINT.errors = [];
- JSHINT.undefs = [];
- JSHINT.internals = [];
- JSHINT.blacklist = {};
- JSHINT.scope = "(main)";
- }
- predefined = Object.create(null);
- combine(predefined, vars.ecmaIdentifiers);
- combine(predefined, vars.reservedVars);
- combine(predefined, g || {});
- declared = Object.create(null);
- exported = Object.create(null);
- function each(obj, cb) {
- if (!obj)
- return;
- if (!Array.isArray(obj) && typeof obj === "object")
- obj = Object.keys(obj);
- obj.forEach(cb);
- }
- if (o) {
- each(o.predef || null, function (item) {
- var slice, prop;
- if (item[0] === "-") {
- slice = item.slice(1);
- JSHINT.blacklist[slice] = slice;
- } else {
- prop = Object.getOwnPropertyDescriptor(o.predef, item);
- predefined[item] = prop ? prop.value : false;
- }
- });
- each(o.exported || null, function (item) {
- exported[item] = true;
- });
- delete o.predef;
- delete o.exported;
- optionKeys = Object.keys(o);
- for (x = 0; x < optionKeys.length; x++) {
- if (/^-W\d{3}$/g.test(optionKeys[x])) {
- newIgnoredObj[optionKeys[x].slice(1)] = true;
- } else {
- newOptionObj[optionKeys[x]] = o[optionKeys[x]];
- if (optionKeys[x] === "newcap" && o[optionKeys[x]] === false)
- newOptionObj["(explicitNewcap)"] = true;
- if (optionKeys[x] === "indent")
- newOptionObj["(explicitIndent)"] = o[optionKeys[x]] === false ? false : true;
- }
- }
- }
- state.option = newOptionObj;
- state.ignored = newIgnoredObj;
- state.option.indent = state.option.indent || 4;
- state.option.maxerr = state.option.maxerr || 50;
- indent = 1;
- global = Object.create(predefined);
- scope = global;
- funct = {
- "(global)": true,
- "(name)": "(global)",
- "(scope)": scope,
- "(breakage)": 0,
- "(loopage)": 0,
- "(tokens)": {},
- "(metrics)": createMetrics(state.tokens.next),
- "(blockscope)": blockScope(),
- "(comparray)": arrayComprehension()
- };
- functions = [funct];
- urls = [];
- stack = null;
- member = {};
- membersOnly = null;
- implied = {};
- inblock = false;
- lookahead = [];
- warnings = 0;
- unuseds = [];
- if (!isString(s) && !Array.isArray(s)) {
- errorAt("E004", 0);
- return false;
- }
- api = {
- get isJSON() {
- return state.jsonMode;
- },
- getOption: function (name) {
- return state.option[name] || null;
- },
- getCache: function (name) {
- return state.cache[name];
- },
- setCache: function (name, value) {
- state.cache[name] = value;
- },
- warn: function (code, data) {
- warningAt.apply(null, [ code, data.line, data.char ].concat(data.data));
- },
- on: function (names, listener) {
- names.split(" ").forEach(function (name) {
- emitter.on(name, listener);
- }.bind(this));
- }
- };
- emitter.removeAllListeners();
- (extraModules || []).forEach(function (func) {
- func(api);
- });
- state.tokens.prev = state.tokens.curr = state.tokens.next = state.syntax["(begin)"];
- lex = new Lexer(s);
- lex.on("warning", function (ev) {
- warningAt.apply(null, [ ev.code, ev.line, ev.character].concat(ev.data));
- });
- lex.on("error", function (ev) {
- errorAt.apply(null, [ ev.code, ev.line, ev.character ].concat(ev.data));
- });
- lex.on("fatal", function (ev) {
- quit("E041", ev.line, ev.from);
- });
- lex.on("Identifier", function (ev) {
- emitter.emit("Identifier", ev);
- });
- lex.on("String", function (ev) {
- emitter.emit("String", ev);
- });
- lex.on("Number", function (ev) {
- emitter.emit("Number", ev);
- });
- lex.start();
- // Check options
- for (var name in o) {
- if (_.has(o, name)) {
- checkOption(name, state.tokens.curr);
- }
- }
- assume();
- // combine the passed globals after we've assumed all our options
- combine(predefined, g || {});
- //reset values
- comma.first = true;
- try {
- advance();
- switch (state.tokens.next.id) {
- case "{":
- case "[":
- destructuringAssignOrJsonValue();
- break;
- default:
- directives();
- if (state.directive["use strict"]) {
- if (!state.option.globalstrict && !state.option.node) {
- warning("W097", state.tokens.prev);
- }
- }
- statements();
- }
- advance((state.tokens.next && state.tokens.next.value !== ".") ? "(end)" : undefined);
- funct["(blockscope)"].unstack();
- var markDefined = function (name, context) {
- do {
- if (typeof context[name] === "string") {
- // JSHINT marks unused variables as 'unused' and
- // unused function declaration as 'unction'. This
- // code changes such instances back 'var' and
- // 'closure' so that the code in JSHINT.data()
- // doesn't think they're unused.
- if (context[name] === "unused")
- context[name] = "var";
- else if (context[name] === "unction")
- context[name] = "closure";
- return true;
- }
- context = context["(context)"];
- } while (context);
- return false;
- };
- var clearImplied = function (name, line) {
- if (!implied[name])
- return;
- var newImplied = [];
- for (var i = 0; i < implied[name].length; i += 1) {
- if (implied[name][i] !== line)
- newImplied.push(implied[name][i]);
- }
- if (newImplied.length === 0)
- delete implied[name];
- else
- implied[name] = newImplied;
- };
- var warnUnused = function (name, tkn, type, unused_opt) {
- var line = tkn.line;
- var chr = tkn.character;
- if (unused_opt === undefined) {
- unused_opt = state.option.unused;
- }
- if (unused_opt === true) {
- unused_opt = "last-param";
- }
- var warnable_types = {
- "vars": ["var"],
- "last-param": ["var", "param"],
- "strict": ["var", "param", "last-param"]
- };
- if (unused_opt) {
- if (warnable_types[unused_opt] && warnable_types[unused_opt].indexOf(type) !== -1) {
- warningAt("W098", line, chr, name);
- }
- }
- unuseds.push({
- name: name,
- line: line,
- character: chr
- });
- };
- var checkUnused = function (func, key) {
- var type = func[key];
- var tkn = func["(tokens)"][key];
- if (key.charAt(0) === "(")
- return;
- if (type !== "unused" && type !== "unction")
- return;
- // Params are checked separately from other variables.
- if (func["(params)"] && func["(params)"].indexOf(key) !== -1)
- return;
- // Variable is in global scope and defined as exported.
- if (func["(global)"] && _.has(exported, key)) {
- return;
- }
- warnUnused(key, tkn, "var");
- };
- // Check queued 'x is not defined' instances to see if they're still undefined.
- for (i = 0; i < JSHINT.undefs.length; i += 1) {
- k = JSHINT.undefs[i].slice(0);
- if (markDefined(k[2].value, k[0])) {
- clearImplied(k[2].value, k[2].line);
- } else if (state.option.undef) {
- warning.apply(warning, k.slice(1));
- }
- }
- functions.forEach(function (func) {
- if (func["(unusedOption)"] === false) {
- return;
- }
- for (var key in func) {
- if (_.has(func, key)) {
- checkUnused(func, key);
- }
- }
- if (!func["(params)"])
- return;
- var params = func["(params)"].slice();
- var param = params.pop();
- var type, unused_opt;
- while (param) {
- type = func[param];
- unused_opt = func["(unusedOption)"] || state.option.unused;
- unused_opt = unused_opt === true ? "last-param" : unused_opt;
- // 'undefined' is a special case for (function (window, undefined) { ... })();
- // patterns.
- if (param === "undefined")
- return;
- if (type === "unused" || type === "unction") {
- warnUnused(param, func["(tokens)"][param], "param", func["(unusedOption)"]);
- } else if (unused_opt === "last-param") {
- return;
- }
- param = params.pop();
- }
- });
- for (var key in declared) {
- if (_.has(declared, key) && !_.has(global, key)) {
- warnUnused(key, declared[key], "var");
- }
- }
- } catch (err) {
- if (err && err.name === "JSHintError") {
- var nt = state.tokens.next || {};
- JSHINT.errors.push({
- scope : "(main)",
- raw : err.raw,
- code : err.code,
- reason : err.message,
- line : err.line || nt.line,
- character : err.character || nt.from
- }, null);
- } else {
- throw err;
- }
- }
- // Loop over the listed "internals", and check them as well.
- if (JSHINT.scope === "(main)") {
- o = o || {};
- for (i = 0; i < JSHINT.internals.length; i += 1) {
- k = JSHINT.internals[i];
- o.scope = k.elem;
- itself(k.value, o, g);
- }
- }
- return JSHINT.errors.length === 0;
- };
- // Modules.
- itself.addModule = function (func) {
- extraModules.push(func);
- };
- itself.addModule(style.register);
- // Data summary.
- itself.data = function () {
- var data = {
- functions: [],
- options: state.option
- };
- var implieds = [];
- var members = [];
- var fu, f, i, j, n, globals;
- if (itself.errors.length) {
- data.errors = itself.errors;
- }
- if (state.jsonMode) {
- data.json = true;
- }
- for (n in implied) {
- if (_.has(implied, n)) {
- implieds.push({
- name: n,
- line: implied[n]
- });
- }
- }
- if (implieds.length > 0) {
- data.implieds = implieds;
- }
- if (urls.length > 0) {
- data.urls = urls;
- }
- globals = Object.keys(scope);
- if (globals.length > 0) {
- data.globals = globals;
- }
- for (i = 1; i < functions.length; i += 1) {
- f = functions[i];
- fu = {};
- for (j = 0; j < functionicity.length; j += 1) {
- fu[functionicity[j]] = [];
- }
- for (j = 0; j < functionicity.length; j += 1) {
- if (fu[functionicity[j]].length === 0) {
- delete fu[functionicity[j]];
- }
- }
- fu.name = f["(name)"];
- fu.param = f["(params)"];
- fu.line = f["(line)"];
- fu.character = f["(character)"];
- fu.last = f["(last)"];
- fu.lastcharacter = f["(lastcharacter)"];
- data.functions.push(fu);
- }
- if (unuseds.length > 0) {
- data.unused = unuseds;
- }
- members = [];
- for (n in member) {
- if (typeof member[n] === "number") {
- data.member = member;
- break;
- }
- }
- return data;
- };
- itself.jshint = itself;
- return itself;
- }());
- // Make JSHINT a Node module, if possible.
- if (typeof exports === "object" && exports) {
- exports.JSHINT = JSHINT;
- }
- },
- {"../shared/messages.js":2,"../shared/vars.js":3,"./lex.js":5,"./reg.js":6,"./state.js":7,"./style.js":8,"console-browserify":9,"events":10,"underscore":1}],
- 5:[function(req,module,exports){
- /*
- * Lexical analysis and token construction.
- */
- "use strict";
- var _ = req("underscore");
- var events = req("events");
- var reg = req("./reg.js");
- var state = req("./state.js").state;
- // Some of these token types are from JavaScript Parser API
- // while others are specific to JSHint parser.
- // JS Parser API: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API
- var Token = {
- Identifier: 1,
- Punctuator: 2,
- NumericLiteral: 3,
- StringLiteral: 4,
- Comment: 5,
- Keyword: 6,
- NullLiteral: 7,
- BooleanLiteral: 8,
- RegExp: 9
- };
- // This is auto generated from the unicode tables.
- // The tables are at:
- // http://www.fileformat.info/info/unicode/category/Lu/list.htm
- // http://www.fileformat.info/info/unicode/category/Ll/list.htm
- // http://www.fileformat.info/info/unicode/category/Lt/list.htm
- // http://www.fileformat.info/info/unicode/category/Lm/list.htm
- // http://www.fileformat.info/info/unicode/category/Lo/list.htm
- // http://www.fileformat.info/info/unicode/category/Nl/list.htm
- var unicodeLetterTable = [
- 170, 170, 181, 181, 186, 186, 192, 214,
- 216, 246, 248, 705, 710, 721, 736, 740, 748, 748, 750, 750,
- 880, 884, 886, 887, 890, 893, 902, 902, 904, 906, 908, 908,
- 910, 929, 931, 1013, 1015, 1153, 1162, 1319, 1329, 1366,
- 1369, 1369, 1377, 1415, 1488, 1514, 1520, 1522, 1568, 1610,
- 1646, 1647, 1649, 1747, 1749, 1749, 1765, 1766, 1774, 1775,
- 1786, 1788, 1791, 1791, 1808, 1808, 1810, 1839, 1869, 1957,
- 1969, 1969, 1994, 2026, 2036, 2037, 2042, 2042, 2048, 2069,
- 2074, 2074, 2084, 2084, 2088, 2088, 2112, 2136, 2308, 2361,
- 2365, 2365, 2384, 2384, 2392, 2401, 2417, 2423, 2425, 2431,
- 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482,
- 2486, 2489, 2493, 2493, 2510, 2510, 2524, 2525, 2527, 2529,
- 2544, 2545, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608,
- 2610, 2611, 2613, 2614, 2616, 2617, 2649, 2652, 2654, 2654,
- 2674, 2676, 2693, 2701, 2703, 2705, 2707, 2728, 2730, 2736,
- 2738, 2739, 2741, 2745, 2749, 2749, 2768, 2768, 2784, 2785,
- 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867,
- 2869, 2873, 2877, 2877, 2908, 2909, 2911, 2913, 2929, 2929,
- 2947, 2947, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970,
- 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, 2990, 3001,
- 3024, 3024, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3123,
- 3125, 3129, 3133, 3133, 3160, 3161, 3168, 3169, 3205, 3212,
- 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3261, 3261,
- 3294, 3294, 3296, 3297, 3313, 3314, 3333, 3340, 3342, 3344,
- 3346, 3386, 3389, 3389, 3406, 3406, 3424, 3425, 3450, 3455,
- 3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526,
- 3585, 3632, 3634, 3635, 3648, 3654, 3713, 3714, 3716, 3716,
- 3719, 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743,
- 3745, 3747, 3749, 3749, 3751, 3751, 3754, 3755, 3757, 3760,
- 3762, 3763, 3773, 3773, 3776, 3780, 3782, 3782, 3804, 3805,
- 3840, 3840, 3904, 3911, 3913, 3948, 3976, 3980, 4096, 4138,
- 4159, 4159, 4176, 4181, 4186, 4189, 4193, 4193, 4197, 4198,
- 4206, 4208, 4213, 4225, 4238, 4238, 4256, 4293, 4304, 4346,
- 4348, 4348, 4352, 4680, 4682, 4685, 4688, 4694, 4696, 4696,
- 4698, 4701, 4704, 4744, 4746, 4749, 4752, 4784, 4786, 4789,
- 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4822, 4824, 4880,
- 4882, 4885, 4888, 4954, 4992, 5007, 5024, 5108, 5121, 5740,
- 5743, 5759, 5761, 5786, 5792, 5866, 5870, 5872, 5888, 5900,
- 5902, 5905, 5920, 5937, 5952, 5969, 5984, 5996, 5998, 6000,
- 6016, 6067, 6103, 6103, 6108, 6108, 6176, 6263, 6272, 6312,
- 6314, 6314, 6320, 6389, 6400, 6428, 6480, 6509, 6512, 6516,
- 6528, 6571, 6593, 6599, 6656, 6678, 6688, 6740, 6823, 6823,
- 6917, 6963, 6981, 6987, 7043, 7072, 7086, 7087, 7104, 7141,
- 7168, 7203, 7245, 7247, 7258, 7293, 7401, 7404, 7406, 7409,
- 7424, 7615, 7680, 7957, 7960, 7965, 7968, 8005, 8008, 8013,
- 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061,
- 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140,
- 8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188,
- 8305, 8305, 8319, 8319, 8336, 8348, 8450, 8450, 8455, 8455,
- 8458, 8467, 8469, 8469, 8473, 8477, 8484, 8484, 8486, 8486,
- 8488, 8488, 8490, 8493, 8495, 8505, 8508, 8511, 8517, 8521,
- 8526, 8526, 8544, 8584, 11264, 11310, 11312, 11358,
- 11360, 11492, 11499, 11502, 11520, 11557, 11568, 11621,
- 11631, 11631, 11648, 11670, 11680, 11686, 11688, 11694,
- 11696, 11702, 11704, 11710, 11712, 11718, 11720, 11726,
- 11728, 11734, 11736, 11742, 11823, 11823, 12293, 12295,
- 12321, 12329, 12337, 12341, 12344, 12348, 12353, 12438,
- 12445, 12447, 12449, 12538, 12540, 12543, 12549, 12589,
- 12593, 12686, 12704, 12730, 12784, 12799, 13312, 13312,
- 19893, 19893, 19968, 19968, 40907, 40907, 40960, 42124,
- 42192, 42237, 42240, 42508, 42512, 42527, 42538, 42539,
- 42560, 42606, 42623, 42647, 42656, 42735, 42775, 42783,
- 42786, 42888, 42891, 42894, 42896, 42897, 42912, 42921,
- 43002, 43009, 43011, 43013, 43015, 43018, 43020, 43042,
- 43072, 43123, 43138, 43187, 43250, 43255, 43259, 43259,
- 43274, 43301, 43312, 43334, 43360, 43388, 43396, 43442,
- 43471, 43471, 43520, 43560, 43584, 43586, 43588, 43595,
- 43616, 43638, 43642, 43642, 43648, 43695, 43697, 43697,
- 43701, 43702, 43705, 43709, 43712, 43712, 43714, 43714,
- 43739, 43741, 43777, 43782, 43785, 43790, 43793, 43798,
- 43808, 43814, 43816, 43822, 43968, 44002, 44032, 44032,
- 55203, 55203, 55216, 55238, 55243, 55291, 63744, 64045,
- 64048, 64109, 64112, 64217, 64256, 64262, 64275, 64279,
- 64285, 64285, 64287, 64296, 64298, 64310, 64312, 64316,
- 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433,
- 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019,
- 65136, 65140, 65142, 65276, 65313, 65338, 65345, 65370,
- 65382, 65470, 65474, 65479, 65482, 65487, 65490, 65495,
- 65498, 65500, 65536, 65547, 65549, 65574, 65576, 65594,
- 65596, 65597, 65599, 65613, 65616, 65629, 65664, 65786,
- 65856, 65908, 66176, 66204, 66208, 66256, 66304, 66334,
- 66352, 66378, 66432, 66461, 66464, 66499, 66504, 66511,
- 66513, 66517, 66560, 66717, 67584, 67589, 67592, 67592,
- 67594, 67637, 67639, 67640, 67644, 67644, 67647, 67669,
- 67840, 67861, 67872, 67897, 68096, 68096, 68112, 68115,
- 68117, 68119, 68121, 68147, 68192, 68220, 68352, 68405,
- 68416, 68437, 68448, 68466, 68608, 68680, 69635, 69687,
- 69763, 69807, 73728, 74606, 74752, 74850, 77824, 78894,
- 92160, 92728, 110592, 110593, 119808, 119892, 119894, 119964,
- 119966, 119967, 119970, 119970, 119973, 119974, 119977, 119980,
- 119982, 119993, 119995, 119995, 119997, 120003, 120005, 120069,
- 120071, 120074, 120077, 120084, 120086, 120092, 120094, 120121,
- 120123, 120126, 120128, 120132, 120134, 120134, 120138, 120144,
- 120146, 120485, 120488, 120512, 120514, 120538, 120540, 120570,
- 120572, 120596, 120598, 120628, 120630, 120654, 120656, 120686,
- 120688, 120712, 120714, 120744, 120746, 120770, 120772, 120779,
- 131072, 131072, 173782, 173782, 173824, 173824, 177972, 177972,
- 177984, 177984, 178205, 178205, 194560, 195101
- ];
- var identifierStartTable = [];
- for (var i = 0; i < 128; i++) {
- identifierStartTable[i] =
- i === 36 || // $
- i >= 65 && i <= 90 || // A-Z
- i === 95 || // _
- i >= 97 && i <= 122; // a-z
- }
- var identifierPartTable = [];
- for (var i = 0; i < 128; i++) {
- identifierPartTable[i] =
- identifierStartTable[i] || // $, _, A-Z, a-z
- i >= 48 && i <= 57; // 0-9
- }
- // Object that handles postponed lexing verifications that checks the parsed
- // environment state.
- function asyncTrigger() {
- var _checks = [];
- return {
- push: function (fn) {
- _checks.push(fn);
- },
- check: function () {
- for (var check = 0; check < _checks.length; ++check) {
- _checks[check]();
- }
- _checks.splice(0, _checks.length);
- }
- };
- }
- /*
- * Lexer for JSHint.
- *
- * This object does a char-by-char scan of the provided source code
- * and produces a sequence of tokens.
- *
- * var lex = new Lexer("var i = 0;");
- * lex.start();
- * lex.token(); // returns the next token
- *
- * You have to use the token() method to move the lexer forward
- * but you don't have to use its return value to get tokens. In addition
- * to token() method returning the next token, the Lexer object also
- * emits events.
- *
- * lex.on("Identifier", function (data) {
- * if (data.name.indexOf("_") >= 0) {
- * // Produce a warning.
- * }
- * });
- *
- * Note that the token() method returns tokens in a JSLint-compatible
- * format while the event emitter uses a slightly modified version of
- * Mozilla's JavaScript Parser API. Eventually, we will move away from
- * JSLint format.
- */
- function Lexer(source) {
- var lines = source;
- if (typeof lines === "string") {
- lines = lines
- .replace(/\r\n/g, "\n")
- .replace(/\r/g, "\n")
- .split("\n");
- }
- // If the first line is a shebang (#!), make it a blank and move on.
- // Shebangs are used by Node scripts.
- if (lines[0] && lines[0].substr(0, 2) === "#!") {
- lines[0] = "";
- }
- this.emitter = new events.EventEmitter();
- this.source = source;
- this.setLines(lines);
- this.prereg = true;
- this.line = 0;
- this.char = 1;
- this.from = 1;
- this.input = "";
- for (var i = 0; i < state.option.indent; i += 1) {
- state.tab += " ";
- }
- }
- Lexer.prototype = {
- _lines: [],
- getLines: function () {
- this._lines = state.lines;
- return this._lines;
- },
- setLines: function (val) {
- this._lines = val;
- state.lines = this._lines;
- },
- /*
- * Return the next i character without actually moving the
- * char pointer.
- */
- peek: function (i) {
- return this.input.charAt(i || 0);
- },
- /*
- * Move the char pointer forward i times.
- */
- skip: function (i) {
- i = i || 1;
- this.char += i;
- this.input = this.input.slice(i);
- },
- /*
- * Subscribe to a token event. The API for this method is similar
- * Underscore.js i.e. you can subscribe to multiple events with
- * one call:
- *
- * lex.on("Identifier Number", function (data) {
- * // ...
- * });
- */
- on: function (names, listener) {
- names.split(" ").forEach(function (name) {
- this.emitter.on(name, listener);
- }.bind(this));
- },
- /*
- * Trigger a token event. All arguments will be passed to each
- * listener.
- */
- trigger: function () {
- this.emitter.emit.apply(this.emitter, Array.prototype.slice.call(arguments));
- },
- /*
- * Postpone a token event. the checking condition is set as
- * last parameter, and the trigger function is called in a
- * stored callback. To be later called using the check() function
- * by the parser. This avoids parser's peek() to give the lexer
- * a false context.
- */
- triggerAsync: function (type, args, checks, fn) {
- checks.push(function () {
- if (fn()) {
- this.trigger(type, args);
- }
- }.bind(this));
- },
- /*
- * Extract a punctuator out of the next sequence of characters
- * or return 'null' if its not possible.
- *
- * This method's implementation was heavily influenced by the
- * scanPunctuator function in the Esprima parser's source code.
- */
- scanPunctuator: function () {
- var ch1 = this.peek();
- var ch2, ch3, ch4;
- switch (ch1) {
- // Most common single-character punctuators
- case ".":
- if ((/^[0-9]$/).test(this.peek(1))) {
- return null;
- }
- if (this.peek(1) === "." && this.peek(2) === ".") {
- return {
- type: Token.Punctuator,
- value: "..."
- };
- }
- /* falls through */
- case "(":
- case ")":
- case ";":
- case ",":
- case "{":
- case "}":
- case "[":
- case "]":
- case ":":
- case "~":
- case "?":
- return {
- type: Token.Punctuator,
- value: ch1
- };
- // A pound sign (for Node shebangs)
- case "#":
- return {
- type: Token.Punctuator,
- value: ch1
- };
- // We're at the end of input
- case "":
- return null;
- }
- // Peek more characters
- ch2 = this.peek(1);
- ch3 = this.peek(2);
- ch4 = this.peek(3);
- // 4-character punctuator: >>>=
- if (ch1 === ">" && ch2 === ">" && ch3 === ">" && ch4 === "=") {
- return {
- type: Token.Punctuator,
- value: ">>>="
- };
- }
- // 3-character punctuators: === !== >>> <<= >>=
- if (ch1 === "=" && ch2 === "=" && ch3 === "=") {
- return {
- type: Token.Punctuator,
- value: "==="
- };
- }
- if (ch1 === "!" && ch2 === "=" && ch3 === "=") {
- return {
- type: Token.Punctuator,
- value: "!=="
- };
- }
- if (ch1 === ">" && ch2 === ">" && ch3 === ">") {
- return {
- type: Token.Punctuator,
- value: ">>>"
- };
- }
- if (ch1 === "<" && ch2 === "<" && ch3 === "=") {
- return {
- type: Token.Punctuator,
- value: "<<="
- };
- }
- if (ch1 === ">" && ch2 === ">" && ch3 === "=") {
- return {
- type: Token.Punctuator,
- value: ">>="
- };
- }
- // Fat arrow punctuator
- if (ch1 === "=" && ch2 === ">") {
- return {
- type: Token.Punctuator,
- value: ch1 + ch2
- };
- }
- // 2-character punctuators: <= >= == != ++ -- << >> && ||
- // += -= *= %= &= |= ^= (but not /=, see below)
- if (ch1 === ch2 && ("+-<>&|".indexOf(ch1) >= 0)) {
- return {
- type: Token.Punctuator,
- value: ch1 + ch2
- };
- }
- if ("<>=!+-*%&|^".indexOf(ch1) >= 0) {
- if (ch2 === "=") {
- return {
- type: Token.Punctuator,
- value: ch1 + ch2
- };
- }
- return {
- type: Token.Punctuator,
- value: ch1
- };
- }
- // Special case: /=. We need to make sure that this is an
- // operator and not a regular expression.
- if (ch1 === "/") {
- if (ch2 === "=" && /\/=(?!(\S*\/[gim]?))/.test(this.input)) {
- // /= is not a part of a regular expression, return it as a
- // punctuator.
- return {
- type: Token.Punctuator,
- value: "/="
- };
- }
- return {
- type: Token.Punctuator,
- value: "/"
- };
- }
- return null;
- },
- /*
- * Extract a comment out of the next sequence of characters and/or
- * lines or return 'null' if its not possible. Since comments can
- * span across multiple lines this method has to move the char
- * pointer.
- *
- * In addition to normal JavaScript comments (// and /*) this method
- * also recognizes JSHint- and JSLint-specific comments such as
- * /*jshint, /*jslint, /*globals and so on.
- */
- scanComments: function () {
- var ch1 = this.peek();
- var ch2 = this.peek(1);
- var rest = this.input.substr(2);
- var startLine = this.line;
- var startChar = this.char;
- // Create a comment token object and make sure it
- // has all the data JSHint needs to work with special
- // comments.
- function commentToken(label, body, opt) {
- var special = ["jshint", "jslint", "members", "member", "globals", "global", "exported"];
- var isSpecial = false;
- var value = label + body;
- var commentType = "plain";
- opt = opt || {};
- if (opt.isMultiline) {
- value += "*/";
- }
- special.forEach(function (str) {
- if (isSpecial) {
- return;
- }
- // Don't recognize any special comments other than jshint for single-line
- // comments. This introduced many problems with legit comments.
- if (label === "//" && str !== "jshint") {
- return;
- }
- if (body.substr(0, str.length) === str) {
- isSpecial = true;
- label = label + str;
- body = body.substr(str.length);
- }
- if (!isSpecial && body.charAt(0) === " " && body.substr(1, str.length) === str) {
- isSpecial = true;
- label = label + " " + str;
- body = body.substr(str.length + 1);
- }
- if (!isSpecial) {
- return;
- }
- switch (str) {
- case "member":
- commentType = "members";
- break;
- case "global":
- commentType = "globals";
- break;
- default:
- commentType = str;
- }
- });
- return {
- type: Token.Comment,
- commentType: commentType,
- value: value,
- body: body,
- isSpecial: isSpecial,
- isMultiline: opt.isMultiline || false,
- isMalformed: opt.isMalformed || false
- };
- }
- // End of unbegun comment. Raise an error and skip that input.
- if (ch1 === "*" && ch2 === "/") {
- this.trigger("error", {
- code: "E018",
- line: startLine,
- character: startChar
- });
- this.skip(2);
- return null;
- }
- // Comments must start either with // or /*
- if (ch1 !== "/" || (ch2 !== "*" && ch2 !== "/")) {
- return null;
- }
- // One-line comment
- if (ch2 === "/") {
- this.skip(this.input.length); // Skip to the EOL.
- return commentToken("//", rest);
- }
- var body = "";
- /* Multi-line comment */
- if (ch2 === "*") {
- this.skip(2);
- while (this.peek() !== "*" || this.peek(1) !== "/") {
- if (this.peek() === "") { // End of Line
- body += "\n";
- // If we hit EOF and our comment is still unclosed,
- // trigger an error and end the comment implicitly.
- if (!this.nextLine()) {
- this.trigger("error", {
- code: "E017",
- line: startLine,
- character: startChar
- });
- return commentToken("/*", body, {
- isMultiline: true,
- isMalformed: true
- });
- }
- } else {
- body += this.peek();
- this.skip();
- }
- }
- this.skip(2);
- return commentToken("/*", body, { isMultiline: true });
- }
- },
- /*
- * Extract a keyword out of the next sequence of characters or
- * return 'null' if its not possible.
- */
- scanKeyword: function () {
- var result = /^[a-zA-Z_$][a-zA-Z0-9_$]*/.exec(this.input);
- var keywords = [
- "if", "in", "do", "var", "for", "new",
- "try", "let", "this", "else", "case",
- "void", "with", "enum", "while", "break",
- "catch", "throw", "const", "yield", "class",
- "super", "return", "typeof", "delete",
- "switch", "export", "import", "default",
- "finally", "extends", "function", "continue",
- "debugger", "instanceof"
- ];
- if (result && keywords.indexOf(result[0]) >= 0) {
- return {
- type: Token.Keyword,
- value: result[0]
- };
- }
- return null;
- },
- /*
- * Extract a JavaScript identifier out of the next sequence of
- * characters or return 'null' if its not possible. In addition,
- * to Identifier this method can also produce BooleanLiteral
- * (true/false) and NullLiteral (null).
- */
- scanIdentifier: function () {
- var id = "";
- var index = 0;
- var type, char;
- // Detects any character in the Unicode categories "Uppercase
- // letter (Lu)", "Lowercase letter (Ll)", "Titlecase letter
- // (Lt)", "Modifier letter (Lm)", "Other letter (Lo)", or
- // "Letter number (Nl)".
- //
- // Both approach and unicodeLetterTable were borrowed from
- // Google's Traceur.
- function isUnicodeLetter(code) {
- for (var i = 0; i < unicodeLetterTable.length;) {
- if (code < unicodeLetterTable[i++]) {
- return false;
- }
- if (code <= unicodeLetterTable[i++]) {
- return true;
- }
- }
- return false;
- }
- function isHexDigit(str) {
- return (/^[0-9a-fA-F]$/).test(str);
- }
- var readUnicodeEscapeSequence = function () {
- /*jshint validthis:true */
- index += 1;
- if (this.peek(index) !== "u") {
- return null;
- }
- var ch1 = this.peek(index + 1);
- var ch2 = this.peek(index + 2);
- var ch3 = this.peek(index + 3);
- var ch4 = this.peek(index + 4);
- var code;
- if (isHexDigit(ch1) && isHexDigit(ch2) && isHexDigit(ch3) && isHexDigit(ch4)) {
- code = parseInt(ch1 + ch2 + ch3 + ch4, 16);
- if (isUnicodeLetter(code)) {
- index += 5;
- return "\\u" + ch1 + ch2 + ch3 + ch4;
- }
- return null;
- }
- return null;
- }.bind(this);
- var getIdentifierStart = function () {
- /*jshint validthis:true */
- var chr = this.peek(index);
- var code = chr.charCodeAt(0);
- if (code === 92) {
- return readUnicodeEscapeSequence();
- }
- if (code < 128) {
- if (identifierStartTable[code]) {
- index += 1;
- return chr;
- }
- return null;
- }
- if (isUnicodeLetter(code)) {
- index += 1;
- return chr;
- }
- return null;
- }.bind(this);
- var getIdentifierPart = function () {
- /*jshint validthis:true */
- var chr = this.peek(index);
- var code = chr.charCodeAt(0);
- if (code === 92) {
- return readUnicodeEscapeSequence();
- }
- if (code < 128) {
- if (identifierPartTable[code]) {
- index += 1;
- return chr;
- }
- return null;
- }
- if (isUnicodeLetter(code)) {
- index += 1;
- return chr;
- }
- return null;
- }.bind(this);
- char = getIdentifierStart();
- if (char === null) {
- return null;
- }
- id = char;
- for (;;) {
- char = getIdentifierPart();
- if (char === null) {
- break;
- }
- id += char;
- }
- switch (id) {
- case "true":
- case "false":
- type = Token.BooleanLiteral;
- break;
- case "null":
- type = Token.NullLiteral;
- break;
- default:
- type = Token.Identifier;
- }
- return {
- type: type,
- value: id
- };
- },
- /*
- * Extract a numeric literal out of the next sequence of
- * characters or return 'null' if its not possible. This method
- * supports all numeric literals described in section 7.8.3
- * of the EcmaScript 5 specification.
- *
- * This method's implementation was heavily influenced by the
- * scanNumericLiteral function in the Esprima parser's source code.
- */
- scanNumericLiteral: function () {
- var index = 0;
- var value = "";
- var length = this.input.length;
- var char = this.peek(index);
- var bad;
- function isDecimalDigit(str) {
- return (/^[0-9]$/).test(str);
- }
- function isOctalDigit(str) {
- return (/^[0-7]$/).test(str);
- }
- function isHexDigit(str) {
- return (/^[0-9a-fA-F]$/).test(str);
- }
- function isIdentifierStart(ch) {
- return (ch === "$") || (ch === "_") || (ch === "\\") ||
- (ch >= "a" && ch <= "z") || (ch >= "A" && ch <= "Z");
- }
- // Numbers must start either with a decimal digit or a point.
- if (char !== "." && !isDecimalDigit(char)) {
- return null;
- }
- if (char !== ".") {
- value = this.peek(index);
- index += 1;
- char = this.peek(index);
- if (value === "0") {
- // Base-16 numbers.
- if (char === "x" || char === "X") {
- index += 1;
- value += char;
- while (index < length) {
- char = this.peek(index);
- if (!isHexDigit(char)) {
- break;
- }
- value += char;
- index += 1;
- }
- if (value.length <= 2) { // 0x
- return {
- type: Token.NumericLiteral,
- value: value,
- isMalformed: true
- };
- }
- if (index < length) {
- char = this.peek(index);
- if (isIdentifierStart(char)) {
- return null;
- }
- }
- return {
- type: Token.NumericLiteral,
- value: value,
- base: 16,
- isMalformed: false
- };
- }
- // Base-8 numbers.
- if (isOctalDigit(char)) {
- index += 1;
- value += char;
- bad = false;
- while (index < length) {
- char = this.peek(index);
- // Numbers like '019' (note the 9) are not valid octals
- // but we still parse them and mark as malformed.
- if (isDecimalDigit(char)) {
- bad = true;
- } else if (!isOctalDigit(char)) {
- break;
- }
- value += char;
- index += 1;
- }
- if (index < length) {
- char = this.peek(index);
- if (isIdentifierStart(char)) {
- return null;
- }
- }
- return {
- type: Token.NumericLiteral,
- value: value,
- base: 8,
- isMalformed: false
- };
- }
- // Decimal numbers that start with '0' such as '09' are illegal
- // but we still parse them and return as malformed.
- if (isDecimalDigit(char)) {
- index += 1;
- value += char;
- }
- }
- while (index < length) {
- char = this.peek(index);
- if (!isDecimalDigit(char)) {
- break;
- }
- value += char;
- index += 1;
- }
- }
- // Decimal digits.
- if (char === ".") {
- value += char;
- index += 1;
- while (index < length) {
- char = this.peek(index);
- if (!isDecimalDigit(char)) {
- break;
- }
- value += char;
- index += 1;
- }
- }
- // Exponent part.
- if (char === "e" || char === "E") {
- value += char;
- index += 1;
- char = this.peek(index);
- if (char === "+" || char === "-") {
- value += this.peek(index);
- index += 1;
- }
- char = this.peek(index);
- if (isDecimalDigit(char)) {
- value += char;
- index += 1;
- while (index < length) {
- char = this.peek(index);
- if (!isDecimalDigit(char)) {
- break;
- }
- value += char;
- index += 1;
- }
- } else {
- return null;
- }
- }
- if (index < length) {
- char = this.peek(index);
- if (isIdentifierStart(char)) {
- return null;
- }
- }
- return {
- type: Token.NumericLiteral,
- value: value,
- base: 10,
- isMalformed: !isFinite(value)
- };
- },
- /*
- * Extract a string out of the next sequence of characters and/or
- * lines or return 'null' if its not possible. Since strings can
- * span across multiple lines this method has to move the char
- * pointer.
- *
- * This method recognizes pseudo-multiline JavaScript strings:
- *
- * var str = "hello\
- * world";
- */
- scanStringLiteral: function (checks) {
- /*jshint loopfunc:true */
- var quote = this.peek();
- // String must start with a quote.
- if (quote !== "\"" && quote !== "'") {
- return null;
- }
- // In JSON strings must always use double quotes.
- this.triggerAsync("warning", {
- code: "W108",
- line: this.line,
- character: this.char // +1?
- }, checks, function () { return state.jsonMode && quote !== "\""; });
- var value = "";
- var startLine = this.line;
- var startChar = this.char;
- var allowNewLine = false;
- this.skip();
- outer: while (this.peek() !== quote) {
- while (this.peek() === "") { // End Of Line
- // If an EOL is not preceded by a backslash, show a warning
- // and proceed like it was a legit multi-line string where
- // author simply forgot to escape the newline symbol.
- //
- // Another approach is to implicitly close a string on EOL
- // but it generates too many false positives.
- if (!allowNewLine) {
- this.trigger("warning", {
- code: "W112",
- line: this.line,
- character: this.char
- });
- } else {
- allowNewLine = false;
- // Otherwise show a warning if multistr option was not set.
- // For JSON, show warning no matter what.
- this.triggerAsync("warning", {
- code: "W043",
- line: this.line,
- character: this.char
- }, checks, function () { return !state.option.multistr; });
- this.triggerAsync("warning", {
- code: "W042",
- line: this.line,
- character: this.char
- }, checks, function () { return state.jsonMode && state.option.multistr; });
- }
- // If we get an EOF inside of an unclosed string, show an
- // error and implicitly close it at the EOF point.
- if (!this.nextLine()) {
- this.trigger("error", {
- code: "E029",
- line: startLine,
- character: startChar
- });
- return {
- type: Token.StringLiteral,
- value: value,
- isUnclosed: true,
- quote: quote
- };
- }
-
- if (this.peek() == quote)
- break outer;
- }
- allowNewLine = false;
- var char = this.peek();
- var jump = 1; // A length of a jump, after we're done
- // parsing this character.
- if (char < " ") {
- // Warn about a control character in a string.
- this.trigger("warning", {
- code: "W113",
- line: this.line,
- character: this.char,
- data: [ "<non-printable>" ]
- });
- }
- // Special treatment for some escaped characters.
- if (char === "\\") {
- this.skip();
- char = this.peek();
- switch (char) {
- case "'":
- this.triggerAsync("warning", {
- code: "W114",
- line: this.line,
- character: this.char,
- data: [ "\\'" ]
- }, checks, function () {return state.jsonMode; });
- break;
- case "b":
- char = "\b";
- break;
- case "f":
- char = "\f";
- break;
- case "n":
- char = "\n";
- break;
- case "r":
- char = "\r";
- break;
- case "t":
- char = "\t";
- break;
- case "0":
- char = "\0";
- // Octal literals fail in strict mode.
- // Check if the number is between 00 and 07.
- var n = parseInt(this.peek(1), 10);
- this.triggerAsync("warning", {
- code: "W115",
- line: this.line,
- character: this.char
- }, checks,
- function () { return n >= 0 && n <= 7 && state.directive["use strict"]; });
- break;
- case "u":
- char = String.fromCharCode(parseInt(this.input.substr(1, 4), 16));
- jump = 5;
- break;
- case "v":
- this.triggerAsync("warning", {
- code: "W114",
- line: this.line,
- character: this.char,
- data: [ "\\v" ]
- }, checks, function () { return state.jsonMode; });
- char = "\v";
- break;
- case "x":
- var x = parseInt(this.input.substr(1, 2), 16);
- this.triggerAsync("warning", {
- code: "W114",
- line: this.line,
- character: this.char,
- data: [ "\\x-" ]
- }, checks, function () { return state.jsonMode; });
- char = String.fromCharCode(x);
- jump = 3;
- break;
- case "\\":
- case "\"":
- case "/":
- break;
- case "":
- allowNewLine = true;
- char = "";
- break;
- case "!":
- if (value.slice(value.length - 2) === "<") {
- break;
- }
- /*falls through */
- default:
- // Weird escaping.
- this.trigger("warning", {
- code: "W044",
- line: this.line,
- character: this.char
- });
- }
- }
- value += char;
- this.skip(jump);
- }
- this.skip();
- return {
- type: Token.StringLiteral,
- value: value,
- isUnclosed: false,
- quote: quote
- };
- },
- /*
- * Extract a regular expression out of the next sequence of
- * characters and/or lines or return 'null' if its not possible.
- *
- * This method is platform dependent: it accepts almost any
- * regular expression values but then tries to compile and run
- * them using system's RegExp object. This means that there are
- * rare edge cases where one JavaScript engine complains about
- * your regular expression while others don't.
- */
- scanRegExp: function () {
- var index = 0;
- var length = this.input.length;
- var char = this.peek();
- var value = char;
- var body = "";
- var flags = [];
- var malformed = false;
- var isCharSet = false;
- var terminated;
- var scanUnexpectedChars = function () {
- // Unexpected control character
- if (char < " ") {
- malformed = true;
- this.trigger("warning", {
- code: "W048",
- line: this.line,
- character: this.char
- });
- }
- // Unexpected escaped character
- if (char === "<") {
- malformed = true;
- this.trigger("warning", {
- code: "W049",
- line: this.line,
- character: this.char,
- data: [ char ]
- });
- }
- }.bind(this);
- // Regular expressions must start with '/'
- if (!this.prereg || char !== "/") {
- return null;
- }
- index += 1;
- terminated = false;
- // Try to get everything in between slashes. A couple of
- // cases aside (see scanUnexpectedChars) we don't really
- // care whether the resulting expression is valid or not.
- // We will check that later using the RegExp object.
- while (index < length) {
- char = this.peek(index);
- value += char;
- body += char;
- if (isCharSet) {
- if (char === "]") {
- if (this.peek(index - 1) !== "\\" || this.peek(index - 2) === "\\") {
- isCharSet = false;
- }
- }
- if (char === "\\") {
- index += 1;
- char = this.peek(index);
- body += char;
- value += char;
- scanUnexpectedChars();
- }
- index += 1;
- continue;
- }
- if (char === "\\") {
- index += 1;
- char = this.peek(index);
- body += char;
- value += char;
- scanUnexpectedChars();
- if (char === "/") {
- index += 1;
- continue;
- }
- if (char === "[") {
- index += 1;
- continue;
- }
- }
- if (char === "[") {
- isCharSet = true;
- index += 1;
- continue;
- }
- if (char === "/") {
- body = body.substr(0, body.length - 1);
- terminated = true;
- index += 1;
- break;
- }
- index += 1;
- }
- // A regular expression that was never closed is an
- // error from which we cannot recover.
- if (!terminated) {
- this.trigger("error", {
- code: "E015",
- line: this.line,
- character: this.from
- });
- return void this.trigger("fatal", {
- line: this.line,
- from: this.from
- });
- }
- // Parse flags (if any).
- while (index < length) {
- char = this.peek(index);
- if (!/[gim]/.test(char)) {
- break;
- }
- flags.push(char);
- value += char;
- index += 1;
- }
- // Check regular expression for correctness.
- try {
- new RegExp(body, flags.join(""));
- } catch (err) {
- malformed = true;
- this.trigger("error", {
- code: "E016",
- line: this.line,
- character: this.char,
- data: [ err.message ] // Platform dependent!
- });
- }
- return {
- type: Token.RegExp,
- value: value,
- flags: flags,
- isMalformed: malformed
- };
- },
- /*
- * Scan for any occurence of mixed tabs and spaces. If smarttabs option
- * is on, ignore tabs followed by spaces.
- *
- * Tabs followed by one space followed by a block comment are allowed.
- */
- scanMixedSpacesAndTabs: function () {
- var at, match;
- if (state.option.smarttabs) {
- // Negative look-behind for "//"
- match = this.input.match(/(\/\/|^\s?\*)? \t/);
- at = match && !match[1] ? 0 : -1;
- } else {
- at = this.input.search(/ \t|\t [^\*]/);
- }
- return at;
- },
- /*
- * Scan for characters that get silently deleted by one or more browsers.
- */
- scanUnsafeChars: function () {
- return this.input.search(reg.unsafeChars);
- },
- /*
- * Produce the next raw token or return 'null' if no tokens can be matched.
- * This method skips over all space characters.
- */
- next: function (checks) {
- this.from = this.char;
- // Move to the next non-space character.
- var start;
- if (/\s/.test(this.peek())) {
- start = this.char;
- while (/\s/.test(this.peek())) {
- this.from += 1;
- this.skip();
- }
- if (this.peek() === "") { // EOL
- if (!/^\s*$/.test(this.getLines()[this.line - 1]) && state.option.trailing) {
- this.trigger("warning", { code: "W102", line: this.line, character: start });
- }
- }
- }
- // Methods that work with multi-line structures and move the
- // character pointer.
- var match = this.scanComments() ||
- this.scanStringLiteral(checks);
- if (match) {
- return match;
- }
- // Methods that don't move the character pointer.
- match =
- this.scanRegExp() ||
- this.scanPunctuator() ||
- this.scanKeyword() ||
- this.scanIdentifier() ||
- this.scanNumericLiteral();
- if (match) {
- this.skip(match.value.length);
- return match;
- }
- // No token could be matched, give up.
- return null;
- },
- /*
- * Switch to the next line and reset all char pointers. Once
- * switched, this method also checks for mixed spaces and tabs
- * and other minor warnings.
- */
- nextLine: function () {
- var char;
- if (this.line >= this.getLines().length) {
- return false;
- }
- this.input = this.getLines()[this.line];
- this.line += 1;
- this.char = 1;
- this.from = 1;
- char = this.scanMixedSpacesAndTabs();
- if (char >= 0) {
- this.trigger("warning", { code: "W099", line: this.line, character: char + 1 });
- }
- this.input = this.input.replace(/\t/g, state.tab);
- char = this.scanUnsafeChars();
- if (char >= 0) {
- this.trigger("warning", { code: "W100", line: this.line, character: char });
- }
- // If there is a limit on line length, warn when lines get too
- // long.
- if (state.option.maxlen && state.option.maxlen < this.input.length) {
- this.trigger("warning", { code: "W101", line: this.line, character: this.input.length });
- }
- return true;
- },
- /*
- * This is simply a synonym for nextLine() method with a friendlier
- * public name.
- */
- start: function () {
- this.nextLine();
- },
- /*
- * Produce the next token. This function is called by advance() to get
- * the next token. It retuns a token in a JSLint-compatible format.
- */
- token: function () {
- /*jshint loopfunc:true */
- var checks = asyncTrigger();
- var token;
- function isReserved(token, isProperty) {
- if (!token.reserved) {
- return false;
- }
- var meta = token.meta;
- if (meta && meta.isFutureReservedWord && state.option.inES5()) {
- // ES3 FutureReservedWord in an ES5 environment.
- if (!meta.es5) {
- return false;
- }
- // Some ES5 FutureReservedWord identifiers are active only
- // within a strict mode environment.
- if (meta.strictOnly) {
- if (!state.option.strict && !state.directive["use strict"]) {
- return false;
- }
- }
- if (isProperty) {
- return false;
- }
- }
- return true;
- }
- // Produce a token object.
- var create = function (type, value, isProperty) {
- /*jshint validthis:true */
- var obj;
- if (type !== "(endline)" && type !== "(end)") {
- this.prereg = false;
- }
- if (type === "(punctuator)") {
- switch (value) {
- case ".":
- case ")":
- case "~":
- case "#":
- case "]":
- this.prereg = false;
- break;
- default:
- this.prereg = true;
- }
- obj = Object.create(state.syntax[value] || state.syntax["(error)"]);
- }
- if (type === "(identifier)") {
- if (value === "return" || value === "case" || value === "typeof") {
- this.prereg = true;
- }
- if (_.has(state.syntax, value)) {
- obj = Object.create(state.syntax[value] || state.syntax["(error)"]);
- // If this can't be a reserved keyword, reset the object.
- if (!isReserved(obj, isProperty && type === "(identifier)")) {
- obj = null;
- }
- }
- }
- if (!obj) {
- obj = Object.create(state.syntax[type]);
- }
- obj.identifier = (type === "(identifier)");
- obj.type = obj.type || type;
- obj.value = value;
- obj.line = this.line;
- obj.character = this.char;
- obj.from = this.from;
- if (isProperty && obj.identifier) {
- obj.isProperty = isProperty;
- }
- obj.check = checks.check;
- return obj;
- }.bind(this);
- for (;;) {
- if (!this.input.length) {
- return create(this.nextLine() ? "(endline)" : "(end)", "");
- }
- token = this.next(checks);
- if (!token) {
- if (this.input.length) {
- // Unexpected character.
- this.trigger("error", {
- code: "E024",
- line: this.line,
- character: this.char,
- data: [ this.peek() ]
- });
- this.input = "";
- }
- continue;
- }
- switch (token.type) {
- case Token.StringLiteral:
- this.triggerAsync("String", {
- line: this.line,
- char: this.char,
- from: this.from,
- value: token.value,
- quote: token.quote
- }, checks, function () { return true; });
- return create("(string)", token.value);
- case Token.Identifier:
- this.trigger("Identifier", {
- line: this.line,
- char: this.char,
- from: this.form,
- name: token.value,
- isProperty: state.tokens.curr.id === "."
- });
- /* falls through */
- case Token.Keyword:
- case Token.NullLiteral:
- case Token.BooleanLiteral:
- return create("(identifier)", token.value, state.tokens.curr.id === ".");
- case Token.NumericLiteral:
- if (token.isMalformed) {
- this.trigger("warning", {
- code: "W045",
- line: this.line,
- character: this.char,
- data: [ token.value ]
- });
- }
- this.triggerAsync("warning", {
- code: "W114",
- line: this.line,
- character: this.char,
- data: [ "0x-" ]
- }, checks, function () { return token.base === 16 && state.jsonMode; });
- this.triggerAsync("warning", {
- code: "W115",
- line: this.line,
- character: this.char
- }, checks, function () {
- return state.directive["use strict"] && token.base === 8;
- });
- this.trigger("Number", {
- line: this.line,
- char: this.char,
- from: this.from,
- value: token.value,
- base: token.base,
- isMalformed: token.malformed
- });
- return create("(number)", token.value);
- case Token.RegExp:
- return create("(regexp)", token.value);
- case Token.Comment:
- state.tokens.curr.comment = true;
- if (token.isSpecial) {
- return {
- value: token.value,
- body: token.body,
- type: token.commentType,
- isSpecial: token.isSpecial,
- line: this.line,
- character: this.char,
- from: this.from
- };
- }
- break;
- case "":
- break;
- default:
- return create("(punctuator)", token.value);
- }
- }
- }
- };
- exports.Lexer = Lexer;
- },
- {"./reg.js":6,"./state.js":7,"events":10,"underscore":1}],
- 6:[function(req,module,exports){
- /*
- * Regular expressions. Some of these are stupidly long.
- */
- /*jshint maxlen:1000 */
- "use string";
- // Unsafe comment or string (ax)
- exports.unsafeString =
- /@cc|<\/?|script|\]\s*\]|<\s*!|</i;
- // Unsafe characters that are silently deleted by one or more browsers (cx)
- exports.unsafeChars =
- /[\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/;
- // Characters in strings that need escaping (nx and nxg)
- exports.needEsc =
- /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/;
- exports.needEscGlobal =
- /[\u0000-\u001f&<"\/\\\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
- // Star slash (lx)
- exports.starSlash = /\*\//;
- // Identifier (ix)
- exports.identifier = /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/;
- // JavaScript URL (jx)
- exports.javascriptURL = /^(?:javascript|jscript|ecmascript|vbscript|mocha|livescript)\s*:/i;
- // Catches /* falls through */ comments (ft)
- exports.fallsThrough = /^\s*\/\*\s*falls?\sthrough\s*\*\/\s*$/;
- },
- {}],
- 7:[function(req,module,exports){
- "use strict";
- var state = {
- syntax: {},
- reset: function () {
- this.tokens = {
- prev: null,
- next: null,
- curr: null
- };
- this.option = {};
- this.ignored = {};
- this.directive = {};
- this.jsonMode = false;
- this.jsonWarnings = [];
- this.lines = [];
- this.tab = "";
- this.cache = {}; // Node.JS doesn't have Map. Sniff.
- }
- };
- exports.state = state;
- },
- {}],
- 8:[function(req,module,exports){
- "use strict";
- exports.register = function (linter) {
- // Check for properties named __proto__. This special property was
- // deprecated and then re-introduced for ES6.
- linter.on("Identifier", function style_scanProto(data) {
- if (linter.getOption("proto")) {
- return;
- }
- if (data.name === "__proto__") {
- linter.warn("W103", {
- line: data.line,
- char: data.char,
- data: [ data.name ]
- });
- }
- });
- // Check for properties named __iterator__. This is a special property
- // available only in browsers with JavaScript 1.7 implementation.
- linter.on("Identifier", function style_scanIterator(data) {
- if (linter.getOption("iterator")) {
- return;
- }
- if (data.name === "__iterator__") {
- linter.warn("W104", {
- line: data.line,
- char: data.char,
- data: [ data.name ]
- });
- }
- });
- // Check for dangling underscores.
- linter.on("Identifier", function style_scanDangling(data) {
- if (!linter.getOption("nomen")) {
- return;
- }
- // Underscore.js
- if (data.name === "_") {
- return;
- }
- // In Node, __dirname and __filename should be ignored.
- if (linter.getOption("node")) {
- if (/^(__dirname|__filename)$/.test(data.name) && !data.isProperty) {
- return;
- }
- }
- if (/^(_+.*|.*_+)$/.test(data.name)) {
- linter.warn("W105", {
- line: data.line,
- char: data.from,
- data: [ "dangling '_'", data.name ]
- });
- }
- });
- // Check that all identifiers are using camelCase notation.
- // Exceptions: names like MY_VAR and _myVar.
- linter.on("Identifier", function style_scanCamelCase(data) {
- if (!linter.getOption("camelcase")) {
- return;
- }
- if (data.name.replace(/^_+/, "").indexOf("_") > -1 && !data.name.match(/^[A-Z0-9_]*$/)) {
- linter.warn("W106", {
- line: data.line,
- char: data.from,
- data: [ data.name ]
- });
- }
- });
- // Enforce consistency in style of quoting.
- linter.on("String", function style_scanQuotes(data) {
- var quotmark = linter.getOption("quotmark");
- var code;
- if (!quotmark) {
- return;
- }
- // If quotmark is set to 'single' warn about all double-quotes.
- if (quotmark === "single" && data.quote !== "'") {
- code = "W109";
- }
- // If quotmark is set to 'double' warn about all single-quotes.
- if (quotmark === "double" && data.quote !== "\"") {
- code = "W108";
- }
- // If quotmark is set to true, remember the first quotation style
- // and then warn about all others.
- if (quotmark === true) {
- if (!linter.getCache("quotmark")) {
- linter.setCache("quotmark", data.quote);
- }
- if (linter.getCache("quotmark") !== data.quote) {
- code = "W110";
- }
- }
- if (code) {
- linter.warn(code, {
- line: data.line,
- char: data.char,
- });
- }
- });
- linter.on("Number", function style_scanNumbers(data) {
- if (data.value.charAt(0) === ".") {
- // Warn about a leading decimal point.
- linter.warn("W008", {
- line: data.line,
- char: data.char,
- data: [ data.value ]
- });
- }
- if (data.value.substr(data.value.length - 1) === ".") {
- // Warn about a trailing decimal point.
- linter.warn("W047", {
- line: data.line,
- char: data.char,
- data: [ data.value ]
- });
- }
- if (/^00+/.test(data.value)) {
- // Multiple leading zeroes.
- linter.warn("W046", {
- line: data.line,
- char: data.char,
- data: [ data.value ]
- });
- }
- });
- // Warn about script URLs.
- linter.on("String", function style_scanJavaScriptURLs(data) {
- var re = /^(?:javascript|jscript|ecmascript|vbscript|mocha|livescript)\s*:/i;
- if (linter.getOption("scripturl")) {
- return;
- }
- if (re.test(data.value)) {
- linter.warn("W107", {
- line: data.line,
- char: data.char
- });
- }
- });
- };
- },
- {}],
- 9:[function(req,module,exports){
- },
- {}],
- 10:[function(req,module,exports){
- var process=req("__browserify_process");if (!process.EventEmitter) process.EventEmitter = function () {};
- var EventEmitter = exports.EventEmitter = process.EventEmitter;
- var isArray = typeof Array.isArray === 'function'
- ? Array.isArray
- : function (xs) {
- return Object.prototype.toString.call(xs) === '[object Array]'
- }
- ;
- function indexOf (xs, x) {
- if (xs.indexOf) return xs.indexOf(x);
- for (var i = 0; i < xs.length; i++) {
- if (x === xs[i]) return i;
- }
- return -1;
- }
- // By default EventEmitters will print a warning if more than
- // 10 listeners are added to it. This is a useful default which
- // helps finding memory leaks.
- //
- // Obviously not all Emitters should be limited to 10. This function allows
- // that to be increased. Set to zero for unlimited.
- var defaultMaxListeners = 200;
- EventEmitter.prototype.setMaxListeners = function(n) {
- if (!this._events) this._events = {};
- this._events.maxListeners = n;
- };
- EventEmitter.prototype.emit = function(type) {
- // If there is no 'error' event listener then throw.
- if (type === 'error') {
- if (!this._events || !this._events.error ||
- (isArray(this._events.error) && !this._events.error.length))
- {
- if (arguments[1] instanceof Error) {
- throw arguments[1]; // Unhandled 'error' event
- } else {
- throw new Error("Uncaught, unspecified 'error' event.");
- }
- return false;
- }
- }
- if (!this._events) return false;
- var handler = this._events[type];
- if (!handler) return false;
- if (typeof handler == 'function') {
- switch (arguments.length) {
- // fast cases
- case 1:
- handler.call(this);
- break;
- case 2:
- handler.call(this, arguments[1]);
- break;
- case 3:
- handler.call(this, arguments[1], arguments[2]);
- break;
- // slower
- default:
- var args = Array.prototype.slice.call(arguments, 1);
- handler.apply(this, args);
- }
- return true;
- } else if (isArray(handler)) {
- var args = Array.prototype.slice.call(arguments, 1);
- var listeners = handler.slice();
- for (var i = 0, l = listeners.length; i < l; i++) {
- listeners[i].apply(this, args);
- }
- return true;
- } else {
- return false;
- }
- };
- // EventEmitter is defined in src/node_events.cc
- // EventEmitter.prototype.emit() is also defined there.
- EventEmitter.prototype.addListener = function(type, listener) {
- if ('function' !== typeof listener) {
- throw new Error('addListener only takes instances of Function');
- }
- if (!this._events) this._events = {};
- // To avoid recursion in the case that type == "newListeners"! Before
- // adding it to the listeners, first emit "newListeners".
- this.emit('newListener', type, listener);
- if (!this._events[type]) {
- // Optimize the case of one listener. Don't need the extra array object.
- this._events[type] = listener;
- } else if (isArray(this._events[type])) {
- // Check for listener leak
- if (!this._events[type].warned) {
- var m;
- if (this._events.maxListeners !== undefined) {
- m = this._events.maxListeners;
- } else {
- m = defaultMaxListeners;
- }
- if (m && m > 0 && this._events[type].length > m) {
- this._events[type].warned = true;
- console.error('(node) warning: possible EventEmitter memory ' +
- 'leak detected. %d listeners added. ' +
- 'Use emitter.setMaxListeners() to increase limit.',
- this._events[type].length);
- console.trace();
- }
- }
- // If we've already got an array, just append.
- this._events[type].push(listener);
- } else {
- // Adding the second element, need to change to array.
- this._events[type] = [this._events[type], listener];
- }
- return this;
- };
- EventEmitter.prototype.on = EventEmitter.prototype.addListener;
- EventEmitter.prototype.once = function(type, listener) {
- var self = this;
- self.on(type, function g() {
- self.removeListener(type, g);
- listener.apply(this, arguments);
- });
- return this;
- };
- EventEmitter.prototype.removeListener = function(type, listener) {
- if ('function' !== typeof listener) {
- throw new Error('removeListener only takes instances of Function');
- }
- // does not use listeners(), so no side effect of creating _events[type]
- if (!this._events || !this._events[type]) return this;
- var list = this._events[type];
- if (isArray(list)) {
- var i = indexOf(list, listener);
- if (i < 0) return this;
- list.splice(i, 1);
- if (list.length == 0)
- delete this._events[type];
- } else if (this._events[type] === listener) {
- delete this._events[type];
- }
- return this;
- };
- EventEmitter.prototype.removeAllListeners = function(type) {
- if (arguments.length === 0) {
- this._events = {};
- return this;
- }
- // does not use listeners(), so no side effect of creating _events[type]
- if (type && this._events && this._events[type]) this._events[type] = null;
- return this;
- };
- EventEmitter.prototype.listeners = function(type) {
- if (!this._events) this._events = {};
- if (!this._events[type]) this._events[type] = [];
- if (!isArray(this._events[type])) {
- this._events[type] = [this._events[type]];
- }
- return this._events[type];
- };
- EventEmitter.listenerCount = function(emitter, type) {
- var ret;
- if (!emitter._events || !emitter._events[type])
- ret = 0;
- else if (typeof emitter._events[type] === 'function')
- ret = 1;
- else
- ret = emitter._events[type].length;
- return ret;
- };
- },
- {"__browserify_process":11}],
- 11:[function(req,module,exports){
- // shim for using process in browser
- var process = module.exports = {};
- process.nextTick = (function () {
- var canSetImmediate = typeof window !== 'undefined'
- && window.setImmediate;
- var canPost = typeof window !== 'undefined'
- && window.postMessage && window.addEventListener
- ;
- if (canSetImmediate) {
- return function (f) { return window.setImmediate(f) };
- }
- if (canPost) {
- var queue = [];
- window.addEventListener('message', function (ev) {
- if (ev.source === window && ev.data === 'process-tick') {
- ev.stopPropagation();
- if (queue.length > 0) {
- var fn = queue.shift();
- fn();
- }
- }
- }, true);
- return function nextTick(fn) {
- queue.push(fn);
- window.postMessage('process-tick', '*');
- };
- }
- return function nextTick(fn) {
- setTimeout(fn, 0);
- };
- })();
- process.title = 'browser';
- process.browser = true;
- process.env = {};
- process.argv = [];
- process.binding = function (name) {
- throw new Error('process.binding is not supported');
- }
- // TODO(shtylman)
- process.cwd = function () { return '/' };
- process.chdir = function (dir) {
- throw new Error('process.chdir is not supported');
- };
- },
- {}],
- "jshint":[function(req,module,exports){
- module.exports=req('n4bKNg');
- },
- {}]},{},["n4bKNg"])
- ;
- function req() {return require.apply(this, arguments)}
- module.exports = req("jshint");
- });
|