| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871987298739874987598769877987898799880988198829883988498859886988798889889989098919892989398949895989698979898989999009901990299039904990599069907990899099910991199129913991499159916991799189919992099219922992399249925992699279928992999309931993299339934993599369937993899399940994199429943994499459946994799489949995099519952995399549955995699579958995999609961996299639964996599669967996899699970997199729973997499759976997799789979998099819982998399849985998699879988998999909991999299939994999599969997999899991000010001100021000310004100051000610007100081000910010100111001210013100141001510016100171001810019100201002110022100231002410025100261002710028100291003010031100321003310034100351003610037100381003910040100411004210043100441004510046100471004810049100501005110052100531005410055100561005710058100591006010061100621006310064100651006610067100681006910070100711007210073100741007510076100771007810079100801008110082100831008410085100861008710088100891009010091100921009310094100951009610097100981009910100101011010210103101041010510106101071010810109101101011110112101131011410115101161011710118101191012010121101221012310124101251012610127101281012910130101311013210133101341013510136101371013810139101401014110142101431014410145101461014710148101491015010151101521015310154101551015610157101581015910160101611016210163101641016510166101671016810169101701017110172101731017410175101761017710178101791018010181101821018310184101851018610187101881018910190101911019210193101941019510196101971019810199102001020110202102031020410205102061020710208102091021010211102121021310214102151021610217102181021910220102211022210223102241022510226102271022810229102301023110232102331023410235102361023710238102391024010241102421024310244102451024610247102481024910250102511025210253102541025510256102571025810259102601026110262102631026410265102661026710268102691027010271102721027310274102751027610277102781027910280102811028210283102841028510286102871028810289102901029110292102931029410295102961029710298102991030010301103021030310304103051030610307103081030910310103111031210313103141031510316103171031810319103201032110322103231032410325103261032710328103291033010331103321033310334103351033610337103381033910340103411034210343103441034510346103471034810349103501035110352103531035410355103561035710358103591036010361103621036310364103651036610367103681036910370103711037210373103741037510376103771037810379103801038110382103831038410385103861038710388103891039010391103921039310394103951039610397103981039910400104011040210403104041040510406104071040810409104101041110412104131041410415104161041710418104191042010421104221042310424104251042610427104281042910430104311043210433104341043510436104371043810439104401044110442104431044410445104461044710448104491045010451104521045310454104551045610457104581045910460104611046210463104641046510466104671046810469104701047110472104731047410475104761047710478104791048010481104821048310484104851048610487104881048910490104911049210493104941049510496104971049810499105001050110502105031050410505105061050710508105091051010511105121051310514105151051610517105181051910520105211052210523105241052510526105271052810529105301053110532105331053410535105361053710538105391054010541105421054310544105451054610547105481054910550105511055210553105541055510556105571055810559105601056110562105631056410565105661056710568105691057010571105721057310574105751057610577105781057910580105811058210583105841058510586105871058810589105901059110592105931059410595105961059710598105991060010601106021060310604106051060610607106081060910610106111061210613106141061510616106171061810619106201062110622106231062410625106261062710628106291063010631106321063310634106351063610637106381063910640106411064210643106441064510646106471064810649106501065110652106531065410655106561065710658106591066010661106621066310664106651066610667106681066910670106711067210673106741067510676106771067810679106801068110682106831068410685106861068710688106891069010691106921069310694106951069610697106981069910700107011070210703107041070510706107071070810709107101071110712107131071410715107161071710718107191072010721107221072310724107251072610727107281072910730107311073210733107341073510736107371073810739107401074110742107431074410745107461074710748107491075010751107521075310754107551075610757107581075910760107611076210763107641076510766107671076810769107701077110772107731077410775107761077710778107791078010781107821078310784107851078610787107881078910790107911079210793107941079510796107971079810799108001080110802108031080410805108061080710808108091081010811108121081310814108151081610817108181081910820108211082210823108241082510826108271082810829108301083110832108331083410835108361083710838108391084010841108421084310844108451084610847108481084910850108511085210853108541085510856108571085810859108601086110862108631086410865108661086710868108691087010871108721087310874108751087610877108781087910880108811088210883108841088510886108871088810889108901089110892108931089410895108961089710898108991090010901109021090310904109051090610907109081090910910109111091210913109141091510916109171091810919109201092110922109231092410925109261092710928109291093010931109321093310934109351093610937109381093910940109411094210943109441094510946109471094810949109501095110952109531095410955109561095710958109591096010961109621096310964109651096610967109681096910970109711097210973109741097510976109771097810979109801098110982109831098410985109861098710988109891099010991109921099310994109951099610997109981099911000110011100211003110041100511006110071100811009110101101111012110131101411015110161101711018110191102011021110221102311024110251102611027110281102911030110311103211033110341103511036110371103811039110401104111042110431104411045110461104711048110491105011051110521105311054110551105611057110581105911060110611106211063110641106511066110671106811069110701107111072110731107411075110761107711078110791108011081110821108311084110851108611087110881108911090110911109211093110941109511096110971109811099111001110111102111031110411105111061110711108111091111011111111121111311114111151111611117111181111911120111211112211123111241112511126111271112811129111301113111132111331113411135111361113711138111391114011141111421114311144111451114611147111481114911150111511115211153111541115511156111571115811159111601116111162111631116411165111661116711168111691117011171111721117311174111751117611177111781117911180111811118211183111841118511186111871118811189111901119111192111931119411195111961119711198111991120011201112021120311204112051120611207112081120911210112111121211213112141121511216112171121811219112201122111222112231122411225112261122711228112291123011231112321123311234112351123611237112381123911240112411124211243112441124511246112471124811249112501125111252112531125411255112561125711258112591126011261112621126311264112651126611267112681126911270112711127211273112741127511276112771127811279112801128111282112831128411285112861128711288112891129011291112921129311294112951129611297112981129911300113011130211303113041130511306113071130811309113101131111312113131131411315113161131711318113191132011321113221132311324113251132611327113281132911330113311133211333113341133511336113371133811339113401134111342113431134411345113461134711348113491135011351113521135311354113551135611357113581135911360113611136211363113641136511366113671136811369113701137111372113731137411375113761137711378113791138011381113821138311384113851138611387113881138911390113911139211393113941139511396113971139811399114001140111402114031140411405114061140711408114091141011411114121141311414114151141611417114181141911420114211142211423114241142511426114271142811429114301143111432114331143411435114361143711438114391144011441114421144311444114451144611447114481144911450114511145211453114541145511456114571145811459114601146111462114631146411465114661146711468114691147011471114721147311474114751147611477114781147911480114811148211483114841148511486114871148811489114901149111492114931149411495114961149711498114991150011501115021150311504115051150611507115081150911510115111151211513115141151511516115171151811519115201152111522115231152411525115261152711528115291153011531115321153311534115351153611537115381153911540115411154211543115441154511546115471154811549115501155111552115531155411555115561155711558115591156011561115621156311564115651156611567115681156911570115711157211573115741157511576115771157811579115801158111582115831158411585115861158711588115891159011591115921159311594115951159611597115981159911600116011160211603116041160511606116071160811609116101161111612116131161411615116161161711618116191162011621116221162311624116251162611627116281162911630116311163211633116341163511636116371163811639116401164111642116431164411645116461164711648116491165011651116521165311654116551165611657116581165911660 |
- define(function(require, exports, module) {
- module.exports = (function outer (modules, cache, entry) {
- var previousRequire = typeof require == "function" && require;
- function newRequire(name, jumped){
- if(!cache[name]) {
- if(!modules[name]) {
- var currentRequire = typeof require == "function" && require;
- if (!jumped && currentRequire) return currentRequire(name, true);
- if (previousRequire) return previousRequire(name, true);
- var err = new Error('Cannot find module \'' + name + '\'');
- err.code = 'MODULE_NOT_FOUND';
- throw err;
- }
- var m = cache[name] = {exports:{}};
- modules[name][0].call(m.exports, function(x){
- var id = modules[name][1][x];
- return newRequire(id ? id : x);
- },m,m.exports,outer,modules,cache,entry);
- }
- return cache[name].exports;
- }
- for(var i=0;i<entry.length;i++) newRequire(entry[i]);
- return newRequire(entry[0]);
- })
- ({"/node_modules/browserify/node_modules/events/events.js":[function(_dereq_,module,exports){
- // Copyright Joyent, Inc. and other Node contributors.
- //
- // 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 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.
- function EventEmitter() {
- this._events = this._events || {};
- this._maxListeners = this._maxListeners || undefined;
- }
- module.exports = EventEmitter;
- // Backwards-compat with node 0.10.x
- EventEmitter.EventEmitter = EventEmitter;
- EventEmitter.prototype._events = undefined;
- EventEmitter.prototype._maxListeners = undefined;
- // 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.
- EventEmitter.defaultMaxListeners = 10;
- // Obviously not all Emitters should be limited to 10. This function allows
- // that to be increased. Set to zero for unlimited.
- EventEmitter.prototype.setMaxListeners = function(n) {
- if (!isNumber(n) || n < 0 || isNaN(n))
- throw TypeError('n must be a positive number');
- this._maxListeners = n;
- return this;
- };
- EventEmitter.prototype.emit = function(type) {
- var er, handler, len, args, i, listeners;
- if (!this._events)
- this._events = {};
- // If there is no 'error' event listener then throw.
- if (type === 'error') {
- if (!this._events.error ||
- (isObject(this._events.error) && !this._events.error.length)) {
- er = arguments[1];
- if (er instanceof Error) {
- throw er; // Unhandled 'error' event
- }
- throw TypeError('Uncaught, unspecified "error" event.');
- }
- }
- handler = this._events[type];
- if (isUndefined(handler))
- return false;
- if (isFunction(handler)) {
- 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:
- len = arguments.length;
- args = new Array(len - 1);
- for (i = 1; i < len; i++)
- args[i - 1] = arguments[i];
- handler.apply(this, args);
- }
- } else if (isObject(handler)) {
- len = arguments.length;
- args = new Array(len - 1);
- for (i = 1; i < len; i++)
- args[i - 1] = arguments[i];
- listeners = handler.slice();
- len = listeners.length;
- for (i = 0; i < len; i++)
- listeners[i].apply(this, args);
- }
- return true;
- };
- EventEmitter.prototype.addListener = function(type, listener) {
- var m;
- if (!isFunction(listener))
- throw TypeError('listener must be a function');
- if (!this._events)
- this._events = {};
- // To avoid recursion in the case that type === "newListener"! Before
- // adding it to the listeners, first emit "newListener".
- if (this._events.newListener)
- this.emit('newListener', type,
- isFunction(listener.listener) ?
- listener.listener : listener);
- if (!this._events[type])
- // Optimize the case of one listener. Don't need the extra array object.
- this._events[type] = listener;
- else if (isObject(this._events[type]))
- // 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];
- // Check for listener leak
- if (isObject(this._events[type]) && !this._events[type].warned) {
- var m;
- if (!isUndefined(this._maxListeners)) {
- m = this._maxListeners;
- } else {
- m = EventEmitter.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);
- if (typeof console.trace === 'function') {
- // not supported in IE 10
- console.trace();
- }
- }
- }
- return this;
- };
- EventEmitter.prototype.on = EventEmitter.prototype.addListener;
- EventEmitter.prototype.once = function(type, listener) {
- if (!isFunction(listener))
- throw TypeError('listener must be a function');
- var fired = false;
- function g() {
- this.removeListener(type, g);
- if (!fired) {
- fired = true;
- listener.apply(this, arguments);
- }
- }
- g.listener = listener;
- this.on(type, g);
- return this;
- };
- // emits a 'removeListener' event iff the listener was removed
- EventEmitter.prototype.removeListener = function(type, listener) {
- var list, position, length, i;
- if (!isFunction(listener))
- throw TypeError('listener must be a function');
- if (!this._events || !this._events[type])
- return this;
- list = this._events[type];
- length = list.length;
- position = -1;
- if (list === listener ||
- (isFunction(list.listener) && list.listener === listener)) {
- delete this._events[type];
- if (this._events.removeListener)
- this.emit('removeListener', type, listener);
- } else if (isObject(list)) {
- for (i = length; i-- > 0;) {
- if (list[i] === listener ||
- (list[i].listener && list[i].listener === listener)) {
- position = i;
- break;
- }
- }
- if (position < 0)
- return this;
- if (list.length === 1) {
- list.length = 0;
- delete this._events[type];
- } else {
- list.splice(position, 1);
- }
- if (this._events.removeListener)
- this.emit('removeListener', type, listener);
- }
- return this;
- };
- EventEmitter.prototype.removeAllListeners = function(type) {
- var key, listeners;
- if (!this._events)
- return this;
- // not listening for removeListener, no need to emit
- if (!this._events.removeListener) {
- if (arguments.length === 0)
- this._events = {};
- else if (this._events[type])
- delete this._events[type];
- return this;
- }
- // emit removeListener for all listeners on all events
- if (arguments.length === 0) {
- for (key in this._events) {
- if (key === 'removeListener') continue;
- this.removeAllListeners(key);
- }
- this.removeAllListeners('removeListener');
- this._events = {};
- return this;
- }
- listeners = this._events[type];
- if (isFunction(listeners)) {
- this.removeListener(type, listeners);
- } else {
- // LIFO order
- while (listeners.length)
- this.removeListener(type, listeners[listeners.length - 1]);
- }
- delete this._events[type];
- return this;
- };
- EventEmitter.prototype.listeners = function(type) {
- var ret;
- if (!this._events || !this._events[type])
- ret = [];
- else if (isFunction(this._events[type]))
- ret = [this._events[type]];
- else
- ret = this._events[type].slice();
- return ret;
- };
- EventEmitter.listenerCount = function(emitter, type) {
- var ret;
- if (!emitter._events || !emitter._events[type])
- ret = 0;
- else if (isFunction(emitter._events[type]))
- ret = 1;
- else
- ret = emitter._events[type].length;
- return ret;
- };
- function isFunction(arg) {
- return typeof arg === 'function';
- }
- function isNumber(arg) {
- return typeof arg === 'number';
- }
- function isObject(arg) {
- return typeof arg === 'object' && arg !== null;
- }
- function isUndefined(arg) {
- return arg === void 0;
- }
- },{}],"/node_modules/jshint/data/ascii-identifier-data.js":[function(_dereq_,module,exports){
- 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
- }
- module.exports = {
- asciiIdentifierStartTable: identifierStartTable,
- asciiIdentifierPartTable: identifierPartTable
- };
- },{}],"/node_modules/jshint/node_modules/underscore/underscore.js":[function(_dereq_,module,exports){
- // Underscore.js 1.8.3
- // http://underscorejs.org
- // (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
- // Underscore may be freely distributed under the MIT license.
- (function() {
- // Baseline setup
- // --------------
- // Establish the root object, `window` in the browser, or `exports` on the server.
- var root = this;
- // Save the previous value of the `_` variable.
- var previousUnderscore = root._;
- // 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,
- toString = ObjProto.toString,
- hasOwnProperty = ObjProto.hasOwnProperty;
- // All **ECMAScript 5** native function implementations that we hope to use
- // are declared here.
- var
- nativeIsArray = Array.isArray,
- nativeKeys = Object.keys,
- nativeBind = FuncProto.bind,
- nativeCreate = Object.create;
- // Naked function reference for surrogate-prototype-swapping.
- var Ctor = function(){};
- // 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.
- if (typeof exports !== 'undefined') {
- if (typeof module !== 'undefined' && module.exports) {
- exports = module.exports = _;
- }
- exports._ = _;
- } else {
- root._ = _;
- }
- // Current version.
- _.VERSION = '1.8.3';
- // Internal function that returns an efficient (for current engines) version
- // of the passed-in callback, to be repeatedly applied in other Underscore
- // functions.
- var optimizeCb = function(func, context, argCount) {
- if (context === void 0) return func;
- switch (argCount == null ? 3 : argCount) {
- case 1: return function(value) {
- return func.call(context, value);
- };
- case 2: return function(value, other) {
- return func.call(context, value, other);
- };
- case 3: return function(value, index, collection) {
- return func.call(context, value, index, collection);
- };
- case 4: return function(accumulator, value, index, collection) {
- return func.call(context, accumulator, value, index, collection);
- };
- }
- return function() {
- return func.apply(context, arguments);
- };
- };
- // A mostly-internal function to generate callbacks that can be applied
- // to each element in a collection, returning the desired result — either
- // identity, an arbitrary callback, a property matcher, or a property accessor.
- var cb = function(value, context, argCount) {
- if (value == null) return _.identity;
- if (_.isFunction(value)) return optimizeCb(value, context, argCount);
- if (_.isObject(value)) return _.matcher(value);
- return _.property(value);
- };
- _.iteratee = function(value, context) {
- return cb(value, context, Infinity);
- };
- // An internal function for creating assigner functions.
- var createAssigner = function(keysFunc, undefinedOnly) {
- return function(obj) {
- var length = arguments.length;
- if (length < 2 || obj == null) return obj;
- for (var index = 1; index < length; index++) {
- var source = arguments[index],
- keys = keysFunc(source),
- l = keys.length;
- for (var i = 0; i < l; i++) {
- var key = keys[i];
- if (!undefinedOnly || obj[key] === void 0) obj[key] = source[key];
- }
- }
- return obj;
- };
- };
- // An internal function for creating a new object that inherits from another.
- var baseCreate = function(prototype) {
- if (!_.isObject(prototype)) return {};
- if (nativeCreate) return nativeCreate(prototype);
- Ctor.prototype = prototype;
- var result = new Ctor;
- Ctor.prototype = null;
- return result;
- };
- var property = function(key) {
- return function(obj) {
- return obj == null ? void 0 : obj[key];
- };
- };
- // Helper for collection methods to determine whether a collection
- // should be iterated as an array or as an object
- // Related: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength
- // Avoids a very nasty iOS 8 JIT bug on ARM-64. #2094
- var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;
- var getLength = property('length');
- var isArrayLike = function(collection) {
- var length = getLength(collection);
- return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX;
- };
- // Collection Functions
- // --------------------
- // The cornerstone, an `each` implementation, aka `forEach`.
- // Handles raw objects in addition to array-likes. Treats all
- // sparse array-likes as if they were dense.
- _.each = _.forEach = function(obj, iteratee, context) {
- iteratee = optimizeCb(iteratee, context);
- var i, length;
- if (isArrayLike(obj)) {
- for (i = 0, length = obj.length; i < length; i++) {
- iteratee(obj[i], i, obj);
- }
- } else {
- var keys = _.keys(obj);
- for (i = 0, length = keys.length; i < length; i++) {
- iteratee(obj[keys[i]], keys[i], obj);
- }
- }
- return obj;
- };
- // Return the results of applying the iteratee to each element.
- _.map = _.collect = function(obj, iteratee, context) {
- iteratee = cb(iteratee, context);
- var keys = !isArrayLike(obj) && _.keys(obj),
- length = (keys || obj).length,
- results = Array(length);
- for (var index = 0; index < length; index++) {
- var currentKey = keys ? keys[index] : index;
- results[index] = iteratee(obj[currentKey], currentKey, obj);
- }
- return results;
- };
- // Create a reducing function iterating left or right.
- function createReduce(dir) {
- // Optimized iterator function as using arguments.length
- // in the main function will deoptimize the, see #1991.
- function iterator(obj, iteratee, memo, keys, index, length) {
- for (; index >= 0 && index < length; index += dir) {
- var currentKey = keys ? keys[index] : index;
- memo = iteratee(memo, obj[currentKey], currentKey, obj);
- }
- return memo;
- }
- return function(obj, iteratee, memo, context) {
- iteratee = optimizeCb(iteratee, context, 4);
- var keys = !isArrayLike(obj) && _.keys(obj),
- length = (keys || obj).length,
- index = dir > 0 ? 0 : length - 1;
- // Determine the initial value if none is provided.
- if (arguments.length < 3) {
- memo = obj[keys ? keys[index] : index];
- index += dir;
- }
- return iterator(obj, iteratee, memo, keys, index, length);
- };
- }
- // **Reduce** builds up a single result from a list of values, aka `inject`,
- // or `foldl`.
- _.reduce = _.foldl = _.inject = createReduce(1);
- // The right-associative version of reduce, also known as `foldr`.
- _.reduceRight = _.foldr = createReduce(-1);
- // Return the first value which passes a truth test. Aliased as `detect`.
- _.find = _.detect = function(obj, predicate, context) {
- var key;
- if (isArrayLike(obj)) {
- key = _.findIndex(obj, predicate, context);
- } else {
- key = _.findKey(obj, predicate, context);
- }
- if (key !== void 0 && key !== -1) return obj[key];
- };
- // Return all the elements that pass a truth test.
- // Aliased as `select`.
- _.filter = _.select = function(obj, predicate, context) {
- var results = [];
- predicate = cb(predicate, context);
- _.each(obj, function(value, index, list) {
- if (predicate(value, index, list)) results.push(value);
- });
- return results;
- };
- // Return all the elements for which a truth test fails.
- _.reject = function(obj, predicate, context) {
- return _.filter(obj, _.negate(cb(predicate)), context);
- };
- // Determine whether all of the elements match a truth test.
- // Aliased as `all`.
- _.every = _.all = function(obj, predicate, context) {
- predicate = cb(predicate, context);
- var keys = !isArrayLike(obj) && _.keys(obj),
- length = (keys || obj).length;
- for (var index = 0; index < length; index++) {
- var currentKey = keys ? keys[index] : index;
- if (!predicate(obj[currentKey], currentKey, obj)) return false;
- }
- return true;
- };
- // Determine if at least one element in the object matches a truth test.
- // Aliased as `any`.
- _.some = _.any = function(obj, predicate, context) {
- predicate = cb(predicate, context);
- var keys = !isArrayLike(obj) && _.keys(obj),
- length = (keys || obj).length;
- for (var index = 0; index < length; index++) {
- var currentKey = keys ? keys[index] : index;
- if (predicate(obj[currentKey], currentKey, obj)) return true;
- }
- return false;
- };
- // Determine if the array or object contains a given item (using `===`).
- // Aliased as `includes` and `include`.
- _.contains = _.includes = _.include = function(obj, item, fromIndex, guard) {
- if (!isArrayLike(obj)) obj = _.values(obj);
- if (typeof fromIndex != 'number' || guard) fromIndex = 0;
- return _.indexOf(obj, item, fromIndex) >= 0;
- };
- // 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) {
- var func = isFunc ? method : value[method];
- return func == null ? func : func.apply(value, args);
- });
- };
- // Convenience version of a common use case of `map`: fetching a property.
- _.pluck = function(obj, key) {
- return _.map(obj, _.property(key));
- };
- // Convenience version of a common use case of `filter`: selecting only objects
- // containing specific `key:value` pairs.
- _.where = function(obj, attrs) {
- return _.filter(obj, _.matcher(attrs));
- };
- // Convenience version of a common use case of `find`: getting the first object
- // containing specific `key:value` pairs.
- _.findWhere = function(obj, attrs) {
- return _.find(obj, _.matcher(attrs));
- };
- // Return the maximum element (or element-based computation).
- _.max = function(obj, iteratee, context) {
- var result = -Infinity, lastComputed = -Infinity,
- value, computed;
- if (iteratee == null && obj != null) {
- obj = isArrayLike(obj) ? obj : _.values(obj);
- for (var i = 0, length = obj.length; i < length; i++) {
- value = obj[i];
- if (value > result) {
- result = value;
- }
- }
- } else {
- iteratee = cb(iteratee, context);
- _.each(obj, function(value, index, list) {
- computed = iteratee(value, index, list);
- if (computed > lastComputed || computed === -Infinity && result === -Infinity) {
- result = value;
- lastComputed = computed;
- }
- });
- }
- return result;
- };
- // Return the minimum element (or element-based computation).
- _.min = function(obj, iteratee, context) {
- var result = Infinity, lastComputed = Infinity,
- value, computed;
- if (iteratee == null && obj != null) {
- obj = isArrayLike(obj) ? obj : _.values(obj);
- for (var i = 0, length = obj.length; i < length; i++) {
- value = obj[i];
- if (value < result) {
- result = value;
- }
- }
- } else {
- iteratee = cb(iteratee, context);
- _.each(obj, function(value, index, list) {
- computed = iteratee(value, index, list);
- if (computed < lastComputed || computed === Infinity && result === Infinity) {
- result = value;
- lastComputed = computed;
- }
- });
- }
- return result;
- };
- // Shuffle a collection, using the modern version of the
- // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle).
- _.shuffle = function(obj) {
- var set = isArrayLike(obj) ? obj : _.values(obj);
- var length = set.length;
- var shuffled = Array(length);
- for (var index = 0, rand; index < length; index++) {
- rand = _.random(0, index);
- if (rand !== index) shuffled[index] = shuffled[rand];
- shuffled[rand] = set[index];
- }
- return shuffled;
- };
- // Sample **n** random values from a collection.
- // If **n** is not specified, returns a single random element.
- // The internal `guard` argument allows it to work with `map`.
- _.sample = function(obj, n, guard) {
- if (n == null || guard) {
- if (!isArrayLike(obj)) obj = _.values(obj);
- return obj[_.random(obj.length - 1)];
- }
- return _.shuffle(obj).slice(0, Math.max(0, n));
- };
- // Sort the object's values by a criterion produced by an iteratee.
- _.sortBy = function(obj, iteratee, context) {
- iteratee = cb(iteratee, context);
- return _.pluck(_.map(obj, function(value, index, list) {
- return {
- value: value,
- index: index,
- criteria: iteratee(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;
- }), 'value');
- };
- // An internal function used for aggregate "group by" operations.
- var group = function(behavior) {
- return function(obj, iteratee, context) {
- var result = {};
- iteratee = cb(iteratee, context);
- _.each(obj, function(value, index) {
- var key = iteratee(value, index, obj);
- behavior(result, value, key);
- });
- 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 = group(function(result, value, key) {
- if (_.has(result, key)) result[key].push(value); else result[key] = [value];
- });
- // Indexes the object's values by a criterion, similar to `groupBy`, but for
- // when you know that your index values will be unique.
- _.indexBy = group(function(result, value, key) {
- result[key] = 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 = group(function(result, value, key) {
- if (_.has(result, key)) result[key]++; else result[key] = 1;
- });
- // Safely create a real, live array from anything iterable.
- _.toArray = function(obj) {
- if (!obj) return [];
- if (_.isArray(obj)) return slice.call(obj);
- if (isArrayLike(obj)) return _.map(obj, _.identity);
- return _.values(obj);
- };
- // Return the number of elements in an object.
- _.size = function(obj) {
- if (obj == null) return 0;
- return isArrayLike(obj) ? obj.length : _.keys(obj).length;
- };
- // Split a collection into two arrays: one whose elements all satisfy the given
- // predicate, and one whose elements all do not satisfy the predicate.
- _.partition = function(obj, predicate, context) {
- predicate = cb(predicate, context);
- var pass = [], fail = [];
- _.each(obj, function(value, key, obj) {
- (predicate(value, key, obj) ? pass : fail).push(value);
- });
- return [pass, fail];
- };
- // 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;
- if (n == null || guard) return array[0];
- return _.initial(array, array.length - n);
- };
- // 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.
- _.initial = function(array, n, guard) {
- return slice.call(array, 0, Math.max(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.
- _.last = function(array, n, guard) {
- if (array == null) return void 0;
- if (n == null || guard) return array[array.length - 1];
- return _.rest(array, Math.max(0, array.length - n));
- };
- // 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.
- _.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, strict, startIndex) {
- var output = [], idx = 0;
- for (var i = startIndex || 0, length = getLength(input); i < length; i++) {
- var value = input[i];
- if (isArrayLike(value) && (_.isArray(value) || _.isArguments(value))) {
- //flatten current level of array or arguments object
- if (!shallow) value = flatten(value, shallow, strict);
- var j = 0, len = value.length;
- output.length += len;
- while (j < len) {
- output[idx++] = value[j++];
- }
- } else if (!strict) {
- output[idx++] = value;
- }
- }
- return output;
- };
- // Flatten out an array, either recursively (by default), or just one level.
- _.flatten = function(array, shallow) {
- return flatten(array, shallow, false);
- };
- // 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, iteratee, context) {
- if (!_.isBoolean(isSorted)) {
- context = iteratee;
- iteratee = isSorted;
- isSorted = false;
- }
- if (iteratee != null) iteratee = cb(iteratee, context);
- var result = [];
- var seen = [];
- for (var i = 0, length = getLength(array); i < length; i++) {
- var value = array[i],
- computed = iteratee ? iteratee(value, i, array) : value;
- if (isSorted) {
- if (!i || seen !== computed) result.push(value);
- seen = computed;
- } else if (iteratee) {
- if (!_.contains(seen, computed)) {
- seen.push(computed);
- result.push(value);
- }
- } else if (!_.contains(result, value)) {
- result.push(value);
- }
- }
- return result;
- };
- // Produce an array that contains the union: each distinct element from all of
- // the passed-in arrays.
- _.union = function() {
- return _.uniq(flatten(arguments, true, true));
- };
- // Produce an array that contains every item shared between all the
- // passed-in arrays.
- _.intersection = function(array) {
- var result = [];
- var argsLength = arguments.length;
- for (var i = 0, length = getLength(array); i < length; i++) {
- var item = array[i];
- if (_.contains(result, item)) continue;
- for (var j = 1; j < argsLength; j++) {
- if (!_.contains(arguments[j], item)) break;
- }
- if (j === argsLength) result.push(item);
- }
- return result;
- };
- // 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 = flatten(arguments, true, true, 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() {
- return _.unzip(arguments);
- };
- // Complement of _.zip. Unzip accepts an array of arrays and groups
- // each array's elements on shared indices
- _.unzip = function(array) {
- var length = array && _.max(array, getLength).length || 0;
- var result = Array(length);
- for (var index = 0; index < length; index++) {
- result[index] = _.pluck(array, index);
- }
- return result;
- };
- // 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) {
- var result = {};
- for (var i = 0, length = getLength(list); i < length; i++) {
- if (values) {
- result[list[i]] = values[i];
- } else {
- result[list[i][0]] = list[i][1];
- }
- }
- return result;
- };
- // Generator function to create the findIndex and findLastIndex functions
- function createPredicateIndexFinder(dir) {
- return function(array, predicate, context) {
- predicate = cb(predicate, context);
- var length = getLength(array);
- var index = dir > 0 ? 0 : length - 1;
- for (; index >= 0 && index < length; index += dir) {
- if (predicate(array[index], index, array)) return index;
- }
- return -1;
- };
- }
- // Returns the first index on an array-like that passes a predicate test
- _.findIndex = createPredicateIndexFinder(1);
- _.findLastIndex = createPredicateIndexFinder(-1);
- // 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, iteratee, context) {
- iteratee = cb(iteratee, context, 1);
- var value = iteratee(obj);
- var low = 0, high = getLength(array);
- while (low < high) {
- var mid = Math.floor((low + high) / 2);
- if (iteratee(array[mid]) < value) low = mid + 1; else high = mid;
- }
- return low;
- };
- // Generator function to create the indexOf and lastIndexOf functions
- function createIndexFinder(dir, predicateFind, sortedIndex) {
- return function(array, item, idx) {
- var i = 0, length = getLength(array);
- if (typeof idx == 'number') {
- if (dir > 0) {
- i = idx >= 0 ? idx : Math.max(idx + length, i);
- } else {
- length = idx >= 0 ? Math.min(idx + 1, length) : idx + length + 1;
- }
- } else if (sortedIndex && idx && length) {
- idx = sortedIndex(array, item);
- return array[idx] === item ? idx : -1;
- }
- if (item !== item) {
- idx = predicateFind(slice.call(array, i, length), _.isNaN);
- return idx >= 0 ? idx + i : -1;
- }
- for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir) {
- if (array[idx] === item) return idx;
- }
- return -1;
- };
- }
- // Return the position of the first occurrence of an item in an array,
- // or -1 if the item is not included in the array.
- // If the array is large and already in sort order, pass `true`
- // for **isSorted** to use binary search.
- _.indexOf = createIndexFinder(1, _.findIndex, _.sortedIndex);
- _.lastIndexOf = createIndexFinder(-1, _.findLastIndex);
- // 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 (stop == null) {
- stop = start || 0;
- start = 0;
- }
- step = step || 1;
- var length = Math.max(Math.ceil((stop - start) / step), 0);
- var range = Array(length);
- for (var idx = 0; idx < length; idx++, start += step) {
- range[idx] = start;
- }
- return range;
- };
- // Function (ahem) Functions
- // ------------------
- // Determines whether to execute a function as a constructor
- // or a normal function with the provided arguments
- var executeBound = function(sourceFunc, boundFunc, context, callingContext, args) {
- if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args);
- var self = baseCreate(sourceFunc.prototype);
- var result = sourceFunc.apply(self, args);
- if (_.isObject(result)) return result;
- return self;
- };
- // 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 (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
- if (!_.isFunction(func)) throw new TypeError('Bind must be called on a function');
- var args = slice.call(arguments, 2);
- var bound = function() {
- return executeBound(func, bound, context, this, args.concat(slice.call(arguments)));
- };
- return bound;
- };
- // Partially apply a function by creating a version that has had some of its
- // arguments pre-filled, without changing its dynamic `this` context. _ acts
- // as a placeholder, allowing any combination of arguments to be pre-filled.
- _.partial = function(func) {
- var boundArgs = slice.call(arguments, 1);
- var bound = function() {
- var position = 0, length = boundArgs.length;
- var args = Array(length);
- for (var i = 0; i < length; i++) {
- args[i] = boundArgs[i] === _ ? arguments[position++] : boundArgs[i];
- }
- while (position < arguments.length) args.push(arguments[position++]);
- return executeBound(func, bound, this, this, args);
- };
- return bound;
- };
- // Bind a number of an object's methods to that object. Remaining arguments
- // are the method names to be bound. Useful for ensuring that all callbacks
- // defined on an object belong to it.
- _.bindAll = function(obj) {
- var i, length = arguments.length, key;
- if (length <= 1) throw new Error('bindAll must be passed function names');
- for (i = 1; i < length; i++) {
- key = arguments[i];
- obj[key] = _.bind(obj[key], obj);
- }
- return obj;
- };
- // Memoize an expensive function by storing its results.
- _.memoize = function(func, hasher) {
- var memoize = function(key) {
- var cache = memoize.cache;
- var address = '' + (hasher ? hasher.apply(this, arguments) : key);
- if (!_.has(cache, address)) cache[address] = func.apply(this, arguments);
- return cache[address];
- };
- memoize.cache = {};
- return memoize;
- };
- // 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 = _.partial(_.delay, _, 1);
- // Returns a function, that, when invoked, will only be triggered at most once
- // during a given window of time. Normally, the throttled function will run
- // as much as it can, without ever going more than once per `wait` duration;
- // but if you'd like to disable the execution on the leading edge, pass
- // `{leading: false}`. To disable execution on the trailing edge, ditto.
- _.throttle = function(func, wait, options) {
- var context, args, result;
- var timeout = null;
- var previous = 0;
- if (!options) options = {};
- var later = function() {
- previous = options.leading === false ? 0 : _.now();
- timeout = null;
- result = func.apply(context, args);
- if (!timeout) context = args = null;
- };
- return function() {
- var now = _.now();
- if (!previous && options.leading === false) previous = now;
- var remaining = wait - (now - previous);
- context = this;
- args = arguments;
- if (remaining <= 0 || remaining > wait) {
- if (timeout) {
- clearTimeout(timeout);
- timeout = null;
- }
- previous = now;
- result = func.apply(context, args);
- if (!timeout) context = args = null;
- } else if (!timeout && options.trailing !== false) {
- 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, args, context, timestamp, result;
- var later = function() {
- var last = _.now() - timestamp;
- if (last < wait && last >= 0) {
- timeout = setTimeout(later, wait - last);
- } else {
- timeout = null;
- if (!immediate) {
- result = func.apply(context, args);
- if (!timeout) context = args = null;
- }
- }
- };
- return function() {
- context = this;
- args = arguments;
- timestamp = _.now();
- var callNow = immediate && !timeout;
- if (!timeout) timeout = setTimeout(later, wait);
- if (callNow) {
- result = func.apply(context, args);
- context = args = null;
- }
- return result;
- };
- };
- // 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 _.partial(wrapper, func);
- };
- // Returns a negated version of the passed-in predicate.
- _.negate = function(predicate) {
- return function() {
- return !predicate.apply(this, arguments);
- };
- };
- // 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 args = arguments;
- var start = args.length - 1;
- return function() {
- var i = start;
- var result = args[start].apply(this, arguments);
- while (i--) result = args[i].call(this, result);
- return result;
- };
- };
- // Returns a function that will only be executed on and after the Nth call.
- _.after = function(times, func) {
- return function() {
- if (--times < 1) {
- return func.apply(this, arguments);
- }
- };
- };
- // Returns a function that will only be executed up to (but not including) the Nth call.
- _.before = function(times, func) {
- var memo;
- return function() {
- if (--times > 0) {
- memo = func.apply(this, arguments);
- }
- if (times <= 1) func = null;
- return memo;
- };
- };
- // Returns a function that will be executed at most one time, no matter how
- // often you call it. Useful for lazy initialization.
- _.once = _.partial(_.before, 2);
- // Object Functions
- // ----------------
- // Keys in IE < 9 that won't be iterated by `for key in ...` and thus missed.
- var hasEnumBug = !{toString: null}.propertyIsEnumerable('toString');
- var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString',
- 'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString'];
- function collectNonEnumProps(obj, keys) {
- var nonEnumIdx = nonEnumerableProps.length;
- var constructor = obj.constructor;
- var proto = (_.isFunction(constructor) && constructor.prototype) || ObjProto;
- // Constructor is a special case.
- var prop = 'constructor';
- if (_.has(obj, prop) && !_.contains(keys, prop)) keys.push(prop);
- while (nonEnumIdx--) {
- prop = nonEnumerableProps[nonEnumIdx];
- if (prop in obj && obj[prop] !== proto[prop] && !_.contains(keys, prop)) {
- keys.push(prop);
- }
- }
- }
- // Retrieve the names of an object's own properties.
- // Delegates to **ECMAScript 5**'s native `Object.keys`
- _.keys = function(obj) {
- if (!_.isObject(obj)) return [];
- if (nativeKeys) return nativeKeys(obj);
- var keys = [];
- for (var key in obj) if (_.has(obj, key)) keys.push(key);
- // Ahem, IE < 9.
- if (hasEnumBug) collectNonEnumProps(obj, keys);
- return keys;
- };
- // Retrieve all the property names of an object.
- _.allKeys = function(obj) {
- if (!_.isObject(obj)) return [];
- var keys = [];
- for (var key in obj) keys.push(key);
- // Ahem, IE < 9.
- if (hasEnumBug) collectNonEnumProps(obj, keys);
- return keys;
- };
- // Retrieve the values of an object's properties.
- _.values = function(obj) {
- var keys = _.keys(obj);
- var length = keys.length;
- var values = Array(length);
- for (var i = 0; i < length; i++) {
- values[i] = obj[keys[i]];
- }
- return values;
- };
- // Returns the results of applying the iteratee to each element of the object
- // In contrast to _.map it returns an object
- _.mapObject = function(obj, iteratee, context) {
- iteratee = cb(iteratee, context);
- var keys = _.keys(obj),
- length = keys.length,
- results = {},
- currentKey;
- for (var index = 0; index < length; index++) {
- currentKey = keys[index];
- results[currentKey] = iteratee(obj[currentKey], currentKey, obj);
- }
- return results;
- };
- // Convert an object into a list of `[key, value]` pairs.
- _.pairs = function(obj) {
- var keys = _.keys(obj);
- var length = keys.length;
- var pairs = Array(length);
- for (var i = 0; i < length; i++) {
- pairs[i] = [keys[i], obj[keys[i]]];
- }
- return pairs;
- };
- // Invert the keys and values of an object. The values must be serializable.
- _.invert = function(obj) {
- var result = {};
- var keys = _.keys(obj);
- for (var i = 0, length = keys.length; i < length; i++) {
- result[obj[keys[i]]] = keys[i];
- }
- 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 = createAssigner(_.allKeys);
- // Assigns a given object with all the own properties in the passed-in object(s)
- // (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)
- _.extendOwn = _.assign = createAssigner(_.keys);
- // Returns the first key on an object that passes a predicate test
- _.findKey = function(obj, predicate, context) {
- predicate = cb(predicate, context);
- var keys = _.keys(obj), key;
- for (var i = 0, length = keys.length; i < length; i++) {
- key = keys[i];
- if (predicate(obj[key], key, obj)) return key;
- }
- };
- // Return a copy of the object only containing the whitelisted properties.
- _.pick = function(object, oiteratee, context) {
- var result = {}, obj = object, iteratee, keys;
- if (obj == null) return result;
- if (_.isFunction(oiteratee)) {
- keys = _.allKeys(obj);
- iteratee = optimizeCb(oiteratee, context);
- } else {
- keys = flatten(arguments, false, false, 1);
- iteratee = function(value, key, obj) { return key in obj; };
- obj = Object(obj);
- }
- for (var i = 0, length = keys.length; i < length; i++) {
- var key = keys[i];
- var value = obj[key];
- if (iteratee(value, key, obj)) result[key] = value;
- }
- return result;
- };
- // Return a copy of the object without the blacklisted properties.
- _.omit = function(obj, iteratee, context) {
- if (_.isFunction(iteratee)) {
- iteratee = _.negate(iteratee);
- } else {
- var keys = _.map(flatten(arguments, false, false, 1), String);
- iteratee = function(value, key) {
- return !_.contains(keys, key);
- };
- }
- return _.pick(obj, iteratee, context);
- };
- // Fill in a given object with default properties.
- _.defaults = createAssigner(_.allKeys, true);
- // Creates an object that inherits from the given prototype object.
- // If additional properties are provided then they will be added to the
- // created object.
- _.create = function(prototype, props) {
- var result = baseCreate(prototype);
- if (props) _.extendOwn(result, props);
- return result;
- };
- // 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;
- };
- // Returns whether an object has a given set of `key:value` pairs.
- _.isMatch = function(object, attrs) {
- var keys = _.keys(attrs), length = keys.length;
- if (object == null) return !length;
- var obj = Object(object);
- for (var i = 0; i < length; i++) {
- var key = keys[i];
- if (attrs[key] !== obj[key] || !(key in obj)) return false;
- }
- return true;
- };
- // 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, regular expressions, dates, and booleans are compared by value.
- case '[object RegExp]':
- // RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i')
- case '[object String]':
- // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
- // equivalent to `new String("5")`.
- return '' + a === '' + b;
- case '[object Number]':
- // `NaN`s are equivalent, but non-reflexive.
- // Object(NaN) is equivalent to NaN
- if (+a !== +a) return +b !== +b;
- // An `egal` comparison is performed for other numeric values.
- return +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;
- }
- var areArrays = className === '[object Array]';
- if (!areArrays) {
- if (typeof a != 'object' || typeof b != 'object') return false;
- // Objects with different constructors are not equivalent, but `Object`s or `Array`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)
- && ('constructor' in a && 'constructor' in b)) {
- 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`.
- // Initializing stack of traversed objects.
- // It's done here since we only need them for objects and arrays comparison.
- aStack = aStack || [];
- bStack = bStack || [];
- 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);
- // Recursively compare objects and arrays.
- if (areArrays) {
- // Compare array lengths to determine if a deep comparison is necessary.
- length = a.length;
- if (length !== b.length) return false;
- // Deep compare the contents, ignoring non-numeric properties.
- while (length--) {
- if (!eq(a[length], b[length], aStack, bStack)) return false;
- }
- } else {
- // Deep compare objects.
- var keys = _.keys(a), key;
- length = keys.length;
- // Ensure that both objects contain the same number of properties before comparing deep equality.
- if (_.keys(b).length !== length) return false;
- while (length--) {
- // Deep compare each member
- key = keys[length];
- if (!(_.has(b, key) && eq(a[key], b[key], aStack, bStack))) return false;
- }
- }
- // Remove the first object from the stack of traversed objects.
- aStack.pop();
- bStack.pop();
- return true;
- };
- // 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 (isArrayLike(obj) && (_.isArray(obj) || _.isString(obj) || _.isArguments(obj))) return obj.length === 0;
- return _.keys(obj).length === 0;
- };
- // 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) {
- var type = typeof obj;
- return type === 'function' || type === 'object' && !!obj;
- };
- // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp, isError.
- _.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error'], function(name) {
- _['is' + name] = function(obj) {
- return toString.call(obj) === '[object ' + name + ']';
- };
- });
- // Define a fallback version of the method in browsers (ahem, IE < 9), where
- // there isn't any inspectable "Arguments" type.
- if (!_.isArguments(arguments)) {
- _.isArguments = function(obj) {
- return _.has(obj, 'callee');
- };
- }
- // Optimize `isFunction` if appropriate. Work around some typeof bugs in old v8,
- // IE 11 (#1621), and in Safari 8 (#1929).
- if (typeof /./ != 'function' && typeof Int8Array != 'object') {
- _.isFunction = function(obj) {
- return typeof obj == 'function' || false;
- };
- }
- // 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 obj != null && 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 iteratees.
- _.identity = function(value) {
- return value;
- };
- // Predicate-generating functions. Often useful outside of Underscore.
- _.constant = function(value) {
- return function() {
- return value;
- };
- };
- _.noop = function(){};
- _.property = property;
- // Generates a function for a given object that returns a given property.
- _.propertyOf = function(obj) {
- return obj == null ? function(){} : function(key) {
- return obj[key];
- };
- };
- // Returns a predicate for checking whether an object has a given set of
- // `key:value` pairs.
- _.matcher = _.matches = function(attrs) {
- attrs = _.extendOwn({}, attrs);
- return function(obj) {
- return _.isMatch(obj, attrs);
- };
- };
- // Run a function **n** times.
- _.times = function(n, iteratee, context) {
- var accum = Array(Math.max(0, n));
- iteratee = optimizeCb(iteratee, context, 1);
- for (var i = 0; i < n; i++) accum[i] = iteratee(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));
- };
- // A (possibly faster) way to get the current timestamp as an integer.
- _.now = Date.now || function() {
- return new Date().getTime();
- };
- // List of HTML entities for escaping.
- var escapeMap = {
- '&': '&',
- '<': '<',
- '>': '>',
- '"': '"',
- "'": ''',
- '`': '`'
- };
- var unescapeMap = _.invert(escapeMap);
- // Functions for escaping and unescaping strings to/from HTML interpolation.
- var createEscaper = function(map) {
- var escaper = function(match) {
- return map[match];
- };
- // Regexes for identifying a key that needs to be escaped
- var source = '(?:' + _.keys(map).join('|') + ')';
- var testRegexp = RegExp(source);
- var replaceRegexp = RegExp(source, 'g');
- return function(string) {
- string = string == null ? '' : '' + string;
- return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string;
- };
- };
- _.escape = createEscaper(escapeMap);
- _.unescape = createEscaper(unescapeMap);
- // If the value of the named `property` is a function then invoke it with the
- // `object` as context; otherwise, return it.
- _.result = function(object, property, fallback) {
- var value = object == null ? void 0 : object[property];
- if (value === void 0) {
- value = fallback;
- }
- return _.isFunction(value) ? value.call(object) : value;
- };
- // 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',
- '\u2028': 'u2028',
- '\u2029': 'u2029'
- };
- var escaper = /\\|'|\r|\n|\u2028|\u2029/g;
- var escapeChar = function(match) {
- return '\\' + escapes[match];
- };
- // JavaScript micro-templating, similar to John Resig's implementation.
- // Underscore templating handles arbitrary delimiters, preserves whitespace,
- // and correctly escapes quotes within interpolated code.
- // NB: `oldSettings` only exists for backwards compatibility.
- _.template = function(text, settings, oldSettings) {
- if (!settings && oldSettings) settings = oldSettings;
- settings = _.defaults({}, settings, _.templateSettings);
- // Combine delimiters into one regular expression via alternation.
- var matcher = 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, escapeChar);
- index = offset + match.length;
- if (escape) {
- source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
- } else if (interpolate) {
- source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
- } else if (evaluate) {
- source += "';\n" + evaluate + "\n__p+='";
- }
- // Adobe VMs need the match returned to produce the correct offest.
- 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 {
- var render = new Function(settings.variable || 'obj', '_', source);
- } catch (e) {
- e.source = source;
- throw e;
- }
- var template = function(data) {
- return render.call(this, data, _);
- };
- // Provide the compiled source as a convenience for precompilation.
- var argument = settings.variable || 'obj';
- template.source = 'function(' + argument + '){\n' + source + '}';
- return template;
- };
- // Add a "chain" function. Start chaining a wrapped Underscore object.
- _.chain = function(obj) {
- var instance = _(obj);
- instance._chain = true;
- return instance;
- };
- // 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(instance, obj) {
- return instance._chain ? _(obj).chain() : obj;
- };
- // 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(this, func.apply(_, args));
- };
- });
- };
- // 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(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(this, method.apply(this._wrapped, arguments));
- };
- });
- // Extracts the result from a wrapped and chained object.
- _.prototype.value = function() {
- return this._wrapped;
- };
- // Provide unwrapping proxy for some methods used in engine operations
- // such as arithmetic and JSON stringification.
- _.prototype.valueOf = _.prototype.toJSON = _.prototype.value;
- _.prototype.toString = function() {
- return '' + this._wrapped;
- };
- // AMD registration happens at the end for compatibility with AMD loaders
- // that may not enforce next-turn semantics on modules. Even though general
- // practice for AMD registration is to be anonymous, underscore registers
- // as a named module because, like jQuery, it is a base library that is
- // popular enough to be bundled in a third party lib, but not be part of
- // an AMD load request. Those cases could generate an error when an
- // anonymous define() is called outside of a loader request.
- if (typeof define === 'function' && define.amd) {
- define('underscore', [], function() {
- return _;
- });
- }
- }.call(this));
- },{}],"/node_modules/jshint/src/jshint.js":[function(_dereq_,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 _ = _dereq_("underscore");
- var events = _dereq_("events");
- var vars = _dereq_("./vars.js");
- var messages = _dereq_("./messages.js");
- var Lexer = _dereq_("./lex.js").Lexer;
- var reg = _dereq_("./reg.js");
- var state = _dereq_("./state.js").state;
- var style = _dereq_("./style.js");
- var options = _dereq_("./options.js");
- // 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 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
- },
- 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"
- ],
- functions, // All of the functions
- global, // The global scope
- implied, // Implied globals
- inblock,
- indent,
- lookahead,
- lex,
- member,
- membersOnly,
- predefined, // Global variables defined by option
- scope, // The current scope
- stack,
- unuseds,
- urls,
- extraModules = [],
- emitter = new events.EventEmitter();
- function checkOption(name, t) {
- name = name.trim();
- if (/^[+-]W\d{3}$/g.test(name)) {
- return true;
- }
- if (options.validNames.indexOf(name) === -1) {
- if (t.type !== "jslint" && !_.has(options.removed, name)) {
- 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.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.isStrict()) {
- 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(dest, src) {
- Object.keys(src).forEach(function(name) {
- if (_.has(JSHINT.blacklist, name)) return;
- dest[name] = src[name];
- });
- }
- function processenforceall() {
- if (state.option.enforceall) {
- for (var enforceopt in options.bool.enforcing) {
- if (state.option[enforceopt] === undefined &&
- !options.noenforceall[enforceopt]) {
- state.option[enforceopt] = true;
- }
- }
- for (var relaxopt in options.bool.relaxing) {
- if (state.option[relaxopt] === undefined) {
- state.option[relaxopt] = false;
- }
- }
- }
- }
- function assume() {
- processenforceall();
- if (!state.option.es3) {
- combine(predefined, vars.ecmaIdentifiers[5]);
- }
- if (state.option.esnext) {
- combine(predefined, vars.ecmaIdentifiers[6]);
- }
- if (state.option.module) {
- /**
- * TODO: Extend this restriction to *all* "environmental" options.
- */
- if (!hasParsedCode(state.funct)) {
- error("E055", state.tokens.next, "module");
- }
- /**
- * TODO: Extend this restriction to *all* ES6-specific options.
- */
- if (!state.inESNext()) {
- warning("W134", state.tokens.next, "module", 6);
- }
- }
- if (state.option.couch) {
- combine(predefined, vars.couch);
- }
- if (state.option.qunit) {
- combine(predefined, vars.qunit);
- }
- if (state.option.rhino) {
- combine(predefined, vars.rhino);
- }
- if (state.option.shelljs) {
- combine(predefined, vars.shelljs);
- combine(predefined, vars.node);
- }
- if (state.option.typed) {
- combine(predefined, vars.typed);
- }
- if (state.option.phantom) {
- combine(predefined, vars.phantom);
- }
- if (state.option.prototypejs) {
- combine(predefined, vars.prototypejs);
- }
- if (state.option.node) {
- combine(predefined, vars.node);
- combine(predefined, vars.typed);
- }
- if (state.option.devel) {
- combine(predefined, vars.devel);
- }
- if (state.option.dojo) {
- combine(predefined, vars.dojo);
- }
- if (state.option.browser) {
- combine(predefined, vars.browser);
- combine(predefined, vars.typed);
- }
- if (state.option.browserify) {
- combine(predefined, vars.browser);
- combine(predefined, vars.typed);
- combine(predefined, vars.browserify);
- }
- if (state.option.nonstandard) {
- combine(predefined, vars.nonstandard);
- }
- if (state.option.jasmine) {
- combine(predefined, vars.jasmine);
- }
- 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);
- }
- if (state.option.mocha) {
- combine(predefined, vars.mocha);
- }
- }
- // 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) {
- if (!state.ignored[code] && state.option.undef !== false) {
- JSHINT.undefs.push([scope, code, token, a]);
- }
- }
- function removeIgnoredMessages() {
- var ignored = state.ignoredLines;
- if (_.isEmpty(ignored)) return;
- JSHINT.errors = _.reject(JSHINT.errors, function(err) { return ignored[err.line] });
- }
- 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);
- removeIgnoredMessages();
- if (JSHINT.errors.length >= 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;
- }
- // adds an indentifier to the relevant current scope and creates warnings/errors as necessary
- // name: string
- // opts: { type: string, token: token, isblockscoped: bool }
- function addlabel(name, opts) {
- var type = opts.type;
- var token = opts.token;
- var isblockscoped = opts.isblockscoped;
- // Define label in the current function in the current scope.
- if (type === "exception") {
- if (_.has(state.funct["(context)"], name)) {
- if (state.funct[name] !== true && !state.option.node) {
- warning("W002", state.tokens.next, name);
- }
- }
- }
- if (_.has(state.funct, name) && !state.funct["(global)"]) {
- if (state.funct[name] === true) {
- if (state.option.latedef) {
- if ((state.option.latedef === true && _.contains([state.funct[name], type], "unction")) ||
- !_.contains([state.funct[name], type], "unction")) {
- warning("W003", state.tokens.next, name);
- }
- }
- } else {
- if ((!state.option.shadow || _.contains([ "inner", "outer" ], state.option.shadow)) &&
- type !== "exception" || state.funct["(blockscope)"].getlabel(name)) {
- warning("W004", state.tokens.next, name);
- }
- }
- }
- if (state.funct["(context)"] && _.has(state.funct["(context)"], name) && type !== "function") {
- if (state.option.shadow === "outer") {
- warning("W123", state.tokens.next, name);
- }
- }
- // if the identifier is blockscoped (a let or a const), add it only to the current blockscope
- if (isblockscoped) {
- state.funct["(blockscope)"].current.add(name, type, state.tokens.curr);
- if (state.funct["(blockscope)"].atTop() && exported[name]) {
- state.tokens.curr.exported = true;
- }
- } else {
- state.funct["(blockscope)"].shadow(name);
- state.funct[name] = type;
- if (token) {
- state.funct["(tokens)"][name] = token;
- }
- if (state.funct["(global)"]) {
- global[name] = state.funct;
- if (_.has(implied, name)) {
- if (state.option.latedef) {
- if ((state.option.latedef === true &&
- _.contains([state.funct[name], type], "unction")) ||
- !_.contains([state.funct[name], type], "unction")) {
- warning("W003", state.tokens.next, name);
- }
- }
- delete implied[name];
- }
- } else {
- scope[name] = state.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, idx) {
- g = g.split(":");
- var key = (g[0] || "").trim();
- var val = (g[1] || "").trim();
- if (key === "-" || !key.length) {
- // Ignore trailing comma
- if (idx > 0 && idx === body.length - 1) {
- return;
- }
- error("E002", nt);
- return;
- }
- if (key.charAt(0) === "-") {
- key = key.slice(1);
- val = false;
- JSHINT.blacklist[key] = key;
- delete predefined[key];
- } 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, idx) {
- if (!e.length) {
- // Ignore trailing comma
- if (idx > 0 && idx === body.length - 1) {
- return;
- }
- error("E002", nt);
- return;
- }
- 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("\\\"", "\"");
- }
- 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;
- }
- state.option[key] = val;
- } else {
- state.option[key] = key === "indent" ? 4 : false;
- }
- return;
- }
- if (key === "validthis") {
- // `validthis` is valid only within a function scope.
- if (state.funct["(global)"])
- return void error("E009");
- if (val !== "true" && val !== "false")
- return void error("E002", nt);
- state.option.validthis = (val === "true");
- 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 === "shadow") {
- switch (val) {
- case "true":
- state.option.shadow = true;
- break;
- case "outer":
- state.option.shadow = "outer";
- break;
- case "false":
- case "inner":
- state.option.shadow = "inner";
- 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;
- }
- if (key === "ignore") {
- switch (val) {
- case "start":
- state.ignoreLinterErrors = true;
- break;
- case "end":
- state.ignoreLinterErrors = false;
- break;
- case "line":
- state.ignoredLines[nt.line] = true;
- removeIgnoredMessages();
- 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 = options.renamed[key] || key;
- state.option[tn] = (val === "true");
- if (options.inverted[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;
- }
- // Peeking past the end of the program should produce the "(end)" token.
- if (!t && state.tokens.next.id === "(end)") {
- return state.tokens.next;
- }
- return t;
- }
- function peekIgnoreEOL() {
- var i = 0;
- var t;
- do {
- t = peek(i++);
- } while (t.id === "(endline)");
- 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 (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.template && !!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.inMoz())) {
- return curr.line !== startLine(next);
- }
- return false;
- }
- function isBeginOfExpr(prev) {
- return !prev.left && prev.arity !== "unary";
- }
- // 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;
- state.nameStack.push();
- // if current expression is a let expression
- if (!initial && state.tokens.next.value === "let" && peek(0).value === "(") {
- if (!state.inMoz()) {
- warning("W118", state.tokens.next, "let expressions");
- }
- isLetExpr = true;
- // create a new block scope we use only for the current expression
- state.funct["(blockscope)"].stack();
- advance("let");
- advance("(");
- state.tokens.prev.fud();
- advance(")");
- }
- if (state.tokens.next.id === "(end)")
- error("E006", state.tokens.curr);
- var isDangerous =
- state.option.asi &&
- state.tokens.prev.line !== startLine(state.tokens.curr) &&
- _.contains(["]", ")"], state.tokens.prev.id) &&
- _.contains(["[", "("], state.tokens.curr.id);
- if (isDangerous)
- warning("W014", state.tokens.curr, state.tokens.curr.id);
- advance();
- if (initial) {
- state.funct["(verb)"] = state.tokens.curr.value;
- state.tokens.curr.beginsStmt = true;
- }
- 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);
- }
- // TODO: use pratt mechanics rather than special casing template tokens
- while ((rbp < state.tokens.next.lbp || state.tokens.next.type === "(template)") &&
- !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) {
- state.funct["(blockscope)"].unstack();
- }
- state.nameStack.pop();
- return left;
- }
- // Functions for conformance of style.
- function startLine(token) {
- return token.startLine || token.line;
- }
- function nobreaknonadjacent(left, right) {
- left = left || state.tokens.curr;
- right = right || state.tokens.next;
- if (!state.option.laxbreak && left.line !== startLine(right)) {
- warning("W014", right, right.value);
- }
- }
- function nolinebreak(t) {
- t = t || state.tokens.curr;
- if (t.line !== startLine(state.tokens.next)) {
- warning("E022", t, t.value);
- }
- }
- function nobreakcomma(left, right) {
- if (left.line !== startLine(right)) {
- if (!state.option.laxcomma) {
- if (comma.first) {
- warning("I001");
- comma.first = false;
- }
- warning("W014", left, right.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);
- }
- if (state.tokens.next.identifier && !(opts.property && state.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) {
- var x = symbol(s, 0);
- x.delim = true;
- return x;
- }
- 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.arity = "unary";
- this.right = expression(150);
- if (this.id === "++" || this.id === "--") {
- if (state.option.plusplus) {
- warning("W016", this, this.id);
- } else if (this.right && (!this.right.identifier || isReserved(this.right)) &&
- this.right.id !== "." && this.right.id !== "[") {
- warning("W017", this);
- }
- // detect increment/decrement of a const
- // in the case of a.b, right will be the "." punctuator
- if (this.right && this.right.identifier) {
- if (state.funct["(blockscope)"].labeltype(this.right.value) === "const") {
- error("E013", this, this.right.value);
- }
- }
- }
- 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);
- }
- if ((s === "in" || s === "instanceof") && 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) {
- nobreaknonadjacent(state.tokens.prev, state.tokens.curr);
- this.left = left;
- this.right = doFunction({ type: "arrow", loneArg: 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);
- this.left = left;
- var right = this.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, "!");
- }
- 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");
- }
- var typeofValues = {};
- typeofValues.legacy = [
- // E4X extended the `typeof` operator to return "xml" for the XML and
- // XMLList types it introduced.
- // Ref: 11.3.2 The typeof Operator
- // http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-357.pdf
- "xml",
- // IE<9 reports "unknown" when the `typeof` operator is applied to an
- // object existing across a COM+ bridge. In lieu of official documentation
- // (which does not exist), see:
- // http://robertnyman.com/2005/12/21/what-is-typeof-unknown/
- "unknown"
- ];
- typeofValues.es3 = [
- "undefined", "boolean", "number", "string", "function", "object",
- ];
- typeofValues.es3 = typeofValues.es3.concat(typeofValues.legacy);
- typeofValues.es6 = typeofValues.es3.concat("symbol");
- // Checks whether the 'typeof' operator is used with the correct
- // value. For docs on 'typeof' see:
- // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof
- function isTypoTypeof(left, right, state) {
- var values;
- if (state.option.notypeof)
- return false;
- if (!left || !right)
- return false;
- values = state.inESNext() ? typeofValues.es6 : typeofValues.es3;
- if (right.type === "(identifier)" && right.value === "typeof" && left.type === "(string)")
- return !_.contains(values, left.value);
- return false;
- }
- function isGlobalEval(left, state) {
- var isGlobal = false;
- // permit methods to refer to an "eval" key in their own context
- if (left.type === "this" && state.funct["(context)"] === null) {
- isGlobal = true;
- }
- // permit use of "eval" members of objects
- else if (left.type === "(identifier)") {
- if (state.option.node && left.value === "global") {
- isGlobal = true;
- }
- else if (state.option.browser && (left.value === "window" || left.value === "document")) {
- isGlobal = true;
- }
- }
- return isGlobal;
- }
- function findNativePrototype(left) {
- var natives = [
- "Array", "ArrayBuffer", "Boolean", "Collator", "DataView", "Date",
- "DateTimeFormat", "Error", "EvalError", "Float32Array", "Float64Array",
- "Function", "Infinity", "Intl", "Int16Array", "Int32Array", "Int8Array",
- "Iterator", "Number", "NumberFormat", "Object", "RangeError",
- "ReferenceError", "RegExp", "StopIteration", "String", "SyntaxError",
- "TypeError", "Uint16Array", "Uint32Array", "Uint8Array", "Uint8ClampedArray",
- "URIError"
- ];
- function walkPrototype(obj) {
- if (typeof obj !== "object") return;
- return obj.right === "prototype" ? obj : walkPrototype(obj.left);
- }
- function walkNative(obj) {
- while (!obj.identifier && typeof obj.left === "object")
- obj = obj.left;
- if (obj.identifier && natives.indexOf(obj.value) >= 0)
- return obj.value;
- }
- var prototype = walkPrototype(left);
- if (prototype) return walkNative(prototype);
- }
- function assignop(s, f, p) {
- var x = infix(s, typeof f === "function" ? f : function(left, that) {
- that.left = left;
- if (left) {
- if (state.option.freeze) {
- var nativeObject = findNativePrototype(left);
- if (nativeObject)
- warning("W121", left, nativeObject);
- }
- if (predefined[left.value] === false &&
- scope[left.value]["(global)"] === true) {
- warning("W020", left);
- } else if (left["function"]) {
- warning("W021", left, left.value);
- }
- if (state.funct["(blockscope)"].labeltype(left.value) === "const") {
- error("E013", left, left.value);
- }
- if (left.id === ".") {
- if (!left.left) {
- warning("E031", that);
- } else if (left.left.value === "arguments" && !state.isStrict()) {
- warning("E031", that);
- }
- state.nameStack.set(state.tokens.prev);
- 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 (t && state.funct[t.value] === "const") {
- error("E013", t, t.value);
- }
- });
- } else if (!left.left) {
- warning("E031", that);
- } else if (left.left.value === "arguments" && !state.isStrict()) {
- warning("E031", that);
- }
- state.nameStack.set(left.right);
- that.right = expression(10);
- return that;
- } else if (left.identifier && !isReserved(left)) {
- if (state.funct[left.value] === "exception") {
- warning("W022", left);
- }
- state.nameStack.set(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);
- }
- 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) {
- // this = suffix e.g. "++" punctuator
- // left = symbol operated e.g. "a" identifier or "a.b" punctuator
- if (state.option.plusplus) {
- warning("W016", this, this.id);
- } else if ((!left.identifier || isReserved(left)) && left.id !== "." && left.id !== "[") {
- warning("W017", this);
- }
- // detect increment/decrement of a const
- // in the case of a.b, left will be the "." punctuator
- if (left && left.identifier) {
- if (state.funct["(blockscope)"].labeltype(left.value) === "const") {
- error("E013", this, left.value);
- }
- }
- 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, preserve) {
- if (!state.tokens.next.identifier) {
- return;
- }
- if (!preserve) {
- advance();
- }
- var curr = state.tokens.curr;
- var val = state.tokens.curr.value;
- if (!isReserved(curr)) {
- return val;
- }
- if (prop) {
- if (state.inES5()) {
- return val;
- }
- }
- if (fnparam && val === "undefined") {
- return val;
- }
- 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, false);
- if (i) {
- return i;
- }
- // parameter destructuring with rest operator
- if (state.tokens.next.value === "...") {
- if (!state.option.esnext) {
- warning("W119", state.tokens.next, "spread/rest operator");
- }
- advance();
- if (checkPunctuators(state.tokens.next, ["..."])) {
- warning("E024", state.tokens.next, "...");
- while (checkPunctuators(state.tokens.next, ["..."])) {
- advance();
- }
- }
- if (!state.tokens.next.identifier) {
- warning("E024", state.tokens.curr, "...");
- return;
- }
- return identifier(fnparam, prop);
- } else {
- error("E030", state.tokens.next, state.tokens.next.value);
- // The token should be consumed after a warning is issued so the parser
- // can continue as though an identifier were found. The semicolon token
- // should not be consumed in this way so that the parser interprets it as
- // a statement delimeter;
- if (state.tokens.next.id !== ";") {
- advance();
- }
- }
- }
- function reachable(controlToken) {
- var i = 0, t;
- if (state.tokens.next.id !== ";" || controlToken.inBracelessBlock) {
- return;
- }
- for (;;) {
- do {
- t = peek(i);
- i += 1;
- } while (t.id !== "(end)" && t.id === "(comment)");
- if (t.reach) {
- return;
- }
- if (t.id !== "(endline)") {
- if (t.id === "function") {
- if (state.option.latedef === true) {
- warning("W026", t);
- }
- break;
- }
- warning("W027", t, t.value, controlToken.value);
- break;
- }
- }
- }
- function parseFinalSemicolon() {
- if (state.tokens.next.id !== ";") {
- // don't complain about unclosed templates / strings
- if (state.tokens.next.isUnclosed) return advance();
- 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 !== "}" ||
- startLine(state.tokens.next) !== state.tokens.curr.line) {
- warningAt("W033", state.tokens.curr.line, state.tokens.curr.character);
- }
- }
- } else {
- advance(";");
- }
- }
- function statement() {
- 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 module import declaration
- if (t.value === "module" && t.type === "(identifier)") {
- if (peek().type === "(identifier)") {
- if (!state.inESNext()) {
- warning("W119", state.tokens.curr, "module");
- }
- advance("module");
- var name = identifier();
- addlabel(name, { type: "unused", token: state.tokens.curr });
- advance("from");
- advance("(string)");
- parseFinalSemicolon();
- return;
- }
- }
- if (t.identifier && !res && peek().id === ":") {
- advance();
- advance(":");
- scope = Object.create(s);
- addlabel(t.value, { type: "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 === "{") {
- // Is it a switch case block?
- //
- // switch (foo) {
- // case bar: { <= here.
- // ...
- // }
- // }
- var iscase = (state.funct["(verb)"] === "case" && state.tokens.curr.value === ":");
- block(true, true, false, false, iscase);
- return;
- }
- // Parse the statement.
- r = expression(0, true);
- if (r && (!r.identifier || r.value !== "function") && (r.type !== "(punctuator)")) {
- if (!state.isStrict() &&
- state.option.globalstrict &&
- state.option.strict) {
- warning("E007");
- }
- }
- // 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);
- }
- parseFinalSemicolon();
- }
- // Restore the indentation.
- indent = i;
- scope = s;
- return r;
- }
- function statements() {
- 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());
- }
- }
- return a;
- }
- /*
- * read all directives
- * recognizes a simple form of asi, but always
- * warns, if it is used
- */
- function directives() {
- var i, p, pn;
- while (state.tokens.next.id === "(string)") {
- p = peek(0);
- if (p.id === "(endline)") {
- i = 1;
- do {
- pn = peek(i++);
- } while (pn.id === "(endline)");
- if (pn.id === ";") {
- p = pn;
- } else if (pn.value === "[" || pn.value === ".") {
- // string -> [ | . is a valid production
- return;
- } else if (!state.option.asi || pn.value === "(") {
- // string -> ( is not a valid production
- warning("W033", state.tokens.next);
- }
- } else if (p.id === "." || p.id === "[") {
- return;
- } else if (p.id !== ";") {
- warning("W033", p);
- }
- 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(";");
- }
- }
- }
- /*
- * 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
- * isfatarrow - true if its a body of a fat arrow function
- * iscase - true if block is a switch case block
- */
- function block(ordinary, stmt, isfunc, isfatarrow, iscase) {
- var a,
- b = inblock,
- old_indent = indent,
- m,
- s = scope,
- t,
- line,
- d;
- inblock = ordinary;
- if (!ordinary || !state.option.funcscope)
- scope = Object.create(scope);
- t = state.tokens.next;
- var metrics = state.funct["(metrics)"];
- metrics.nestedBlockDepth += 1;
- metrics.verifyMaxNestedBlockDepthPerFunction();
- if (state.tokens.next.id === "{") {
- advance("{");
- // create a new block scope
- state.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 && state.funct["(context)"]["(global)"]) {
- if (!m["use strict"] && !state.isStrict()) {
- warning("E007");
- }
- }
- }
- a = statements();
- metrics.statementCount += a.length;
- if (isfunc) {
- state.directive = m;
- }
- indent -= state.option.indent;
- }
- advance("}", t);
- state.funct["(blockscope)"].unstack();
- indent = old_indent;
- } else if (!ordinary) {
- if (isfunc) {
- m = {};
- if (stmt && !isfatarrow && !state.inMoz()) {
- 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 && state.funct["(context)"]["(global)"]) {
- if (!m["use strict"] && !state.isStrict()) {
- warning("E007");
- }
- }
- } else {
- error("E021", state.tokens.next, "{", state.tokens.next.value);
- }
- } else {
- // check to avoid let declaration not within a block
- state.funct["(noblockscopedvar)"] = true;
- if (!stmt || state.option.curly) {
- warning("W116", state.tokens.next, "{", state.tokens.next.value);
- }
- state.tokens.next.inBracelessBlock = true;
- indent += state.option.indent;
- // test indentation only if statement is in new line
- a = [statement()];
- indent -= state.option.indent;
- delete state.funct["(noblockscopedvar)"];
- }
- // Don't clear and let it propagate out if it is "break", "return" or similar in switch case
- switch (state.funct["(verb)"]) {
- case "break":
- case "continue":
- case "return":
- case "throw":
- if (iscase) {
- break;
- }
- /* falls through */
- default:
- state.funct["(verb)"] = null;
- }
- if (!ordinary || !state.option.funcscope) scope = s;
- inblock = b;
- if (ordinary && state.option.noempty && (!a || a.length === 0)) {
- warning("W035", state.tokens.prev);
- }
- 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;
- var desc = Object.getOwnPropertyDescriptor(implied, name);
- if (!desc)
- implied[name] = [tkn.line];
- else
- desc.value.push(tkn.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 will be either the function object 'state.funct' that the identifier points at
- // or it will be a boolean if it is a predefined variable
- var s = scope[v];
- var f;
- var block;
- // If this identifier is the lone parameter to a shorthand "fat arrow"
- // function definition, i.e.
- //
- // x => x;
- //
- // ...it should not be considered as a variable in the current scope. It
- // will be added to the scope of the new function when the next token is
- // parsed, so it can be safely ignored for now.
- if (state.tokens.next.id === "=>") {
- return this;
- }
- block = state.funct["(blockscope)"].getlabel(v);
- if (typeof s === "function") {
- // Protection against accidental inheritance.
- s = undefined;
- } else if (!block && typeof s === "boolean") {
- f = state.funct;
- state.funct = functions[0];
- addlabel(v, { type: "var" });
- s = state.funct;
- state.funct = f;
- }
- // The name is in scope and defined in the current function or it exists in the blockscope.
- if (state.funct === s || block) {
- // Change 'unused' to 'var', and reject labels.
- // the name is in a block scope.
- switch (block ? block[v]["(type)"] : state.funct[v]) {
- case "unused":
- if (block) block[v]["(type)"] = "var";
- else state.funct[v] = "var";
- break;
- case "unction":
- if (block) block[v]["(type)"] = "function";
- else state.funct[v] = "function";
- this["function"] = true;
- break;
- case "const":
- // consts can only exist inside block
- // because they are never added to the scope, s
- block[v]["(unused)"] = false;
- break;
- case "function":
- this["function"] = true;
- break;
- case "label":
- warning("W037", state.tokens.curr, v);
- break;
- }
- } else {
- // If the name is already defined in the current
- // function, but not as outer, then there is a scope error.
- switch (state.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) {
- state.funct[v] = true;
- } else if (s === null) {
- warning("W039", state.tokens.curr, v);
- note_implied(state.tokens.curr);
- } else if (typeof s !== "object") {
- // 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 (!state.funct["(comparray)"].check(v)) {
- isundef(state.funct, "W117", state.tokens.curr, v);
- }
- // Explicitly mark the variable as used within function scopes
- if (!state.funct["(global)"]) {
- state.funct[v] = true;
- }
- note_implied(state.tokens.curr);
- } else {
- switch (s[v]) {
- case "function":
- case "unction":
- this["function"] = true;
- s[v] = "closure";
- state.funct[v] = s["(global)"] ? "global" : "outer";
- break;
- case "var":
- case "unused":
- s[v] = "closure";
- state.funct[v] = s["(global)"] ? "global" : "outer";
- break;
- case "closure":
- state.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);
- }
- };
- var baseTemplateSyntax = {
- lbp: 0,
- identifier: false,
- template: true,
- };
- state.syntax["(template)"] = _.extend({
- type: "(template)",
- nud: doTemplateLiteral,
- led: doTemplateLiteral,
- noSubst: false
- }, baseTemplateSyntax);
- state.syntax["(template middle)"] = _.extend({
- type: "(template middle)",
- middle: true,
- noSubst: false
- }, baseTemplateSyntax);
- state.syntax["(template tail)"] = _.extend({
- type: "(template tail)",
- tail: true,
- noSubst: false
- }, baseTemplateSyntax);
- state.syntax["(no subst template)"] = _.extend({
- type: "(template)",
- nud: doTemplateLiteral,
- led: doTemplateLiteral,
- noSubst: true,
- tail: true // mark as tail, since it's always the last component
- }, baseTemplateSyntax);
- 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.isStrict() && state.funct["(global)"]) {
- warning("E008", x);
- }
- });
- reservevar("eval");
- reservevar("false");
- reservevar("Infinity");
- reservevar("null");
- reservevar("this", function(x) {
- if (state.isStrict() && !isMethod() &&
- !state.option.validthis && ((state.funct["(statement)"] &&
- state.funct["(name)"].charAt(0) > "Z") || state.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("&=");
- bitwiseassignop("|=");
- bitwiseassignop("^=");
- bitwiseassignop("<<=");
- bitwiseassignop(">>=");
- bitwiseassignop(">>>=");
- infix(",", function(left, that) {
- var expr;
- that.exprs = [left];
- if (state.option.nocomma) {
- warning("W127");
- }
- 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");
- switch (true) {
- case !eqnull && state.option.eqeqeq:
- this.from = this.character;
- warning("W116", this, "===", "==");
- break;
- case isPoorRelation(left):
- warning("W041", this, "===", left.value);
- break;
- case isPoorRelation(right):
- warning("W041", this, "===", right.value);
- break;
- case isTypoTypeof(right, left, state):
- warning("W122", this, right.value);
- break;
- case isTypoTypeof(left, right, state):
- warning("W122", this, left.value);
- break;
- }
- return this;
- });
- relation("===", function(left, right) {
- if (isTypoTypeof(right, left, state)) {
- warning("W122", this, right.value);
- } else if (isTypoTypeof(left, right, state)) {
- warning("W122", this, left.value);
- }
- return this;
- });
- relation("!=", function(left, right) {
- var eqnull = state.option.eqnull &&
- (left.value === "null" || right.value === "null");
- if (!eqnull && state.option.eqeqeq) {
- this.from = this.character;
- warning("W116", this, "!==", "!=");
- } else if (isPoorRelation(left)) {
- warning("W041", this, "!==", left.value);
- } else if (isPoorRelation(right)) {
- warning("W041", this, "!==", right.value);
- } else if (isTypoTypeof(right, left, state)) {
- warning("W122", this, right.value);
- } else if (isTypoTypeof(left, right, state)) {
- warning("W122", this, left.value);
- }
- return this;
- });
- relation("!==", function(left, right) {
- if (isTypoTypeof(right, left, state)) {
- warning("W122", this, right.value);
- } else if (isTypoTypeof(left, right, state)) {
- warning("W122", this, left.value);
- }
- return this;
- });
- 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;
- that.left = left;
- that.right = 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;
- }
- return that;
- }, 130);
- prefix("+", "num");
- prefix("+++", function() {
- warning("W007");
- this.arity = "unary";
- this.right = expression(150);
- 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.arity = "unary";
- this.right = expression(150);
- 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("++");
- prefix("++", "preinc");
- state.syntax["++"].exps = true;
- suffix("--");
- prefix("--", "predec");
- state.syntax["--"].exps = true;
- prefix("delete", function() {
- var p = expression(10);
- if (!p) {
- return this;
- }
- if (p.id !== "." && p.id !== "[") {
- warning("W051");
- }
- this.first = p;
- // The `delete` operator accepts unresolvable references when not in strict
- // mode, so the operand may be undefined.
- if (p.identifier && !state.isStrict()) {
- p.forgiveUndef = true;
- }
- return this;
- }).exps = true;
- prefix("~", function() {
- if (state.option.bitwise) {
- warning("W016", this, "~");
- }
- this.arity = "unary";
- expression(150);
- return this;
- });
- prefix("...", function() {
- if (!state.option.esnext) {
- warning("W119", this, "spread/rest operator");
- }
- // TODO: Allow all AssignmentExpression
- // once parsing permits.
- //
- // How to handle eg. number, boolean when the built-in
- // prototype of may have an @@iterator definition?
- //
- // Number.prototype[Symbol.iterator] = function * () {
- // yield this.valueOf();
- // };
- //
- // var a = [ ...1 ];
- // console.log(a); // [1];
- //
- // for (let n of [...10]) {
- // console.log(n);
- // }
- // // 10
- //
- //
- // Boolean.prototype[Symbol.iterator] = function * () {
- // yield this.valueOf();
- // };
- //
- // var a = [ ...true ];
- // console.log(a); // [true];
- //
- // for (let n of [...false]) {
- // console.log(n);
- // }
- // // false
- //
- if (!state.tokens.next.identifier &&
- state.tokens.next.type !== "(string)" &&
- !checkPunctuators(state.tokens.next, ["[", "("])) {
- error("E030", state.tokens.next, state.tokens.next.value);
- }
- expression(150);
- return this;
- });
- prefix("!", function() {
- this.arity = "unary";
- this.right = expression(150);
- 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", (function() {
- var p = expression(150);
- this.first = p;
- // The `typeof` operator accepts unresolvable references, so the operand
- // may be undefined.
- if (p.identifier) {
- p.forgiveUndef = true;
- }
- return this;
- }));
- 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 "Symbol":
- if (state.option.esnext) {
- warning("W053", state.tokens.prev, c.value);
- }
- break;
- case "Function":
- if (!state.option.evil) {
- warning("W054");
- }
- break;
- case "Date":
- case "RegExp":
- case "this":
- 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);
- }
- 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) {
- 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.isStrict())
- 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")) {
- if (isGlobalEval(left, state)) {
- warning("W061");
- }
- }
- return that;
- }, 160, true);
- infix("(", function(left, that) {
- 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 Error Symbol".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(")");
- if (typeof left === "object") {
- if (state.inES3() && 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 !== "?" && !(state.option.esnext && left["(name)"])) {
- warning("W067", that);
- }
- }
- that.left = left;
- return that;
- }, 155, true).exps = true;
- prefix("(", function() {
- var pn = state.tokens.next, pn1, i = -1;
- var ret, triggerFnExpr, first, last;
- var parens = 1;
- var opening = state.tokens.curr;
- var preceeding = state.tokens.prev;
- var isNecessary = !state.option.singleGroups;
- do {
- if (pn.value === "(") {
- parens += 1;
- } else if (pn.value === ")") {
- parens -= 1;
- }
- i += 1;
- pn1 = pn;
- pn = peek(i);
- } while (!(parens === 0 && pn1.value === ")") && pn.value !== ";" && pn.type !== "(end)");
- if (state.tokens.next.id === "function") {
- triggerFnExpr = state.tokens.next.immed = true;
- }
- // If the balanced grouping operator is followed by a "fat arrow", the
- // current token marks the beginning of a "fat arrow" function and parsing
- // should proceed accordingly.
- if (pn.value === "=>") {
- return doFunction({ type: "arrow", parsedOpening: true });
- }
- var exprs = [];
- if (state.tokens.next.id !== ")") {
- for (;;) {
- exprs.push(expression(10));
- if (state.tokens.next.id !== ",") {
- break;
- }
- if (state.option.nocomma) {
- warning("W127");
- }
- comma();
- }
- }
- advance(")", this);
- if (state.option.immed && exprs[0] && exprs[0].id === "function") {
- if (state.tokens.next.id !== "(" &&
- state.tokens.next.id !== "." && state.tokens.next.id !== "[") {
- warning("W068", this);
- }
- }
- if (!exprs.length) {
- return;
- }
- if (exprs.length > 1) {
- ret = Object.create(state.syntax[","]);
- ret.exprs = exprs;
- first = exprs[0];
- last = exprs[exprs.length - 1];
- if (!isNecessary) {
- isNecessary = preceeding.assign || preceeding.delim;
- }
- } else {
- ret = first = last = exprs[0];
- if (!isNecessary) {
- isNecessary =
- // Used to distinguish from an ExpressionStatement which may not
- // begin with the `{` and `function` tokens
- (opening.beginsStmt && (ret.id === "{" || triggerFnExpr || isFunctor(ret))) ||
- // Used to signal that a function expression is being supplied to
- // some other operator.
- (triggerFnExpr &&
- // For parenthesis wrapping a function expression to be considered
- // necessary, the grouping operator should be the left-hand-side of
- // some other operator--either within the parenthesis or directly
- // following them.
- (!isEndOfExpr() || state.tokens.prev.id !== "}")) ||
- // Used to demarcate an arrow function as the left-hand side of some
- // operator.
- (isFunctor(ret) && !isEndOfExpr()) ||
- // Used as the return value of a single-statement arrow function
- (ret.id === "{" && preceeding.id === "=>");
- }
- }
- if (ret) {
- // The operator may be necessary to override the default binding power of
- // neighboring operators (whenever there is an operator in use within the
- // first expression *or* the current group contains multiple expressions)
- if (!isNecessary && (first.left || ret.exprs)) {
- isNecessary =
- (!isBeginOfExpr(preceeding) && first.lbp <= preceeding.lbp) ||
- (!isEndOfExpr() && last.lbp < state.tokens.next.lbp);
- }
- if (!isNecessary) {
- warning("W126", opening);
- }
- ret.paren = true;
- }
- return ret;
- });
- application("=>");
- infix("[", function(left, that) {
- var e = expression(10), s;
- if (e && e.type === "(string)") {
- if (!state.option.evil && (e.value === "eval" || e.value === "execScript")) {
- if (isGlobalEval(left, state)) {
- warning("W061");
- }
- }
- 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");
- }
- that.left = left;
- that.right = e;
- return that;
- }, 160, true);
- function comprehensiveArrayExpression() {
- var res = {};
- res.exps = true;
- state.funct["(comparray)"].stack();
- // Handle reversed for expressions, used in spidermonkey
- var reversed = false;
- if (state.tokens.next.value !== "for") {
- reversed = true;
- if (!state.inMoz()) {
- warning("W116", state.tokens.next, "for", state.tokens.next.value);
- }
- state.funct["(comparray)"].setState("use");
- res.right = expression(10);
- }
- advance("for");
- if (state.tokens.next.value === "each") {
- advance("each");
- if (!state.inMoz()) {
- warning("W118", state.tokens.curr, "for each");
- }
- }
- advance("(");
- state.funct["(comparray)"].setState("define");
- res.left = expression(130);
- if (_.contains(["in", "of"], state.tokens.next.value)) {
- advance();
- } else {
- error("E045", state.tokens.curr);
- }
- state.funct["(comparray)"].setState("generate");
- expression(10);
- advance(")");
- if (state.tokens.next.value === "if") {
- advance("if");
- advance("(");
- state.funct["(comparray)"].setState("filter");
- res.filter = expression(10);
- advance(")");
- }
- if (!reversed) {
- state.funct["(comparray)"].setState("use");
- res.right = expression(10);
- }
- advance("]");
- state.funct["(comparray)"].unstack();
- return res;
- }
- prefix("[", function() {
- var blocktype = lookupBlockType();
- if (blocktype.isCompArray) {
- if (!state.inESNext()) {
- warning("W119", state.tokens.curr, "array comprehension");
- }
- return comprehensiveArrayExpression();
- } else if (blocktype.isDestAssign && !state.inESNext()) {
- warning("W104", state.tokens.curr, "destructuring assignment");
- }
- var b = state.tokens.curr.line !== startLine(state.tokens.next);
- 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.elision) {
- if (!state.inES5()) {
- // Maintain compat with old options --- ES5 mode without
- // elision=true will warn once per comma
- warning("W070");
- } else {
- warning("W128");
- do {
- advance(",");
- } while (state.tokens.next.id === ",");
- continue;
- }
- }
- advance(",");
- }
- if (state.tokens.next.id === "]") {
- break;
- }
- this.first.push(expression(10));
- if (state.tokens.next.id === ",") {
- comma({ allowTrailing: true });
- if (state.tokens.next.id === "]" && !state.inES5(true)) {
- warning("W070", state.tokens.curr);
- break;
- }
- } else {
- break;
- }
- }
- if (b) {
- indent -= state.option.indent;
- }
- advance("]", this);
- return this;
- });
- function isMethod() {
- return state.funct["(statement)"] && state.funct["(statement)"].type === "class" ||
- state.funct["(context)"] && state.funct["(context)"]["(verb)"] === "class";
- }
- function isPropertyName(token) {
- return token.identifier || token.id === "(string)" || token.id === "(number)";
- }
- function propertyName(preserveOrToken) {
- var id;
- var preserve = true;
- if (typeof preserveOrToken === "object") {
- id = preserveOrToken;
- } else {
- preserve = preserveOrToken;
- id = optionalidentifier(false, true, preserve);
- }
- if (!id) {
- if (state.tokens.next.id === "(string)") {
- id = state.tokens.next.value;
- if (!preserve) {
- advance();
- }
- } else if (state.tokens.next.id === "(number)") {
- id = state.tokens.next.value.toString();
- if (!preserve) {
- advance();
- }
- }
- } else if (typeof id === "object") {
- if (id.id === "(string)" || id.id === "(identifier)") id = id.value;
- else if (id.id === "(number)") id = id.value.toString();
- }
- if (id === "hasOwnProperty") {
- warning("W001");
- }
- return id;
- }
- /**
- * @param {Object} [options]
- * @param {token} [options.loneArg] The argument to the function in cases
- * where it was defined using the
- * single-argument shorthand.
- * @param {bool} [options.parsedOpening] Whether the opening parenthesis has
- * already been parsed.
- */
- function functionparams(options) {
- var next;
- var params = [];
- var ident;
- var tokens = [];
- var t;
- var pastDefault = false;
- var pastRest = false;
- var loneArg = options && options.loneArg;
- if (loneArg && loneArg.identifier === true) {
- addlabel(loneArg.value, { type: "unused", token: loneArg });
- return [loneArg.value];
- }
- next = state.tokens.next;
- if (!options || !options.parsedOpening) {
- advance("(");
- }
- 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, { type: "unused", token: t.token });
- }
- }
- } else {
- if (checkPunctuators(state.tokens.next, ["..."])) pastRest = true;
- ident = identifier(true);
- if (ident) {
- params.push(ident);
- addlabel(ident, { type: "unused", token: state.tokens.curr });
- } else {
- // Skip invalid parameter.
- while (!checkPunctuators(state.tokens.next, [",", ")"])) advance();
- }
- }
- // 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.inESNext()) {
- warning("W119", state.tokens.next, "default parameters");
- }
- advance("=");
- pastDefault = true;
- expression(10);
- }
- if (state.tokens.next.id === ",") {
- if (pastRest) {
- warning("W131", state.tokens.next);
- }
- comma();
- } else {
- advance(")", next);
- return params;
- }
- }
- }
- function functor(name, token, scope, overwrites) {
- var funct = {
- "(name)" : name,
- "(breakage)" : 0,
- "(loopage)" : 0,
- "(scope)" : scope,
- "(tokens)" : {},
- "(properties)": {},
- "(catch)" : false,
- "(global)" : false,
- "(line)" : null,
- "(character)" : null,
- "(metrics)" : null,
- "(statement)" : null,
- "(context)" : null,
- "(blockscope)": null,
- "(comparray)" : null,
- "(generator)" : null,
- "(params)" : null
- };
- if (token) {
- _.extend(funct, {
- "(line)" : token.line,
- "(character)": token.character,
- "(metrics)" : createMetrics(token)
- });
- }
- _.extend(funct, overwrites);
- if (funct["(context)"]) {
- funct["(blockscope)"] = funct["(context)"]["(blockscope)"];
- funct["(comparray)"] = funct["(context)"]["(comparray)"];
- }
- return funct;
- }
- function isFunctor(token) {
- return "(scope)" in token;
- }
- /**
- * Determine if the parser has begun parsing executable code.
- *
- * @param {Token} funct - The current "functor" token
- *
- * @returns {boolean}
- */
- function hasParsedCode(funct) {
- return funct["(global)"] && !funct["(verb)"];
- }
- function doTemplateLiteral(left) {
- // ASSERT: this.type === "(template)"
- // jshint validthis: true
- var ctx = this.context;
- var noSubst = this.noSubst;
- var depth = this.depth;
- if (!noSubst) {
- while (!end()) {
- if (!state.tokens.next.template || state.tokens.next.depth > depth) {
- expression(0); // should probably have different rbp?
- } else {
- // skip template start / middle
- advance();
- }
- }
- }
- return {
- id: "(template)",
- type: "(template)",
- tag: left
- };
- function end() {
- if (state.tokens.curr.template && state.tokens.curr.tail &&
- state.tokens.curr.context === ctx) return true;
- var complete = (state.tokens.next.template && state.tokens.next.tail &&
- state.tokens.next.context === ctx);
- if (complete) advance();
- return complete || state.tokens.next.isUnclosed;
- }
- }
- /**
- * @param {Object} [options]
- * @param {token} [options.name] The identifier belonging to the function (if
- * any)
- * @param {boolean} [options.statement] The statement that triggered creation
- * of the current function.
- * @param {string} [options.type] If specified, either "generator" or "arrow"
- * @param {token} [options.loneArg] The argument to the function in cases
- * where it was defined using the
- * single-argument shorthand
- * @param {bool} [options.parsedOpening] Whether the opening parenthesis has
- * already been parsed
- * @param {token} [options.classExprBinding] Define a function with this
- * identifier in the new function's
- * scope, mimicking the bahavior of
- * class expression names within
- * the body of member functions.
- */
- function doFunction(options) {
- var f, name, statement, classExprBinding, isGenerator, isArrow;
- var oldOption = state.option;
- var oldIgnored = state.ignored;
- var oldScope = scope;
- if (options) {
- name = options.name;
- statement = options.statement;
- classExprBinding = options.classExprBinding;
- isGenerator = options.type === "generator";
- isArrow = options.type === "arrow";
- }
- state.option = Object.create(state.option);
- state.ignored = Object.create(state.ignored);
- scope = Object.create(scope);
- state.funct = functor(name || state.nameStack.infer(), state.tokens.next, scope, {
- "(statement)": statement,
- "(context)": state.funct,
- "(generator)": isGenerator
- });
- f = state.funct;
- state.tokens.curr.funct = state.funct;
- functions.push(state.funct);
- if (name) {
- addlabel(name, { type: "function" });
- }
- if (classExprBinding) {
- addlabel(classExprBinding, { type: "function" });
- }
- state.funct["(params)"] = functionparams(options);
- state.funct["(metrics)"].verifyMaxParametersPerFunction(state.funct["(params)"]);
- if (isArrow) {
- if (!state.option.esnext) {
- warning("W119", state.tokens.curr, "arrow function syntax (=>)");
- }
- if (!options.loneArg) {
- advance("=>");
- }
- }
- block(false, true, true, isArrow);
- if (!state.option.noyield && isGenerator &&
- state.funct["(generator)"] !== "yielded") {
- warning("W124", state.tokens.curr);
- }
- state.funct["(metrics)"].verifyMaxStatementsPerFunction();
- state.funct["(metrics)"].verifyMaxComplexityPerFunction();
- state.funct["(unusedOption)"] = state.option.unused;
- scope = oldScope;
- state.option = oldOption;
- state.ignored = oldIgnored;
- state.funct["(last)"] = state.tokens.curr.line;
- state.funct["(lastcharacter)"] = state.tokens.curr.character;
- _.map(Object.keys(state.funct), function(key) {
- if (key[0] === "(") return;
- state.funct["(blockscope)"].unshadow(key);
- });
- state.funct = state.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 (_.isNumber(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() {
- state.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");
- }
- }
- }
- /**
- * @param {object} props Collection of property descriptors for a given
- * object.
- */
- function checkProperties(props) {
- // Check for lonely setters if in the ES5 mode.
- if (state.inES5()) {
- for (var name in props) {
- if (_.has(props, name) && props[name].setterToken && !props[name].getterToken) {
- warning("W078", props[name].setterToken);
- }
- }
- }
- }
- (function(x) {
- x.nud = function() {
- var b, f, i, p, t, isGeneratorMethod = false, nextVal;
- var props = {}; // All properties, including accessors
- b = state.tokens.curr.line !== startLine(state.tokens.next);
- 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;
- }
- nextVal = state.tokens.next.value;
- if (state.tokens.next.identifier &&
- (peekIgnoreEOL().id === "," || peekIgnoreEOL().id === "}")) {
- if (!state.inESNext()) {
- warning("W104", state.tokens.next, "object short notation");
- }
- i = propertyName(true);
- saveProperty(props, i, state.tokens.next);
- expression(10);
- } else if (peek().id !== ":" && (nextVal === "get" || nextVal === "set")) {
- advance(nextVal);
- if (!state.inES5()) {
- error("E034");
- }
- i = propertyName();
- // ES6 allows for get() {...} and set() {...} method
- // definition shorthand syntax, so we don't produce an error
- // if the esnext option is enabled.
- if (!i && !state.inESNext()) {
- error("E035");
- }
- // We don't want to save this getter unless it's an actual getter
- // and not an ES6 concise method
- if (i) {
- saveAccessor(nextVal, props, i, state.tokens.curr);
- }
- t = state.tokens.next;
- f = doFunction();
- p = f["(params)"];
- // Don't warn about getter/setter pairs if this is an ES6 concise method
- if (nextVal === "get" && i && p) {
- warning("W076", t, p[0], i);
- } else if (nextVal === "set" && i && (!p || p.length !== 1)) {
- warning("W077", t, i);
- }
- } else {
- if (state.tokens.next.value === "*" && state.tokens.next.type === "(punctuator)") {
- if (!state.inESNext()) {
- warning("W104", state.tokens.next, "generator functions");
- }
- advance("*");
- isGeneratorMethod = true;
- } else {
- isGeneratorMethod = false;
- }
- if (state.tokens.next.id === "[") {
- i = computedPropertyName();
- state.nameStack.set(i);
- } else {
- state.nameStack.set(state.tokens.next);
- i = propertyName();
- saveProperty(props, i, state.tokens.next);
- if (typeof i !== "string") {
- break;
- }
- }
- if (state.tokens.next.value === "(") {
- if (!state.inESNext()) {
- warning("W104", state.tokens.curr, "concise methods");
- }
- doFunction({ type: isGeneratorMethod ? "generator" : null });
- } else {
- advance(":");
- expression(10);
- }
- }
- countMember(i);
- 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.inES5(true)) {
- warning("W070", state.tokens.curr);
- }
- } else {
- break;
- }
- }
- if (b) {
- indent -= state.option.indent;
- }
- advance("}", this);
- checkProperties(props);
- return this;
- };
- x.fud = function() {
- error("E036", state.tokens.curr);
- };
- }(delim("{")));
- function destructuringExpression() {
- var id, ids;
- var identifiers = [];
- if (!state.inESNext()) {
- warning("W104", state.tokens.curr, "destructuring expression");
- }
- var nextInnerDE = function() {
- var ident;
- if (checkPunctuators(state.tokens.next, ["[", "{"])) {
- ids = destructuringExpression();
- for (var id in ids) {
- id = ids[id];
- identifiers.push({ id: id.id, token: id.token });
- }
- } else if (checkPunctuators(state.tokens.next, [","])) {
- identifiers.push({ id: null, token: state.tokens.curr });
- } else if (checkPunctuators(state.tokens.next, ["("])) {
- advance("(");
- nextInnerDE();
- advance(")");
- } else {
- var is_rest = checkPunctuators(state.tokens.next, ["..."]);
- ident = identifier();
- if (ident)
- identifiers.push({ id: ident, token: state.tokens.curr });
- return is_rest;
- }
- return false;
- };
- if (checkPunctuators(state.tokens.next, ["["])) {
- advance("[");
- var element_after_rest = false;
- if (nextInnerDE() && checkPunctuators(state.tokens.next, [","]) &&
- !element_after_rest) {
- warning("W130", state.tokens.next);
- element_after_rest = true;
- }
- while (!checkPunctuators(state.tokens.next, ["]"])) {
- advance(",");
- if (checkPunctuators(state.tokens.next, ["]"])) {
- // Trailing comma
- break;
- }
- if (nextInnerDE() && checkPunctuators(state.tokens.next, [","]) &&
- !element_after_rest) {
- warning("W130", state.tokens.next);
- element_after_rest = true;
- }
- }
- advance("]");
- } else if (checkPunctuators(state.tokens.next, ["{"])) {
- advance("{");
- id = identifier();
- if (checkPunctuators(state.tokens.next, [":"])) {
- advance(":");
- nextInnerDE();
- } else {
- identifiers.push({ id: id, token: state.tokens.curr });
- }
- while (!checkPunctuators(state.tokens.next, ["}"])) {
- advance(",");
- if (checkPunctuators(state.tokens.next, ["}"])) {
- // Trailing comma
- // ObjectBindingPattern: { BindingPropertyList , }
- break;
- }
- id = identifier();
- if (checkPunctuators(state.tokens.next, [":"])) {
- advance(":");
- nextInnerDE();
- } else {
- identifiers.push({ id: id, token: state.tokens.curr });
- }
- }
- advance("}");
- }
- return identifiers;
- }
- function destructuringExpressionMatch(tokens, value) {
- var first = value.first;
- if (!first)
- return;
- _.zip(tokens, Array.isArray(first) ? first : [ 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);
- });
- }
- function blockVariableStatement(type, statement, context) {
- // used for both let and const statements
- var prefix = context && context.prefix;
- var inexport = context && context.inexport;
- var isLet = type === "let";
- var isConst = type === "const";
- var tokens, lone, value, letblock;
- if (!state.inESNext()) {
- warning("W104", state.tokens.curr, type);
- }
- if (isLet && state.tokens.next.value === "(") {
- if (!state.inMoz()) {
- warning("W118", state.tokens.next, "let block");
- }
- advance("(");
- state.funct["(blockscope)"].stack();
- letblock = true;
- } else if (state.funct["(noblockscopedvar)"]) {
- error("E048", state.tokens.curr, isConst ? "Const" : "Let");
- }
- statement.first = [];
- for (;;) {
- var names = [];
- if (_.contains(["{", "["], state.tokens.next.value)) {
- tokens = destructuringExpression();
- lone = false;
- } else {
- tokens = [ { id: identifier(), token: state.tokens.curr } ];
- lone = true;
- if (inexport) {
- exported[state.tokens.curr.value] = true;
- state.tokens.curr.exported = true;
- }
- }
- for (var t in tokens) {
- if (tokens.hasOwnProperty(t)) {
- t = tokens[t];
- if (state.inESNext()) {
- // only look in the latest scope because we can shadow
- if (state.funct["(blockscope)"].current.labeltype(t.id) === "const") {
- warning("E011", null, t.id);
- }
- }
- if (state.funct["(global)"]) {
- if (predefined[t.id] === false) {
- warning("W079", t.token, t.id);
- }
- }
- if (t.id && !state.funct["(noblockscopedvar)"]) {
- addlabel(t.id, {
- type: isConst ? "const" : "unused",
- token: t.token,
- isblockscoped: true });
- names.push(t.token);
- }
- }
- }
- statement.first = statement.first.concat(names);
- if (!prefix && isConst && state.tokens.next.id !== "=") {
- warning("E012", state.tokens.curr, state.tokens.curr.value);
- }
- if (state.tokens.next.id === "=") {
- advance("=");
- if (!prefix && state.tokens.next.id === "undefined") {
- warning("W080", state.tokens.prev, state.tokens.prev.value);
- }
- if (!prefix && peek(0).id === "=" && state.tokens.next.identifier) {
- warning("W120", state.tokens.next, state.tokens.next.value);
- }
- // don't accept `in` in expression if prefix is used for ForIn/Of loop.
- value = expression(prefix ? 120 : 10);
- if (lone) {
- tokens[0].first = value;
- } else {
- destructuringExpressionMatch(names, value);
- }
- }
- if (state.tokens.next.id !== ",") {
- break;
- }
- comma();
- }
- if (letblock) {
- advance(")");
- block(true, true);
- statement.block = true;
- state.funct["(blockscope)"].unstack();
- }
- return statement;
- }
- var conststatement = stmt("const", function(context) {
- return blockVariableStatement("const", this, context);
- });
- conststatement.exps = true;
- var letstatement = stmt("let", function(context) {
- return blockVariableStatement("let", this, context);
- });
- letstatement.exps = true;
- var varstatement = stmt("var", function(context) {
- var prefix = context && context.prefix;
- var inexport = context && context.inexport;
- var tokens, lone, value;
- // If the `implied` option is set, bindings are set differently.
- var implied = context && context.implied;
- var report = !(context && context.ignore);
- this.first = [];
- for (;;) {
- var names = [];
- if (_.contains(["{", "["], state.tokens.next.value)) {
- tokens = destructuringExpression();
- lone = false;
- } else {
- tokens = [ { id: identifier(), token: state.tokens.curr } ];
- lone = true;
- if (inexport) {
- exported[state.tokens.curr.value] = true;
- state.tokens.curr.exported = true;
- }
- }
- for (var t in tokens) {
- if (tokens.hasOwnProperty(t)) {
- t = tokens[t];
- if (state.inESNext()) {
- // because var is function scoped, look in the whole function
- if (state.funct["(blockscope)"].labeltype(t.id) === "const") {
- warning("E011", null, t.id);
- }
- }
- if (!implied && state.funct["(global)"]) {
- if (predefined[t.id] === false) {
- warning("W079", t.token, t.id);
- } else if (state.option.futurehostile === false) {
- if ((!state.inES5() && vars.ecmaIdentifiers[5][t.id] === false) ||
- (!state.inESNext() && vars.ecmaIdentifiers[6][t.id] === false)) {
- warning("W129", t.token, t.id);
- }
- }
- }
- if (t.id) {
- if (implied === "for") {
- var ident = t.token.value;
- switch (state.funct[ident]) {
- case "unused":
- state.funct[ident] = "var";
- break;
- case "var":
- break;
- default:
- if (!state.funct["(blockscope)"].getlabel(ident) &&
- !(scope[ident] || {})[ident]) {
- if (report) warning("W088", t.token, ident);
- }
- }
- } else {
- addlabel(t.id, { type: "unused", token: t.token });
- }
- names.push(t.token);
- }
- }
- }
- if (!prefix && report && state.option.varstmt) {
- warning("W132", this);
- }
- this.first = this.first.concat(names);
- if (state.tokens.next.id === "=") {
- state.nameStack.set(state.tokens.curr);
- advance("=");
- if (!prefix && report && state.tokens.next.id === "undefined") {
- warning("W080", state.tokens.prev, state.tokens.prev.value);
- }
- if (peek(0).id === "=" && state.tokens.next.identifier) {
- if (!prefix && report &&
- !state.funct["(params)"] ||
- state.funct["(params)"].indexOf(state.tokens.next.value) === -1) {
- warning("W120", state.tokens.next, state.tokens.next.value);
- }
- }
- // don't accept `in` in expression if prefix is used for ForIn/Of loop.
- value = expression(prefix ? 120 : 10);
- if (lone) {
- tokens[0].first = value;
- } else {
- destructuringExpressionMatch(names, value);
- }
- }
- if (state.tokens.next.id !== ",") {
- break;
- }
- comma();
- }
- return this;
- });
- varstatement.exps = true;
- blockstmt("class", function() {
- return classdef.call(this, true);
- });
- function classdef(isStatement) {
- /*jshint validthis:true */
- if (!state.inESNext()) {
- warning("W104", state.tokens.curr, "class");
- }
- if (isStatement) {
- // BindingIdentifier
- this.name = identifier();
- addlabel(this.name, { type: "unused", token: state.tokens.curr });
- } else if (state.tokens.next.identifier && state.tokens.next.value !== "extends") {
- // BindingIdentifier(opt)
- this.name = identifier();
- this.namedExpr = true;
- } else {
- this.name = state.nameStack.infer();
- }
- classtail(this);
- return this;
- }
- function classtail(c) {
- var wasInClassBody = state.inClassBody;
- // ClassHeritage(opt)
- if (state.tokens.next.value === "extends") {
- advance("extends");
- c.heritage = expression(10);
- }
- state.inClassBody = true;
- advance("{");
- // ClassBody(opt)
- c.body = classbody(c);
- advance("}");
- state.inClassBody = wasInClassBody;
- }
- function classbody(c) {
- var name;
- var isStatic;
- var isGenerator;
- var getset;
- var props = {};
- var staticProps = {};
- var computed;
- for (var i = 0; state.tokens.next.id !== "}"; ++i) {
- name = state.tokens.next;
- isStatic = false;
- isGenerator = false;
- getset = null;
- // The ES6 grammar for ClassElement includes the `;` token, but it is
- // defined only as a placeholder to facilitate future language
- // extensions. In ES6 code, it serves no purpose.
- if (name.id === ";") {
- warning("W032");
- advance(";");
- continue;
- }
- if (name.id === "*") {
- isGenerator = true;
- advance("*");
- name = state.tokens.next;
- }
- if (name.id === "[") {
- name = computedPropertyName();
- computed = true;
- } else if (isPropertyName(name)) {
- // Non-Computed PropertyName
- advance();
- computed = false;
- if (name.identifier && name.value === "static") {
- if (checkPunctuators(state.tokens.next, ["*"])) {
- isGenerator = true;
- advance("*");
- }
- if (isPropertyName(state.tokens.next) || state.tokens.next.id === "[") {
- computed = state.tokens.next.id === "[";
- isStatic = true;
- name = state.tokens.next;
- if (state.tokens.next.id === "[") {
- name = computedPropertyName();
- } else advance();
- }
- }
- if (name.identifier && (name.value === "get" || name.value === "set")) {
- if (isPropertyName(state.tokens.next) || state.tokens.next.id === "[") {
- computed = state.tokens.next.id === "[";
- getset = name;
- name = state.tokens.next;
- if (state.tokens.next.id === "[") {
- name = computedPropertyName();
- } else advance();
- }
- }
- } else {
- warning("W052", state.tokens.next, state.tokens.next.value || state.tokens.next.type);
- advance();
- continue;
- }
- if (!checkPunctuators(state.tokens.next, ["("])) {
- // error --- class properties must be methods
- error("E054", state.tokens.next, state.tokens.next.value);
- while (state.tokens.next.id !== "}" &&
- !checkPunctuators(state.tokens.next, ["("])) {
- advance();
- }
- if (state.tokens.next.value !== "(") {
- doFunction({ statement: c });
- }
- }
- if (!computed) {
- // We don't know how to determine if we have duplicate computed property names :(
- if (getset) {
- saveAccessor(
- getset.value, isStatic ? staticProps : props, name.value, name, true, isStatic);
- } else {
- if (name.value === "constructor") {
- state.nameStack.set(c);
- } else {
- state.nameStack.set(name);
- }
- saveProperty(isStatic ? staticProps : props, name.value, name, true, isStatic);
- }
- }
- if (getset && name.value === "constructor") {
- var propDesc = getset.value === "get" ? "class getter method" : "class setter method";
- error("E049", name, propDesc, "constructor");
- } else if (name.value === "prototype") {
- error("E049", name, "class method", "prototype");
- }
- propertyName(name);
- doFunction({
- statement: c,
- type: isGenerator ? "generator" : null,
- classExprBinding: c.namedExpr ? c.name : null
- });
- }
- checkProperties(props);
- }
- blockstmt("function", function() {
- var generator = false;
- if (state.tokens.next.value === "*") {
- advance("*");
- if (state.inESNext({ strict: true })) {
- generator = true;
- } else {
- warning("W119", state.tokens.curr, "function*");
- }
- }
- if (inblock) {
- warning("W082", state.tokens.curr);
- }
- var i = optionalidentifier();
- if (i === undefined) {
- warning("W025");
- }
- // check if a identifier with the same name is already defined
- // in the blockscope as a const
- if (state.funct["(blockscope)"].labeltype(i) === "const") {
- warning("E011", null, i);
- }
- addlabel(i, { type: "unction", token: state.tokens.curr });
- doFunction({
- name: i,
- statement: this,
- type: generator ? "generator" : null
- });
- 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.inESNext()) {
- warning("W119", state.tokens.curr, "function*");
- }
- advance("*");
- generator = true;
- }
- var i = optionalidentifier();
- var fn = doFunction({ name: i, type: generator ? "generator" : null });
- function isVariable(name) { return name[0] !== "("; }
- function isLocal(name) { return fn[name] === "var"; }
- if (!state.option.loopfunc && state.funct["(loopage)"]) {
- // If the function we just parsed accesses any non-local variables
- // trigger a warning. Otherwise, the function is safe even within
- // a loop.
- if (_.some(fn, function(val, name) { return isVariable(name) && !isLocal(name); })) {
- warning("W083");
- }
- }
- return this;
- });
- blockstmt("if", function() {
- var t = state.tokens.next;
- increaseComplexityCount();
- state.condition = true;
- advance("(");
- var expr = expression(0);
- checkCondAssignment(expr);
- // When the if is within a for-in loop, check if the condition
- // starts with a negation operator
- var forinifcheck = null;
- if (state.option.forin && state.forinifcheckneeded) {
- state.forinifcheckneeded = false; // We only need to analyze the first if inside the loop
- forinifcheck = state.forinifchecks[state.forinifchecks.length - 1];
- if (expr.type === "(punctuator)" && expr.value === "!") {
- forinifcheck.type = "(negative)";
- } else {
- forinifcheck.type = "(positive)";
- }
- }
- advance(")", t);
- state.condition = false;
- var s = block(true, true);
- // When the if is within a for-in loop and the condition has a negative form,
- // check if the body contains nothing but a continue statement
- if (forinifcheck && forinifcheck.type === "(negative)") {
- if (s && s.length === 1 && s[0].type === "(identifier)" && s[0].value === "continue") {
- forinifcheck.type = "(negative-with-continue)";
- }
- }
- if (state.tokens.next.id === "else") {
- advance("else");
- if (state.tokens.next.id === "if" || state.tokens.next.id === "switch") {
- statement();
- } else {
- block(true, true);
- }
- }
- return this;
- });
- blockstmt("try", function() {
- var b;
- function doCatch() {
- var oldScope = scope;
- var e;
- advance("catch");
- 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();
- state.funct = functor("(catch)", state.tokens.next, scope, {
- "(context)" : state.funct,
- "(breakage)" : state.funct["(breakage)"],
- "(loopage)" : state.funct["(loopage)"],
- "(statement)": false,
- "(catch)" : true
- });
- if (e) {
- addlabel(e, { type: "exception" });
- }
- if (state.tokens.next.value === "if") {
- if (!state.inMoz()) {
- warning("W118", state.tokens.curr, "catch filter");
- }
- advance("if");
- expression(0);
- }
- advance(")");
- state.tokens.curr.funct = state.funct;
- functions.push(state.funct);
- block(false);
- scope = oldScope;
- state.funct["(last)"] = state.tokens.curr.line;
- state.funct["(lastcharacter)"] = state.tokens.curr.character;
- state.funct = state.funct["(context)"];
- }
- block(true);
- while (state.tokens.next.id === "catch") {
- increaseComplexityCount();
- if (b && (!state.inMoz())) {
- warning("W118", state.tokens.next, "multiple catch blocks");
- }
- doCatch();
- b = true;
- }
- if (state.tokens.next.id === "finally") {
- advance("finally");
- block(true);
- return;
- }
- if (!b) {
- error("E021", state.tokens.next, "catch", state.tokens.next.value);
- }
- return this;
- });
- blockstmt("while", function() {
- var t = state.tokens.next;
- state.funct["(breakage)"] += 1;
- state.funct["(loopage)"] += 1;
- increaseComplexityCount();
- advance("(");
- checkCondAssignment(expression(0));
- advance(")", t);
- block(true, true);
- state.funct["(breakage)"] -= 1;
- state.funct["(loopage)"] -= 1;
- return this;
- }).labelled = true;
- blockstmt("with", function() {
- var t = state.tokens.next;
- if (state.isStrict()) {
- error("E010", state.tokens.curr);
- } else if (!state.option.withstmt) {
- warning("W085", state.tokens.curr);
- }
- advance("(");
- expression(0);
- advance(")", t);
- block(true, true);
- return this;
- });
- blockstmt("switch", function() {
- var t = state.tokens.next;
- var g = false;
- var noindent = false;
- state.funct["(breakage)"] += 1;
- advance("(");
- checkCondAssignment(expression(0));
- advance(")", t);
- t = state.tokens.next;
- advance("{");
- if (state.tokens.next.from === indent)
- noindent = true;
- if (!noindent)
- indent += state.option.indent;
- this.cases = [];
- for (;;) {
- switch (state.tokens.next.id) {
- case "case":
- switch (state.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");
- }
- }
- advance("case");
- this.cases.push(expression(0));
- increaseComplexityCount();
- g = true;
- advance(":");
- state.funct["(verb)"] = "case";
- break;
- case "default":
- switch (state.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");
- }
- }
- }
- advance("default");
- g = true;
- advance(":");
- break;
- case "}":
- if (!noindent)
- indent -= state.option.indent;
- advance("}", t);
- state.funct["(breakage)"] -= 1;
- state.funct["(verb)"] = undefined;
- return;
- case "(end)":
- error("E023", state.tokens.next, "}");
- return;
- default:
- indent += state.option.indent;
- 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;
- }
- }
- indent -= state.option.indent;
- }
- }
- }).labelled = true;
- stmt("debugger", function() {
- if (!state.option.debug) {
- warning("W087", this);
- }
- return this;
- }).exps = true;
- (function() {
- var x = stmt("do", function() {
- state.funct["(breakage)"] += 1;
- state.funct["(loopage)"] += 1;
- increaseComplexityCount();
- this.first = block(true, true);
- advance("while");
- var t = state.tokens.next;
- advance("(");
- checkCondAssignment(expression(0));
- advance(")", t);
- state.funct["(breakage)"] -= 1;
- state.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.inMoz()) {
- warning("W118", state.tokens.curr, "for each");
- }
- }
- state.funct["(breakage)"] += 1;
- state.funct["(loopage)"] += 1;
- increaseComplexityCount();
- advance("(");
- // 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"];
- var level = 0; // BindingPattern "level" --- level 0 === no BindingPattern
- var comma; // First comma punctuator at level 0
- var initializer; // First initializer at level 0
- // If initial token is a BindingPattern, count it as such.
- if (checkPunctuators(state.tokens.next, ["{", "["])) ++level;
- do {
- nextop = peek(i);
- ++i;
- if (checkPunctuators(nextop, ["{", "["])) ++level;
- else if (checkPunctuators(nextop, ["}", "]"])) --level;
- if (level < 0) break;
- if (level === 0) {
- if (!comma && checkPunctuators(nextop, [","])) comma = nextop;
- else if (!initializer && checkPunctuators(nextop, ["="])) initializer = nextop;
- }
- } while (level > 0 || !_.contains(inof, nextop.value) && nextop.value !== ";" &&
- nextop.type !== "(end)"); // Is this a JSCS bug? This looks really weird.
- // if we're in a for (… in|of …) statement
- if (_.contains(inof, nextop.value)) {
- if (!state.inESNext() && nextop.value === "of") {
- error("W104", nextop, "for of");
- }
- var ok = !(initializer || comma);
- if (initializer) {
- error("W133", comma, nextop.value, "initializer is forbidden");
- }
- if (comma) {
- error("W133", comma, nextop.value, "more than one ForBinding");
- }
- if (state.tokens.next.id === "var") {
- advance("var");
- state.tokens.curr.fud({ prefix: true });
- } else if (state.tokens.next.id === "let" || state.tokens.next.id === "const") {
- advance(state.tokens.next.id);
- // create a new block scope
- letscope = true;
- state.funct["(blockscope)"].stack();
- state.tokens.curr.fud({ prefix: true });
- } else {
- // Parse as a var statement, with implied bindings. Ignore errors if an error
- // was already reported
- Object.create(varstatement).fud({ prefix: true, implied: "for", ignore: !ok });
- }
- advance(nextop.value);
- expression(20);
- advance(")", t);
- if (nextop.value === "in" && state.option.forin) {
- state.forinifcheckneeded = true;
- if (state.forinifchecks === undefined) {
- state.forinifchecks = [];
- }
- // Push a new for-in-if check onto the stack. The type will be modified
- // when the loop's body is parsed and a suitable if statement exists.
- state.forinifchecks.push({
- type: "(none)"
- });
- }
- s = block(true, true);
- if (nextop.value === "in" && state.option.forin) {
- if (state.forinifchecks && state.forinifchecks.length > 0) {
- var check = state.forinifchecks.pop();
- if (// No if statement or not the first statement in loop body
- s && s.length > 0 && (typeof s[0] !== "object" || s[0].value !== "if") ||
- // Positive if statement is not the only one in loop body
- check.type === "(positive)" && s.length > 1 ||
- // Negative if statement but no continue
- check.type === "(negative)") {
- warning("W089", this);
- }
- }
- // Reset the flag in case no if statement was contained in the loop body
- state.forinifcheckneeded = false;
- }
- state.funct["(breakage)"] -= 1;
- state.funct["(loopage)"] -= 1;
- } else {
- if (foreachtok) {
- error("E045", foreachtok);
- }
- if (state.tokens.next.id !== ";") {
- if (state.tokens.next.id === "var") {
- advance("var");
- state.tokens.curr.fud();
- } else if (state.tokens.next.id === "let") {
- advance("let");
- // create a new block scope
- letscope = true;
- state.funct["(blockscope)"].stack();
- state.tokens.curr.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);
- block(true, true);
- state.funct["(breakage)"] -= 1;
- state.funct["(loopage)"] -= 1;
- }
- // unstack loop blockscope
- if (letscope) {
- state.funct["(blockscope)"].unstack();
- }
- return this;
- }).labelled = true;
- stmt("break", function() {
- var v = state.tokens.next.value;
- if (state.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 === startLine(state.tokens.next)) {
- if (state.funct[v] !== "label") {
- warning("W090", state.tokens.next, v);
- } else if (scope[v] !== state.funct) {
- warning("W091", state.tokens.next, v);
- }
- this.first = state.tokens.next;
- advance();
- }
- }
- reachable(this);
- return this;
- }).exps = true;
- stmt("continue", function() {
- var v = state.tokens.next.value;
- if (state.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 === startLine(state.tokens.next)) {
- if (state.funct[v] !== "label") {
- warning("W090", state.tokens.next, v);
- } else if (scope[v] !== state.funct) {
- warning("W091", state.tokens.next, v);
- }
- this.first = state.tokens.next;
- advance();
- }
- } else if (!state.funct["(loopage)"]) {
- warning("W052", state.tokens.next, this.value);
- }
- reachable(this);
- return this;
- }).exps = true;
- stmt("return", function() {
- if (this.line === startLine(state.tokens.next)) {
- if (state.tokens.next.id !== ";" && !state.tokens.next.reach) {
- this.first = expression(0);
- if (this.first &&
- this.first.type === "(punctuator)" && this.first.value === "=" &&
- !this.first.paren && !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(this);
- return this;
- }).exps = true;
- (function(x) {
- x.exps = true;
- x.lbp = 25;
- }(prefix("yield", function() {
- var prev = state.tokens.prev;
- if (state.inESNext(true) && !state.funct["(generator)"]) {
- // If it's a yield within a catch clause inside a generator then that's ok
- if (!("(catch)" === state.funct["(name)"] && state.funct["(context)"]["(generator)"])) {
- error("E046", state.tokens.curr, "yield");
- }
- } else if (!state.inESNext()) {
- warning("W104", state.tokens.curr, "yield");
- }
- state.funct["(generator)"] = "yielded";
- var delegatingYield = false;
- if (state.tokens.next.value === "*") {
- delegatingYield = true;
- advance("*");
- }
- if (this.line === startLine(state.tokens.next) || !state.inMoz()) {
- if (delegatingYield ||
- (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 === "=" &&
- !this.first.paren && !state.option.boss) {
- warningAt("W093", this.first.line, this.first.character);
- }
- }
- if (state.inMoz() && 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);
- this.first = expression(20);
- reachable(this);
- return this;
- }).exps = true;
- stmt("import", function() {
- if (!state.inESNext()) {
- warning("W119", state.tokens.curr, "import");
- }
- if (state.tokens.next.type === "(string)") {
- // ModuleSpecifier :: StringLiteral
- advance("(string)");
- return this;
- }
- if (state.tokens.next.identifier) {
- // ImportClause :: ImportedDefaultBinding
- this.name = identifier();
- addlabel(this.name, { type: "unused", token: state.tokens.curr });
- if (state.tokens.next.value === ",") {
- // ImportClause :: ImportedDefaultBinding , NameSpaceImport
- // ImportClause :: ImportedDefaultBinding , NamedImports
- advance(",");
- // At this point, we intentionally fall through to continue matching
- // either NameSpaceImport or NamedImports.
- // Discussion:
- // https://github.com/jshint/jshint/pull/2144#discussion_r23978406
- } else {
- advance("from");
- advance("(string)");
- return this;
- }
- }
- if (state.tokens.next.id === "*") {
- // ImportClause :: NameSpaceImport
- advance("*");
- advance("as");
- if (state.tokens.next.identifier) {
- this.name = identifier();
- addlabel(this.name, { type: "unused", token: state.tokens.curr });
- }
- } else {
- // ImportClause :: NamedImports
- advance("{");
- for (;;) {
- if (state.tokens.next.value === "}") {
- advance("}");
- break;
- }
- 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, { type: "unused", token: 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;
- }
- }
- }
- // FromClause
- advance("from");
- advance("(string)");
- return this;
- }).exps = true;
- stmt("export", function() {
- var ok = true;
- var token;
- var identifier;
- if (!state.inESNext()) {
- warning("W119", state.tokens.curr, "export");
- ok = false;
- }
- if (!state.funct["(global)"] || !state.funct["(blockscope)"].atTop()) {
- error("E053", state.tokens.curr);
- ok = false;
- }
- if (state.tokens.next.value === "*") {
- // ExportDeclaration :: export * FromClause
- advance("*");
- advance("from");
- advance("(string)");
- return this;
- }
- if (state.tokens.next.type === "default") {
- // ExportDeclaration :: export default HoistableDeclaration
- // ExportDeclaration :: export default ClassDeclaration
- state.nameStack.set(state.tokens.next);
- advance("default");
- if (state.tokens.next.id === "function" || state.tokens.next.id === "class") {
- this.block = true;
- }
- token = peek();
- expression(10);
- if (state.tokens.next.id === "class") {
- identifier = token.name;
- } else {
- identifier = token.value;
- }
- addlabel(identifier, {
- type: "function", token: token
- });
- return this;
- }
- if (state.tokens.next.value === "{") {
- // ExportDeclaration :: export ExportClause
- advance("{");
- var exportedTokens = [];
- for (;;) {
- if (!state.tokens.next.identifier) {
- error("E030", state.tokens.next, state.tokens.next.value);
- }
- advance();
- state.tokens.curr.exported = ok;
- exportedTokens.push(state.tokens.curr);
- if (state.tokens.next.value === "as") {
- advance("as");
- if (!state.tokens.next.identifier) {
- error("E030", state.tokens.next, state.tokens.next.value);
- }
- advance();
- }
- 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;
- }
- }
- if (state.tokens.next.value === "from") {
- // ExportDeclaration :: export ExportClause FromClause
- advance("from");
- advance("(string)");
- } else if (ok) {
- exportedTokens.forEach(function(token) {
- if (!state.funct[token.value]) {
- isundef(state.funct, "W117", token, token.value);
- }
- exported[token.value] = true;
- state.funct["(blockscope)"].setExported(token.value);
- });
- }
- return this;
- }
- if (state.tokens.next.id === "var") {
- // ExportDeclaration :: export VariableStatement
- advance("var");
- state.tokens.curr.fud({ inexport:true });
- } else if (state.tokens.next.id === "let") {
- // ExportDeclaration :: export VariableStatement
- advance("let");
- state.tokens.curr.fud({ inexport:true });
- } else if (state.tokens.next.id === "const") {
- // ExportDeclaration :: export VariableStatement
- advance("const");
- state.tokens.curr.fud({ inexport:true });
- } else if (state.tokens.next.id === "function") {
- // ExportDeclaration :: export Declaration
- this.block = true;
- advance("function");
- exported[state.tokens.next.value] = ok;
- state.tokens.next.exported = true;
- state.syntax["function"].fud();
- } else if (state.tokens.next.id === "class") {
- // ExportDeclaration :: export Declaration
- this.block = true;
- advance("class");
- exported[state.tokens.next.value] = ok;
- state.tokens.next.exported = true;
- 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("transient");
- FutureReservedWord("volatile");
- // this function is used to determine whether a squarebracket or a curlybracket
- // expression is a comprehension array, destructuring assignment or a json value.
- var lookupBlockType = function() {
- var pn, pn1;
- var i = -1;
- var bracketStack = 0;
- var ret = {};
- if (checkPunctuators(state.tokens.curr, ["[", "{"]))
- bracketStack += 1;
- do {
- pn = (i === -1) ? state.tokens.next : peek(i);
- pn1 = peek(i + 1);
- i = i + 1;
- if (checkPunctuators(pn, ["[", "{"])) {
- bracketStack += 1;
- } else if (checkPunctuators(pn, ["]", "}"])) {
- bracketStack -= 1;
- }
- if (pn.identifier && pn.value === "for" && bracketStack === 1) {
- ret.isCompArray = true;
- ret.notJson = true;
- break;
- }
- if (checkPunctuators(pn, ["}", "]"]) && bracketStack === 0) {
- if (pn1.value === "=") {
- ret.isDestAssign = true;
- ret.notJson = true;
- break;
- } else if (pn1.value === ".") {
- ret.notJson = true;
- break;
- }
- }
- if (pn.value === ";") {
- ret.isBlock = true;
- ret.notJson = true;
- }
- } while (bracketStack > 0 && pn.id !== "(end)");
- return ret;
- };
- function saveProperty(props, name, tkn, isClass, isStatic) {
- var msg = ["key", "class method", "static class method"];
- msg = msg[(isClass || false) + (isStatic || false)];
- if (tkn.identifier) {
- name = tkn.value;
- }
- if (props[name] && _.has(props, name)) {
- warning("W075", state.tokens.next, msg, name);
- } else {
- props[name] = {};
- }
- props[name].basic = true;
- props[name].basictkn = tkn;
- }
- /**
- * @param {string} accessorType - Either "get" or "set"
- * @param {object} props - a collection of all properties of the object to
- * which the current accessor is being assigned
- * @param {object} tkn - the identifier token representing the accessor name
- * @param {boolean} isClass - whether the accessor is part of an ES6 Class
- * definition
- * @param {boolean} isStatic - whether the accessor is a static method
- */
- function saveAccessor(accessorType, props, name, tkn, isClass, isStatic) {
- var flagName = accessorType === "get" ? "getterToken" : "setterToken";
- var msg = "";
- if (isClass) {
- if (isStatic) {
- msg += "static ";
- }
- msg += accessorType + "ter method";
- } else {
- msg = "key";
- }
- state.tokens.curr.accessorType = accessorType;
- state.nameStack.set(tkn);
- if (props[name] && _.has(props, name)) {
- if (props[name].basic || props[name][flagName]) {
- warning("W075", state.tokens.next, msg, name);
- }
- } else {
- props[name] = {};
- }
- props[name][flagName] = tkn;
- }
- function computedPropertyName() {
- advance("[");
- if (!state.option.esnext) {
- warning("W119", state.tokens.curr, "computed property names");
- }
- var value = expression(10);
- advance("]");
- return value;
- }
- // Test whether a given token is a punctuator matching one of the specified values
- function checkPunctuators(token, values) {
- return token.type === "(punctuator)" && _.contains(values, token.value);
- }
- // 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.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.raw_text || v.value);
- if (v.undef)
- isundef(v.state.funct, "W117", v.token, v.value);
- });
- _carrays.splice(-1, 1);
- _current = _carrays[_carrays.length - 1];
- },
- setState: function(s) {
- if (_.contains(["use", "define", "generate", "filter"], s))
- _current.mode = s;
- },
- check: function(v) {
- if (!_current) {
- return;
- }
- // When we are in "use" state of the list comp, we enqueue that var
- if (_current && _current.mode === "use") {
- if (use(v)) {
- _current.variables.push({
- funct: state.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: state.funct,
- token: state.tokens.curr,
- value: v,
- undef: false,
- unused: true
- });
- }
- return true;
- // When we are in the "generate" state of the list comp,
- } else if (_current && _current.mode === "generate") {
- isundef(state.funct, "W117", state.tokens.curr, v);
- 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(state.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, "key", 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("-");
- advance("(number)");
- break;
- default:
- error("E003", state.tokens.next);
- }
- }
- var warnUnused = function(name, tkn, type, unused_opt) {
- var line = tkn.line;
- var chr = tkn.from;
- var raw_name = tkn.raw_text || name;
- 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) {
- if (!tkn.exported) {
- warningAt("W098", line, chr, raw_name);
- }
- }
- }
- unuseds.push({
- name: name,
- line: line,
- character: chr
- });
- };
- var blockScope = function() {
- var _current = {};
- var _variables = [_current];
- function _checkBlockLabels() {
- for (var t in _current) {
- var label = _current[t],
- labelType = label["(type)"];
- if (labelType === "unused" || (labelType === "const" && label["(unused)"])) {
- if (state.option.unused) {
- var tkn = _current[t]["(token)"];
- // Don't report exported labels as unused
- if (tkn.exported) {
- continue;
- }
- warnUnused(t, tkn, "var");
- }
- }
- }
- }
- function _getLabel(l) {
- for (var i = _variables.length - 1 ; i >= 0; --i) {
- if (_.has(_variables[i], l) && !_variables[i][l]["(shadowed)"]) {
- return _variables[i];
- }
- }
- }
- return {
- stack: function() {
- _current = {};
- _variables.push(_current);
- },
- unstack: function() {
- _checkBlockLabels();
- _variables.splice(_variables.length - 1, 1);
- _current = _.last(_variables);
- },
- getlabel: _getLabel,
- labeltype: function(l) {
- // returns a labels type or null if not present
- var block = _getLabel(l);
- if (block) {
- return block[l]["(type)"];
- }
- return null;
- },
- shadow: function(name) {
- for (var i = _variables.length - 1; i >= 0; i--) {
- if (_.has(_variables[i], name)) {
- _variables[i][name]["(shadowed)"] = true;
- }
- }
- },
- unshadow: function(name) {
- for (var i = _variables.length - 1; i >= 0; i--) {
- if (_.has(_variables[i], name)) {
- _variables[i][name]["(shadowed)"] = false;
- }
- }
- },
- atTop: function() {
- return _variables.length === 1;
- },
- setExported: function(id) {
- if (state.funct["(blockscope)"].atTop()) {
- var item = _current[id];
- if (item && item["(token)"]) {
- item["(token)"].exported = true;
- }
- }
- },
- current: {
- labeltype: function(t) {
- if (_current[t]) {
- return _current[t]["(type)"];
- }
- return null;
- },
- has: function(t) {
- return _.has(_current, t);
- },
- add: function(t, type, tok) {
- _current[t] = { "(type)" : type, "(token)": tok, "(shadowed)": false, "(unused)": true };
- }
- }
- };
- };
- var escapeRegex = function(str) {
- return str.replace(/[-\/\\^$*+?.()|[\]{}]/g, "\\$&");
- };
- // The actual JSHINT function itself.
- var itself = function(s, o, g) {
- var i, k, x, reIgnoreStr, reIgnore;
- var optionKeys;
- var newOptionObj = {};
- var newIgnoredObj = {};
- o = _.clone(o);
- 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[3]);
- 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;
- // remove from predefined if there
- delete predefined[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 {
- var optionKey = optionKeys[x];
- newOptionObj[optionKey] = o[optionKey];
- if (optionKey === "es5") {
- if (o[optionKey]) {
- warning("I003");
- }
- }
- if (optionKeys[x] === "newcap" && o[optionKey] === false)
- newOptionObj["(explicitNewcap)"] = 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;
- state.funct = functor("(global)", null, scope, {
- "(global)" : true,
- "(blockscope)": blockScope(),
- "(comparray)" : arrayComprehension(),
- "(metrics)" : createMetrics(state.tokens.next)
- });
- functions = [state.funct];
- urls = [];
- stack = null;
- member = {};
- membersOnly = null;
- implied = {};
- inblock = false;
- lookahead = [];
- 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)"];
- if (o && o.ignoreDelimiters) {
- if (!Array.isArray(o.ignoreDelimiters)) {
- o.ignoreDelimiters = [o.ignoreDelimiters];
- }
- o.ignoreDelimiters.forEach(function(delimiterPair) {
- if (!delimiterPair.start || !delimiterPair.end)
- return;
- reIgnoreStr = escapeRegex(delimiterPair.start) +
- "[\\s\\S]*?" +
- escapeRegex(delimiterPair.end);
- reIgnore = new RegExp(reIgnoreStr, "ig");
- s = s.replace(reIgnore, function(match) {
- return match.replace(/./g, " ");
- });
- });
- }
- 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.isStrict()) {
- if (!state.option.globalstrict) {
- if (!(state.option.module || state.option.node || state.option.phantom ||
- state.option.browserify)) {
- warning("W097", state.tokens.prev);
- }
- }
- }
- statements();
- }
- if (state.tokens.next.id !== "(end)") {
- quit("E041", state.tokens.curr.line);
- }
- state.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 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]) || k[2].forgiveUndef) {
- 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) && !_.has(exported, 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)"];
- fu.metrics = {
- complexity: f["(metrics)"].ComplexityCount,
- parameters: (f["(params)"] || []).length,
- statements: f["(metrics)"].statementCount
- };
- 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;
- }
- },{"./lex.js":"/node_modules/jshint/src/lex.js","./messages.js":"/node_modules/jshint/src/messages.js","./options.js":"/node_modules/jshint/src/options.js","./reg.js":"/node_modules/jshint/src/reg.js","./state.js":"/node_modules/jshint/src/state.js","./style.js":"/node_modules/jshint/src/style.js","./vars.js":"/node_modules/jshint/src/vars.js","events":"/node_modules/browserify/node_modules/events/events.js","underscore":"/node_modules/jshint/node_modules/underscore/underscore.js"}],"/node_modules/jshint/src/lex.js":[function(_dereq_,module,exports){
- /*
- * Lexical analysis and token construction.
- */
- "use strict";
- var _ = _dereq_("underscore");
- var events = _dereq_("events");
- var reg = _dereq_("./reg.js");
- var state = _dereq_("./state.js").state;
- var unicodeData = _dereq_("../data/ascii-identifier-data.js");
- var asciiIdentifierStartTable = unicodeData.asciiIdentifierStartTable;
- var asciiIdentifierPartTable = unicodeData.asciiIdentifierPartTable;
- // 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,
- TemplateHead: 10,
- TemplateMiddle: 11,
- TemplateTail: 12,
- NoSubstTemplate: 13
- };
- var Context = {
- Block: 1,
- Template: 2
- };
- // 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) === "#!") {
- if (lines[0].indexOf("node") !== -1) {
- state.option.node = true;
- }
- 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 = "";
- this.inComment = false;
- this.context = [];
- this.templateStarts = [];
- for (var i = 0; i < state.option.indent; i += 1) {
- state.tab += " ";
- }
- }
- Lexer.prototype = {
- _lines: [],
- inContext: function(ctxType) {
- return this.context.length > 0 && this.context[this.context.length - 1].type === ctxType;
- },
- pushContext: function(ctxType) {
- this.context.push({ type: ctxType });
- },
- popContext: function() {
- return this.context.pop();
- },
- isContext: function(context) {
- return this.context.length > 0 && this.context[this.context.length - 1] === context;
- },
- currentContext: function() {
- return this.context.length > 0 && this.context[this.context.length - 1];
- },
- 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 "?":
- return {
- type: Token.Punctuator,
- value: ch1
- };
- // A block/object opener
- case "{":
- this.pushContext(Context.Block);
- return {
- type: Token.Punctuator,
- value: ch1
- };
- // A block/object closer
- case "}":
- if (this.inContext(Context.Block)) {
- this.popContext();
- }
- 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: /=.
- if (ch1 === "/") {
- if (ch2 === "=") {
- 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 += "*/";
- }
- body = body.replace(/\n/g, " ");
- 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.charAt(str.length) === " " && body.substr(0, str.length) === str) {
- isSpecial = true;
- label = label + str;
- body = body.substr(str.length);
- }
- if (!isSpecial && body.charAt(0) === " " && body.charAt(str.length + 1) === " " &&
- 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.inComment = true;
- 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
- });
- this.inComment = false;
- return commentToken("/*", body, {
- isMultiline: true,
- isMalformed: true
- });
- }
- } else {
- body += this.peek();
- this.skip();
- }
- }
- this.skip(2);
- this.inComment = false;
- 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;
- function isNonAsciiIdentifierStart(code) {
- return code > 256;
- }
- function isNonAsciiIdentifierPart(code) {
- return code > 256;
- }
- 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 (asciiIdentifierPartTable[code] || isNonAsciiIdentifierPart(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 (asciiIdentifierStartTable[code]) {
- index += 1;
- return chr;
- }
- return null;
- }
- if (isNonAsciiIdentifierStart(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 (asciiIdentifierPartTable[code]) {
- index += 1;
- return chr;
- }
- return null;
- }
- if (isNonAsciiIdentifierPart(code)) {
- index += 1;
- return chr;
- }
- return null;
- }.bind(this);
- function removeEscapeSequences(id) {
- return id.replace(/\\u([0-9a-fA-F]{4})/g, function(m0, codepoint) {
- return String.fromCharCode(parseInt(codepoint, 16));
- });
- }
- 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: removeEscapeSequences(id),
- text: id,
- tokenLength: id.length
- };
- },
- /*
- * 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;
- var isAllowedDigit = isDecimalDigit;
- var base = 10;
- var isLegacy = false;
- function isDecimalDigit(str) {
- return (/^[0-9]$/).test(str);
- }
- function isOctalDigit(str) {
- return (/^[0-7]$/).test(str);
- }
- function isBinaryDigit(str) {
- return (/^[01]$/).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") {
- isAllowedDigit = isHexDigit;
- base = 16;
- index += 1;
- value += char;
- }
- // Base-8 numbers.
- if (char === "o" || char === "O") {
- isAllowedDigit = isOctalDigit;
- base = 8;
- if (!state.option.esnext) {
- this.trigger("warning", {
- code: "W119",
- line: this.line,
- character: this.char,
- data: [ "Octal integer literal" ]
- });
- }
- index += 1;
- value += char;
- }
- // Base-2 numbers.
- if (char === "b" || char === "B") {
- isAllowedDigit = isBinaryDigit;
- base = 2;
- if (!state.option.esnext) {
- this.trigger("warning", {
- code: "W119",
- line: this.line,
- character: this.char,
- data: [ "Binary integer literal" ]
- });
- }
- index += 1;
- value += char;
- }
- // Legacy base-8 numbers.
- if (isOctalDigit(char)) {
- isAllowedDigit = isOctalDigit;
- base = 8;
- isLegacy = true;
- bad = false;
- index += 1;
- value += char;
- }
- // Decimal numbers that start with '0' such as '09' are illegal
- // but we still parse them and return as malformed.
- if (!isOctalDigit(char) && isDecimalDigit(char)) {
- index += 1;
- value += char;
- }
- }
- while (index < length) {
- char = this.peek(index);
- if (isLegacy && isDecimalDigit(char)) {
- // Numbers like '019' (note the 9) are not valid octals
- // but we still parse them and mark as malformed.
- bad = true;
- } else if (!isAllowedDigit(char)) {
- break;
- }
- value += char;
- index += 1;
- }
- if (isAllowedDigit !== isDecimalDigit) {
- if (!isLegacy && 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: base,
- isLegacy: isLegacy,
- isMalformed: false
- };
- }
- }
- // 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: base,
- isMalformed: !isFinite(value)
- };
- },
- // Assumes previously parsed character was \ (=== '\\') and was not skipped.
- scanEscapeSequence: function(checks) {
- var allowNewLine = false;
- var jump = 1;
- this.skip();
- var 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.isStrict(); });
- break;
- case "u":
- var hexCode = this.input.substr(1, 4);
- var code = parseInt(hexCode, 16);
- if (isNaN(code)) {
- this.trigger("warning", {
- code: "W052",
- line: this.line,
- character: this.char,
- data: [ "u" + hexCode ]
- });
- }
- char = String.fromCharCode(code);
- 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 "\\":
- char = "\\\\";
- break;
- case "\"":
- char = "\\\"";
- break;
- case "/":
- break;
- case "":
- allowNewLine = true;
- char = "";
- break;
- }
- return { char: char, jump: jump, allowNewLine: allowNewLine };
- },
- /*
- * Extract a template literal out of the next sequence of characters
- * and/or lines or return 'null' if its not possible. Since template
- * literals can span across multiple lines, this method has to move
- * the char pointer.
- */
- scanTemplateLiteral: function(checks) {
- var tokenType;
- var value = "";
- var ch;
- var startLine = this.line;
- var startChar = this.char;
- var depth = this.templateStarts.length;
- if (!state.option.esnext) {
- // Only lex template strings in ESNext mode.
- return null;
- } else if (this.peek() === "`") {
- // Template must start with a backtick.
- tokenType = Token.TemplateHead;
- this.templateStarts.push({ line: this.line, char: this.char });
- depth = this.templateStarts.length;
- this.skip(1);
- this.pushContext(Context.Template);
- } else if (this.inContext(Context.Template) && this.peek() === "}") {
- // If we're in a template context, and we have a '}', lex a TemplateMiddle.
- tokenType = Token.TemplateMiddle;
- } else {
- // Go lex something else.
- return null;
- }
- while (this.peek() !== "`") {
- while ((ch = this.peek()) === "") {
- value += "\n";
- if (!this.nextLine()) {
- // Unclosed template literal --- point to the starting "`"
- var startPos = this.templateStarts.pop();
- this.trigger("error", {
- code: "E052",
- line: startPos.line,
- character: startPos.char
- });
- return {
- type: tokenType,
- value: value,
- startLine: startLine,
- startChar: startChar,
- isUnclosed: true,
- depth: depth,
- context: this.popContext()
- };
- }
- }
- if (ch === '$' && this.peek(1) === '{') {
- value += '${';
- this.skip(2);
- return {
- type: tokenType,
- value: value,
- startLine: startLine,
- startChar: startChar,
- isUnclosed: false,
- depth: depth,
- context: this.currentContext()
- };
- } else if (ch === '\\') {
- var escape = this.scanEscapeSequence(checks);
- value += escape.char;
- this.skip(escape.jump);
- } else if (ch !== '`') {
- // Otherwise, append the value and continue.
- value += ch;
- this.skip(1);
- }
- }
- // Final value is either NoSubstTemplate or TemplateTail
- tokenType = tokenType === Token.TemplateHead ? Token.NoSubstTemplate : Token.TemplateTail;
- this.skip(1);
- this.templateStarts.pop();
- return {
- type: tokenType,
- value: value,
- startLine: startLine,
- startChar: startChar,
- isUnclosed: false,
- depth: depth,
- context: this.popContext()
- };
- },
- /*
- * 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();
- while (this.peek() !== quote) {
- if (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,
- startLine: startLine,
- startChar: startChar,
- isUnclosed: true,
- quote: quote
- };
- }
- } else { // Any character other than End Of Line
- 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 === "\\") {
- var parsed = this.scanEscapeSequence(checks);
- char = parsed.char;
- jump = parsed.jump;
- allowNewLine = parsed.allowNewLine;
- }
- value += char;
- this.skip(jump);
- }
- }
- this.skip();
- return {
- type: Token.StringLiteral,
- value: value,
- startLine: startLine,
- startChar: startChar,
- 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 occurrence of non-breaking spaces. Non-breaking spaces
- * can be mistakenly typed on OS X with option-space. Non UTF-8 web
- * pages with non-breaking pages produce syntax errors.
- */
- scanNonBreakingSpaces: function() {
- return state.option.nonbsp ?
- this.input.search(/(\u00A0)/) : -1;
- },
- /*
- * 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();
- }
- }
- // Methods that work with multi-line structures and move the
- // character pointer.
- var match = this.scanComments() ||
- this.scanStringLiteral(checks) ||
- this.scanTemplateLiteral(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.tokenLength || 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 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;
- var inputTrimmed = this.input.trim();
- var startsWith = function() {
- return _.some(arguments, function(prefix) {
- return inputTrimmed.indexOf(prefix) === 0;
- });
- };
- var endsWith = function() {
- return _.some(arguments, function(suffix) {
- return inputTrimmed.indexOf(suffix, inputTrimmed.length - suffix.length) !== -1;
- });
- };
- // If we are ignoring linter errors, replace the input with empty string
- // if it doesn't already at least start or end a multi-line comment
- if (state.ignoreLinterErrors === true) {
- if (!startsWith("/*", "//") && !(this.inComment && endsWith("*/"))) {
- this.input = "";
- }
- }
- char = this.scanNonBreakingSpaces();
- if (char >= 0) {
- this.trigger("warning", { code: "W125", 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) {
- var inComment = this.inComment ||
- startsWith.call(inputTrimmed, "//") ||
- startsWith.call(inputTrimmed, "/*");
- var shouldTriggerError = !inComment || !reg.maxlenException.test(inputTrimmed);
- if (shouldTriggerError) {
- 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 returns 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.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.isStrict()) {
- return false;
- }
- }
- if (isProperty) {
- return false;
- }
- }
- return true;
- }
- // Produce a token object.
- var create = function(type, value, isProperty, token) {
- /*jshint validthis:true */
- var obj;
- if (type !== "(endline)" && type !== "(end)") {
- this.prereg = false;
- }
- if (type === "(punctuator)") {
- switch (value) {
- case ".":
- case ")":
- 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 (obj.identifier && token) obj.raw_text = token.text || token.value;
- if (token && token.startLine && token.startLine !== this.line) {
- obj.startLine = token.startLine;
- }
- if (token && token.context) {
- // Context of current token
- obj.context = token.context;
- }
- if (token && token.depth) {
- // Nested template depth
- obj.depth = token.depth;
- }
- if (token && token.isUnclosed) {
- // Mark token as unclosed string / template literal
- obj.isUnclosed = token.isUnclosed;
- }
- if (isProperty && obj.identifier) {
- obj.isProperty = isProperty;
- }
- obj.check = checks.check;
- return obj;
- }.bind(this);
- for (;;) {
- if (!this.input.length) {
- if (this.nextLine()) {
- return create("(endline)", "");
- }
- if (this.exhausted) {
- return null;
- }
- this.exhausted = true;
- return create("(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,
- startLine: token.startLine,
- startChar: token.startChar,
- value: token.value,
- quote: token.quote
- }, checks, function() { return true; });
- return create("(string)", token.value, null, token);
- case Token.TemplateHead:
- this.trigger("TemplateHead", {
- line: this.line,
- char: this.char,
- from: this.from,
- startLine: token.startLine,
- startChar: token.startChar,
- value: token.value
- });
- return create("(template)", token.value, null, token);
- case Token.TemplateMiddle:
- this.trigger("TemplateMiddle", {
- line: this.line,
- char: this.char,
- from: this.from,
- startLine: token.startLine,
- startChar: token.startChar,
- value: token.value
- });
- return create("(template middle)", token.value, null, token);
- case Token.TemplateTail:
- this.trigger("TemplateTail", {
- line: this.line,
- char: this.char,
- from: this.from,
- startLine: token.startLine,
- startChar: token.startChar,
- value: token.value
- });
- return create("(template tail)", token.value, null, token);
- case Token.NoSubstTemplate:
- this.trigger("NoSubstTemplate", {
- line: this.line,
- char: this.char,
- from: this.from,
- startLine: token.startLine,
- startChar: token.startChar,
- value: token.value
- });
- return create("(no subst template)", token.value, null, token);
- case Token.Identifier:
- this.trigger("Identifier", {
- line: this.line,
- char: this.char,
- from: this.form,
- name: token.value,
- raw_name: token.text,
- 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 === ".", token);
- 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.isStrict() && token.base === 8 && token.isLegacy;
- });
- 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 {
- id: '(comment)',
- 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;
- exports.Context = Context;
- },{"../data/ascii-identifier-data.js":"/node_modules/jshint/data/ascii-identifier-data.js","./reg.js":"/node_modules/jshint/src/reg.js","./state.js":"/node_modules/jshint/src/state.js","events":"/node_modules/browserify/node_modules/events/events.js","underscore":"/node_modules/jshint/node_modules/underscore/underscore.js"}],"/node_modules/jshint/src/messages.js":[function(_dereq_,module,exports){
- "use strict";
- var _ = _dereq_("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 '[' from 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,
- E038: null,
- 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: null,
- E045: "Invalid for each loop.",
- E046: "A yield statement shall be within a generator function (with syntax: `function*`)",
- E047: null, // Vacant
- E048: "{a} 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.",
- E052: "Unclosed template literal.",
- E053: "Export declaration must be in global scope.",
- E054: "Class properties must be methods. Expected '(' but instead saw '{a}'.",
- E055: "The '{a}' option cannot be set after any executable code."
- };
- 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 plusses.",
- W008: "A leading decimal point can be confused with a dot: '{a}'.",
- W009: "The array literal notation [] is preferable.",
- W010: "The object literal notation {} is preferable.",
- W011: null,
- W012: null,
- W013: null,
- W014: "Bad line breaking before '{a}'.",
- W015: null,
- 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.", /* TODO(caitp): remove W044 */
- 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' necessary?",
- 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 {a} '{b}'.",
- 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: null,
- 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.",
- 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: null,
- W100: "This character may get silently deleted by one or more browsers.",
- W101: "Line is too long.",
- W102: null,
- W103: "The '{a}' property is deprecated.",
- W104: "'{a}' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).",
- 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.",
- W121: "Extending prototype of native object: '{a}'.",
- W122: "Invalid typeof value '{a}'",
- W123: "'{a}' is already defined in outer scope.",
- W124: "A generator function shall contain a yield statement.",
- W125: "This line contains non-breaking spaces: http://jshint.com/doc/options/#nonbsp",
- W126: "Unnecessary grouping operator.",
- W127: "Unexpected use of a comma operator.",
- W128: "Empty array elements require elision=true.",
- W129: "'{a}' is defined in a future version of JavaScript. Use a " +
- "different variable name to avoid migration issues.",
- W130: "Invalid element after rest element.",
- W131: "Invalid parameter after rest parameter.",
- W132: "`var` declarations are forbidden. Use `let` or `const` instead.",
- W133: "Invalid for-{a} loop left-hand-side: {b}.",
- W134: "The '{a}' option is only available when linting ECMAScript {b} code."
- };
- var info = {
- I001: "Comma warnings can be turned off with 'laxcomma'.",
- I002: null,
- 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":"/node_modules/jshint/node_modules/underscore/underscore.js"}],"/node_modules/jshint/src/name-stack.js":[function(_dereq_,module,exports){
- "use strict";
- function NameStack() {
- this._stack = [];
- }
- Object.defineProperty(NameStack.prototype, "length", {
- get: function() {
- return this._stack.length;
- }
- });
- /**
- * Create a new entry in the stack. Useful for tracking names across
- * expressions.
- */
- NameStack.prototype.push = function() {
- this._stack.push(null);
- };
- /**
- * Discard the most recently-created name on the stack.
- */
- NameStack.prototype.pop = function() {
- this._stack.pop();
- };
- /**
- * Update the most recent name on the top of the stack.
- *
- * @param {object} token The token to consider as the source for the most
- * recent name.
- */
- NameStack.prototype.set = function(token) {
- this._stack[this.length - 1] = token;
- };
- /**
- * Generate a string representation of the most recent name.
- *
- * @returns {string}
- */
- NameStack.prototype.infer = function() {
- var nameToken = this._stack[this.length - 1];
- var prefix = "";
- var type;
- // During expected operation, the topmost entry on the stack will only
- // reflect the current function's name when the function is declared without
- // the `function` keyword (i.e. for in-line accessor methods). In other
- // cases, the `function` expression itself will introduce an empty entry on
- // the top of the stack, and this should be ignored.
- if (!nameToken || nameToken.type === "class") {
- nameToken = this._stack[this.length - 2];
- }
- if (!nameToken) {
- return "(empty)";
- }
- type = nameToken.type;
- if (type !== "(string)" && type !== "(number)" && type !== "(identifier)" && type !== "default") {
- return "(expression)";
- }
- if (nameToken.accessorType) {
- prefix = nameToken.accessorType + " ";
- }
- return prefix + nameToken.value;
- };
- module.exports = NameStack;
- },{}],"/node_modules/jshint/src/options.js":[function(_dereq_,module,exports){
- "use strict";
- // These are the JSHint boolean options.
- exports.bool = {
- enforcing: {
- /**
- * This option prohibits the use of bitwise operators such as `^` (XOR),
- * `|` (OR) and others. Bitwise operators are very rare in JavaScript
- * programs and quite often `&` is simply a mistyped `&&`.
- */
- bitwise : true,
- /**
- *
- * This options prohibits overwriting prototypes of native objects such as
- * `Array`, `Date` and so on.
- *
- * // jshint freeze:true
- * Array.prototype.count = function (value) { return 4; };
- * // -> Warning: Extending prototype of native object: 'Array'.
- */
- freeze : true,
- /**
- * This option allows you to force all variable names to use either
- * camelCase style or UPPER_CASE with underscores.
- *
- * @deprecated JSHint is limiting its scope to issues of code correctness.
- * If you would like to enforce rules relating to code style,
- * check out [the JSCS
- * project](https://github.com/jscs-dev/node-jscs).
- */
- camelcase : true,
- /**
- * This option requires you to always put curly braces around blocks in
- * loops and conditionals. JavaScript allows you to omit curly braces when
- * the block consists of only one statement, for example:
- *
- * while (day)
- * shuffle();
- *
- * However, in some circumstances, it can lead to bugs (you'd think that
- * `sleep()` is a part of the loop while in reality it is not):
- *
- * while (day)
- * shuffle();
- * sleep();
- */
- curly : true,
- /**
- * This options prohibits the use of `==` and `!=` in favor of `===` and
- * `!==`. The former try to coerce values before comparing them which can
- * lead to some unexpected results. The latter don't do any coercion so
- * they are generally safer. If you would like to learn more about type
- * coercion in JavaScript, we recommend [Truth, Equality and
- * JavaScript](http://javascriptweblog.wordpress.com/2011/02/07/truth-equality-and-javascript/)
- * by Angus Croll.
- */
- eqeqeq : true,
- /**
- * This option enables warnings about the use of identifiers which are
- * defined in future versions of JavaScript. Although overwriting them has
- * no effect in contexts where they are not implemented, this practice can
- * cause issues when migrating codebases to newer versions of the language.
- */
- futurehostile: true,
- /**
- * This option suppresses warnings about invalid `typeof` operator values.
- * This operator has only [a limited set of possible return
- * values](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof).
- * By default, JSHint warns when you compare its result with an invalid
- * value which often can be a typo.
- *
- * // 'fuction' instead of 'function'
- * if (typeof a == "fuction") { // Invalid typeof value 'fuction'
- * // ...
- * }
- *
- * Do not use this option unless you're absolutely sure you don't want
- * these checks.
- */
- notypeof : true,
- /**
- * This option tells JSHint that your code needs to adhere to ECMAScript 3
- * specification. Use this option if you need your program to be executable
- * in older browsers—such as Internet Explorer 6/7/8/9—and other legacy
- * JavaScript environments.
- */
- es3 : true,
- /**
- * This option enables syntax first defined in [the ECMAScript 5.1
- * specification](http://es5.github.io/). This includes allowing reserved
- * keywords as object properties.
- */
- es5 : true,
- /**
- * This option requires all `for in` loops to filter object's items. The
- * for in statement allows for looping through the names of all of the
- * properties of an object including those inherited through the prototype
- * chain. This behavior can lead to unexpected items in your object so it
- * is generally safer to always filter inherited properties out as shown in
- * the example:
- *
- * for (key in obj) {
- * if (obj.hasOwnProperty(key)) {
- * // We are sure that obj[key] belongs to the object and was not inherited.
- * }
- * }
- *
- * For more in-depth understanding of `for in` loops in JavaScript, read
- * [Exploring JavaScript for-in
- * loops](http://javascriptweblog.wordpress.com/2011/01/04/exploring-javascript-for-in-loops/)
- * by Angus Croll.
- */
- forin : true,
- /**
- * This option suppresses warnings about declaring variables inside of
- * control
- * structures while accessing them later from the outside. Even though
- * JavaScript has only two real scopes—global and function—such practice
- * leads to confusion among people new to the language and hard-to-debug
- * bugs. This is why, by default, JSHint warns about variables that are
- * used outside of their intended scope.
- *
- * function test() {
- * if (true) {
- * var x = 0;
- * }
- *
- * x += 1; // Default: 'x' used out of scope.
- * // No warning when funcscope:true
- * }
- */
- funcscope : true,
- /**
- * This option prohibits the use of immediate function invocations without
- * wrapping them in parentheses. Wrapping parentheses assists readers of
- * your code in understanding that the expression is the result of a
- * function, and not the function itself.
- *
- * @deprecated JSHint is limiting its scope to issues of code correctness.
- * If you would like to enforce rules relating to code style,
- * check out [the JSCS
- * project](https://github.com/jscs-dev/node-jscs).
- */
- immed : true,
- /**
- * This option suppresses warnings about the `__iterator__` property. This
- * property is not supported by all browsers so use it carefully.
- */
- iterator : true,
- /**
- * This option requires you to capitalize names of constructor functions.
- * Capitalizing functions that are intended to be used with `new` operator
- * is just a convention that helps programmers to visually distinguish
- * constructor functions from other types of functions to help spot
- * mistakes when using `this`.
- *
- * Not doing so won't break your code in any browsers or environments but
- * it will be a bit harder to figure out—by reading the code—if the
- * function was supposed to be used with or without new. And this is
- * important because when the function that was intended to be used with
- * `new` is used without it, `this` will point to the global object instead
- * of a new object.
- *
- * @deprecated JSHint is limiting its scope to issues of code correctness.
- * If you would like to enforce rules relating to code style,
- * check out [the JSCS
- * project](https://github.com/jscs-dev/node-jscs).
- */
- newcap : true,
- /**
- * This option prohibits the use of `arguments.caller` and
- * `arguments.callee`. Both `.caller` and `.callee` make quite a few
- * optimizations impossible so they were deprecated in future versions of
- * JavaScript. In fact, ECMAScript 5 forbids the use of `arguments.callee`
- * in strict mode.
- */
- noarg : true,
- /**
- * This option prohibits the use of the comma operator. When misused, the
- * comma operator can obscure the value of a statement and promote
- * incorrect code.
- */
- nocomma : true,
- /**
- * This option warns when you have an empty block in your code. JSLint was
- * originally warning for all empty blocks and we simply made it optional.
- * There were no studies reporting that empty blocks in JavaScript break
- * your code in any way.
- *
- * @deprecated JSHint is limiting its scope to issues of code correctness.
- * If you would like to enforce rules relating to code style,
- * check out [the JSCS
- * project](https://github.com/jscs-dev/node-jscs).
- */
- noempty : true,
- /**
- * This option warns about "non-breaking whitespace" characters. These
- * characters can be entered with option-space on Mac computers and have a
- * potential of breaking non-UTF8 web pages.
- */
- nonbsp : true,
- /**
- * This option prohibits the use of constructor functions for side-effects.
- * Some people like to call constructor functions without assigning its
- * result to any variable:
- *
- * new MyConstructor();
- *
- * There is no advantage in this approach over simply calling
- * `MyConstructor` since the object that the operator `new` creates isn't
- * used anywhere so you should generally avoid constructors like this one.
- */
- nonew : true,
- /**
- * This option prohibits the use of explicitly undeclared variables. This
- * option is very useful for spotting leaking and mistyped variables.
- *
- * // jshint undef:true
- *
- * function test() {
- * var myVar = 'Hello, World';
- * console.log(myvar); // Oops, typoed here. JSHint with undef will complain
- * }
- *
- * If your variable is defined in another file, you can use the `global`
- * directive to tell JSHint about it.
- */
- undef : true,
- /**
- * This option prohibits the use of the grouping operator when it is not
- * strictly required. Such usage commonly reflects a misunderstanding of
- * unary operators, for example:
- *
- * // jshint singleGroups: true
- *
- * delete(obj.attr); // Warning: Unnecessary grouping operator.
- */
- singleGroups: false,
- /**
- * This option requires all functions to run in ECMAScript 5's strict mode.
- * [Strict mode](https://developer.mozilla.org/en/JavaScript/Strict_mode)
- * is a way to opt in to a restricted variant of JavaScript. Strict mode
- * eliminates some JavaScript pitfalls that didn't cause errors by changing
- * them to produce errors. It also fixes mistakes that made it difficult
- * for the JavaScript engines to perform certain optimizations.
- *
- * *Note:* This option enables strict mode for function scope only. It
- * *prohibits* the global scoped strict mode because it might break
- * third-party widgets on your page. If you really want to use global
- * strict mode, see the *globalstrict* option.
- */
- strict : true,
- /**
- * When set to true, the use of VariableStatements are forbidden.
- * For example:
- *
- * // jshint varstmt: true
- *
- * var a; // Warning: `var` declarations are forbidden. Use `let` or `const` instead.
- */
- varstmt: false,
- /**
- * This option is a short hand for the most strict JSHint configuration as
- * available in JSHint version 2.6.3. It enables all enforcing options and
- * disables all relaxing options that were defined in that release.
- *
- * @deprecated The option cannot be maintained without automatically opting
- * users in to new features. This can lead to unexpected
- * warnings/errors in when upgrading between minor versions of
- * JSHint.
- */
- enforceall : false
- },
- relaxing: {
- /**
- * This option suppresses warnings about missing semicolons. There is a lot
- * of FUD about semicolon spread by quite a few people in the community.
- * The common myths are that semicolons are required all the time (they are
- * not) and that they are unreliable. JavaScript has rules about semicolons
- * which are followed by *all* browsers so it is up to you to decide
- * whether you should or should not use semicolons in your code.
- *
- * For more information about semicolons in JavaScript read [An Open Letter
- * to JavaScript Leaders Regarding
- * Semicolons](http://blog.izs.me/post/2353458699/an-open-letter-to-javascript-leaders-regarding)
- * by Isaac Schlueter and [JavaScript Semicolon
- * Insertion](http://inimino.org/~inimino/blog/javascript_semicolons).
- */
- asi : true,
- /**
- * This option suppresses warnings about multi-line strings. Multi-line
- * strings can be dangerous in JavaScript because all hell breaks loose if
- * you accidentally put a whitespace in between the escape character (`\`)
- * and a new line.
- *
- * Note that even though this option allows correct multi-line strings, it
- * still warns about multi-line strings without escape characters or with
- * anything in between the escape character and a whitespace.
- *
- * // jshint multistr:true
- *
- * var text = "Hello\
- * World"; // All good.
- *
- * text = "Hello
- * World"; // Warning, no escape character.
- *
- * text = "Hello\
- * World"; // Warning, there is a space after \
- *
- * @deprecated JSHint is limiting its scope to issues of code correctness.
- * If you would like to enforce rules relating to code style,
- * check out [the JSCS
- * project](https://github.com/jscs-dev/node-jscs).
- */
- multistr : true,
- /**
- * This option suppresses warnings about the `debugger` statements in your
- * code.
- */
- debug : true,
- /**
- * This option suppresses warnings about the use of assignments in cases
- * where comparisons are expected. More often than not, code like `if (a =
- * 10) {}` is a typo. However, it can be useful in cases like this one:
- *
- * for (var i = 0, person; person = people[i]; i++) {}
- *
- * You can silence this error on a per-use basis by surrounding the assignment
- * with parenthesis, such as:
- *
- * for (var i = 0, person; (person = people[i]); i++) {}
- */
- boss : true,
- /**
- * This option suppresses warnings about the use of `eval`. The use of
- * `eval` is discouraged because it can make your code vulnerable to
- * various injection attacks and it makes it hard for JavaScript
- * interpreter to do certain optimizations.
- */
- evil : true,
- /**
- * This option suppresses warnings about the use of global strict mode.
- * Global strict mode can break third-party widgets so it is not
- * recommended.
- *
- * For more info about strict mode see the `strict` option.
- */
- globalstrict: true,
- /**
- * This option prohibits the use of unary increment and decrement
- * operators. Some people think that `++` and `--` reduces the quality of
- * their coding styles and there are programming languages—such as
- * Python—that go completely without these operators.
- */
- plusplus : true,
- /**
- * This option suppresses warnings about the `__proto__` property.
- */
- proto : true,
- /**
- * This option suppresses warnings about the use of script-targeted
- * URLs—such as `javascript:...`.
- */
- scripturl : true,
- /**
- * This option suppresses warnings about using `[]` notation when it can be
- * expressed in dot notation: `person['name']` vs. `person.name`.
- *
- * @deprecated JSHint is limiting its scope to issues of code correctness.
- * If you would like to enforce rules relating to code style,
- * check out [the JSCS
- * project](https://github.com/jscs-dev/node-jscs).
- */
- sub : true,
- /**
- * This option suppresses warnings about "weird" constructions like
- * `new function () { ... }` and `new Object;`. Such constructions are
- * sometimes used to produce singletons in JavaScript:
- *
- * var singleton = new function() {
- * var privateVar;
- *
- * this.publicMethod = function () {}
- * this.publicMethod2 = function () {}
- * };
- */
- supernew : true,
- /**
- * This option suppresses most of the warnings about possibly unsafe line
- * breakings in your code. It doesn't suppress warnings about comma-first
- * coding style. To suppress those you have to use `laxcomma` (see below).
- *
- * @deprecated JSHint is limiting its scope to issues of code correctness.
- * If you would like to enforce rules relating to code style,
- * check out [the JSCS
- * project](https://github.com/jscs-dev/node-jscs).
- */
- laxbreak : true,
- /**
- * This option suppresses warnings about comma-first coding style:
- *
- * var obj = {
- * name: 'Anton'
- * , handle: 'valueof'
- * , role: 'SW Engineer'
- * };
- *
- * @deprecated JSHint is limiting its scope to issues of code correctness.
- * If you would like to enforce rules relating to code style,
- * check out [the JSCS
- * project](https://github.com/jscs-dev/node-jscs).
- */
- laxcomma : true,
- /**
- * This option suppresses warnings about possible strict violations when
- * the code is running in strict mode and you use `this` in a
- * non-constructor function. You should use this option—in a function scope
- * only—when you are positive that your use of `this` is valid in the
- * strict mode (for example, if you call your function using
- * `Function.call`).
- *
- * **Note:** This option can be used only inside of a function scope.
- * JSHint will fail with an error if you will try to set this option
- * globally.
- */
- validthis : true,
- /**
- * This option suppresses warnings about the use of the `with` statement.
- * The semantics of the `with` statement can cause confusion among
- * developers and accidental definition of global variables.
- *
- * More info:
- *
- * * [with Statement Considered
- * Harmful](http://yuiblog.com/blog/2006/04/11/with-statement-considered-harmful/)
- */
- withstmt : true,
- /**
- * This options tells JSHint that your code uses Mozilla JavaScript
- * extensions. Unless you develop specifically for the Firefox web browser
- * you don't need this option.
- *
- * More info:
- *
- * * [New in JavaScript
- * 1.7](https://developer.mozilla.org/en-US/docs/JavaScript/New_in_JavaScript/1.7)
- */
- moz : true,
- /**
- * This option suppresses warnings about generator functions with no
- * `yield` statement in them.
- */
- noyield : true,
- /**
- * This option suppresses warnings about `== null` comparisons. Such
- * comparisons are often useful when you want to check if a variable is
- * `null` or `undefined`.
- */
- eqnull : true,
- /**
- * This option suppresses warnings about missing semicolons, but only when
- * the semicolon is omitted for the last statement in a one-line block:
- *
- * var name = (function() { return 'Anton' }());
- *
- * This is a very niche use case that is useful only when you use automatic
- * JavaScript code generators.
- */
- lastsemic : true,
- /**
- * This option suppresses warnings about functions inside of loops.
- * Defining functions inside of loops can lead to bugs such as this one:
- *
- * var nums = [];
- *
- * for (var i = 0; i < 10; i++) {
- * nums[i] = function (j) {
- * return i + j;
- * };
- * }
- *
- * nums[0](2); // Prints 12 instead of 2
- *
- * To fix the code above you need to copy the value of `i`:
- *
- * var nums = [];
- *
- * for (var i = 0; i < 10; i++) {
- * (function (i) {
- * nums[i] = function (j) {
- * return i + j;
- * };
- * }(i));
- * }
- */
- loopfunc : true,
- /**
- * This option suppresses warnings about the use of expressions where
- * normally you would expect to see assignments or function calls. Most of
- * the time, such code is a typo. However, it is not forbidden by the spec
- * and that's why this warning is optional.
- */
- expr : true,
- /**
- * This option tells JSHint that your code uses ECMAScript 6 specific
- * syntax. Note that these features are not finalized yet and not all
- * browsers implement them.
- *
- * More info:
- *
- * * [Draft Specification for ES.next (ECMA-262 Ed.
- * 6)](http://wiki.ecmascript.org/doku.php?id=harmony:specification_drafts)
- */
- esnext : true,
- /**
- * This option tells JSHint that your code uses ES3 array elision elements,
- * or empty elements (for example, `[1, , , 4, , , 7]`).
- */
- elision : true,
- },
- // Third party globals
- environments: {
- /**
- * This option defines globals exposed by the
- * [MooTools](http://mootools.net/) JavaScript framework.
- */
- mootools : true,
- /**
- * This option defines globals exposed by
- * [CouchDB](http://couchdb.apache.org/). CouchDB is a document-oriented
- * database that can be queried and indexed in a MapReduce fashion using
- * JavaScript.
- */
- couch : true,
- /**
- * This option defines globals exposed by [the Jasmine unit testing
- * framework](https://jasmine.github.io/).
- */
- jasmine : true,
- /**
- * This option defines globals exposed by the [jQuery](http://jquery.com/)
- * JavaScript library.
- */
- jquery : true,
- /**
- * This option defines globals available when your code is running inside
- * of the Node runtime environment. [Node.js](http://nodejs.org/) is a
- * server-side JavaScript environment that uses an asynchronous
- * event-driven model. This option also skips some warnings that make sense
- * in the browser environments but don't make sense in Node such as
- * file-level `use strict` pragmas and `console.log` statements.
- */
- node : true,
- /**
- * This option defines globals exposed by [the QUnit unit testing
- * framework](http://qunitjs.com/).
- */
- qunit : true,
- /**
- * This option defines globals available when your code is running inside
- * of the Rhino runtime environment. [Rhino](http://www.mozilla.org/rhino/)
- * is an open-source implementation of JavaScript written entirely in Java.
- */
- rhino : true,
- /**
- * This option defines globals exposed by [the ShellJS
- * library](http://documentup.com/arturadib/shelljs).
- */
- shelljs : true,
- /**
- * This option defines globals exposed by the
- * [Prototype](http://www.prototypejs.org/) JavaScript framework.
- */
- prototypejs : true,
- /**
- * This option defines globals exposed by the [YUI](http://yuilibrary.com/)
- * JavaScript framework.
- */
- yui : true,
- /**
- * This option defines globals exposed by the "BDD" and "TDD" UIs of the
- * [Mocha unit testing framework](http://mochajs.org/).
- */
- mocha : true,
- /**
- * This option informs JSHint that the input code describes an ECMAScript 6
- * module. All module code is interpreted as strict mode code.
- */
- module : true,
- /**
- * This option defines globals available when your code is running as a
- * script for the [Windows Script
- * Host](http://en.wikipedia.org/wiki/Windows_Script_Host).
- */
- wsh : true,
- /**
- * This option defines globals available when your code is running inside
- * of a Web Worker. [Web
- * Workers](https://developer.mozilla.org/en/Using_web_workers) provide a
- * simple means for web content to run scripts in background threads.
- */
- worker : true,
- /**
- * This option defines non-standard but widely adopted globals such as
- * `escape` and `unescape`.
- */
- nonstandard : true,
- /**
- * This option defines globals exposed by modern browsers: all the way from
- * good old `document` and `navigator` to the HTML5 `FileReader` and other
- * new developments in the browser world.
- *
- * **Note:** This option doesn't expose variables like `alert` or
- * `console`. See option `devel` for more information.
- */
- browser : true,
- /**
- * This option defines globals available when using [the Browserify
- * tool](http://browserify.org/) to build a project.
- */
- browserify : true,
- /**
- * This option defines globals that are usually used for logging poor-man's
- * debugging: `console`, `alert`, etc. It is usually a good idea to not
- * ship them in production because, for example, `console.log` breaks in
- * legacy versions of Internet Explorer.
- */
- devel : true,
- /**
- * This option defines globals exposed by the [Dojo
- * Toolkit](http://dojotoolkit.org/).
- */
- dojo : true,
- /**
- * This option defines globals for typed array constructors.
- *
- * More info:
- *
- * * [JavaScript typed
- * arrays](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays)
- */
- typed : true,
- /**
- * This option defines globals available when your core is running inside
- * of the PhantomJS runtime environment. [PhantomJS](http://phantomjs.org/)
- * is a headless WebKit scriptable with a JavaScript API. It has fast and
- * native support for various web standards: DOM handling, CSS selector,
- * JSON, Canvas, and SVG.
- */
- phantom : true
- },
- // Obsolete options
- obsolete: {
- 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)
- exports.val = {
- /**
- * This option lets you set the maximum length of a line.
- *
- * @deprecated JSHint is limiting its scope to issues of code correctness. If
- * you would like to enforce rules relating to code style, check
- * out [the JSCS project](https://github.com/jscs-dev/node-jscs).
- */
- maxlen : false,
- /**
- * This option sets a specific tab width for your code.
- *
- * @deprecated JSHint is limiting its scope to issues of code correctness. If
- * you would like to enforce rules relating to code style, check
- * out [the JSCS project](https://github.com/jscs-dev/node-jscs).
- */
- indent : false,
- /**
- * This options allows you to set the maximum amount of warnings JSHint will
- * produce before giving up. Default is 50.
- */
- maxerr : false,
- predef : false, // predef is deprecated and being replaced by globals
- /**
- * This option can be used to specify a white list of global variables that
- * are not formally defined in the source code. This is most useful when
- * combined with the `undef` option in order to suppress warnings for
- * project-specific global variables.
- *
- * Setting an entry to `true` enables reading and writing to that variable.
- * Setting it to `false` will trigger JSHint to consider that variable
- * read-only.
- *
- * See also the "environment" options: a set of options to be used as short
- * hand for enabling global variables defined in common JavaScript
- * environments.
- */
- globals : false,
- /**
- * This option enforces the consistency of quotation marks used throughout
- * your code. It accepts three values: `true` if you don't want to enforce
- * one particular style but want some consistency, `"single"` if you want to
- * allow only single quotes and `"double"` if you want to allow only double
- * quotes.
- *
- * @deprecated JSHint is limiting its scope to issues of code correctness. If
- * you would like to enforce rules relating to code style, check
- * out [the JSCS project](https://github.com/jscs-dev/node-jscs).
- */
- quotmark : false,
- scope : false,
- /**
- * This option lets you set the max number of statements allowed per function:
- *
- * // jshint maxstatements:4
- *
- * function main() {
- * var i = 0;
- * var j = 0;
- *
- * // Function declarations count as one statement. Their bodies
- * // don't get taken into account for the outer function.
- * function inner() {
- * var i2 = 1;
- * var j2 = 1;
- *
- * return i2 + j2;
- * }
- *
- * j = i + j;
- * return j; // JSHint: Too many statements per function. (5)
- * }
- */
- maxstatements: false,
- /**
- * This option lets you control how nested do you want your blocks to be:
- *
- * // jshint maxdepth:2
- *
- * function main(meaning) {
- * var day = true;
- *
- * if (meaning === 42) {
- * while (day) {
- * shuffle();
- *
- * if (tired) { // JSHint: Blocks are nested too deeply (3).
- * sleep();
- * }
- * }
- * }
- * }
- */
- maxdepth : false,
- /**
- * This option lets you set the max number of formal parameters allowed per
- * function:
- *
- * // jshint maxparams:3
- *
- * function login(request, onSuccess) {
- * // ...
- * }
- *
- * // JSHint: Too many parameters per function (4).
- * function logout(request, isManual, whereAmI, onSuccess) {
- * // ...
- * }
- */
- maxparams : false,
- /**
- * This option lets you control cyclomatic complexity throughout your code.
- * Cyclomatic complexity measures the number of linearly independent paths
- * through a program's source code. Read more about [cyclomatic complexity on
- * Wikipedia](http://en.wikipedia.org/wiki/Cyclomatic_complexity).
- */
- maxcomplexity: false,
- /**
- * This option suppresses warnings about variable shadowing i.e. declaring a
- * variable that had been already declared somewhere in the outer scope.
- *
- * - "inner" - check for variables defined in the same scope only
- * - "outer" - check for variables defined in outer scopes as well
- * - false - same as inner
- * - true - allow variable shadowing
- */
- shadow : false,
- /**
- * This option warns when you define and never use your variables. It is very
- * useful for general code cleanup, especially when used in addition to
- * `undef`.
- *
- * // jshint unused:true
- *
- * function test(a, b) {
- * var c, d = 2;
- *
- * return a + d;
- * }
- *
- * test(1, 2);
- *
- * // Line 3: 'b' was defined but never used.
- * // Line 4: 'c' was defined but never used.
- *
- * In addition to that, this option will warn you about unused global
- * variables declared via the `global` directive.
- *
- * This can be set to `vars` to only check for variables, not function
- * parameters, or `strict` to check all variables and parameters. The
- * default (true) behavior is to allow unused parameters that are followed by
- * a used parameter.
- */
- unused : true,
- /**
- * This option prohibits the use of a variable before it was defined.
- * JavaScript has function scope only and, in addition to that, all variables
- * are always moved—or hoisted— to the top of the function. This behavior can
- * lead to some very nasty bugs and that's why it is safer to always use
- * variable only after they have been explicitly defined.
- *
- * Setting this option to "nofunc" will allow function declarations to be
- * ignored.
- *
- * For more in-depth understanding of scoping and hoisting in JavaScript,
- * read [JavaScript Scoping and
- * Hoisting](http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting)
- * by Ben Cherry.
- */
- latedef : false,
- ignore : false, // start/end ignoring lines of code, bypassing the lexer
- // start - start ignoring lines, including the current line
- // end - stop ignoring lines, starting on the next line
- // line - ignore warnings / errors for just a single line
- // (this option does not bypass the lexer)
- ignoreDelimiters: false // array of start/end delimiters used to ignore
- // certain chunks from code
- };
- // These are JSHint boolean options which are shared with JSLint
- // where the definition in JSHint is opposite JSLint
- exports.inverted = {
- bitwise : true,
- forin : true,
- newcap : true,
- plusplus: true,
- regexp : true,
- undef : true,
- // Inverted and renamed, use JSHint name here
- eqeqeq : true,
- strict : true
- };
- exports.validNames = Object.keys(exports.val)
- .concat(Object.keys(exports.bool.relaxing))
- .concat(Object.keys(exports.bool.enforcing))
- .concat(Object.keys(exports.bool.obsolete))
- .concat(Object.keys(exports.bool.environments));
- // These are JSHint boolean options which are shared with JSLint
- // where the name has been changed but the effect is unchanged
- exports.renamed = {
- eqeq : "eqeqeq",
- windows: "wsh",
- sloppy : "strict"
- };
- exports.removed = {
- nomen: true,
- onevar: true,
- passfail: true,
- white: true,
- gcl: true,
- smarttabs: true,
- trailing: true
- };
- // Add options here which should not be automatically enforced by
- // `enforceall`.
- exports.noenforceall = {
- varstmt: true,
- strict: true
- };
- },{}],"/node_modules/jshint/src/reg.js":[function(_dereq_,module,exports){
- /*
- * Regular expressions. Some of these are stupidly long.
- */
- /*jshint maxlen:1000 */
- "use strict";
- // 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|livescript)\s*:/i;
- // Catches /* falls through */ comments (ft)
- exports.fallsThrough = /^\s*\/\*\s*falls?\sthrough\s*\*\/\s*$/;
- // very conservative rule (eg: only one space between the start of the comment and the first character)
- // to relax the maxlen option
- exports.maxlenException = /^(?:(?:\/\/|\/\*|\*) ?)?[^ ]+$/;
- },{}],"/node_modules/jshint/src/state.js":[function(_dereq_,module,exports){
- "use strict";
- var NameStack = _dereq_("./name-stack.js");
- var state = {
- syntax: {},
- /**
- * Determine if the code currently being linted is strict mode code.
- *
- * @returns {boolean}
- */
- isStrict: function() {
- return this.directive["use strict"] || this.inClassBody ||
- this.option.module;
- },
- // Assumption: chronologically ES3 < ES5 < ES6/ESNext < Moz
- inMoz: function() {
- return this.option.moz;
- },
- /**
- * @param {object} options
- * @param {boolean} options.strict - When `true`, only consider ESNext when
- * in "esnext" code and *not* in "moz".
- */
- inESNext: function() {
- return this.option.moz || this.option.esnext;
- },
- inES5: function() {
- return !this.option.es3;
- },
- inES3: function() {
- return this.option.es3;
- },
- reset: function() {
- this.tokens = {
- prev: null,
- next: null,
- curr: null
- };
- this.option = {};
- this.funct = null;
- this.ignored = {};
- this.directive = {};
- this.jsonMode = false;
- this.jsonWarnings = [];
- this.lines = [];
- this.tab = "";
- this.cache = {}; // Node.JS doesn't have Map. Sniff.
- this.ignoredLines = {};
- this.forinifcheckneeded = false;
- this.nameStack = new NameStack();
- this.inClassBody = false;
- // Blank out non-multi-line-commented lines when ignoring linter errors
- this.ignoreLinterErrors = false;
- }
- };
- exports.state = state;
- },{"./name-stack.js":"/node_modules/jshint/src/name-stack.js"}],"/node_modules/jshint/src/style.js":[function(_dereq_,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 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(/^_+|_+$/g, "").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|livescript)\s*:/i;
- if (linter.getOption("scripturl")) {
- return;
- }
- if (re.test(data.value)) {
- linter.warn("W107", {
- line: data.line,
- char: data.char
- });
- }
- });
- };
- },{}],"/node_modules/jshint/src/vars.js":[function(_dereq_,module,exports){
- // jshint -W001
- "use strict";
- // Identifiers provided by the ECMAScript standard.
- exports.reservedVars = {
- arguments : false,
- NaN : false
- };
- exports.ecmaIdentifiers = {
- 3: {
- 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,
- Math : false,
- Number : false,
- Object : false,
- parseInt : false,
- parseFloat : false,
- RangeError : false,
- ReferenceError : false,
- RegExp : false,
- String : false,
- SyntaxError : false,
- TypeError : false,
- URIError : false
- },
- 5: {
- JSON : false
- },
- 6: {
- Map : false,
- Promise : false,
- Proxy : false,
- Reflect : false,
- Set : false,
- Symbol : false,
- WeakMap : false,
- WeakSet : false
- }
- };
- // Global variables commonly provided by a web browser environment.
- exports.browser = {
- Audio : false,
- Blob : false,
- addEventListener : false,
- applicationCache : false,
- atob : false,
- blur : false,
- btoa : false,
- cancelAnimationFrame : false,
- CanvasGradient : false,
- CanvasPattern : false,
- CanvasRenderingContext2D: false,
- CSS : false,
- clearInterval : false,
- clearTimeout : false,
- close : false,
- closed : false,
- Comment : false,
- CustomEvent : false,
- DOMParser : false,
- defaultStatus : false,
- Document : false,
- document : false,
- DocumentFragment : false,
- Element : false,
- ElementTimeControl : false,
- Event : false,
- event : false,
- fetch : false,
- FileReader : 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,
- HTMLCollection : 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,
- HTMLTemplateElement : false,
- HTMLTextAreaElement : false,
- HTMLTitleElement : false,
- HTMLUListElement : false,
- HTMLVideoElement : false,
- history : false,
- Image : false,
- Intl : false,
- length : false,
- localStorage : false,
- location : false,
- matchMedia : false,
- MessageChannel : false,
- MessageEvent : false,
- MessagePort : false,
- MouseEvent : false,
- moveBy : false,
- moveTo : false,
- MutationObserver : false,
- name : false,
- Node : false,
- NodeFilter : false,
- NodeList : false,
- Notification : 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,
- performance : false,
- print : false,
- Range : false,
- requestAnimationFrame : 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,
- Text : false,
- TextDecoder : false,
- TextEncoder : false,
- TimeEvent : false,
- top : false,
- URL : false,
- WebGLActiveInfo : false,
- WebGLBuffer : false,
- WebGLContextEvent : false,
- WebGLFramebuffer : false,
- WebGLProgram : false,
- WebGLRenderbuffer : false,
- WebGLRenderingContext: false,
- WebGLShader : false,
- WebGLShaderPrecisionFormat: false,
- WebGLTexture : false,
- WebGLUniformLocation : false,
- WebSocket : false,
- window : false,
- Worker : false,
- XDomainRequest : 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,
- FileReaderSync : 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,
- GLOBAL : false,
- global : false,
- module : false,
- require : false,
- // These globals are writeable because Node allows the following
- // usage pattern: var Buffer = require("buffer").Buffer;
- Buffer : true,
- console : true,
- exports : true,
- process : true,
- setTimeout : true,
- clearTimeout : true,
- setInterval : true,
- clearInterval : true,
- setImmediate : true, // v0.9.1+
- clearImmediate: true // v0.9.1+
- };
- exports.browserify = {
- __filename : false,
- __dirname : false,
- global : false,
- module : false,
- require : false,
- Buffer : true,
- exports : true,
- process : true
- };
- exports.phantom = {
- phantom : true,
- require : true,
- WebPage : true,
- console : true, // in examples, but undocumented
- exports : true // v1.7+
- };
- exports.qunit = {
- asyncTest : false,
- deepEqual : false,
- equal : false,
- expect : false,
- module : false,
- notDeepEqual : false,
- notEqual : false,
- notPropEqual : false,
- notStrictEqual : false,
- ok : false,
- propEqual : false,
- QUnit : false,
- raises : false,
- start : false,
- stop : false,
- strictEqual : false,
- test : false,
- "throws" : false
- };
- exports.rhino = {
- defineClass : false,
- deserialize : false,
- gc : false,
- help : false,
- importClass : false,
- importPackage: false,
- "java" : false,
- load : false,
- loadClass : false,
- Packages : 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.typed = {
- ArrayBuffer : false,
- ArrayBufferView : false,
- DataView : false,
- Float32Array : false,
- Float64Array : false,
- Int16Array : false,
- Int32Array : false,
- Int8Array : false,
- Uint16Array : false,
- Uint32Array : false,
- Uint8Array : false,
- Uint8ClampedArray : 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
- };
- exports.mocha = {
- // Global (for config etc.)
- mocha : false,
- // BDD
- describe : false,
- xdescribe : false,
- it : false,
- xit : false,
- context : false,
- xcontext : false,
- before : false,
- after : false,
- beforeEach : false,
- afterEach : false,
- // TDD
- suite : false,
- test : false,
- setup : false,
- teardown : false,
- suiteSetup : false,
- suiteTeardown : false
- };
- exports.jasmine = {
- jasmine : false,
- describe : false,
- xdescribe : false,
- it : false,
- xit : false,
- beforeEach : false,
- afterEach : false,
- setFixtures : false,
- loadFixtures: false,
- spyOn : false,
- expect : false,
- // Jasmine 1.3
- runs : false,
- waitsFor : false,
- waits : false,
- // Jasmine 2.1
- beforeAll : false,
- afterAll : false,
- fail : false,
- fdescribe : false,
- fit : false
- };
- },{}]},{},["/node_modules/jshint/src/jshint.js"]);
- });
|