123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730 |
- 'use strict';
- Object.defineProperty(exports, '__esModule', { value: true });
- var shared = require('@vue/shared');
- var parser = require('@babel/parser');
- var sourceMap = require('source-map');
- var estreeWalker = require('estree-walker');
- function defaultOnError(error) {
- throw error;
- }
- function defaultOnWarn(msg) {
- }
- function createCompilerError(code, loc, messages, additionalMessage) {
- const msg = (messages || errorMessages)[code] + (additionalMessage || ``)
- ;
- const error = new SyntaxError(String(msg));
- error.code = code;
- error.loc = loc;
- return error;
- }
- const errorMessages = {
- // parse errors
- [0 /* ErrorCodes.ABRUPT_CLOSING_OF_EMPTY_COMMENT */]: 'Illegal comment.',
- [1 /* ErrorCodes.CDATA_IN_HTML_CONTENT */]: 'CDATA section is allowed only in XML context.',
- [2 /* ErrorCodes.DUPLICATE_ATTRIBUTE */]: 'Duplicate attribute.',
- [3 /* ErrorCodes.END_TAG_WITH_ATTRIBUTES */]: 'End tag cannot have attributes.',
- [4 /* ErrorCodes.END_TAG_WITH_TRAILING_SOLIDUS */]: "Illegal '/' in tags.",
- [5 /* ErrorCodes.EOF_BEFORE_TAG_NAME */]: 'Unexpected EOF in tag.',
- [6 /* ErrorCodes.EOF_IN_CDATA */]: 'Unexpected EOF in CDATA section.',
- [7 /* ErrorCodes.EOF_IN_COMMENT */]: 'Unexpected EOF in comment.',
- [8 /* ErrorCodes.EOF_IN_SCRIPT_HTML_COMMENT_LIKE_TEXT */]: 'Unexpected EOF in script.',
- [9 /* ErrorCodes.EOF_IN_TAG */]: 'Unexpected EOF in tag.',
- [10 /* ErrorCodes.INCORRECTLY_CLOSED_COMMENT */]: 'Incorrectly closed comment.',
- [11 /* ErrorCodes.INCORRECTLY_OPENED_COMMENT */]: 'Incorrectly opened comment.',
- [12 /* ErrorCodes.INVALID_FIRST_CHARACTER_OF_TAG_NAME */]: "Illegal tag name. Use '<' to print '<'.",
- [13 /* ErrorCodes.MISSING_ATTRIBUTE_VALUE */]: 'Attribute value was expected.',
- [14 /* ErrorCodes.MISSING_END_TAG_NAME */]: 'End tag name was expected.',
- [15 /* ErrorCodes.MISSING_WHITESPACE_BETWEEN_ATTRIBUTES */]: 'Whitespace was expected.',
- [16 /* ErrorCodes.NESTED_COMMENT */]: "Unexpected '<!--' in comment.",
- [17 /* ErrorCodes.UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME */]: 'Attribute name cannot contain U+0022 ("), U+0027 (\'), and U+003C (<).',
- [18 /* ErrorCodes.UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE */]: 'Unquoted attribute value cannot contain U+0022 ("), U+0027 (\'), U+003C (<), U+003D (=), and U+0060 (`).',
- [19 /* ErrorCodes.UNEXPECTED_EQUALS_SIGN_BEFORE_ATTRIBUTE_NAME */]: "Attribute name cannot start with '='.",
- [21 /* ErrorCodes.UNEXPECTED_QUESTION_MARK_INSTEAD_OF_TAG_NAME */]: "'<?' is allowed only in XML context.",
- [20 /* ErrorCodes.UNEXPECTED_NULL_CHARACTER */]: `Unexpected null character.`,
- [22 /* ErrorCodes.UNEXPECTED_SOLIDUS_IN_TAG */]: "Illegal '/' in tags.",
- // Vue-specific parse errors
- [23 /* ErrorCodes.X_INVALID_END_TAG */]: 'Invalid end tag.',
- [24 /* ErrorCodes.X_MISSING_END_TAG */]: 'Element is missing end tag.',
- [25 /* ErrorCodes.X_MISSING_INTERPOLATION_END */]: 'Interpolation end sign was not found.',
- [27 /* ErrorCodes.X_MISSING_DYNAMIC_DIRECTIVE_ARGUMENT_END */]: 'End bracket for dynamic directive argument was not found. ' +
- 'Note that dynamic directive argument cannot contain spaces.',
- [26 /* ErrorCodes.X_MISSING_DIRECTIVE_NAME */]: 'Legal directive name was expected.',
- // transform errors
- [28 /* ErrorCodes.X_V_IF_NO_EXPRESSION */]: `v-if/v-else-if is missing expression.`,
- [29 /* ErrorCodes.X_V_IF_SAME_KEY */]: `v-if/else branches must use unique keys.`,
- [30 /* ErrorCodes.X_V_ELSE_NO_ADJACENT_IF */]: `v-else/v-else-if has no adjacent v-if or v-else-if.`,
- [31 /* ErrorCodes.X_V_FOR_NO_EXPRESSION */]: `v-for is missing expression.`,
- [32 /* ErrorCodes.X_V_FOR_MALFORMED_EXPRESSION */]: `v-for has invalid expression.`,
- [33 /* ErrorCodes.X_V_FOR_TEMPLATE_KEY_PLACEMENT */]: `<template v-for> key should be placed on the <template> tag.`,
- [34 /* ErrorCodes.X_V_BIND_NO_EXPRESSION */]: `v-bind is missing expression.`,
- [35 /* ErrorCodes.X_V_ON_NO_EXPRESSION */]: `v-on is missing expression.`,
- [36 /* ErrorCodes.X_V_SLOT_UNEXPECTED_DIRECTIVE_ON_SLOT_OUTLET */]: `Unexpected custom directive on <slot> outlet.`,
- [37 /* ErrorCodes.X_V_SLOT_MIXED_SLOT_USAGE */]: `Mixed v-slot usage on both the component and nested <template>.` +
- `When there are multiple named slots, all slots should use <template> ` +
- `syntax to avoid scope ambiguity.`,
- [38 /* ErrorCodes.X_V_SLOT_DUPLICATE_SLOT_NAMES */]: `Duplicate slot names found. `,
- [39 /* ErrorCodes.X_V_SLOT_EXTRANEOUS_DEFAULT_SLOT_CHILDREN */]: `Extraneous children found when component already has explicitly named ` +
- `default slot. These children will be ignored.`,
- [40 /* ErrorCodes.X_V_SLOT_MISPLACED */]: `v-slot can only be used on components or <template> tags.`,
- [41 /* ErrorCodes.X_V_MODEL_NO_EXPRESSION */]: `v-model is missing expression.`,
- [42 /* ErrorCodes.X_V_MODEL_MALFORMED_EXPRESSION */]: `v-model value must be a valid JavaScript member expression.`,
- [43 /* ErrorCodes.X_V_MODEL_ON_SCOPE_VARIABLE */]: `v-model cannot be used on v-for or v-slot scope variables because they are not writable.`,
- [44 /* ErrorCodes.X_V_MODEL_ON_PROPS */]: `v-model cannot be used on a prop, because local prop bindings are not writable.\nUse a v-bind binding combined with a v-on listener that emits update:x event instead.`,
- [45 /* ErrorCodes.X_INVALID_EXPRESSION */]: `Error parsing JavaScript expression: `,
- [46 /* ErrorCodes.X_KEEP_ALIVE_INVALID_CHILDREN */]: `<KeepAlive> expects exactly one child component.`,
- // generic errors
- [47 /* ErrorCodes.X_PREFIX_ID_NOT_SUPPORTED */]: `"prefixIdentifiers" option is not supported in this build of compiler.`,
- [48 /* ErrorCodes.X_MODULE_MODE_NOT_SUPPORTED */]: `ES module mode is not supported in this build of compiler.`,
- [49 /* ErrorCodes.X_CACHE_HANDLER_NOT_SUPPORTED */]: `"cacheHandlers" option is only supported when the "prefixIdentifiers" option is enabled.`,
- [50 /* ErrorCodes.X_SCOPE_ID_NOT_SUPPORTED */]: `"scopeId" option is only supported in module mode.`,
- // just to fulfill types
- [51 /* ErrorCodes.__EXTEND_POINT__ */]: ``
- };
- const FRAGMENT = Symbol(``);
- const TELEPORT = Symbol(``);
- const SUSPENSE = Symbol(``);
- const KEEP_ALIVE = Symbol(``);
- const BASE_TRANSITION = Symbol(``);
- const OPEN_BLOCK = Symbol(``);
- const CREATE_BLOCK = Symbol(``);
- const CREATE_ELEMENT_BLOCK = Symbol(``);
- const CREATE_VNODE = Symbol(``);
- const CREATE_ELEMENT_VNODE = Symbol(``);
- const CREATE_COMMENT = Symbol(``);
- const CREATE_TEXT = Symbol(``);
- const CREATE_STATIC = Symbol(``);
- const RESOLVE_COMPONENT = Symbol(``);
- const RESOLVE_DYNAMIC_COMPONENT = Symbol(``);
- const RESOLVE_DIRECTIVE = Symbol(``);
- const RESOLVE_FILTER = Symbol(``);
- const WITH_DIRECTIVES = Symbol(``);
- const RENDER_LIST = Symbol(``);
- const RENDER_SLOT = Symbol(``);
- const CREATE_SLOTS = Symbol(``);
- const TO_DISPLAY_STRING = Symbol(``);
- const MERGE_PROPS = Symbol(``);
- const NORMALIZE_CLASS = Symbol(``);
- const NORMALIZE_STYLE = Symbol(``);
- const NORMALIZE_PROPS = Symbol(``);
- const GUARD_REACTIVE_PROPS = Symbol(``);
- const TO_HANDLERS = Symbol(``);
- const CAMELIZE = Symbol(``);
- const CAPITALIZE = Symbol(``);
- const TO_HANDLER_KEY = Symbol(``);
- const SET_BLOCK_TRACKING = Symbol(``);
- const PUSH_SCOPE_ID = Symbol(``);
- const POP_SCOPE_ID = Symbol(``);
- const WITH_CTX = Symbol(``);
- const UNREF = Symbol(``);
- const IS_REF = Symbol(``);
- const WITH_MEMO = Symbol(``);
- const IS_MEMO_SAME = Symbol(``);
- // Name mapping for runtime helpers that need to be imported from 'vue' in
- // generated code. Make sure these are correctly exported in the runtime!
- const helperNameMap = {
- [FRAGMENT]: `Fragment`,
- [TELEPORT]: `Teleport`,
- [SUSPENSE]: `Suspense`,
- [KEEP_ALIVE]: `KeepAlive`,
- [BASE_TRANSITION]: `BaseTransition`,
- [OPEN_BLOCK]: `openBlock`,
- [CREATE_BLOCK]: `createBlock`,
- [CREATE_ELEMENT_BLOCK]: `createElementBlock`,
- [CREATE_VNODE]: `createVNode`,
- [CREATE_ELEMENT_VNODE]: `createElementVNode`,
- [CREATE_COMMENT]: `createCommentVNode`,
- [CREATE_TEXT]: `createTextVNode`,
- [CREATE_STATIC]: `createStaticVNode`,
- [RESOLVE_COMPONENT]: `resolveComponent`,
- [RESOLVE_DYNAMIC_COMPONENT]: `resolveDynamicComponent`,
- [RESOLVE_DIRECTIVE]: `resolveDirective`,
- [RESOLVE_FILTER]: `resolveFilter`,
- [WITH_DIRECTIVES]: `withDirectives`,
- [RENDER_LIST]: `renderList`,
- [RENDER_SLOT]: `renderSlot`,
- [CREATE_SLOTS]: `createSlots`,
- [TO_DISPLAY_STRING]: `toDisplayString`,
- [MERGE_PROPS]: `mergeProps`,
- [NORMALIZE_CLASS]: `normalizeClass`,
- [NORMALIZE_STYLE]: `normalizeStyle`,
- [NORMALIZE_PROPS]: `normalizeProps`,
- [GUARD_REACTIVE_PROPS]: `guardReactiveProps`,
- [TO_HANDLERS]: `toHandlers`,
- [CAMELIZE]: `camelize`,
- [CAPITALIZE]: `capitalize`,
- [TO_HANDLER_KEY]: `toHandlerKey`,
- [SET_BLOCK_TRACKING]: `setBlockTracking`,
- [PUSH_SCOPE_ID]: `pushScopeId`,
- [POP_SCOPE_ID]: `popScopeId`,
- [WITH_CTX]: `withCtx`,
- [UNREF]: `unref`,
- [IS_REF]: `isRef`,
- [WITH_MEMO]: `withMemo`,
- [IS_MEMO_SAME]: `isMemoSame`
- };
- function registerRuntimeHelpers(helpers) {
- Object.getOwnPropertySymbols(helpers).forEach(s => {
- helperNameMap[s] = helpers[s];
- });
- }
- // AST Utilities ---------------------------------------------------------------
- // Some expressions, e.g. sequence and conditional expressions, are never
- // associated with template nodes, so their source locations are just a stub.
- // Container types like CompoundExpression also don't need a real location.
- const locStub = {
- source: '',
- start: { line: 1, column: 1, offset: 0 },
- end: { line: 1, column: 1, offset: 0 }
- };
- function createRoot(children, loc = locStub) {
- return {
- type: 0 /* NodeTypes.ROOT */,
- children,
- helpers: [],
- components: [],
- directives: [],
- hoists: [],
- imports: [],
- cached: 0,
- temps: 0,
- codegenNode: undefined,
- loc
- };
- }
- function createVNodeCall(context, tag, props, children, patchFlag, dynamicProps, directives, isBlock = false, disableTracking = false, isComponent = false, loc = locStub) {
- if (context) {
- if (isBlock) {
- context.helper(OPEN_BLOCK);
- context.helper(getVNodeBlockHelper(context.inSSR, isComponent));
- }
- else {
- context.helper(getVNodeHelper(context.inSSR, isComponent));
- }
- if (directives) {
- context.helper(WITH_DIRECTIVES);
- }
- }
- return {
- type: 13 /* NodeTypes.VNODE_CALL */,
- tag,
- props,
- children,
- patchFlag,
- dynamicProps,
- directives,
- isBlock,
- disableTracking,
- isComponent,
- loc
- };
- }
- function createArrayExpression(elements, loc = locStub) {
- return {
- type: 17 /* NodeTypes.JS_ARRAY_EXPRESSION */,
- loc,
- elements
- };
- }
- function createObjectExpression(properties, loc = locStub) {
- return {
- type: 15 /* NodeTypes.JS_OBJECT_EXPRESSION */,
- loc,
- properties
- };
- }
- function createObjectProperty(key, value) {
- return {
- type: 16 /* NodeTypes.JS_PROPERTY */,
- loc: locStub,
- key: shared.isString(key) ? createSimpleExpression(key, true) : key,
- value
- };
- }
- function createSimpleExpression(content, isStatic = false, loc = locStub, constType = 0 /* ConstantTypes.NOT_CONSTANT */) {
- return {
- type: 4 /* NodeTypes.SIMPLE_EXPRESSION */,
- loc,
- content,
- isStatic,
- constType: isStatic ? 3 /* ConstantTypes.CAN_STRINGIFY */ : constType
- };
- }
- function createInterpolation(content, loc) {
- return {
- type: 5 /* NodeTypes.INTERPOLATION */,
- loc,
- content: shared.isString(content)
- ? createSimpleExpression(content, false, loc)
- : content
- };
- }
- function createCompoundExpression(children, loc = locStub) {
- return {
- type: 8 /* NodeTypes.COMPOUND_EXPRESSION */,
- loc,
- children
- };
- }
- function createCallExpression(callee, args = [], loc = locStub) {
- return {
- type: 14 /* NodeTypes.JS_CALL_EXPRESSION */,
- loc,
- callee,
- arguments: args
- };
- }
- function createFunctionExpression(params, returns = undefined, newline = false, isSlot = false, loc = locStub) {
- return {
- type: 18 /* NodeTypes.JS_FUNCTION_EXPRESSION */,
- params,
- returns,
- newline,
- isSlot,
- loc
- };
- }
- function createConditionalExpression(test, consequent, alternate, newline = true) {
- return {
- type: 19 /* NodeTypes.JS_CONDITIONAL_EXPRESSION */,
- test,
- consequent,
- alternate,
- newline,
- loc: locStub
- };
- }
- function createCacheExpression(index, value, isVNode = false) {
- return {
- type: 20 /* NodeTypes.JS_CACHE_EXPRESSION */,
- index,
- value,
- isVNode,
- loc: locStub
- };
- }
- function createBlockStatement(body) {
- return {
- type: 21 /* NodeTypes.JS_BLOCK_STATEMENT */,
- body,
- loc: locStub
- };
- }
- function createTemplateLiteral(elements) {
- return {
- type: 22 /* NodeTypes.JS_TEMPLATE_LITERAL */,
- elements,
- loc: locStub
- };
- }
- function createIfStatement(test, consequent, alternate) {
- return {
- type: 23 /* NodeTypes.JS_IF_STATEMENT */,
- test,
- consequent,
- alternate,
- loc: locStub
- };
- }
- function createAssignmentExpression(left, right) {
- return {
- type: 24 /* NodeTypes.JS_ASSIGNMENT_EXPRESSION */,
- left,
- right,
- loc: locStub
- };
- }
- function createSequenceExpression(expressions) {
- return {
- type: 25 /* NodeTypes.JS_SEQUENCE_EXPRESSION */,
- expressions,
- loc: locStub
- };
- }
- function createReturnStatement(returns) {
- return {
- type: 26 /* NodeTypes.JS_RETURN_STATEMENT */,
- returns,
- loc: locStub
- };
- }
- const isStaticExp = (p) => p.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */ && p.isStatic;
- const isBuiltInType = (tag, expected) => tag === expected || tag === shared.hyphenate(expected);
- function isCoreComponent(tag) {
- if (isBuiltInType(tag, 'Teleport')) {
- return TELEPORT;
- }
- else if (isBuiltInType(tag, 'Suspense')) {
- return SUSPENSE;
- }
- else if (isBuiltInType(tag, 'KeepAlive')) {
- return KEEP_ALIVE;
- }
- else if (isBuiltInType(tag, 'BaseTransition')) {
- return BASE_TRANSITION;
- }
- }
- const nonIdentifierRE = /^\d|[^\$\w]/;
- const isSimpleIdentifier = (name) => !nonIdentifierRE.test(name);
- const validFirstIdentCharRE = /[A-Za-z_$\xA0-\uFFFF]/;
- const validIdentCharRE = /[\.\?\w$\xA0-\uFFFF]/;
- const whitespaceRE = /\s+[.[]\s*|\s*[.[]\s+/g;
- /**
- * Simple lexer to check if an expression is a member expression. This is
- * lax and only checks validity at the root level (i.e. does not validate exps
- * inside square brackets), but it's ok since these are only used on template
- * expressions and false positives are invalid expressions in the first place.
- */
- const isMemberExpressionBrowser = (path) => {
- // remove whitespaces around . or [ first
- path = path.trim().replace(whitespaceRE, s => s.trim());
- let state = 0 /* MemberExpLexState.inMemberExp */;
- let stateStack = [];
- let currentOpenBracketCount = 0;
- let currentOpenParensCount = 0;
- let currentStringType = null;
- for (let i = 0; i < path.length; i++) {
- const char = path.charAt(i);
- switch (state) {
- case 0 /* MemberExpLexState.inMemberExp */:
- if (char === '[') {
- stateStack.push(state);
- state = 1 /* MemberExpLexState.inBrackets */;
- currentOpenBracketCount++;
- }
- else if (char === '(') {
- stateStack.push(state);
- state = 2 /* MemberExpLexState.inParens */;
- currentOpenParensCount++;
- }
- else if (!(i === 0 ? validFirstIdentCharRE : validIdentCharRE).test(char)) {
- return false;
- }
- break;
- case 1 /* MemberExpLexState.inBrackets */:
- if (char === `'` || char === `"` || char === '`') {
- stateStack.push(state);
- state = 3 /* MemberExpLexState.inString */;
- currentStringType = char;
- }
- else if (char === `[`) {
- currentOpenBracketCount++;
- }
- else if (char === `]`) {
- if (!--currentOpenBracketCount) {
- state = stateStack.pop();
- }
- }
- break;
- case 2 /* MemberExpLexState.inParens */:
- if (char === `'` || char === `"` || char === '`') {
- stateStack.push(state);
- state = 3 /* MemberExpLexState.inString */;
- currentStringType = char;
- }
- else if (char === `(`) {
- currentOpenParensCount++;
- }
- else if (char === `)`) {
- // if the exp ends as a call then it should not be considered valid
- if (i === path.length - 1) {
- return false;
- }
- if (!--currentOpenParensCount) {
- state = stateStack.pop();
- }
- }
- break;
- case 3 /* MemberExpLexState.inString */:
- if (char === currentStringType) {
- state = stateStack.pop();
- currentStringType = null;
- }
- break;
- }
- }
- return !currentOpenBracketCount && !currentOpenParensCount;
- };
- const isMemberExpressionNode = (path, context) => {
- try {
- let ret = parser.parseExpression(path, {
- plugins: context.expressionPlugins
- });
- if (ret.type === 'TSAsExpression' || ret.type === 'TSTypeAssertion') {
- ret = ret.expression;
- }
- return (ret.type === 'MemberExpression' ||
- ret.type === 'OptionalMemberExpression' ||
- ret.type === 'Identifier');
- }
- catch (e) {
- return false;
- }
- };
- const isMemberExpression = isMemberExpressionNode;
- function getInnerRange(loc, offset, length) {
- const source = loc.source.slice(offset, offset + length);
- const newLoc = {
- source,
- start: advancePositionWithClone(loc.start, loc.source, offset),
- end: loc.end
- };
- if (length != null) {
- newLoc.end = advancePositionWithClone(loc.start, loc.source, offset + length);
- }
- return newLoc;
- }
- function advancePositionWithClone(pos, source, numberOfCharacters = source.length) {
- return advancePositionWithMutation(shared.extend({}, pos), source, numberOfCharacters);
- }
- // advance by mutation without cloning (for performance reasons), since this
- // gets called a lot in the parser
- function advancePositionWithMutation(pos, source, numberOfCharacters = source.length) {
- let linesCount = 0;
- let lastNewLinePos = -1;
- for (let i = 0; i < numberOfCharacters; i++) {
- if (source.charCodeAt(i) === 10 /* newline char code */) {
- linesCount++;
- lastNewLinePos = i;
- }
- }
- pos.offset += numberOfCharacters;
- pos.line += linesCount;
- pos.column =
- lastNewLinePos === -1
- ? pos.column + numberOfCharacters
- : numberOfCharacters - lastNewLinePos;
- return pos;
- }
- function assert(condition, msg) {
- /* istanbul ignore if */
- if (!condition) {
- throw new Error(msg || `unexpected compiler condition`);
- }
- }
- function findDir(node, name, allowEmpty = false) {
- for (let i = 0; i < node.props.length; i++) {
- const p = node.props[i];
- if (p.type === 7 /* NodeTypes.DIRECTIVE */ &&
- (allowEmpty || p.exp) &&
- (shared.isString(name) ? p.name === name : name.test(p.name))) {
- return p;
- }
- }
- }
- function findProp(node, name, dynamicOnly = false, allowEmpty = false) {
- for (let i = 0; i < node.props.length; i++) {
- const p = node.props[i];
- if (p.type === 6 /* NodeTypes.ATTRIBUTE */) {
- if (dynamicOnly)
- continue;
- if (p.name === name && (p.value || allowEmpty)) {
- return p;
- }
- }
- else if (p.name === 'bind' &&
- (p.exp || allowEmpty) &&
- isStaticArgOf(p.arg, name)) {
- return p;
- }
- }
- }
- function isStaticArgOf(arg, name) {
- return !!(arg && isStaticExp(arg) && arg.content === name);
- }
- function hasDynamicKeyVBind(node) {
- return node.props.some(p => p.type === 7 /* NodeTypes.DIRECTIVE */ &&
- p.name === 'bind' &&
- (!p.arg || // v-bind="obj"
- p.arg.type !== 4 /* NodeTypes.SIMPLE_EXPRESSION */ || // v-bind:[_ctx.foo]
- !p.arg.isStatic) // v-bind:[foo]
- );
- }
- function isText(node) {
- return node.type === 5 /* NodeTypes.INTERPOLATION */ || node.type === 2 /* NodeTypes.TEXT */;
- }
- function isVSlot(p) {
- return p.type === 7 /* NodeTypes.DIRECTIVE */ && p.name === 'slot';
- }
- function isTemplateNode(node) {
- return (node.type === 1 /* NodeTypes.ELEMENT */ && node.tagType === 3 /* ElementTypes.TEMPLATE */);
- }
- function isSlotOutlet(node) {
- return node.type === 1 /* NodeTypes.ELEMENT */ && node.tagType === 2 /* ElementTypes.SLOT */;
- }
- function getVNodeHelper(ssr, isComponent) {
- return ssr || isComponent ? CREATE_VNODE : CREATE_ELEMENT_VNODE;
- }
- function getVNodeBlockHelper(ssr, isComponent) {
- return ssr || isComponent ? CREATE_BLOCK : CREATE_ELEMENT_BLOCK;
- }
- const propsHelperSet = new Set([NORMALIZE_PROPS, GUARD_REACTIVE_PROPS]);
- function getUnnormalizedProps(props, callPath = []) {
- if (props &&
- !shared.isString(props) &&
- props.type === 14 /* NodeTypes.JS_CALL_EXPRESSION */) {
- const callee = props.callee;
- if (!shared.isString(callee) && propsHelperSet.has(callee)) {
- return getUnnormalizedProps(props.arguments[0], callPath.concat(props));
- }
- }
- return [props, callPath];
- }
- function injectProp(node, prop, context) {
- let propsWithInjection;
- /**
- * 1. mergeProps(...)
- * 2. toHandlers(...)
- * 3. normalizeProps(...)
- * 4. normalizeProps(guardReactiveProps(...))
- *
- * we need to get the real props before normalization
- */
- let props = node.type === 13 /* NodeTypes.VNODE_CALL */ ? node.props : node.arguments[2];
- let callPath = [];
- let parentCall;
- if (props &&
- !shared.isString(props) &&
- props.type === 14 /* NodeTypes.JS_CALL_EXPRESSION */) {
- const ret = getUnnormalizedProps(props);
- props = ret[0];
- callPath = ret[1];
- parentCall = callPath[callPath.length - 1];
- }
- if (props == null || shared.isString(props)) {
- propsWithInjection = createObjectExpression([prop]);
- }
- else if (props.type === 14 /* NodeTypes.JS_CALL_EXPRESSION */) {
- // merged props... add ours
- // only inject key to object literal if it's the first argument so that
- // if doesn't override user provided keys
- const first = props.arguments[0];
- if (!shared.isString(first) && first.type === 15 /* NodeTypes.JS_OBJECT_EXPRESSION */) {
- // #6631
- if (!hasProp(prop, first)) {
- first.properties.unshift(prop);
- }
- }
- else {
- if (props.callee === TO_HANDLERS) {
- // #2366
- propsWithInjection = createCallExpression(context.helper(MERGE_PROPS), [
- createObjectExpression([prop]),
- props
- ]);
- }
- else {
- props.arguments.unshift(createObjectExpression([prop]));
- }
- }
- !propsWithInjection && (propsWithInjection = props);
- }
- else if (props.type === 15 /* NodeTypes.JS_OBJECT_EXPRESSION */) {
- if (!hasProp(prop, props)) {
- props.properties.unshift(prop);
- }
- propsWithInjection = props;
- }
- else {
- // single v-bind with expression, return a merged replacement
- propsWithInjection = createCallExpression(context.helper(MERGE_PROPS), [
- createObjectExpression([prop]),
- props
- ]);
- // in the case of nested helper call, e.g. `normalizeProps(guardReactiveProps(props))`,
- // it will be rewritten as `normalizeProps(mergeProps({ key: 0 }, props))`,
- // the `guardReactiveProps` will no longer be needed
- if (parentCall && parentCall.callee === GUARD_REACTIVE_PROPS) {
- parentCall = callPath[callPath.length - 2];
- }
- }
- if (node.type === 13 /* NodeTypes.VNODE_CALL */) {
- if (parentCall) {
- parentCall.arguments[0] = propsWithInjection;
- }
- else {
- node.props = propsWithInjection;
- }
- }
- else {
- if (parentCall) {
- parentCall.arguments[0] = propsWithInjection;
- }
- else {
- node.arguments[2] = propsWithInjection;
- }
- }
- }
- // check existing key to avoid overriding user provided keys
- function hasProp(prop, props) {
- let result = false;
- if (prop.key.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */) {
- const propKeyName = prop.key.content;
- result = props.properties.some(p => p.key.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */ &&
- p.key.content === propKeyName);
- }
- return result;
- }
- function toValidAssetId(name, type) {
- // see issue#4422, we need adding identifier on validAssetId if variable `name` has specific character
- return `_${type}_${name.replace(/[^\w]/g, (searchValue, replaceValue) => {
- return searchValue === '-' ? '_' : name.charCodeAt(replaceValue).toString();
- })}`;
- }
- // Check if a node contains expressions that reference current context scope ids
- function hasScopeRef(node, ids) {
- if (!node || Object.keys(ids).length === 0) {
- return false;
- }
- switch (node.type) {
- case 1 /* NodeTypes.ELEMENT */:
- for (let i = 0; i < node.props.length; i++) {
- const p = node.props[i];
- if (p.type === 7 /* NodeTypes.DIRECTIVE */ &&
- (hasScopeRef(p.arg, ids) || hasScopeRef(p.exp, ids))) {
- return true;
- }
- }
- return node.children.some(c => hasScopeRef(c, ids));
- case 11 /* NodeTypes.FOR */:
- if (hasScopeRef(node.source, ids)) {
- return true;
- }
- return node.children.some(c => hasScopeRef(c, ids));
- case 9 /* NodeTypes.IF */:
- return node.branches.some(b => hasScopeRef(b, ids));
- case 10 /* NodeTypes.IF_BRANCH */:
- if (hasScopeRef(node.condition, ids)) {
- return true;
- }
- return node.children.some(c => hasScopeRef(c, ids));
- case 4 /* NodeTypes.SIMPLE_EXPRESSION */:
- return (!node.isStatic &&
- isSimpleIdentifier(node.content) &&
- !!ids[node.content]);
- case 8 /* NodeTypes.COMPOUND_EXPRESSION */:
- return node.children.some(c => shared.isObject(c) && hasScopeRef(c, ids));
- case 5 /* NodeTypes.INTERPOLATION */:
- case 12 /* NodeTypes.TEXT_CALL */:
- return hasScopeRef(node.content, ids);
- case 2 /* NodeTypes.TEXT */:
- case 3 /* NodeTypes.COMMENT */:
- return false;
- default:
- return false;
- }
- }
- function getMemoedVNodeCall(node) {
- if (node.type === 14 /* NodeTypes.JS_CALL_EXPRESSION */ && node.callee === WITH_MEMO) {
- return node.arguments[1].returns;
- }
- else {
- return node;
- }
- }
- function makeBlock(node, { helper, removeHelper, inSSR }) {
- if (!node.isBlock) {
- node.isBlock = true;
- removeHelper(getVNodeHelper(inSSR, node.isComponent));
- helper(OPEN_BLOCK);
- helper(getVNodeBlockHelper(inSSR, node.isComponent));
- }
- }
- const deprecationData = {
- ["COMPILER_IS_ON_ELEMENT" /* CompilerDeprecationTypes.COMPILER_IS_ON_ELEMENT */]: {
- message: `Platform-native elements with "is" prop will no longer be ` +
- `treated as components in Vue 3 unless the "is" value is explicitly ` +
- `prefixed with "vue:".`,
- link: `https://v3-migration.vuejs.org/breaking-changes/custom-elements-interop.html`
- },
- ["COMPILER_V_BIND_SYNC" /* CompilerDeprecationTypes.COMPILER_V_BIND_SYNC */]: {
- message: key => `.sync modifier for v-bind has been removed. Use v-model with ` +
- `argument instead. \`v-bind:${key}.sync\` should be changed to ` +
- `\`v-model:${key}\`.`,
- link: `https://v3-migration.vuejs.org/breaking-changes/v-model.html`
- },
- ["COMPILER_V_BIND_PROP" /* CompilerDeprecationTypes.COMPILER_V_BIND_PROP */]: {
- message: `.prop modifier for v-bind has been removed and no longer necessary. ` +
- `Vue 3 will automatically set a binding as DOM property when appropriate.`
- },
- ["COMPILER_V_BIND_OBJECT_ORDER" /* CompilerDeprecationTypes.COMPILER_V_BIND_OBJECT_ORDER */]: {
- message: `v-bind="obj" usage is now order sensitive and behaves like JavaScript ` +
- `object spread: it will now overwrite an existing non-mergeable attribute ` +
- `that appears before v-bind in the case of conflict. ` +
- `To retain 2.x behavior, move v-bind to make it the first attribute. ` +
- `You can also suppress this warning if the usage is intended.`,
- link: `https://v3-migration.vuejs.org/breaking-changes/v-bind.html`
- },
- ["COMPILER_V_ON_NATIVE" /* CompilerDeprecationTypes.COMPILER_V_ON_NATIVE */]: {
- message: `.native modifier for v-on has been removed as is no longer necessary.`,
- link: `https://v3-migration.vuejs.org/breaking-changes/v-on-native-modifier-removed.html`
- },
- ["COMPILER_V_IF_V_FOR_PRECEDENCE" /* CompilerDeprecationTypes.COMPILER_V_IF_V_FOR_PRECEDENCE */]: {
- message: `v-if / v-for precedence when used on the same element has changed ` +
- `in Vue 3: v-if now takes higher precedence and will no longer have ` +
- `access to v-for scope variables. It is best to avoid the ambiguity ` +
- `with <template> tags or use a computed property that filters v-for ` +
- `data source.`,
- link: `https://v3-migration.vuejs.org/breaking-changes/v-if-v-for.html`
- },
- ["COMPILER_NATIVE_TEMPLATE" /* CompilerDeprecationTypes.COMPILER_NATIVE_TEMPLATE */]: {
- message: `<template> with no special directives will render as a native template ` +
- `element instead of its inner content in Vue 3.`
- },
- ["COMPILER_INLINE_TEMPLATE" /* CompilerDeprecationTypes.COMPILER_INLINE_TEMPLATE */]: {
- message: `"inline-template" has been removed in Vue 3.`,
- link: `https://v3-migration.vuejs.org/breaking-changes/inline-template-attribute.html`
- },
- ["COMPILER_FILTER" /* CompilerDeprecationTypes.COMPILER_FILTERS */]: {
- message: `filters have been removed in Vue 3. ` +
- `The "|" symbol will be treated as native JavaScript bitwise OR operator. ` +
- `Use method calls or computed properties instead.`,
- link: `https://v3-migration.vuejs.org/breaking-changes/filters.html`
- }
- };
- function getCompatValue(key, context) {
- const config = context.options
- ? context.options.compatConfig
- : context.compatConfig;
- const value = config && config[key];
- if (key === 'MODE') {
- return value || 3; // compiler defaults to v3 behavior
- }
- else {
- return value;
- }
- }
- function isCompatEnabled(key, context) {
- const mode = getCompatValue('MODE', context);
- const value = getCompatValue(key, context);
- // in v3 mode, only enable if explicitly set to true
- // otherwise enable for any non-false value
- return mode === 3 ? value === true : value !== false;
- }
- function checkCompatEnabled(key, context, loc, ...args) {
- const enabled = isCompatEnabled(key, context);
- return enabled;
- }
- function warnDeprecation(key, context, loc, ...args) {
- const val = getCompatValue(key, context);
- if (val === 'suppress-warning') {
- return;
- }
- const { message, link } = deprecationData[key];
- const msg = `(deprecation ${key}) ${typeof message === 'function' ? message(...args) : message}${link ? `\n Details: ${link}` : ``}`;
- const err = new SyntaxError(msg);
- err.code = key;
- if (loc)
- err.loc = loc;
- context.onWarn(err);
- }
- // The default decoder only provides escapes for characters reserved as part of
- // the template syntax, and is only used if the custom renderer did not provide
- // a platform-specific decoder.
- const decodeRE = /&(gt|lt|amp|apos|quot);/g;
- const decodeMap = {
- gt: '>',
- lt: '<',
- amp: '&',
- apos: "'",
- quot: '"'
- };
- const defaultParserOptions = {
- delimiters: [`{{`, `}}`],
- getNamespace: () => 0 /* Namespaces.HTML */,
- getTextMode: () => 0 /* TextModes.DATA */,
- isVoidTag: shared.NO,
- isPreTag: shared.NO,
- isCustomElement: shared.NO,
- decodeEntities: (rawText) => rawText.replace(decodeRE, (_, p1) => decodeMap[p1]),
- onError: defaultOnError,
- onWarn: defaultOnWarn,
- comments: false
- };
- function baseParse(content, options = {}) {
- const context = createParserContext(content, options);
- const start = getCursor(context);
- return createRoot(parseChildren(context, 0 /* TextModes.DATA */, []), getSelection(context, start));
- }
- function createParserContext(content, rawOptions) {
- const options = shared.extend({}, defaultParserOptions);
- let key;
- for (key in rawOptions) {
- // @ts-ignore
- options[key] =
- rawOptions[key] === undefined
- ? defaultParserOptions[key]
- : rawOptions[key];
- }
- return {
- options,
- column: 1,
- line: 1,
- offset: 0,
- originalSource: content,
- source: content,
- inPre: false,
- inVPre: false,
- onWarn: options.onWarn
- };
- }
- function parseChildren(context, mode, ancestors) {
- const parent = last(ancestors);
- const ns = parent ? parent.ns : 0 /* Namespaces.HTML */;
- const nodes = [];
- while (!isEnd(context, mode, ancestors)) {
- const s = context.source;
- let node = undefined;
- if (mode === 0 /* TextModes.DATA */ || mode === 1 /* TextModes.RCDATA */) {
- if (!context.inVPre && startsWith(s, context.options.delimiters[0])) {
- // '{{'
- node = parseInterpolation(context, mode);
- }
- else if (mode === 0 /* TextModes.DATA */ && s[0] === '<') {
- // https://html.spec.whatwg.org/multipage/parsing.html#tag-open-state
- if (s.length === 1) {
- emitError(context, 5 /* ErrorCodes.EOF_BEFORE_TAG_NAME */, 1);
- }
- else if (s[1] === '!') {
- // https://html.spec.whatwg.org/multipage/parsing.html#markup-declaration-open-state
- if (startsWith(s, '<!--')) {
- node = parseComment(context);
- }
- else if (startsWith(s, '<!DOCTYPE')) {
- // Ignore DOCTYPE by a limitation.
- node = parseBogusComment(context);
- }
- else if (startsWith(s, '<![CDATA[')) {
- if (ns !== 0 /* Namespaces.HTML */) {
- node = parseCDATA(context, ancestors);
- }
- else {
- emitError(context, 1 /* ErrorCodes.CDATA_IN_HTML_CONTENT */);
- node = parseBogusComment(context);
- }
- }
- else {
- emitError(context, 11 /* ErrorCodes.INCORRECTLY_OPENED_COMMENT */);
- node = parseBogusComment(context);
- }
- }
- else if (s[1] === '/') {
- // https://html.spec.whatwg.org/multipage/parsing.html#end-tag-open-state
- if (s.length === 2) {
- emitError(context, 5 /* ErrorCodes.EOF_BEFORE_TAG_NAME */, 2);
- }
- else if (s[2] === '>') {
- emitError(context, 14 /* ErrorCodes.MISSING_END_TAG_NAME */, 2);
- advanceBy(context, 3);
- continue;
- }
- else if (/[a-z]/i.test(s[2])) {
- emitError(context, 23 /* ErrorCodes.X_INVALID_END_TAG */);
- parseTag(context, 1 /* TagType.End */, parent);
- continue;
- }
- else {
- emitError(context, 12 /* ErrorCodes.INVALID_FIRST_CHARACTER_OF_TAG_NAME */, 2);
- node = parseBogusComment(context);
- }
- }
- else if (/[a-z]/i.test(s[1])) {
- node = parseElement(context, ancestors);
- // 2.x <template> with no directive compat
- if (isCompatEnabled("COMPILER_NATIVE_TEMPLATE" /* CompilerDeprecationTypes.COMPILER_NATIVE_TEMPLATE */, context) &&
- node &&
- node.tag === 'template' &&
- !node.props.some(p => p.type === 7 /* NodeTypes.DIRECTIVE */ &&
- isSpecialTemplateDirective(p.name))) {
- node = node.children;
- }
- }
- else if (s[1] === '?') {
- emitError(context, 21 /* ErrorCodes.UNEXPECTED_QUESTION_MARK_INSTEAD_OF_TAG_NAME */, 1);
- node = parseBogusComment(context);
- }
- else {
- emitError(context, 12 /* ErrorCodes.INVALID_FIRST_CHARACTER_OF_TAG_NAME */, 1);
- }
- }
- }
- if (!node) {
- node = parseText(context, mode);
- }
- if (shared.isArray(node)) {
- for (let i = 0; i < node.length; i++) {
- pushNode(nodes, node[i]);
- }
- }
- else {
- pushNode(nodes, node);
- }
- }
- // Whitespace handling strategy like v2
- let removedWhitespace = false;
- if (mode !== 2 /* TextModes.RAWTEXT */ && mode !== 1 /* TextModes.RCDATA */) {
- const shouldCondense = context.options.whitespace !== 'preserve';
- for (let i = 0; i < nodes.length; i++) {
- const node = nodes[i];
- if (node.type === 2 /* NodeTypes.TEXT */) {
- if (!context.inPre) {
- if (!/[^\t\r\n\f ]/.test(node.content)) {
- const prev = nodes[i - 1];
- const next = nodes[i + 1];
- // Remove if:
- // - the whitespace is the first or last node, or:
- // - (condense mode) the whitespace is between twos comments, or:
- // - (condense mode) the whitespace is between comment and element, or:
- // - (condense mode) the whitespace is between two elements AND contains newline
- if (!prev ||
- !next ||
- (shouldCondense &&
- ((prev.type === 3 /* NodeTypes.COMMENT */ &&
- next.type === 3 /* NodeTypes.COMMENT */) ||
- (prev.type === 3 /* NodeTypes.COMMENT */ &&
- next.type === 1 /* NodeTypes.ELEMENT */) ||
- (prev.type === 1 /* NodeTypes.ELEMENT */ &&
- next.type === 3 /* NodeTypes.COMMENT */) ||
- (prev.type === 1 /* NodeTypes.ELEMENT */ &&
- next.type === 1 /* NodeTypes.ELEMENT */ &&
- /[\r\n]/.test(node.content))))) {
- removedWhitespace = true;
- nodes[i] = null;
- }
- else {
- // Otherwise, the whitespace is condensed into a single space
- node.content = ' ';
- }
- }
- else if (shouldCondense) {
- // in condense mode, consecutive whitespaces in text are condensed
- // down to a single space.
- node.content = node.content.replace(/[\t\r\n\f ]+/g, ' ');
- }
- }
- else {
- // #6410 normalize windows newlines in <pre>:
- // in SSR, browsers normalize server-rendered \r\n into a single \n
- // in the DOM
- node.content = node.content.replace(/\r\n/g, '\n');
- }
- }
- // Remove comment nodes if desired by configuration.
- else if (node.type === 3 /* NodeTypes.COMMENT */ && !context.options.comments) {
- removedWhitespace = true;
- nodes[i] = null;
- }
- }
- if (context.inPre && parent && context.options.isPreTag(parent.tag)) {
- // remove leading newline per html spec
- // https://html.spec.whatwg.org/multipage/grouping-content.html#the-pre-element
- const first = nodes[0];
- if (first && first.type === 2 /* NodeTypes.TEXT */) {
- first.content = first.content.replace(/^\r?\n/, '');
- }
- }
- }
- return removedWhitespace ? nodes.filter(Boolean) : nodes;
- }
- function pushNode(nodes, node) {
- if (node.type === 2 /* NodeTypes.TEXT */) {
- const prev = last(nodes);
- // Merge if both this and the previous node are text and those are
- // consecutive. This happens for cases like "a < b".
- if (prev &&
- prev.type === 2 /* NodeTypes.TEXT */ &&
- prev.loc.end.offset === node.loc.start.offset) {
- prev.content += node.content;
- prev.loc.end = node.loc.end;
- prev.loc.source += node.loc.source;
- return;
- }
- }
- nodes.push(node);
- }
- function parseCDATA(context, ancestors) {
- advanceBy(context, 9);
- const nodes = parseChildren(context, 3 /* TextModes.CDATA */, ancestors);
- if (context.source.length === 0) {
- emitError(context, 6 /* ErrorCodes.EOF_IN_CDATA */);
- }
- else {
- advanceBy(context, 3);
- }
- return nodes;
- }
- function parseComment(context) {
- const start = getCursor(context);
- let content;
- // Regular comment.
- const match = /--(\!)?>/.exec(context.source);
- if (!match) {
- content = context.source.slice(4);
- advanceBy(context, context.source.length);
- emitError(context, 7 /* ErrorCodes.EOF_IN_COMMENT */);
- }
- else {
- if (match.index <= 3) {
- emitError(context, 0 /* ErrorCodes.ABRUPT_CLOSING_OF_EMPTY_COMMENT */);
- }
- if (match[1]) {
- emitError(context, 10 /* ErrorCodes.INCORRECTLY_CLOSED_COMMENT */);
- }
- content = context.source.slice(4, match.index);
- // Advancing with reporting nested comments.
- const s = context.source.slice(0, match.index);
- let prevIndex = 1, nestedIndex = 0;
- while ((nestedIndex = s.indexOf('<!--', prevIndex)) !== -1) {
- advanceBy(context, nestedIndex - prevIndex + 1);
- if (nestedIndex + 4 < s.length) {
- emitError(context, 16 /* ErrorCodes.NESTED_COMMENT */);
- }
- prevIndex = nestedIndex + 1;
- }
- advanceBy(context, match.index + match[0].length - prevIndex + 1);
- }
- return {
- type: 3 /* NodeTypes.COMMENT */,
- content,
- loc: getSelection(context, start)
- };
- }
- function parseBogusComment(context) {
- const start = getCursor(context);
- const contentStart = context.source[1] === '?' ? 1 : 2;
- let content;
- const closeIndex = context.source.indexOf('>');
- if (closeIndex === -1) {
- content = context.source.slice(contentStart);
- advanceBy(context, context.source.length);
- }
- else {
- content = context.source.slice(contentStart, closeIndex);
- advanceBy(context, closeIndex + 1);
- }
- return {
- type: 3 /* NodeTypes.COMMENT */,
- content,
- loc: getSelection(context, start)
- };
- }
- function parseElement(context, ancestors) {
- // Start tag.
- const wasInPre = context.inPre;
- const wasInVPre = context.inVPre;
- const parent = last(ancestors);
- const element = parseTag(context, 0 /* TagType.Start */, parent);
- const isPreBoundary = context.inPre && !wasInPre;
- const isVPreBoundary = context.inVPre && !wasInVPre;
- if (element.isSelfClosing || context.options.isVoidTag(element.tag)) {
- // #4030 self-closing <pre> tag
- if (isPreBoundary) {
- context.inPre = false;
- }
- if (isVPreBoundary) {
- context.inVPre = false;
- }
- return element;
- }
- // Children.
- ancestors.push(element);
- const mode = context.options.getTextMode(element, parent);
- const children = parseChildren(context, mode, ancestors);
- ancestors.pop();
- // 2.x inline-template compat
- {
- const inlineTemplateProp = element.props.find(p => p.type === 6 /* NodeTypes.ATTRIBUTE */ && p.name === 'inline-template');
- if (inlineTemplateProp &&
- checkCompatEnabled("COMPILER_INLINE_TEMPLATE" /* CompilerDeprecationTypes.COMPILER_INLINE_TEMPLATE */, context, inlineTemplateProp.loc)) {
- const loc = getSelection(context, element.loc.end);
- inlineTemplateProp.value = {
- type: 2 /* NodeTypes.TEXT */,
- content: loc.source,
- loc
- };
- }
- }
- element.children = children;
- // End tag.
- if (startsWithEndTagOpen(context.source, element.tag)) {
- parseTag(context, 1 /* TagType.End */, parent);
- }
- else {
- emitError(context, 24 /* ErrorCodes.X_MISSING_END_TAG */, 0, element.loc.start);
- if (context.source.length === 0 && element.tag.toLowerCase() === 'script') {
- const first = children[0];
- if (first && startsWith(first.loc.source, '<!--')) {
- emitError(context, 8 /* ErrorCodes.EOF_IN_SCRIPT_HTML_COMMENT_LIKE_TEXT */);
- }
- }
- }
- element.loc = getSelection(context, element.loc.start);
- if (isPreBoundary) {
- context.inPre = false;
- }
- if (isVPreBoundary) {
- context.inVPre = false;
- }
- return element;
- }
- const isSpecialTemplateDirective = /*#__PURE__*/ shared.makeMap(`if,else,else-if,for,slot`);
- function parseTag(context, type, parent) {
- // Tag open.
- const start = getCursor(context);
- const match = /^<\/?([a-z][^\t\r\n\f />]*)/i.exec(context.source);
- const tag = match[1];
- const ns = context.options.getNamespace(tag, parent);
- advanceBy(context, match[0].length);
- advanceSpaces(context);
- // save current state in case we need to re-parse attributes with v-pre
- const cursor = getCursor(context);
- const currentSource = context.source;
- // check <pre> tag
- if (context.options.isPreTag(tag)) {
- context.inPre = true;
- }
- // Attributes.
- let props = parseAttributes(context, type);
- // check v-pre
- if (type === 0 /* TagType.Start */ &&
- !context.inVPre &&
- props.some(p => p.type === 7 /* NodeTypes.DIRECTIVE */ && p.name === 'pre')) {
- context.inVPre = true;
- // reset context
- shared.extend(context, cursor);
- context.source = currentSource;
- // re-parse attrs and filter out v-pre itself
- props = parseAttributes(context, type).filter(p => p.name !== 'v-pre');
- }
- // Tag close.
- let isSelfClosing = false;
- if (context.source.length === 0) {
- emitError(context, 9 /* ErrorCodes.EOF_IN_TAG */);
- }
- else {
- isSelfClosing = startsWith(context.source, '/>');
- if (type === 1 /* TagType.End */ && isSelfClosing) {
- emitError(context, 4 /* ErrorCodes.END_TAG_WITH_TRAILING_SOLIDUS */);
- }
- advanceBy(context, isSelfClosing ? 2 : 1);
- }
- if (type === 1 /* TagType.End */) {
- return;
- }
- let tagType = 0 /* ElementTypes.ELEMENT */;
- if (!context.inVPre) {
- if (tag === 'slot') {
- tagType = 2 /* ElementTypes.SLOT */;
- }
- else if (tag === 'template') {
- if (props.some(p => p.type === 7 /* NodeTypes.DIRECTIVE */ && isSpecialTemplateDirective(p.name))) {
- tagType = 3 /* ElementTypes.TEMPLATE */;
- }
- }
- else if (isComponent(tag, props, context)) {
- tagType = 1 /* ElementTypes.COMPONENT */;
- }
- }
- return {
- type: 1 /* NodeTypes.ELEMENT */,
- ns,
- tag,
- tagType,
- props,
- isSelfClosing,
- children: [],
- loc: getSelection(context, start),
- codegenNode: undefined // to be created during transform phase
- };
- }
- function isComponent(tag, props, context) {
- const options = context.options;
- if (options.isCustomElement(tag)) {
- return false;
- }
- if (tag === 'component' ||
- /^[A-Z]/.test(tag) ||
- isCoreComponent(tag) ||
- (options.isBuiltInComponent && options.isBuiltInComponent(tag)) ||
- (options.isNativeTag && !options.isNativeTag(tag))) {
- return true;
- }
- // at this point the tag should be a native tag, but check for potential "is"
- // casting
- for (let i = 0; i < props.length; i++) {
- const p = props[i];
- if (p.type === 6 /* NodeTypes.ATTRIBUTE */) {
- if (p.name === 'is' && p.value) {
- if (p.value.content.startsWith('vue:')) {
- return true;
- }
- else if (checkCompatEnabled("COMPILER_IS_ON_ELEMENT" /* CompilerDeprecationTypes.COMPILER_IS_ON_ELEMENT */, context, p.loc)) {
- return true;
- }
- }
- }
- else {
- // directive
- // v-is (TODO Deprecate)
- if (p.name === 'is') {
- return true;
- }
- else if (
- // :is on plain element - only treat as component in compat mode
- p.name === 'bind' &&
- isStaticArgOf(p.arg, 'is') &&
- true &&
- checkCompatEnabled("COMPILER_IS_ON_ELEMENT" /* CompilerDeprecationTypes.COMPILER_IS_ON_ELEMENT */, context, p.loc)) {
- return true;
- }
- }
- }
- }
- function parseAttributes(context, type) {
- const props = [];
- const attributeNames = new Set();
- while (context.source.length > 0 &&
- !startsWith(context.source, '>') &&
- !startsWith(context.source, '/>')) {
- if (startsWith(context.source, '/')) {
- emitError(context, 22 /* ErrorCodes.UNEXPECTED_SOLIDUS_IN_TAG */);
- advanceBy(context, 1);
- advanceSpaces(context);
- continue;
- }
- if (type === 1 /* TagType.End */) {
- emitError(context, 3 /* ErrorCodes.END_TAG_WITH_ATTRIBUTES */);
- }
- const attr = parseAttribute(context, attributeNames);
- // Trim whitespace between class
- // https://github.com/vuejs/core/issues/4251
- if (attr.type === 6 /* NodeTypes.ATTRIBUTE */ &&
- attr.value &&
- attr.name === 'class') {
- attr.value.content = attr.value.content.replace(/\s+/g, ' ').trim();
- }
- if (type === 0 /* TagType.Start */) {
- props.push(attr);
- }
- if (/^[^\t\r\n\f />]/.test(context.source)) {
- emitError(context, 15 /* ErrorCodes.MISSING_WHITESPACE_BETWEEN_ATTRIBUTES */);
- }
- advanceSpaces(context);
- }
- return props;
- }
- function parseAttribute(context, nameSet) {
- // Name.
- const start = getCursor(context);
- const match = /^[^\t\r\n\f />][^\t\r\n\f />=]*/.exec(context.source);
- const name = match[0];
- if (nameSet.has(name)) {
- emitError(context, 2 /* ErrorCodes.DUPLICATE_ATTRIBUTE */);
- }
- nameSet.add(name);
- if (name[0] === '=') {
- emitError(context, 19 /* ErrorCodes.UNEXPECTED_EQUALS_SIGN_BEFORE_ATTRIBUTE_NAME */);
- }
- {
- const pattern = /["'<]/g;
- let m;
- while ((m = pattern.exec(name))) {
- emitError(context, 17 /* ErrorCodes.UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME */, m.index);
- }
- }
- advanceBy(context, name.length);
- // Value
- let value = undefined;
- if (/^[\t\r\n\f ]*=/.test(context.source)) {
- advanceSpaces(context);
- advanceBy(context, 1);
- advanceSpaces(context);
- value = parseAttributeValue(context);
- if (!value) {
- emitError(context, 13 /* ErrorCodes.MISSING_ATTRIBUTE_VALUE */);
- }
- }
- const loc = getSelection(context, start);
- if (!context.inVPre && /^(v-[A-Za-z0-9-]|:|\.|@|#)/.test(name)) {
- const match = /(?:^v-([a-z0-9-]+))?(?:(?::|^\.|^@|^#)(\[[^\]]+\]|[^\.]+))?(.+)?$/i.exec(name);
- let isPropShorthand = startsWith(name, '.');
- let dirName = match[1] ||
- (isPropShorthand || startsWith(name, ':')
- ? 'bind'
- : startsWith(name, '@')
- ? 'on'
- : 'slot');
- let arg;
- if (match[2]) {
- const isSlot = dirName === 'slot';
- const startOffset = name.lastIndexOf(match[2]);
- const loc = getSelection(context, getNewPosition(context, start, startOffset), getNewPosition(context, start, startOffset + match[2].length + ((isSlot && match[3]) || '').length));
- let content = match[2];
- let isStatic = true;
- if (content.startsWith('[')) {
- isStatic = false;
- if (!content.endsWith(']')) {
- emitError(context, 27 /* ErrorCodes.X_MISSING_DYNAMIC_DIRECTIVE_ARGUMENT_END */);
- content = content.slice(1);
- }
- else {
- content = content.slice(1, content.length - 1);
- }
- }
- else if (isSlot) {
- // #1241 special case for v-slot: vuetify relies extensively on slot
- // names containing dots. v-slot doesn't have any modifiers and Vue 2.x
- // supports such usage so we are keeping it consistent with 2.x.
- content += match[3] || '';
- }
- arg = {
- type: 4 /* NodeTypes.SIMPLE_EXPRESSION */,
- content,
- isStatic,
- constType: isStatic
- ? 3 /* ConstantTypes.CAN_STRINGIFY */
- : 0 /* ConstantTypes.NOT_CONSTANT */,
- loc
- };
- }
- if (value && value.isQuoted) {
- const valueLoc = value.loc;
- valueLoc.start.offset++;
- valueLoc.start.column++;
- valueLoc.end = advancePositionWithClone(valueLoc.start, value.content);
- valueLoc.source = valueLoc.source.slice(1, -1);
- }
- const modifiers = match[3] ? match[3].slice(1).split('.') : [];
- if (isPropShorthand)
- modifiers.push('prop');
- // 2.x compat v-bind:foo.sync -> v-model:foo
- if (dirName === 'bind' && arg) {
- if (modifiers.includes('sync') &&
- checkCompatEnabled("COMPILER_V_BIND_SYNC" /* CompilerDeprecationTypes.COMPILER_V_BIND_SYNC */, context, loc, arg.loc.source)) {
- dirName = 'model';
- modifiers.splice(modifiers.indexOf('sync'), 1);
- }
- }
- return {
- type: 7 /* NodeTypes.DIRECTIVE */,
- name: dirName,
- exp: value && {
- type: 4 /* NodeTypes.SIMPLE_EXPRESSION */,
- content: value.content,
- isStatic: false,
- // Treat as non-constant by default. This can be potentially set to
- // other values by `transformExpression` to make it eligible for hoisting.
- constType: 0 /* ConstantTypes.NOT_CONSTANT */,
- loc: value.loc
- },
- arg,
- modifiers,
- loc
- };
- }
- // missing directive name or illegal directive name
- if (!context.inVPre && startsWith(name, 'v-')) {
- emitError(context, 26 /* ErrorCodes.X_MISSING_DIRECTIVE_NAME */);
- }
- return {
- type: 6 /* NodeTypes.ATTRIBUTE */,
- name,
- value: value && {
- type: 2 /* NodeTypes.TEXT */,
- content: value.content,
- loc: value.loc
- },
- loc
- };
- }
- function parseAttributeValue(context) {
- const start = getCursor(context);
- let content;
- const quote = context.source[0];
- const isQuoted = quote === `"` || quote === `'`;
- if (isQuoted) {
- // Quoted value.
- advanceBy(context, 1);
- const endIndex = context.source.indexOf(quote);
- if (endIndex === -1) {
- content = parseTextData(context, context.source.length, 4 /* TextModes.ATTRIBUTE_VALUE */);
- }
- else {
- content = parseTextData(context, endIndex, 4 /* TextModes.ATTRIBUTE_VALUE */);
- advanceBy(context, 1);
- }
- }
- else {
- // Unquoted
- const match = /^[^\t\r\n\f >]+/.exec(context.source);
- if (!match) {
- return undefined;
- }
- const unexpectedChars = /["'<=`]/g;
- let m;
- while ((m = unexpectedChars.exec(match[0]))) {
- emitError(context, 18 /* ErrorCodes.UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE */, m.index);
- }
- content = parseTextData(context, match[0].length, 4 /* TextModes.ATTRIBUTE_VALUE */);
- }
- return { content, isQuoted, loc: getSelection(context, start) };
- }
- function parseInterpolation(context, mode) {
- const [open, close] = context.options.delimiters;
- const closeIndex = context.source.indexOf(close, open.length);
- if (closeIndex === -1) {
- emitError(context, 25 /* ErrorCodes.X_MISSING_INTERPOLATION_END */);
- return undefined;
- }
- const start = getCursor(context);
- advanceBy(context, open.length);
- const innerStart = getCursor(context);
- const innerEnd = getCursor(context);
- const rawContentLength = closeIndex - open.length;
- const rawContent = context.source.slice(0, rawContentLength);
- const preTrimContent = parseTextData(context, rawContentLength, mode);
- const content = preTrimContent.trim();
- const startOffset = preTrimContent.indexOf(content);
- if (startOffset > 0) {
- advancePositionWithMutation(innerStart, rawContent, startOffset);
- }
- const endOffset = rawContentLength - (preTrimContent.length - content.length - startOffset);
- advancePositionWithMutation(innerEnd, rawContent, endOffset);
- advanceBy(context, close.length);
- return {
- type: 5 /* NodeTypes.INTERPOLATION */,
- content: {
- type: 4 /* NodeTypes.SIMPLE_EXPRESSION */,
- isStatic: false,
- // Set `isConstant` to false by default and will decide in transformExpression
- constType: 0 /* ConstantTypes.NOT_CONSTANT */,
- content,
- loc: getSelection(context, innerStart, innerEnd)
- },
- loc: getSelection(context, start)
- };
- }
- function parseText(context, mode) {
- const endTokens = mode === 3 /* TextModes.CDATA */ ? [']]>'] : ['<', context.options.delimiters[0]];
- let endIndex = context.source.length;
- for (let i = 0; i < endTokens.length; i++) {
- const index = context.source.indexOf(endTokens[i], 1);
- if (index !== -1 && endIndex > index) {
- endIndex = index;
- }
- }
- const start = getCursor(context);
- const content = parseTextData(context, endIndex, mode);
- return {
- type: 2 /* NodeTypes.TEXT */,
- content,
- loc: getSelection(context, start)
- };
- }
- /**
- * Get text data with a given length from the current location.
- * This translates HTML entities in the text data.
- */
- function parseTextData(context, length, mode) {
- const rawText = context.source.slice(0, length);
- advanceBy(context, length);
- if (mode === 2 /* TextModes.RAWTEXT */ ||
- mode === 3 /* TextModes.CDATA */ ||
- !rawText.includes('&')) {
- return rawText;
- }
- else {
- // DATA or RCDATA containing "&"". Entity decoding required.
- return context.options.decodeEntities(rawText, mode === 4 /* TextModes.ATTRIBUTE_VALUE */);
- }
- }
- function getCursor(context) {
- const { column, line, offset } = context;
- return { column, line, offset };
- }
- function getSelection(context, start, end) {
- end = end || getCursor(context);
- return {
- start,
- end,
- source: context.originalSource.slice(start.offset, end.offset)
- };
- }
- function last(xs) {
- return xs[xs.length - 1];
- }
- function startsWith(source, searchString) {
- return source.startsWith(searchString);
- }
- function advanceBy(context, numberOfCharacters) {
- const { source } = context;
- advancePositionWithMutation(context, source, numberOfCharacters);
- context.source = source.slice(numberOfCharacters);
- }
- function advanceSpaces(context) {
- const match = /^[\t\r\n\f ]+/.exec(context.source);
- if (match) {
- advanceBy(context, match[0].length);
- }
- }
- function getNewPosition(context, start, numberOfCharacters) {
- return advancePositionWithClone(start, context.originalSource.slice(start.offset, numberOfCharacters), numberOfCharacters);
- }
- function emitError(context, code, offset, loc = getCursor(context)) {
- if (offset) {
- loc.offset += offset;
- loc.column += offset;
- }
- context.options.onError(createCompilerError(code, {
- start: loc,
- end: loc,
- source: ''
- }));
- }
- function isEnd(context, mode, ancestors) {
- const s = context.source;
- switch (mode) {
- case 0 /* TextModes.DATA */:
- if (startsWith(s, '</')) {
- // TODO: probably bad performance
- for (let i = ancestors.length - 1; i >= 0; --i) {
- if (startsWithEndTagOpen(s, ancestors[i].tag)) {
- return true;
- }
- }
- }
- break;
- case 1 /* TextModes.RCDATA */:
- case 2 /* TextModes.RAWTEXT */: {
- const parent = last(ancestors);
- if (parent && startsWithEndTagOpen(s, parent.tag)) {
- return true;
- }
- break;
- }
- case 3 /* TextModes.CDATA */:
- if (startsWith(s, ']]>')) {
- return true;
- }
- break;
- }
- return !s;
- }
- function startsWithEndTagOpen(source, tag) {
- return (startsWith(source, '</') &&
- source.slice(2, 2 + tag.length).toLowerCase() === tag.toLowerCase() &&
- /[\t\r\n\f />]/.test(source[2 + tag.length] || '>'));
- }
- function hoistStatic(root, context) {
- walk(root, context,
- // Root node is unfortunately non-hoistable due to potential parent
- // fallthrough attributes.
- isSingleElementRoot(root, root.children[0]));
- }
- function isSingleElementRoot(root, child) {
- const { children } = root;
- return (children.length === 1 &&
- child.type === 1 /* NodeTypes.ELEMENT */ &&
- !isSlotOutlet(child));
- }
- function walk(node, context, doNotHoistNode = false) {
- const { children } = node;
- const originalCount = children.length;
- let hoistedCount = 0;
- for (let i = 0; i < children.length; i++) {
- const child = children[i];
- // only plain elements & text calls are eligible for hoisting.
- if (child.type === 1 /* NodeTypes.ELEMENT */ &&
- child.tagType === 0 /* ElementTypes.ELEMENT */) {
- const constantType = doNotHoistNode
- ? 0 /* ConstantTypes.NOT_CONSTANT */
- : getConstantType(child, context);
- if (constantType > 0 /* ConstantTypes.NOT_CONSTANT */) {
- if (constantType >= 2 /* ConstantTypes.CAN_HOIST */) {
- child.codegenNode.patchFlag =
- -1 /* PatchFlags.HOISTED */ + (``);
- child.codegenNode = context.hoist(child.codegenNode);
- hoistedCount++;
- continue;
- }
- }
- else {
- // node may contain dynamic children, but its props may be eligible for
- // hoisting.
- const codegenNode = child.codegenNode;
- if (codegenNode.type === 13 /* NodeTypes.VNODE_CALL */) {
- const flag = getPatchFlag(codegenNode);
- if ((!flag ||
- flag === 512 /* PatchFlags.NEED_PATCH */ ||
- flag === 1 /* PatchFlags.TEXT */) &&
- getGeneratedPropsConstantType(child, context) >=
- 2 /* ConstantTypes.CAN_HOIST */) {
- const props = getNodeProps(child);
- if (props) {
- codegenNode.props = context.hoist(props);
- }
- }
- if (codegenNode.dynamicProps) {
- codegenNode.dynamicProps = context.hoist(codegenNode.dynamicProps);
- }
- }
- }
- }
- // walk further
- if (child.type === 1 /* NodeTypes.ELEMENT */) {
- const isComponent = child.tagType === 1 /* ElementTypes.COMPONENT */;
- if (isComponent) {
- context.scopes.vSlot++;
- }
- walk(child, context);
- if (isComponent) {
- context.scopes.vSlot--;
- }
- }
- else if (child.type === 11 /* NodeTypes.FOR */) {
- // Do not hoist v-for single child because it has to be a block
- walk(child, context, child.children.length === 1);
- }
- else if (child.type === 9 /* NodeTypes.IF */) {
- for (let i = 0; i < child.branches.length; i++) {
- // Do not hoist v-if single child because it has to be a block
- walk(child.branches[i], context, child.branches[i].children.length === 1);
- }
- }
- }
- if (hoistedCount && context.transformHoist) {
- context.transformHoist(children, context, node);
- }
- // all children were hoisted - the entire children array is hoistable.
- if (hoistedCount &&
- hoistedCount === originalCount &&
- node.type === 1 /* NodeTypes.ELEMENT */ &&
- node.tagType === 0 /* ElementTypes.ELEMENT */ &&
- node.codegenNode &&
- node.codegenNode.type === 13 /* NodeTypes.VNODE_CALL */ &&
- shared.isArray(node.codegenNode.children)) {
- node.codegenNode.children = context.hoist(createArrayExpression(node.codegenNode.children));
- }
- }
- function getConstantType(node, context) {
- const { constantCache } = context;
- switch (node.type) {
- case 1 /* NodeTypes.ELEMENT */:
- if (node.tagType !== 0 /* ElementTypes.ELEMENT */) {
- return 0 /* ConstantTypes.NOT_CONSTANT */;
- }
- const cached = constantCache.get(node);
- if (cached !== undefined) {
- return cached;
- }
- const codegenNode = node.codegenNode;
- if (codegenNode.type !== 13 /* NodeTypes.VNODE_CALL */) {
- return 0 /* ConstantTypes.NOT_CONSTANT */;
- }
- if (codegenNode.isBlock &&
- node.tag !== 'svg' &&
- node.tag !== 'foreignObject') {
- return 0 /* ConstantTypes.NOT_CONSTANT */;
- }
- const flag = getPatchFlag(codegenNode);
- if (!flag) {
- let returnType = 3 /* ConstantTypes.CAN_STRINGIFY */;
- // Element itself has no patch flag. However we still need to check:
- // 1. Even for a node with no patch flag, it is possible for it to contain
- // non-hoistable expressions that refers to scope variables, e.g. compiler
- // injected keys or cached event handlers. Therefore we need to always
- // check the codegenNode's props to be sure.
- const generatedPropsType = getGeneratedPropsConstantType(node, context);
- if (generatedPropsType === 0 /* ConstantTypes.NOT_CONSTANT */) {
- constantCache.set(node, 0 /* ConstantTypes.NOT_CONSTANT */);
- return 0 /* ConstantTypes.NOT_CONSTANT */;
- }
- if (generatedPropsType < returnType) {
- returnType = generatedPropsType;
- }
- // 2. its children.
- for (let i = 0; i < node.children.length; i++) {
- const childType = getConstantType(node.children[i], context);
- if (childType === 0 /* ConstantTypes.NOT_CONSTANT */) {
- constantCache.set(node, 0 /* ConstantTypes.NOT_CONSTANT */);
- return 0 /* ConstantTypes.NOT_CONSTANT */;
- }
- if (childType < returnType) {
- returnType = childType;
- }
- }
- // 3. if the type is not already CAN_SKIP_PATCH which is the lowest non-0
- // type, check if any of the props can cause the type to be lowered
- // we can skip can_patch because it's guaranteed by the absence of a
- // patchFlag.
- if (returnType > 1 /* ConstantTypes.CAN_SKIP_PATCH */) {
- for (let i = 0; i < node.props.length; i++) {
- const p = node.props[i];
- if (p.type === 7 /* NodeTypes.DIRECTIVE */ && p.name === 'bind' && p.exp) {
- const expType = getConstantType(p.exp, context);
- if (expType === 0 /* ConstantTypes.NOT_CONSTANT */) {
- constantCache.set(node, 0 /* ConstantTypes.NOT_CONSTANT */);
- return 0 /* ConstantTypes.NOT_CONSTANT */;
- }
- if (expType < returnType) {
- returnType = expType;
- }
- }
- }
- }
- // only svg/foreignObject could be block here, however if they are
- // static then they don't need to be blocks since there will be no
- // nested updates.
- if (codegenNode.isBlock) {
- // except set custom directives.
- for (let i = 0; i < node.props.length; i++) {
- const p = node.props[i];
- if (p.type === 7 /* NodeTypes.DIRECTIVE */) {
- constantCache.set(node, 0 /* ConstantTypes.NOT_CONSTANT */);
- return 0 /* ConstantTypes.NOT_CONSTANT */;
- }
- }
- context.removeHelper(OPEN_BLOCK);
- context.removeHelper(getVNodeBlockHelper(context.inSSR, codegenNode.isComponent));
- codegenNode.isBlock = false;
- context.helper(getVNodeHelper(context.inSSR, codegenNode.isComponent));
- }
- constantCache.set(node, returnType);
- return returnType;
- }
- else {
- constantCache.set(node, 0 /* ConstantTypes.NOT_CONSTANT */);
- return 0 /* ConstantTypes.NOT_CONSTANT */;
- }
- case 2 /* NodeTypes.TEXT */:
- case 3 /* NodeTypes.COMMENT */:
- return 3 /* ConstantTypes.CAN_STRINGIFY */;
- case 9 /* NodeTypes.IF */:
- case 11 /* NodeTypes.FOR */:
- case 10 /* NodeTypes.IF_BRANCH */:
- return 0 /* ConstantTypes.NOT_CONSTANT */;
- case 5 /* NodeTypes.INTERPOLATION */:
- case 12 /* NodeTypes.TEXT_CALL */:
- return getConstantType(node.content, context);
- case 4 /* NodeTypes.SIMPLE_EXPRESSION */:
- return node.constType;
- case 8 /* NodeTypes.COMPOUND_EXPRESSION */:
- let returnType = 3 /* ConstantTypes.CAN_STRINGIFY */;
- for (let i = 0; i < node.children.length; i++) {
- const child = node.children[i];
- if (shared.isString(child) || shared.isSymbol(child)) {
- continue;
- }
- const childType = getConstantType(child, context);
- if (childType === 0 /* ConstantTypes.NOT_CONSTANT */) {
- return 0 /* ConstantTypes.NOT_CONSTANT */;
- }
- else if (childType < returnType) {
- returnType = childType;
- }
- }
- return returnType;
- default:
- return 0 /* ConstantTypes.NOT_CONSTANT */;
- }
- }
- const allowHoistedHelperSet = new Set([
- NORMALIZE_CLASS,
- NORMALIZE_STYLE,
- NORMALIZE_PROPS,
- GUARD_REACTIVE_PROPS
- ]);
- function getConstantTypeOfHelperCall(value, context) {
- if (value.type === 14 /* NodeTypes.JS_CALL_EXPRESSION */ &&
- !shared.isString(value.callee) &&
- allowHoistedHelperSet.has(value.callee)) {
- const arg = value.arguments[0];
- if (arg.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */) {
- return getConstantType(arg, context);
- }
- else if (arg.type === 14 /* NodeTypes.JS_CALL_EXPRESSION */) {
- // in the case of nested helper call, e.g. `normalizeProps(guardReactiveProps(exp))`
- return getConstantTypeOfHelperCall(arg, context);
- }
- }
- return 0 /* ConstantTypes.NOT_CONSTANT */;
- }
- function getGeneratedPropsConstantType(node, context) {
- let returnType = 3 /* ConstantTypes.CAN_STRINGIFY */;
- const props = getNodeProps(node);
- if (props && props.type === 15 /* NodeTypes.JS_OBJECT_EXPRESSION */) {
- const { properties } = props;
- for (let i = 0; i < properties.length; i++) {
- const { key, value } = properties[i];
- const keyType = getConstantType(key, context);
- if (keyType === 0 /* ConstantTypes.NOT_CONSTANT */) {
- return keyType;
- }
- if (keyType < returnType) {
- returnType = keyType;
- }
- let valueType;
- if (value.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */) {
- valueType = getConstantType(value, context);
- }
- else if (value.type === 14 /* NodeTypes.JS_CALL_EXPRESSION */) {
- // some helper calls can be hoisted,
- // such as the `normalizeProps` generated by the compiler for pre-normalize class,
- // in this case we need to respect the ConstantType of the helper's arguments
- valueType = getConstantTypeOfHelperCall(value, context);
- }
- else {
- valueType = 0 /* ConstantTypes.NOT_CONSTANT */;
- }
- if (valueType === 0 /* ConstantTypes.NOT_CONSTANT */) {
- return valueType;
- }
- if (valueType < returnType) {
- returnType = valueType;
- }
- }
- }
- return returnType;
- }
- function getNodeProps(node) {
- const codegenNode = node.codegenNode;
- if (codegenNode.type === 13 /* NodeTypes.VNODE_CALL */) {
- return codegenNode.props;
- }
- }
- function getPatchFlag(node) {
- const flag = node.patchFlag;
- return flag ? parseInt(flag, 10) : undefined;
- }
- function createTransformContext(root, { filename = '', prefixIdentifiers = false, hoistStatic = false, cacheHandlers = false, nodeTransforms = [], directiveTransforms = {}, transformHoist = null, isBuiltInComponent = shared.NOOP, isCustomElement = shared.NOOP, expressionPlugins = [], scopeId = null, slotted = true, ssr = false, inSSR = false, ssrCssVars = ``, bindingMetadata = shared.EMPTY_OBJ, inline = false, isTS = false, onError = defaultOnError, onWarn = defaultOnWarn, compatConfig }) {
- const nameMatch = filename.replace(/\?.*$/, '').match(/([^/\\]+)\.\w+$/);
- const context = {
- // options
- selfName: nameMatch && shared.capitalize(shared.camelize(nameMatch[1])),
- prefixIdentifiers,
- hoistStatic,
- cacheHandlers,
- nodeTransforms,
- directiveTransforms,
- transformHoist,
- isBuiltInComponent,
- isCustomElement,
- expressionPlugins,
- scopeId,
- slotted,
- ssr,
- inSSR,
- ssrCssVars,
- bindingMetadata,
- inline,
- isTS,
- onError,
- onWarn,
- compatConfig,
- // state
- root,
- helpers: new Map(),
- components: new Set(),
- directives: new Set(),
- hoists: [],
- imports: [],
- constantCache: new Map(),
- temps: 0,
- cached: 0,
- identifiers: Object.create(null),
- scopes: {
- vFor: 0,
- vSlot: 0,
- vPre: 0,
- vOnce: 0
- },
- parent: null,
- currentNode: root,
- childIndex: 0,
- inVOnce: false,
- // methods
- helper(name) {
- const count = context.helpers.get(name) || 0;
- context.helpers.set(name, count + 1);
- return name;
- },
- removeHelper(name) {
- const count = context.helpers.get(name);
- if (count) {
- const currentCount = count - 1;
- if (!currentCount) {
- context.helpers.delete(name);
- }
- else {
- context.helpers.set(name, currentCount);
- }
- }
- },
- helperString(name) {
- return `_${helperNameMap[context.helper(name)]}`;
- },
- replaceNode(node) {
- context.parent.children[context.childIndex] = context.currentNode = node;
- },
- removeNode(node) {
- const list = context.parent.children;
- const removalIndex = node
- ? list.indexOf(node)
- : context.currentNode
- ? context.childIndex
- : -1;
- if (!node || node === context.currentNode) {
- // current node removed
- context.currentNode = null;
- context.onNodeRemoved();
- }
- else {
- // sibling node removed
- if (context.childIndex > removalIndex) {
- context.childIndex--;
- context.onNodeRemoved();
- }
- }
- context.parent.children.splice(removalIndex, 1);
- },
- onNodeRemoved: () => { },
- addIdentifiers(exp) {
- // identifier tracking only happens in non-browser builds.
- {
- if (shared.isString(exp)) {
- addId(exp);
- }
- else if (exp.identifiers) {
- exp.identifiers.forEach(addId);
- }
- else if (exp.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */) {
- addId(exp.content);
- }
- }
- },
- removeIdentifiers(exp) {
- {
- if (shared.isString(exp)) {
- removeId(exp);
- }
- else if (exp.identifiers) {
- exp.identifiers.forEach(removeId);
- }
- else if (exp.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */) {
- removeId(exp.content);
- }
- }
- },
- hoist(exp) {
- if (shared.isString(exp))
- exp = createSimpleExpression(exp);
- context.hoists.push(exp);
- const identifier = createSimpleExpression(`_hoisted_${context.hoists.length}`, false, exp.loc, 2 /* ConstantTypes.CAN_HOIST */);
- identifier.hoisted = exp;
- return identifier;
- },
- cache(exp, isVNode = false) {
- return createCacheExpression(context.cached++, exp, isVNode);
- }
- };
- {
- context.filters = new Set();
- }
- function addId(id) {
- const { identifiers } = context;
- if (identifiers[id] === undefined) {
- identifiers[id] = 0;
- }
- identifiers[id]++;
- }
- function removeId(id) {
- context.identifiers[id]--;
- }
- return context;
- }
- function transform(root, options) {
- const context = createTransformContext(root, options);
- traverseNode(root, context);
- if (options.hoistStatic) {
- hoistStatic(root, context);
- }
- if (!options.ssr) {
- createRootCodegen(root, context);
- }
- // finalize meta information
- root.helpers = [...context.helpers.keys()];
- root.components = [...context.components];
- root.directives = [...context.directives];
- root.imports = context.imports;
- root.hoists = context.hoists;
- root.temps = context.temps;
- root.cached = context.cached;
- {
- root.filters = [...context.filters];
- }
- }
- function createRootCodegen(root, context) {
- const { helper } = context;
- const { children } = root;
- if (children.length === 1) {
- const child = children[0];
- // if the single child is an element, turn it into a block.
- if (isSingleElementRoot(root, child) && child.codegenNode) {
- // single element root is never hoisted so codegenNode will never be
- // SimpleExpressionNode
- const codegenNode = child.codegenNode;
- if (codegenNode.type === 13 /* NodeTypes.VNODE_CALL */) {
- makeBlock(codegenNode, context);
- }
- root.codegenNode = codegenNode;
- }
- else {
- // - single <slot/>, IfNode, ForNode: already blocks.
- // - single text node: always patched.
- // root codegen falls through via genNode()
- root.codegenNode = child;
- }
- }
- else if (children.length > 1) {
- // root has multiple nodes - return a fragment block.
- let patchFlag = 64 /* PatchFlags.STABLE_FRAGMENT */;
- shared.PatchFlagNames[64 /* PatchFlags.STABLE_FRAGMENT */];
- root.codegenNode = createVNodeCall(context, helper(FRAGMENT), undefined, root.children, patchFlag + (``), undefined, undefined, true, undefined, false /* isComponent */);
- }
- else ;
- }
- function traverseChildren(parent, context) {
- let i = 0;
- const nodeRemoved = () => {
- i--;
- };
- for (; i < parent.children.length; i++) {
- const child = parent.children[i];
- if (shared.isString(child))
- continue;
- context.parent = parent;
- context.childIndex = i;
- context.onNodeRemoved = nodeRemoved;
- traverseNode(child, context);
- }
- }
- function traverseNode(node, context) {
- context.currentNode = node;
- // apply transform plugins
- const { nodeTransforms } = context;
- const exitFns = [];
- for (let i = 0; i < nodeTransforms.length; i++) {
- const onExit = nodeTransforms[i](node, context);
- if (onExit) {
- if (shared.isArray(onExit)) {
- exitFns.push(...onExit);
- }
- else {
- exitFns.push(onExit);
- }
- }
- if (!context.currentNode) {
- // node was removed
- return;
- }
- else {
- // node may have been replaced
- node = context.currentNode;
- }
- }
- switch (node.type) {
- case 3 /* NodeTypes.COMMENT */:
- if (!context.ssr) {
- // inject import for the Comment symbol, which is needed for creating
- // comment nodes with `createVNode`
- context.helper(CREATE_COMMENT);
- }
- break;
- case 5 /* NodeTypes.INTERPOLATION */:
- // no need to traverse, but we need to inject toString helper
- if (!context.ssr) {
- context.helper(TO_DISPLAY_STRING);
- }
- break;
- // for container types, further traverse downwards
- case 9 /* NodeTypes.IF */:
- for (let i = 0; i < node.branches.length; i++) {
- traverseNode(node.branches[i], context);
- }
- break;
- case 10 /* NodeTypes.IF_BRANCH */:
- case 11 /* NodeTypes.FOR */:
- case 1 /* NodeTypes.ELEMENT */:
- case 0 /* NodeTypes.ROOT */:
- traverseChildren(node, context);
- break;
- }
- // exit transforms
- context.currentNode = node;
- let i = exitFns.length;
- while (i--) {
- exitFns[i]();
- }
- }
- function createStructuralDirectiveTransform(name, fn) {
- const matches = shared.isString(name)
- ? (n) => n === name
- : (n) => name.test(n);
- return (node, context) => {
- if (node.type === 1 /* NodeTypes.ELEMENT */) {
- const { props } = node;
- // structural directive transforms are not concerned with slots
- // as they are handled separately in vSlot.ts
- if (node.tagType === 3 /* ElementTypes.TEMPLATE */ && props.some(isVSlot)) {
- return;
- }
- const exitFns = [];
- for (let i = 0; i < props.length; i++) {
- const prop = props[i];
- if (prop.type === 7 /* NodeTypes.DIRECTIVE */ && matches(prop.name)) {
- // structural directives are removed to avoid infinite recursion
- // also we remove them *before* applying so that it can further
- // traverse itself in case it moves the node around
- props.splice(i, 1);
- i--;
- const onExit = fn(node, prop, context);
- if (onExit)
- exitFns.push(onExit);
- }
- }
- return exitFns;
- }
- };
- }
- const PURE_ANNOTATION = `/*#__PURE__*/`;
- const aliasHelper = (s) => `${helperNameMap[s]}: _${helperNameMap[s]}`;
- function createCodegenContext(ast, { mode = 'function', prefixIdentifiers = mode === 'module', sourceMap: sourceMap$1 = false, filename = `template.vue.html`, scopeId = null, optimizeImports = false, runtimeGlobalName = `Vue`, runtimeModuleName = `vue`, ssrRuntimeModuleName = 'vue/server-renderer', ssr = false, isTS = false, inSSR = false }) {
- const context = {
- mode,
- prefixIdentifiers,
- sourceMap: sourceMap$1,
- filename,
- scopeId,
- optimizeImports,
- runtimeGlobalName,
- runtimeModuleName,
- ssrRuntimeModuleName,
- ssr,
- isTS,
- inSSR,
- source: ast.loc.source,
- code: ``,
- column: 1,
- line: 1,
- offset: 0,
- indentLevel: 0,
- pure: false,
- map: undefined,
- helper(key) {
- return `_${helperNameMap[key]}`;
- },
- push(code, node) {
- context.code += code;
- if (context.map) {
- if (node) {
- let name;
- if (node.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */ && !node.isStatic) {
- const content = node.content.replace(/^_ctx\./, '');
- if (content !== node.content && isSimpleIdentifier(content)) {
- name = content;
- }
- }
- addMapping(node.loc.start, name);
- }
- advancePositionWithMutation(context, code);
- if (node && node.loc !== locStub) {
- addMapping(node.loc.end);
- }
- }
- },
- indent() {
- newline(++context.indentLevel);
- },
- deindent(withoutNewLine = false) {
- if (withoutNewLine) {
- --context.indentLevel;
- }
- else {
- newline(--context.indentLevel);
- }
- },
- newline() {
- newline(context.indentLevel);
- }
- };
- function newline(n) {
- context.push('\n' + ` `.repeat(n));
- }
- function addMapping(loc, name) {
- context.map.addMapping({
- name,
- source: context.filename,
- original: {
- line: loc.line,
- column: loc.column - 1 // source-map column is 0 based
- },
- generated: {
- line: context.line,
- column: context.column - 1
- }
- });
- }
- if (sourceMap$1) {
- // lazy require source-map implementation, only in non-browser builds
- context.map = new sourceMap.SourceMapGenerator();
- context.map.setSourceContent(filename, context.source);
- }
- return context;
- }
- function generate(ast, options = {}) {
- const context = createCodegenContext(ast, options);
- if (options.onContextCreated)
- options.onContextCreated(context);
- const { mode, push, prefixIdentifiers, indent, deindent, newline, scopeId, ssr } = context;
- const hasHelpers = ast.helpers.length > 0;
- const useWithBlock = !prefixIdentifiers && mode !== 'module';
- const genScopeId = scopeId != null && mode === 'module';
- const isSetupInlined = !!options.inline;
- // preambles
- // in setup() inline mode, the preamble is generated in a sub context
- // and returned separately.
- const preambleContext = isSetupInlined
- ? createCodegenContext(ast, options)
- : context;
- if (mode === 'module') {
- genModulePreamble(ast, preambleContext, genScopeId, isSetupInlined);
- }
- else {
- genFunctionPreamble(ast, preambleContext);
- }
- // enter render function
- const functionName = ssr ? `ssrRender` : `render`;
- const args = ssr ? ['_ctx', '_push', '_parent', '_attrs'] : ['_ctx', '_cache'];
- if (options.bindingMetadata && !options.inline) {
- // binding optimization args
- args.push('$props', '$setup', '$data', '$options');
- }
- const signature = options.isTS
- ? args.map(arg => `${arg}: any`).join(',')
- : args.join(', ');
- if (isSetupInlined) {
- push(`(${signature}) => {`);
- }
- else {
- push(`function ${functionName}(${signature}) {`);
- }
- indent();
- if (useWithBlock) {
- push(`with (_ctx) {`);
- indent();
- // function mode const declarations should be inside with block
- // also they should be renamed to avoid collision with user properties
- if (hasHelpers) {
- push(`const { ${ast.helpers.map(aliasHelper).join(', ')} } = _Vue`);
- push(`\n`);
- newline();
- }
- }
- // generate asset resolution statements
- if (ast.components.length) {
- genAssets(ast.components, 'component', context);
- if (ast.directives.length || ast.temps > 0) {
- newline();
- }
- }
- if (ast.directives.length) {
- genAssets(ast.directives, 'directive', context);
- if (ast.temps > 0) {
- newline();
- }
- }
- if (ast.filters && ast.filters.length) {
- newline();
- genAssets(ast.filters, 'filter', context);
- newline();
- }
- if (ast.temps > 0) {
- push(`let `);
- for (let i = 0; i < ast.temps; i++) {
- push(`${i > 0 ? `, ` : ``}_temp${i}`);
- }
- }
- if (ast.components.length || ast.directives.length || ast.temps) {
- push(`\n`);
- newline();
- }
- // generate the VNode tree expression
- if (!ssr) {
- push(`return `);
- }
- if (ast.codegenNode) {
- genNode(ast.codegenNode, context);
- }
- else {
- push(`null`);
- }
- if (useWithBlock) {
- deindent();
- push(`}`);
- }
- deindent();
- push(`}`);
- return {
- ast,
- code: context.code,
- preamble: isSetupInlined ? preambleContext.code : ``,
- // SourceMapGenerator does have toJSON() method but it's not in the types
- map: context.map ? context.map.toJSON() : undefined
- };
- }
- function genFunctionPreamble(ast, context) {
- const { ssr, prefixIdentifiers, push, newline, runtimeModuleName, runtimeGlobalName, ssrRuntimeModuleName } = context;
- const VueBinding = ssr
- ? `require(${JSON.stringify(runtimeModuleName)})`
- : runtimeGlobalName;
- // Generate const declaration for helpers
- // In prefix mode, we place the const declaration at top so it's done
- // only once; But if we not prefixing, we place the declaration inside the
- // with block so it doesn't incur the `in` check cost for every helper access.
- if (ast.helpers.length > 0) {
- if (prefixIdentifiers) {
- push(`const { ${ast.helpers.map(aliasHelper).join(', ')} } = ${VueBinding}\n`);
- }
- else {
- // "with" mode.
- // save Vue in a separate variable to avoid collision
- push(`const _Vue = ${VueBinding}\n`);
- // in "with" mode, helpers are declared inside the with block to avoid
- // has check cost, but hoists are lifted out of the function - we need
- // to provide the helper here.
- if (ast.hoists.length) {
- const staticHelpers = [
- CREATE_VNODE,
- CREATE_ELEMENT_VNODE,
- CREATE_COMMENT,
- CREATE_TEXT,
- CREATE_STATIC
- ]
- .filter(helper => ast.helpers.includes(helper))
- .map(aliasHelper)
- .join(', ');
- push(`const { ${staticHelpers} } = _Vue\n`);
- }
- }
- }
- // generate variables for ssr helpers
- if (ast.ssrHelpers && ast.ssrHelpers.length) {
- // ssr guarantees prefixIdentifier: true
- push(`const { ${ast.ssrHelpers
- .map(aliasHelper)
- .join(', ')} } = require("${ssrRuntimeModuleName}")\n`);
- }
- genHoists(ast.hoists, context);
- newline();
- push(`return `);
- }
- function genModulePreamble(ast, context, genScopeId, inline) {
- const { push, newline, optimizeImports, runtimeModuleName, ssrRuntimeModuleName } = context;
- if (genScopeId && ast.hoists.length) {
- ast.helpers.push(PUSH_SCOPE_ID, POP_SCOPE_ID);
- }
- // generate import statements for helpers
- if (ast.helpers.length) {
- if (optimizeImports) {
- // when bundled with webpack with code-split, calling an import binding
- // as a function leads to it being wrapped with `Object(a.b)` or `(0,a.b)`,
- // incurring both payload size increase and potential perf overhead.
- // therefore we assign the imports to variables (which is a constant ~50b
- // cost per-component instead of scaling with template size)
- push(`import { ${ast.helpers
- .map(s => helperNameMap[s])
- .join(', ')} } from ${JSON.stringify(runtimeModuleName)}\n`);
- push(`\n// Binding optimization for webpack code-split\nconst ${ast.helpers
- .map(s => `_${helperNameMap[s]} = ${helperNameMap[s]}`)
- .join(', ')}\n`);
- }
- else {
- push(`import { ${ast.helpers
- .map(s => `${helperNameMap[s]} as _${helperNameMap[s]}`)
- .join(', ')} } from ${JSON.stringify(runtimeModuleName)}\n`);
- }
- }
- if (ast.ssrHelpers && ast.ssrHelpers.length) {
- push(`import { ${ast.ssrHelpers
- .map(s => `${helperNameMap[s]} as _${helperNameMap[s]}`)
- .join(', ')} } from "${ssrRuntimeModuleName}"\n`);
- }
- if (ast.imports.length) {
- genImports(ast.imports, context);
- newline();
- }
- genHoists(ast.hoists, context);
- newline();
- if (!inline) {
- push(`export `);
- }
- }
- function genAssets(assets, type, { helper, push, newline, isTS }) {
- const resolver = helper(type === 'filter'
- ? RESOLVE_FILTER
- : type === 'component'
- ? RESOLVE_COMPONENT
- : RESOLVE_DIRECTIVE);
- for (let i = 0; i < assets.length; i++) {
- let id = assets[i];
- // potential component implicit self-reference inferred from SFC filename
- const maybeSelfReference = id.endsWith('__self');
- if (maybeSelfReference) {
- id = id.slice(0, -6);
- }
- push(`const ${toValidAssetId(id, type)} = ${resolver}(${JSON.stringify(id)}${maybeSelfReference ? `, true` : ``})${isTS ? `!` : ``}`);
- if (i < assets.length - 1) {
- newline();
- }
- }
- }
- function genHoists(hoists, context) {
- if (!hoists.length) {
- return;
- }
- context.pure = true;
- const { push, newline, helper, scopeId, mode } = context;
- const genScopeId = scopeId != null && mode !== 'function';
- newline();
- // generate inlined withScopeId helper
- if (genScopeId) {
- push(`const _withScopeId = n => (${helper(PUSH_SCOPE_ID)}("${scopeId}"),n=n(),${helper(POP_SCOPE_ID)}(),n)`);
- newline();
- }
- for (let i = 0; i < hoists.length; i++) {
- const exp = hoists[i];
- if (exp) {
- const needScopeIdWrapper = genScopeId && exp.type === 13 /* NodeTypes.VNODE_CALL */;
- push(`const _hoisted_${i + 1} = ${needScopeIdWrapper ? `${PURE_ANNOTATION} _withScopeId(() => ` : ``}`);
- genNode(exp, context);
- if (needScopeIdWrapper) {
- push(`)`);
- }
- newline();
- }
- }
- context.pure = false;
- }
- function genImports(importsOptions, context) {
- if (!importsOptions.length) {
- return;
- }
- importsOptions.forEach(imports => {
- context.push(`import `);
- genNode(imports.exp, context);
- context.push(` from '${imports.path}'`);
- context.newline();
- });
- }
- function isText$1(n) {
- return (shared.isString(n) ||
- n.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */ ||
- n.type === 2 /* NodeTypes.TEXT */ ||
- n.type === 5 /* NodeTypes.INTERPOLATION */ ||
- n.type === 8 /* NodeTypes.COMPOUND_EXPRESSION */);
- }
- function genNodeListAsArray(nodes, context) {
- const multilines = nodes.length > 3 ||
- (nodes.some(n => shared.isArray(n) || !isText$1(n)));
- context.push(`[`);
- multilines && context.indent();
- genNodeList(nodes, context, multilines);
- multilines && context.deindent();
- context.push(`]`);
- }
- function genNodeList(nodes, context, multilines = false, comma = true) {
- const { push, newline } = context;
- for (let i = 0; i < nodes.length; i++) {
- const node = nodes[i];
- if (shared.isString(node)) {
- push(node);
- }
- else if (shared.isArray(node)) {
- genNodeListAsArray(node, context);
- }
- else {
- genNode(node, context);
- }
- if (i < nodes.length - 1) {
- if (multilines) {
- comma && push(',');
- newline();
- }
- else {
- comma && push(', ');
- }
- }
- }
- }
- function genNode(node, context) {
- if (shared.isString(node)) {
- context.push(node);
- return;
- }
- if (shared.isSymbol(node)) {
- context.push(context.helper(node));
- return;
- }
- switch (node.type) {
- case 1 /* NodeTypes.ELEMENT */:
- case 9 /* NodeTypes.IF */:
- case 11 /* NodeTypes.FOR */:
- genNode(node.codegenNode, context);
- break;
- case 2 /* NodeTypes.TEXT */:
- genText(node, context);
- break;
- case 4 /* NodeTypes.SIMPLE_EXPRESSION */:
- genExpression(node, context);
- break;
- case 5 /* NodeTypes.INTERPOLATION */:
- genInterpolation(node, context);
- break;
- case 12 /* NodeTypes.TEXT_CALL */:
- genNode(node.codegenNode, context);
- break;
- case 8 /* NodeTypes.COMPOUND_EXPRESSION */:
- genCompoundExpression(node, context);
- break;
- case 3 /* NodeTypes.COMMENT */:
- genComment(node, context);
- break;
- case 13 /* NodeTypes.VNODE_CALL */:
- genVNodeCall(node, context);
- break;
- case 14 /* NodeTypes.JS_CALL_EXPRESSION */:
- genCallExpression(node, context);
- break;
- case 15 /* NodeTypes.JS_OBJECT_EXPRESSION */:
- genObjectExpression(node, context);
- break;
- case 17 /* NodeTypes.JS_ARRAY_EXPRESSION */:
- genArrayExpression(node, context);
- break;
- case 18 /* NodeTypes.JS_FUNCTION_EXPRESSION */:
- genFunctionExpression(node, context);
- break;
- case 19 /* NodeTypes.JS_CONDITIONAL_EXPRESSION */:
- genConditionalExpression(node, context);
- break;
- case 20 /* NodeTypes.JS_CACHE_EXPRESSION */:
- genCacheExpression(node, context);
- break;
- case 21 /* NodeTypes.JS_BLOCK_STATEMENT */:
- genNodeList(node.body, context, true, false);
- break;
- // SSR only types
- case 22 /* NodeTypes.JS_TEMPLATE_LITERAL */:
- genTemplateLiteral(node, context);
- break;
- case 23 /* NodeTypes.JS_IF_STATEMENT */:
- genIfStatement(node, context);
- break;
- case 24 /* NodeTypes.JS_ASSIGNMENT_EXPRESSION */:
- genAssignmentExpression(node, context);
- break;
- case 25 /* NodeTypes.JS_SEQUENCE_EXPRESSION */:
- genSequenceExpression(node, context);
- break;
- case 26 /* NodeTypes.JS_RETURN_STATEMENT */:
- genReturnStatement(node, context);
- break;
- }
- }
- function genText(node, context) {
- context.push(JSON.stringify(node.content), node);
- }
- function genExpression(node, context) {
- const { content, isStatic } = node;
- context.push(isStatic ? JSON.stringify(content) : content, node);
- }
- function genInterpolation(node, context) {
- const { push, helper, pure } = context;
- if (pure)
- push(PURE_ANNOTATION);
- push(`${helper(TO_DISPLAY_STRING)}(`);
- genNode(node.content, context);
- push(`)`);
- }
- function genCompoundExpression(node, context) {
- for (let i = 0; i < node.children.length; i++) {
- const child = node.children[i];
- if (shared.isString(child)) {
- context.push(child);
- }
- else {
- genNode(child, context);
- }
- }
- }
- function genExpressionAsPropertyKey(node, context) {
- const { push } = context;
- if (node.type === 8 /* NodeTypes.COMPOUND_EXPRESSION */) {
- push(`[`);
- genCompoundExpression(node, context);
- push(`]`);
- }
- else if (node.isStatic) {
- // only quote keys if necessary
- const text = isSimpleIdentifier(node.content)
- ? node.content
- : JSON.stringify(node.content);
- push(text, node);
- }
- else {
- push(`[${node.content}]`, node);
- }
- }
- function genComment(node, context) {
- const { push, helper, pure } = context;
- if (pure) {
- push(PURE_ANNOTATION);
- }
- push(`${helper(CREATE_COMMENT)}(${JSON.stringify(node.content)})`, node);
- }
- function genVNodeCall(node, context) {
- const { push, helper, pure } = context;
- const { tag, props, children, patchFlag, dynamicProps, directives, isBlock, disableTracking, isComponent } = node;
- if (directives) {
- push(helper(WITH_DIRECTIVES) + `(`);
- }
- if (isBlock) {
- push(`(${helper(OPEN_BLOCK)}(${disableTracking ? `true` : ``}), `);
- }
- if (pure) {
- push(PURE_ANNOTATION);
- }
- const callHelper = isBlock
- ? getVNodeBlockHelper(context.inSSR, isComponent)
- : getVNodeHelper(context.inSSR, isComponent);
- push(helper(callHelper) + `(`, node);
- genNodeList(genNullableArgs([tag, props, children, patchFlag, dynamicProps]), context);
- push(`)`);
- if (isBlock) {
- push(`)`);
- }
- if (directives) {
- push(`, `);
- genNode(directives, context);
- push(`)`);
- }
- }
- function genNullableArgs(args) {
- let i = args.length;
- while (i--) {
- if (args[i] != null)
- break;
- }
- return args.slice(0, i + 1).map(arg => arg || `null`);
- }
- // JavaScript
- function genCallExpression(node, context) {
- const { push, helper, pure } = context;
- const callee = shared.isString(node.callee) ? node.callee : helper(node.callee);
- if (pure) {
- push(PURE_ANNOTATION);
- }
- push(callee + `(`, node);
- genNodeList(node.arguments, context);
- push(`)`);
- }
- function genObjectExpression(node, context) {
- const { push, indent, deindent, newline } = context;
- const { properties } = node;
- if (!properties.length) {
- push(`{}`, node);
- return;
- }
- const multilines = properties.length > 1 ||
- (properties.some(p => p.value.type !== 4 /* NodeTypes.SIMPLE_EXPRESSION */));
- push(multilines ? `{` : `{ `);
- multilines && indent();
- for (let i = 0; i < properties.length; i++) {
- const { key, value } = properties[i];
- // key
- genExpressionAsPropertyKey(key, context);
- push(`: `);
- // value
- genNode(value, context);
- if (i < properties.length - 1) {
- // will only reach this if it's multilines
- push(`,`);
- newline();
- }
- }
- multilines && deindent();
- push(multilines ? `}` : ` }`);
- }
- function genArrayExpression(node, context) {
- genNodeListAsArray(node.elements, context);
- }
- function genFunctionExpression(node, context) {
- const { push, indent, deindent } = context;
- const { params, returns, body, newline, isSlot } = node;
- if (isSlot) {
- // wrap slot functions with owner context
- push(`_${helperNameMap[WITH_CTX]}(`);
- }
- push(`(`, node);
- if (shared.isArray(params)) {
- genNodeList(params, context);
- }
- else if (params) {
- genNode(params, context);
- }
- push(`) => `);
- if (newline || body) {
- push(`{`);
- indent();
- }
- if (returns) {
- if (newline) {
- push(`return `);
- }
- if (shared.isArray(returns)) {
- genNodeListAsArray(returns, context);
- }
- else {
- genNode(returns, context);
- }
- }
- else if (body) {
- genNode(body, context);
- }
- if (newline || body) {
- deindent();
- push(`}`);
- }
- if (isSlot) {
- if (node.isNonScopedSlot) {
- push(`, undefined, true`);
- }
- push(`)`);
- }
- }
- function genConditionalExpression(node, context) {
- const { test, consequent, alternate, newline: needNewline } = node;
- const { push, indent, deindent, newline } = context;
- if (test.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */) {
- const needsParens = !isSimpleIdentifier(test.content);
- needsParens && push(`(`);
- genExpression(test, context);
- needsParens && push(`)`);
- }
- else {
- push(`(`);
- genNode(test, context);
- push(`)`);
- }
- needNewline && indent();
- context.indentLevel++;
- needNewline || push(` `);
- push(`? `);
- genNode(consequent, context);
- context.indentLevel--;
- needNewline && newline();
- needNewline || push(` `);
- push(`: `);
- const isNested = alternate.type === 19 /* NodeTypes.JS_CONDITIONAL_EXPRESSION */;
- if (!isNested) {
- context.indentLevel++;
- }
- genNode(alternate, context);
- if (!isNested) {
- context.indentLevel--;
- }
- needNewline && deindent(true /* without newline */);
- }
- function genCacheExpression(node, context) {
- const { push, helper, indent, deindent, newline } = context;
- push(`_cache[${node.index}] || (`);
- if (node.isVNode) {
- indent();
- push(`${helper(SET_BLOCK_TRACKING)}(-1),`);
- newline();
- }
- push(`_cache[${node.index}] = `);
- genNode(node.value, context);
- if (node.isVNode) {
- push(`,`);
- newline();
- push(`${helper(SET_BLOCK_TRACKING)}(1),`);
- newline();
- push(`_cache[${node.index}]`);
- deindent();
- }
- push(`)`);
- }
- function genTemplateLiteral(node, context) {
- const { push, indent, deindent } = context;
- push('`');
- const l = node.elements.length;
- const multilines = l > 3;
- for (let i = 0; i < l; i++) {
- const e = node.elements[i];
- if (shared.isString(e)) {
- push(e.replace(/(`|\$|\\)/g, '\\$1'));
- }
- else {
- push('${');
- if (multilines)
- indent();
- genNode(e, context);
- if (multilines)
- deindent();
- push('}');
- }
- }
- push('`');
- }
- function genIfStatement(node, context) {
- const { push, indent, deindent } = context;
- const { test, consequent, alternate } = node;
- push(`if (`);
- genNode(test, context);
- push(`) {`);
- indent();
- genNode(consequent, context);
- deindent();
- push(`}`);
- if (alternate) {
- push(` else `);
- if (alternate.type === 23 /* NodeTypes.JS_IF_STATEMENT */) {
- genIfStatement(alternate, context);
- }
- else {
- push(`{`);
- indent();
- genNode(alternate, context);
- deindent();
- push(`}`);
- }
- }
- }
- function genAssignmentExpression(node, context) {
- genNode(node.left, context);
- context.push(` = `);
- genNode(node.right, context);
- }
- function genSequenceExpression(node, context) {
- context.push(`(`);
- genNodeList(node.expressions, context);
- context.push(`)`);
- }
- function genReturnStatement({ returns }, context) {
- context.push(`return `);
- if (shared.isArray(returns)) {
- genNodeListAsArray(returns, context);
- }
- else {
- genNode(returns, context);
- }
- }
- function walkIdentifiers(root, onIdentifier, includeAll = false, parentStack = [], knownIds = Object.create(null)) {
- const rootExp = root.type === 'Program' &&
- root.body[0].type === 'ExpressionStatement' &&
- root.body[0].expression;
- estreeWalker.walk(root, {
- enter(node, parent) {
- parent && parentStack.push(parent);
- if (parent &&
- parent.type.startsWith('TS') &&
- parent.type !== 'TSAsExpression' &&
- parent.type !== 'TSNonNullExpression' &&
- parent.type !== 'TSTypeAssertion') {
- return this.skip();
- }
- if (node.type === 'Identifier') {
- const isLocal = !!knownIds[node.name];
- const isRefed = isReferencedIdentifier(node, parent, parentStack);
- if (includeAll || (isRefed && !isLocal)) {
- onIdentifier(node, parent, parentStack, isRefed, isLocal);
- }
- }
- else if (node.type === 'ObjectProperty' &&
- parent.type === 'ObjectPattern') {
- node.inPattern = true;
- }
- else if (isFunctionType(node)) {
- // walk function expressions and add its arguments to known identifiers
- // so that we don't prefix them
- walkFunctionParams(node, id => markScopeIdentifier(node, id, knownIds));
- }
- else if (node.type === 'BlockStatement') {
- // #3445 record block-level local variables
- walkBlockDeclarations(node, id => markScopeIdentifier(node, id, knownIds));
- }
- },
- leave(node, parent) {
- parent && parentStack.pop();
- if (node !== rootExp && node.scopeIds) {
- for (const id of node.scopeIds) {
- knownIds[id]--;
- if (knownIds[id] === 0) {
- delete knownIds[id];
- }
- }
- }
- }
- });
- }
- function isReferencedIdentifier(id, parent, parentStack) {
- if (!parent) {
- return true;
- }
- // is a special keyword but parsed as identifier
- if (id.name === 'arguments') {
- return false;
- }
- if (isReferenced(id, parent)) {
- return true;
- }
- // babel's isReferenced check returns false for ids being assigned to, so we
- // need to cover those cases here
- switch (parent.type) {
- case 'AssignmentExpression':
- case 'AssignmentPattern':
- return true;
- case 'ObjectPattern':
- case 'ArrayPattern':
- return isInDestructureAssignment(parent, parentStack);
- }
- return false;
- }
- function isInDestructureAssignment(parent, parentStack) {
- if (parent &&
- (parent.type === 'ObjectProperty' || parent.type === 'ArrayPattern')) {
- let i = parentStack.length;
- while (i--) {
- const p = parentStack[i];
- if (p.type === 'AssignmentExpression') {
- return true;
- }
- else if (p.type !== 'ObjectProperty' && !p.type.endsWith('Pattern')) {
- break;
- }
- }
- }
- return false;
- }
- function walkFunctionParams(node, onIdent) {
- for (const p of node.params) {
- for (const id of extractIdentifiers(p)) {
- onIdent(id);
- }
- }
- }
- function walkBlockDeclarations(block, onIdent) {
- for (const stmt of block.body) {
- if (stmt.type === 'VariableDeclaration') {
- if (stmt.declare)
- continue;
- for (const decl of stmt.declarations) {
- for (const id of extractIdentifiers(decl.id)) {
- onIdent(id);
- }
- }
- }
- else if (stmt.type === 'FunctionDeclaration' ||
- stmt.type === 'ClassDeclaration') {
- if (stmt.declare || !stmt.id)
- continue;
- onIdent(stmt.id);
- }
- }
- }
- function extractIdentifiers(param, nodes = []) {
- switch (param.type) {
- case 'Identifier':
- nodes.push(param);
- break;
- case 'MemberExpression':
- let object = param;
- while (object.type === 'MemberExpression') {
- object = object.object;
- }
- nodes.push(object);
- break;
- case 'ObjectPattern':
- for (const prop of param.properties) {
- if (prop.type === 'RestElement') {
- extractIdentifiers(prop.argument, nodes);
- }
- else {
- extractIdentifiers(prop.value, nodes);
- }
- }
- break;
- case 'ArrayPattern':
- param.elements.forEach(element => {
- if (element)
- extractIdentifiers(element, nodes);
- });
- break;
- case 'RestElement':
- extractIdentifiers(param.argument, nodes);
- break;
- case 'AssignmentPattern':
- extractIdentifiers(param.left, nodes);
- break;
- }
- return nodes;
- }
- function markScopeIdentifier(node, child, knownIds) {
- const { name } = child;
- if (node.scopeIds && node.scopeIds.has(name)) {
- return;
- }
- if (name in knownIds) {
- knownIds[name]++;
- }
- else {
- knownIds[name] = 1;
- }
- (node.scopeIds || (node.scopeIds = new Set())).add(name);
- }
- const isFunctionType = (node) => {
- return /Function(?:Expression|Declaration)$|Method$/.test(node.type);
- };
- const isStaticProperty = (node) => node &&
- (node.type === 'ObjectProperty' || node.type === 'ObjectMethod') &&
- !node.computed;
- const isStaticPropertyKey = (node, parent) => isStaticProperty(parent) && parent.key === node;
- /**
- * Copied from https://github.com/babel/babel/blob/main/packages/babel-types/src/validators/isReferenced.ts
- * To avoid runtime dependency on @babel/types (which includes process references)
- * This file should not change very often in babel but we may need to keep it
- * up-to-date from time to time.
- *
- * https://github.com/babel/babel/blob/main/LICENSE
- *
- */
- function isReferenced(node, parent, grandparent) {
- switch (parent.type) {
- // yes: PARENT[NODE]
- // yes: NODE.child
- // no: parent.NODE
- case 'MemberExpression':
- case 'OptionalMemberExpression':
- if (parent.property === node) {
- return !!parent.computed;
- }
- return parent.object === node;
- case 'JSXMemberExpression':
- return parent.object === node;
- // no: let NODE = init;
- // yes: let id = NODE;
- case 'VariableDeclarator':
- return parent.init === node;
- // yes: () => NODE
- // no: (NODE) => {}
- case 'ArrowFunctionExpression':
- return parent.body === node;
- // no: class { #NODE; }
- // no: class { get #NODE() {} }
- // no: class { #NODE() {} }
- // no: class { fn() { return this.#NODE; } }
- case 'PrivateName':
- return false;
- // no: class { NODE() {} }
- // yes: class { [NODE]() {} }
- // no: class { foo(NODE) {} }
- case 'ClassMethod':
- case 'ClassPrivateMethod':
- case 'ObjectMethod':
- if (parent.key === node) {
- return !!parent.computed;
- }
- return false;
- // yes: { [NODE]: "" }
- // no: { NODE: "" }
- // depends: { NODE }
- // depends: { key: NODE }
- case 'ObjectProperty':
- if (parent.key === node) {
- return !!parent.computed;
- }
- // parent.value === node
- return !grandparent || grandparent.type !== 'ObjectPattern';
- // no: class { NODE = value; }
- // yes: class { [NODE] = value; }
- // yes: class { key = NODE; }
- case 'ClassProperty':
- if (parent.key === node) {
- return !!parent.computed;
- }
- return true;
- case 'ClassPrivateProperty':
- return parent.key !== node;
- // no: class NODE {}
- // yes: class Foo extends NODE {}
- case 'ClassDeclaration':
- case 'ClassExpression':
- return parent.superClass === node;
- // yes: left = NODE;
- // no: NODE = right;
- case 'AssignmentExpression':
- return parent.right === node;
- // no: [NODE = foo] = [];
- // yes: [foo = NODE] = [];
- case 'AssignmentPattern':
- return parent.right === node;
- // no: NODE: for (;;) {}
- case 'LabeledStatement':
- return false;
- // no: try {} catch (NODE) {}
- case 'CatchClause':
- return false;
- // no: function foo(...NODE) {}
- case 'RestElement':
- return false;
- case 'BreakStatement':
- case 'ContinueStatement':
- return false;
- // no: function NODE() {}
- // no: function foo(NODE) {}
- case 'FunctionDeclaration':
- case 'FunctionExpression':
- return false;
- // no: export NODE from "foo";
- // no: export * as NODE from "foo";
- case 'ExportNamespaceSpecifier':
- case 'ExportDefaultSpecifier':
- return false;
- // no: export { foo as NODE };
- // yes: export { NODE as foo };
- // no: export { NODE as foo } from "foo";
- case 'ExportSpecifier':
- // @ts-expect-error
- if (grandparent === null || grandparent === void 0 ? void 0 : grandparent.source) {
- return false;
- }
- return parent.local === node;
- // no: import NODE from "foo";
- // no: import * as NODE from "foo";
- // no: import { NODE as foo } from "foo";
- // no: import { foo as NODE } from "foo";
- // no: import NODE from "bar";
- case 'ImportDefaultSpecifier':
- case 'ImportNamespaceSpecifier':
- case 'ImportSpecifier':
- return false;
- // no: import "foo" assert { NODE: "json" }
- case 'ImportAttribute':
- return false;
- // no: <div NODE="foo" />
- case 'JSXAttribute':
- return false;
- // no: [NODE] = [];
- // no: ({ NODE }) = [];
- case 'ObjectPattern':
- case 'ArrayPattern':
- return false;
- // no: new.NODE
- // no: NODE.target
- case 'MetaProperty':
- return false;
- // yes: type X = { someProperty: NODE }
- // no: type X = { NODE: OtherType }
- case 'ObjectTypeProperty':
- return parent.key !== node;
- // yes: enum X { Foo = NODE }
- // no: enum X { NODE }
- case 'TSEnumMember':
- return parent.id !== node;
- // yes: { [NODE]: value }
- // no: { NODE: value }
- case 'TSPropertySignature':
- if (parent.key === node) {
- return !!parent.computed;
- }
- return true;
- }
- return true;
- }
- const isLiteralWhitelisted = /*#__PURE__*/ shared.makeMap('true,false,null,this');
- const transformExpression = (node, context) => {
- if (node.type === 5 /* NodeTypes.INTERPOLATION */) {
- node.content = processExpression(node.content, context);
- }
- else if (node.type === 1 /* NodeTypes.ELEMENT */) {
- // handle directives on element
- for (let i = 0; i < node.props.length; i++) {
- const dir = node.props[i];
- // do not process for v-on & v-for since they are special handled
- if (dir.type === 7 /* NodeTypes.DIRECTIVE */ && dir.name !== 'for') {
- const exp = dir.exp;
- const arg = dir.arg;
- // do not process exp if this is v-on:arg - we need special handling
- // for wrapping inline statements.
- if (exp &&
- exp.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */ &&
- !(dir.name === 'on' && arg)) {
- dir.exp = processExpression(exp, context,
- // slot args must be processed as function params
- dir.name === 'slot');
- }
- if (arg && arg.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */ && !arg.isStatic) {
- dir.arg = processExpression(arg, context);
- }
- }
- }
- }
- };
- // Important: since this function uses Node.js only dependencies, it should
- // always be used with a leading !false check so that it can be
- // tree-shaken from the browser build.
- function processExpression(node, context,
- // some expressions like v-slot props & v-for aliases should be parsed as
- // function params
- asParams = false,
- // v-on handler values may contain multiple statements
- asRawStatements = false, localVars = Object.create(context.identifiers)) {
- if (!context.prefixIdentifiers || !node.content.trim()) {
- return node;
- }
- const { inline, bindingMetadata } = context;
- const rewriteIdentifier = (raw, parent, id) => {
- const type = shared.hasOwn(bindingMetadata, raw) && bindingMetadata[raw];
- if (inline) {
- // x = y
- const isAssignmentLVal = parent && parent.type === 'AssignmentExpression' && parent.left === id;
- // x++
- const isUpdateArg = parent && parent.type === 'UpdateExpression' && parent.argument === id;
- // ({ x } = y)
- const isDestructureAssignment = parent && isInDestructureAssignment(parent, parentStack);
- if (type === "setup-const" /* BindingTypes.SETUP_CONST */ ||
- type === "setup-reactive-const" /* BindingTypes.SETUP_REACTIVE_CONST */ ||
- localVars[raw]) {
- return raw;
- }
- else if (type === "setup-ref" /* BindingTypes.SETUP_REF */) {
- return `${raw}.value`;
- }
- else if (type === "setup-maybe-ref" /* BindingTypes.SETUP_MAYBE_REF */) {
- // const binding that may or may not be ref
- // if it's not a ref, then assignments don't make sense -
- // so we ignore the non-ref assignment case and generate code
- // that assumes the value to be a ref for more efficiency
- return isAssignmentLVal || isUpdateArg || isDestructureAssignment
- ? `${raw}.value`
- : `${context.helperString(UNREF)}(${raw})`;
- }
- else if (type === "setup-let" /* BindingTypes.SETUP_LET */) {
- if (isAssignmentLVal) {
- // let binding.
- // this is a bit more tricky as we need to cover the case where
- // let is a local non-ref value, and we need to replicate the
- // right hand side value.
- // x = y --> isRef(x) ? x.value = y : x = y
- const { right: rVal, operator } = parent;
- const rExp = rawExp.slice(rVal.start - 1, rVal.end - 1);
- const rExpString = stringifyExpression(processExpression(createSimpleExpression(rExp, false), context, false, false, knownIds));
- return `${context.helperString(IS_REF)}(${raw})${context.isTS ? ` //@ts-ignore\n` : ``} ? ${raw}.value ${operator} ${rExpString} : ${raw}`;
- }
- else if (isUpdateArg) {
- // make id replace parent in the code range so the raw update operator
- // is removed
- id.start = parent.start;
- id.end = parent.end;
- const { prefix: isPrefix, operator } = parent;
- const prefix = isPrefix ? operator : ``;
- const postfix = isPrefix ? `` : operator;
- // let binding.
- // x++ --> isRef(a) ? a.value++ : a++
- return `${context.helperString(IS_REF)}(${raw})${context.isTS ? ` //@ts-ignore\n` : ``} ? ${prefix}${raw}.value${postfix} : ${prefix}${raw}${postfix}`;
- }
- else if (isDestructureAssignment) {
- // TODO
- // let binding in a destructure assignment - it's very tricky to
- // handle both possible cases here without altering the original
- // structure of the code, so we just assume it's not a ref here
- // for now
- return raw;
- }
- else {
- return `${context.helperString(UNREF)}(${raw})`;
- }
- }
- else if (type === "props" /* BindingTypes.PROPS */) {
- // use __props which is generated by compileScript so in ts mode
- // it gets correct type
- return shared.genPropsAccessExp(raw);
- }
- else if (type === "props-aliased" /* BindingTypes.PROPS_ALIASED */) {
- // prop with a different local alias (from defineProps() destructure)
- return shared.genPropsAccessExp(bindingMetadata.__propsAliases[raw]);
- }
- }
- else {
- if (type && type.startsWith('setup')) {
- // setup bindings in non-inline mode
- return `$setup.${raw}`;
- }
- else if (type === "props-aliased" /* BindingTypes.PROPS_ALIASED */) {
- return `$props['${bindingMetadata.__propsAliases[raw]}']`;
- }
- else if (type) {
- return `$${type}.${raw}`;
- }
- }
- // fallback to ctx
- return `_ctx.${raw}`;
- };
- // fast path if expression is a simple identifier.
- const rawExp = node.content;
- // bail constant on parens (function invocation) and dot (member access)
- const bailConstant = rawExp.indexOf(`(`) > -1 || rawExp.indexOf('.') > 0;
- if (isSimpleIdentifier(rawExp)) {
- const isScopeVarReference = context.identifiers[rawExp];
- const isAllowedGlobal = shared.isGloballyWhitelisted(rawExp);
- const isLiteral = isLiteralWhitelisted(rawExp);
- if (!asParams && !isScopeVarReference && !isAllowedGlobal && !isLiteral) {
- // const bindings exposed from setup can be skipped for patching but
- // cannot be hoisted to module scope
- if (bindingMetadata[node.content] === "setup-const" /* BindingTypes.SETUP_CONST */) {
- node.constType = 1 /* ConstantTypes.CAN_SKIP_PATCH */;
- }
- node.content = rewriteIdentifier(rawExp);
- }
- else if (!isScopeVarReference) {
- if (isLiteral) {
- node.constType = 3 /* ConstantTypes.CAN_STRINGIFY */;
- }
- else {
- node.constType = 2 /* ConstantTypes.CAN_HOIST */;
- }
- }
- return node;
- }
- let ast;
- // exp needs to be parsed differently:
- // 1. Multiple inline statements (v-on, with presence of `;`): parse as raw
- // exp, but make sure to pad with spaces for consistent ranges
- // 2. Expressions: wrap with parens (for e.g. object expressions)
- // 3. Function arguments (v-for, v-slot): place in a function argument position
- const source = asRawStatements
- ? ` ${rawExp} `
- : `(${rawExp})${asParams ? `=>{}` : ``}`;
- try {
- ast = parser.parse(source, {
- plugins: context.expressionPlugins
- }).program;
- }
- catch (e) {
- context.onError(createCompilerError(45 /* ErrorCodes.X_INVALID_EXPRESSION */, node.loc, undefined, e.message));
- return node;
- }
- const ids = [];
- const parentStack = [];
- const knownIds = Object.create(context.identifiers);
- walkIdentifiers(ast, (node, parent, _, isReferenced, isLocal) => {
- if (isStaticPropertyKey(node, parent)) {
- return;
- }
- // v2 wrapped filter call
- if (node.name.startsWith('_filter_')) {
- return;
- }
- const needPrefix = isReferenced && canPrefix(node);
- if (needPrefix && !isLocal) {
- if (isStaticProperty(parent) && parent.shorthand) {
- node.prefix = `${node.name}: `;
- }
- node.name = rewriteIdentifier(node.name, parent, node);
- ids.push(node);
- }
- else {
- // The identifier is considered constant unless it's pointing to a
- // local scope variable (a v-for alias, or a v-slot prop)
- if (!(needPrefix && isLocal) && !bailConstant) {
- node.isConstant = true;
- }
- // also generate sub-expressions for other identifiers for better
- // source map support. (except for property keys which are static)
- ids.push(node);
- }
- }, true, // invoke on ALL identifiers
- parentStack, knownIds);
- // We break up the compound expression into an array of strings and sub
- // expressions (for identifiers that have been prefixed). In codegen, if
- // an ExpressionNode has the `.children` property, it will be used instead of
- // `.content`.
- const children = [];
- ids.sort((a, b) => a.start - b.start);
- ids.forEach((id, i) => {
- // range is offset by -1 due to the wrapping parens when parsed
- const start = id.start - 1;
- const end = id.end - 1;
- const last = ids[i - 1];
- const leadingText = rawExp.slice(last ? last.end - 1 : 0, start);
- if (leadingText.length || id.prefix) {
- children.push(leadingText + (id.prefix || ``));
- }
- const source = rawExp.slice(start, end);
- children.push(createSimpleExpression(id.name, false, {
- source,
- start: advancePositionWithClone(node.loc.start, source, start),
- end: advancePositionWithClone(node.loc.start, source, end)
- }, id.isConstant ? 3 /* ConstantTypes.CAN_STRINGIFY */ : 0 /* ConstantTypes.NOT_CONSTANT */));
- if (i === ids.length - 1 && end < rawExp.length) {
- children.push(rawExp.slice(end));
- }
- });
- let ret;
- if (children.length) {
- ret = createCompoundExpression(children, node.loc);
- }
- else {
- ret = node;
- ret.constType = bailConstant
- ? 0 /* ConstantTypes.NOT_CONSTANT */
- : 3 /* ConstantTypes.CAN_STRINGIFY */;
- }
- ret.identifiers = Object.keys(knownIds);
- return ret;
- }
- function canPrefix(id) {
- // skip whitelisted globals
- if (shared.isGloballyWhitelisted(id.name)) {
- return false;
- }
- // special case for webpack compilation
- if (id.name === 'require') {
- return false;
- }
- return true;
- }
- function stringifyExpression(exp) {
- if (shared.isString(exp)) {
- return exp;
- }
- else if (exp.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */) {
- return exp.content;
- }
- else {
- return exp.children
- .map(stringifyExpression)
- .join('');
- }
- }
- const transformIf = createStructuralDirectiveTransform(/^(if|else|else-if)$/, (node, dir, context) => {
- return processIf(node, dir, context, (ifNode, branch, isRoot) => {
- // #1587: We need to dynamically increment the key based on the current
- // node's sibling nodes, since chained v-if/else branches are
- // rendered at the same depth
- const siblings = context.parent.children;
- let i = siblings.indexOf(ifNode);
- let key = 0;
- while (i-- >= 0) {
- const sibling = siblings[i];
- if (sibling && sibling.type === 9 /* NodeTypes.IF */) {
- key += sibling.branches.length;
- }
- }
- // Exit callback. Complete the codegenNode when all children have been
- // transformed.
- return () => {
- if (isRoot) {
- ifNode.codegenNode = createCodegenNodeForBranch(branch, key, context);
- }
- else {
- // attach this branch's codegen node to the v-if root.
- const parentCondition = getParentCondition(ifNode.codegenNode);
- parentCondition.alternate = createCodegenNodeForBranch(branch, key + ifNode.branches.length - 1, context);
- }
- };
- });
- });
- // target-agnostic transform used for both Client and SSR
- function processIf(node, dir, context, processCodegen) {
- if (dir.name !== 'else' &&
- (!dir.exp || !dir.exp.content.trim())) {
- const loc = dir.exp ? dir.exp.loc : node.loc;
- context.onError(createCompilerError(28 /* ErrorCodes.X_V_IF_NO_EXPRESSION */, dir.loc));
- dir.exp = createSimpleExpression(`true`, false, loc);
- }
- if (context.prefixIdentifiers && dir.exp) {
- // dir.exp can only be simple expression because vIf transform is applied
- // before expression transform.
- dir.exp = processExpression(dir.exp, context);
- }
- if (dir.name === 'if') {
- const branch = createIfBranch(node, dir);
- const ifNode = {
- type: 9 /* NodeTypes.IF */,
- loc: node.loc,
- branches: [branch]
- };
- context.replaceNode(ifNode);
- if (processCodegen) {
- return processCodegen(ifNode, branch, true);
- }
- }
- else {
- // locate the adjacent v-if
- const siblings = context.parent.children;
- let i = siblings.indexOf(node);
- while (i-- >= -1) {
- const sibling = siblings[i];
- if (sibling && sibling.type === 3 /* NodeTypes.COMMENT */) {
- context.removeNode(sibling);
- continue;
- }
- if (sibling &&
- sibling.type === 2 /* NodeTypes.TEXT */ &&
- !sibling.content.trim().length) {
- context.removeNode(sibling);
- continue;
- }
- if (sibling && sibling.type === 9 /* NodeTypes.IF */) {
- // Check if v-else was followed by v-else-if
- if (dir.name === 'else-if' &&
- sibling.branches[sibling.branches.length - 1].condition === undefined) {
- context.onError(createCompilerError(30 /* ErrorCodes.X_V_ELSE_NO_ADJACENT_IF */, node.loc));
- }
- // move the node to the if node's branches
- context.removeNode();
- const branch = createIfBranch(node, dir);
- // check if user is forcing same key on different branches
- {
- const key = branch.userKey;
- if (key) {
- sibling.branches.forEach(({ userKey }) => {
- if (isSameKey(userKey, key)) {
- context.onError(createCompilerError(29 /* ErrorCodes.X_V_IF_SAME_KEY */, branch.userKey.loc));
- }
- });
- }
- }
- sibling.branches.push(branch);
- const onExit = processCodegen && processCodegen(sibling, branch, false);
- // since the branch was removed, it will not be traversed.
- // make sure to traverse here.
- traverseNode(branch, context);
- // call on exit
- if (onExit)
- onExit();
- // make sure to reset currentNode after traversal to indicate this
- // node has been removed.
- context.currentNode = null;
- }
- else {
- context.onError(createCompilerError(30 /* ErrorCodes.X_V_ELSE_NO_ADJACENT_IF */, node.loc));
- }
- break;
- }
- }
- }
- function createIfBranch(node, dir) {
- const isTemplateIf = node.tagType === 3 /* ElementTypes.TEMPLATE */;
- return {
- type: 10 /* NodeTypes.IF_BRANCH */,
- loc: node.loc,
- condition: dir.name === 'else' ? undefined : dir.exp,
- children: isTemplateIf && !findDir(node, 'for') ? node.children : [node],
- userKey: findProp(node, `key`),
- isTemplateIf
- };
- }
- function createCodegenNodeForBranch(branch, keyIndex, context) {
- if (branch.condition) {
- return createConditionalExpression(branch.condition, createChildrenCodegenNode(branch, keyIndex, context),
- // make sure to pass in asBlock: true so that the comment node call
- // closes the current block.
- createCallExpression(context.helper(CREATE_COMMENT), [
- '""',
- 'true'
- ]));
- }
- else {
- return createChildrenCodegenNode(branch, keyIndex, context);
- }
- }
- function createChildrenCodegenNode(branch, keyIndex, context) {
- const { helper } = context;
- const keyProperty = createObjectProperty(`key`, createSimpleExpression(`${keyIndex}`, false, locStub, 2 /* ConstantTypes.CAN_HOIST */));
- const { children } = branch;
- const firstChild = children[0];
- const needFragmentWrapper = children.length !== 1 || firstChild.type !== 1 /* NodeTypes.ELEMENT */;
- if (needFragmentWrapper) {
- if (children.length === 1 && firstChild.type === 11 /* NodeTypes.FOR */) {
- // optimize away nested fragments when child is a ForNode
- const vnodeCall = firstChild.codegenNode;
- injectProp(vnodeCall, keyProperty, context);
- return vnodeCall;
- }
- else {
- let patchFlag = 64 /* PatchFlags.STABLE_FRAGMENT */;
- shared.PatchFlagNames[64 /* PatchFlags.STABLE_FRAGMENT */];
- return createVNodeCall(context, helper(FRAGMENT), createObjectExpression([keyProperty]), children, patchFlag + (``), undefined, undefined, true, false, false /* isComponent */, branch.loc);
- }
- }
- else {
- const ret = firstChild.codegenNode;
- const vnodeCall = getMemoedVNodeCall(ret);
- // Change createVNode to createBlock.
- if (vnodeCall.type === 13 /* NodeTypes.VNODE_CALL */) {
- makeBlock(vnodeCall, context);
- }
- // inject branch key
- injectProp(vnodeCall, keyProperty, context);
- return ret;
- }
- }
- function isSameKey(a, b) {
- if (!a || a.type !== b.type) {
- return false;
- }
- if (a.type === 6 /* NodeTypes.ATTRIBUTE */) {
- if (a.value.content !== b.value.content) {
- return false;
- }
- }
- else {
- // directive
- const exp = a.exp;
- const branchExp = b.exp;
- if (exp.type !== branchExp.type) {
- return false;
- }
- if (exp.type !== 4 /* NodeTypes.SIMPLE_EXPRESSION */ ||
- exp.isStatic !== branchExp.isStatic ||
- exp.content !== branchExp.content) {
- return false;
- }
- }
- return true;
- }
- function getParentCondition(node) {
- while (true) {
- if (node.type === 19 /* NodeTypes.JS_CONDITIONAL_EXPRESSION */) {
- if (node.alternate.type === 19 /* NodeTypes.JS_CONDITIONAL_EXPRESSION */) {
- node = node.alternate;
- }
- else {
- return node;
- }
- }
- else if (node.type === 20 /* NodeTypes.JS_CACHE_EXPRESSION */) {
- node = node.value;
- }
- }
- }
- const transformFor = createStructuralDirectiveTransform('for', (node, dir, context) => {
- const { helper, removeHelper } = context;
- return processFor(node, dir, context, forNode => {
- // create the loop render function expression now, and add the
- // iterator on exit after all children have been traversed
- const renderExp = createCallExpression(helper(RENDER_LIST), [
- forNode.source
- ]);
- const isTemplate = isTemplateNode(node);
- const memo = findDir(node, 'memo');
- const keyProp = findProp(node, `key`);
- const keyExp = keyProp &&
- (keyProp.type === 6 /* NodeTypes.ATTRIBUTE */
- ? createSimpleExpression(keyProp.value.content, true)
- : keyProp.exp);
- const keyProperty = keyProp ? createObjectProperty(`key`, keyExp) : null;
- if (isTemplate) {
- // #2085 / #5288 process :key and v-memo expressions need to be
- // processed on `<template v-for>`. In this case the node is discarded
- // and never traversed so its binding expressions won't be processed
- // by the normal transforms.
- if (memo) {
- memo.exp = processExpression(memo.exp, context);
- }
- if (keyProperty && keyProp.type !== 6 /* NodeTypes.ATTRIBUTE */) {
- keyProperty.value = processExpression(keyProperty.value, context);
- }
- }
- const isStableFragment = forNode.source.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */ &&
- forNode.source.constType > 0 /* ConstantTypes.NOT_CONSTANT */;
- const fragmentFlag = isStableFragment
- ? 64 /* PatchFlags.STABLE_FRAGMENT */
- : keyProp
- ? 128 /* PatchFlags.KEYED_FRAGMENT */
- : 256 /* PatchFlags.UNKEYED_FRAGMENT */;
- forNode.codegenNode = createVNodeCall(context, helper(FRAGMENT), undefined, renderExp, fragmentFlag +
- (``), undefined, undefined, true /* isBlock */, !isStableFragment /* disableTracking */, false /* isComponent */, node.loc);
- return () => {
- // finish the codegen now that all children have been traversed
- let childBlock;
- const { children } = forNode;
- // check <template v-for> key placement
- if (isTemplate) {
- node.children.some(c => {
- if (c.type === 1 /* NodeTypes.ELEMENT */) {
- const key = findProp(c, 'key');
- if (key) {
- context.onError(createCompilerError(33 /* ErrorCodes.X_V_FOR_TEMPLATE_KEY_PLACEMENT */, key.loc));
- return true;
- }
- }
- });
- }
- const needFragmentWrapper = children.length !== 1 || children[0].type !== 1 /* NodeTypes.ELEMENT */;
- const slotOutlet = isSlotOutlet(node)
- ? node
- : isTemplate &&
- node.children.length === 1 &&
- isSlotOutlet(node.children[0])
- ? node.children[0] // api-extractor somehow fails to infer this
- : null;
- if (slotOutlet) {
- // <slot v-for="..."> or <template v-for="..."><slot/></template>
- childBlock = slotOutlet.codegenNode;
- if (isTemplate && keyProperty) {
- // <template v-for="..." :key="..."><slot/></template>
- // we need to inject the key to the renderSlot() call.
- // the props for renderSlot is passed as the 3rd argument.
- injectProp(childBlock, keyProperty, context);
- }
- }
- else if (needFragmentWrapper) {
- // <template v-for="..."> with text or multi-elements
- // should generate a fragment block for each loop
- childBlock = createVNodeCall(context, helper(FRAGMENT), keyProperty ? createObjectExpression([keyProperty]) : undefined, node.children, 64 /* PatchFlags.STABLE_FRAGMENT */ +
- (``), undefined, undefined, true, undefined, false /* isComponent */);
- }
- else {
- // Normal element v-for. Directly use the child's codegenNode
- // but mark it as a block.
- childBlock = children[0]
- .codegenNode;
- if (isTemplate && keyProperty) {
- injectProp(childBlock, keyProperty, context);
- }
- if (childBlock.isBlock !== !isStableFragment) {
- if (childBlock.isBlock) {
- // switch from block to vnode
- removeHelper(OPEN_BLOCK);
- removeHelper(getVNodeBlockHelper(context.inSSR, childBlock.isComponent));
- }
- else {
- // switch from vnode to block
- removeHelper(getVNodeHelper(context.inSSR, childBlock.isComponent));
- }
- }
- childBlock.isBlock = !isStableFragment;
- if (childBlock.isBlock) {
- helper(OPEN_BLOCK);
- helper(getVNodeBlockHelper(context.inSSR, childBlock.isComponent));
- }
- else {
- helper(getVNodeHelper(context.inSSR, childBlock.isComponent));
- }
- }
- if (memo) {
- const loop = createFunctionExpression(createForLoopParams(forNode.parseResult, [
- createSimpleExpression(`_cached`)
- ]));
- loop.body = createBlockStatement([
- createCompoundExpression([`const _memo = (`, memo.exp, `)`]),
- createCompoundExpression([
- `if (_cached`,
- ...(keyExp ? [` && _cached.key === `, keyExp] : []),
- ` && ${context.helperString(IS_MEMO_SAME)}(_cached, _memo)) return _cached`
- ]),
- createCompoundExpression([`const _item = `, childBlock]),
- createSimpleExpression(`_item.memo = _memo`),
- createSimpleExpression(`return _item`)
- ]);
- renderExp.arguments.push(loop, createSimpleExpression(`_cache`), createSimpleExpression(String(context.cached++)));
- }
- else {
- renderExp.arguments.push(createFunctionExpression(createForLoopParams(forNode.parseResult), childBlock, true /* force newline */));
- }
- };
- });
- });
- // target-agnostic transform used for both Client and SSR
- function processFor(node, dir, context, processCodegen) {
- if (!dir.exp) {
- context.onError(createCompilerError(31 /* ErrorCodes.X_V_FOR_NO_EXPRESSION */, dir.loc));
- return;
- }
- const parseResult = parseForExpression(
- // can only be simple expression because vFor transform is applied
- // before expression transform.
- dir.exp, context);
- if (!parseResult) {
- context.onError(createCompilerError(32 /* ErrorCodes.X_V_FOR_MALFORMED_EXPRESSION */, dir.loc));
- return;
- }
- const { addIdentifiers, removeIdentifiers, scopes } = context;
- const { source, value, key, index } = parseResult;
- const forNode = {
- type: 11 /* NodeTypes.FOR */,
- loc: dir.loc,
- source,
- valueAlias: value,
- keyAlias: key,
- objectIndexAlias: index,
- parseResult,
- children: isTemplateNode(node) ? node.children : [node]
- };
- context.replaceNode(forNode);
- // bookkeeping
- scopes.vFor++;
- if (context.prefixIdentifiers) {
- // scope management
- // inject identifiers to context
- value && addIdentifiers(value);
- key && addIdentifiers(key);
- index && addIdentifiers(index);
- }
- const onExit = processCodegen && processCodegen(forNode);
- return () => {
- scopes.vFor--;
- if (context.prefixIdentifiers) {
- value && removeIdentifiers(value);
- key && removeIdentifiers(key);
- index && removeIdentifiers(index);
- }
- if (onExit)
- onExit();
- };
- }
- const forAliasRE = /([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/;
- // This regex doesn't cover the case if key or index aliases have destructuring,
- // but those do not make sense in the first place, so this works in practice.
- const forIteratorRE = /,([^,\}\]]*)(?:,([^,\}\]]*))?$/;
- const stripParensRE = /^\(|\)$/g;
- function parseForExpression(input, context) {
- const loc = input.loc;
- const exp = input.content;
- const inMatch = exp.match(forAliasRE);
- if (!inMatch)
- return;
- const [, LHS, RHS] = inMatch;
- const result = {
- source: createAliasExpression(loc, RHS.trim(), exp.indexOf(RHS, LHS.length)),
- value: undefined,
- key: undefined,
- index: undefined
- };
- if (context.prefixIdentifiers) {
- result.source = processExpression(result.source, context);
- }
- let valueContent = LHS.trim().replace(stripParensRE, '').trim();
- const trimmedOffset = LHS.indexOf(valueContent);
- const iteratorMatch = valueContent.match(forIteratorRE);
- if (iteratorMatch) {
- valueContent = valueContent.replace(forIteratorRE, '').trim();
- const keyContent = iteratorMatch[1].trim();
- let keyOffset;
- if (keyContent) {
- keyOffset = exp.indexOf(keyContent, trimmedOffset + valueContent.length);
- result.key = createAliasExpression(loc, keyContent, keyOffset);
- if (context.prefixIdentifiers) {
- result.key = processExpression(result.key, context, true);
- }
- }
- if (iteratorMatch[2]) {
- const indexContent = iteratorMatch[2].trim();
- if (indexContent) {
- result.index = createAliasExpression(loc, indexContent, exp.indexOf(indexContent, result.key
- ? keyOffset + keyContent.length
- : trimmedOffset + valueContent.length));
- if (context.prefixIdentifiers) {
- result.index = processExpression(result.index, context, true);
- }
- }
- }
- }
- if (valueContent) {
- result.value = createAliasExpression(loc, valueContent, trimmedOffset);
- if (context.prefixIdentifiers) {
- result.value = processExpression(result.value, context, true);
- }
- }
- return result;
- }
- function createAliasExpression(range, content, offset) {
- return createSimpleExpression(content, false, getInnerRange(range, offset, content.length));
- }
- function createForLoopParams({ value, key, index }, memoArgs = []) {
- return createParamsList([value, key, index, ...memoArgs]);
- }
- function createParamsList(args) {
- let i = args.length;
- while (i--) {
- if (args[i])
- break;
- }
- return args
- .slice(0, i + 1)
- .map((arg, i) => arg || createSimpleExpression(`_`.repeat(i + 1), false));
- }
- const defaultFallback = createSimpleExpression(`undefined`, false);
- // A NodeTransform that:
- // 1. Tracks scope identifiers for scoped slots so that they don't get prefixed
- // by transformExpression. This is only applied in non-browser builds with
- // { prefixIdentifiers: true }.
- // 2. Track v-slot depths so that we know a slot is inside another slot.
- // Note the exit callback is executed before buildSlots() on the same node,
- // so only nested slots see positive numbers.
- const trackSlotScopes = (node, context) => {
- if (node.type === 1 /* NodeTypes.ELEMENT */ &&
- (node.tagType === 1 /* ElementTypes.COMPONENT */ ||
- node.tagType === 3 /* ElementTypes.TEMPLATE */)) {
- // We are only checking non-empty v-slot here
- // since we only care about slots that introduce scope variables.
- const vSlot = findDir(node, 'slot');
- if (vSlot) {
- const slotProps = vSlot.exp;
- if (context.prefixIdentifiers) {
- slotProps && context.addIdentifiers(slotProps);
- }
- context.scopes.vSlot++;
- return () => {
- if (context.prefixIdentifiers) {
- slotProps && context.removeIdentifiers(slotProps);
- }
- context.scopes.vSlot--;
- };
- }
- }
- };
- // A NodeTransform that tracks scope identifiers for scoped slots with v-for.
- // This transform is only applied in non-browser builds with { prefixIdentifiers: true }
- const trackVForSlotScopes = (node, context) => {
- let vFor;
- if (isTemplateNode(node) &&
- node.props.some(isVSlot) &&
- (vFor = findDir(node, 'for'))) {
- const result = (vFor.parseResult = parseForExpression(vFor.exp, context));
- if (result) {
- const { value, key, index } = result;
- const { addIdentifiers, removeIdentifiers } = context;
- value && addIdentifiers(value);
- key && addIdentifiers(key);
- index && addIdentifiers(index);
- return () => {
- value && removeIdentifiers(value);
- key && removeIdentifiers(key);
- index && removeIdentifiers(index);
- };
- }
- }
- };
- const buildClientSlotFn = (props, children, loc) => createFunctionExpression(props, children, false /* newline */, true /* isSlot */, children.length ? children[0].loc : loc);
- // Instead of being a DirectiveTransform, v-slot processing is called during
- // transformElement to build the slots object for a component.
- function buildSlots(node, context, buildSlotFn = buildClientSlotFn) {
- context.helper(WITH_CTX);
- const { children, loc } = node;
- const slotsProperties = [];
- const dynamicSlots = [];
- // If the slot is inside a v-for or another v-slot, force it to be dynamic
- // since it likely uses a scope variable.
- let hasDynamicSlots = context.scopes.vSlot > 0 || context.scopes.vFor > 0;
- // with `prefixIdentifiers: true`, this can be further optimized to make
- // it dynamic only when the slot actually uses the scope variables.
- if (!context.ssr && context.prefixIdentifiers) {
- hasDynamicSlots = hasScopeRef(node, context.identifiers);
- }
- // 1. Check for slot with slotProps on component itself.
- // <Comp v-slot="{ prop }"/>
- const onComponentSlot = findDir(node, 'slot', true);
- if (onComponentSlot) {
- const { arg, exp } = onComponentSlot;
- if (arg && !isStaticExp(arg)) {
- hasDynamicSlots = true;
- }
- slotsProperties.push(createObjectProperty(arg || createSimpleExpression('default', true), buildSlotFn(exp, children, loc)));
- }
- // 2. Iterate through children and check for template slots
- // <template v-slot:foo="{ prop }">
- let hasTemplateSlots = false;
- let hasNamedDefaultSlot = false;
- const implicitDefaultChildren = [];
- const seenSlotNames = new Set();
- let conditionalBranchIndex = 0;
- for (let i = 0; i < children.length; i++) {
- const slotElement = children[i];
- let slotDir;
- if (!isTemplateNode(slotElement) ||
- !(slotDir = findDir(slotElement, 'slot', true))) {
- // not a <template v-slot>, skip.
- if (slotElement.type !== 3 /* NodeTypes.COMMENT */) {
- implicitDefaultChildren.push(slotElement);
- }
- continue;
- }
- if (onComponentSlot) {
- // already has on-component slot - this is incorrect usage.
- context.onError(createCompilerError(37 /* ErrorCodes.X_V_SLOT_MIXED_SLOT_USAGE */, slotDir.loc));
- break;
- }
- hasTemplateSlots = true;
- const { children: slotChildren, loc: slotLoc } = slotElement;
- const { arg: slotName = createSimpleExpression(`default`, true), exp: slotProps, loc: dirLoc } = slotDir;
- // check if name is dynamic.
- let staticSlotName;
- if (isStaticExp(slotName)) {
- staticSlotName = slotName ? slotName.content : `default`;
- }
- else {
- hasDynamicSlots = true;
- }
- const slotFunction = buildSlotFn(slotProps, slotChildren, slotLoc);
- // check if this slot is conditional (v-if/v-for)
- let vIf;
- let vElse;
- let vFor;
- if ((vIf = findDir(slotElement, 'if'))) {
- hasDynamicSlots = true;
- dynamicSlots.push(createConditionalExpression(vIf.exp, buildDynamicSlot(slotName, slotFunction, conditionalBranchIndex++), defaultFallback));
- }
- else if ((vElse = findDir(slotElement, /^else(-if)?$/, true /* allowEmpty */))) {
- // find adjacent v-if
- let j = i;
- let prev;
- while (j--) {
- prev = children[j];
- if (prev.type !== 3 /* NodeTypes.COMMENT */) {
- break;
- }
- }
- if (prev && isTemplateNode(prev) && findDir(prev, 'if')) {
- // remove node
- children.splice(i, 1);
- i--;
- // attach this slot to previous conditional
- let conditional = dynamicSlots[dynamicSlots.length - 1];
- while (conditional.alternate.type === 19 /* NodeTypes.JS_CONDITIONAL_EXPRESSION */) {
- conditional = conditional.alternate;
- }
- conditional.alternate = vElse.exp
- ? createConditionalExpression(vElse.exp, buildDynamicSlot(slotName, slotFunction, conditionalBranchIndex++), defaultFallback)
- : buildDynamicSlot(slotName, slotFunction, conditionalBranchIndex++);
- }
- else {
- context.onError(createCompilerError(30 /* ErrorCodes.X_V_ELSE_NO_ADJACENT_IF */, vElse.loc));
- }
- }
- else if ((vFor = findDir(slotElement, 'for'))) {
- hasDynamicSlots = true;
- const parseResult = vFor.parseResult ||
- parseForExpression(vFor.exp, context);
- if (parseResult) {
- // Render the dynamic slots as an array and add it to the createSlot()
- // args. The runtime knows how to handle it appropriately.
- dynamicSlots.push(createCallExpression(context.helper(RENDER_LIST), [
- parseResult.source,
- createFunctionExpression(createForLoopParams(parseResult), buildDynamicSlot(slotName, slotFunction), true /* force newline */)
- ]));
- }
- else {
- context.onError(createCompilerError(32 /* ErrorCodes.X_V_FOR_MALFORMED_EXPRESSION */, vFor.loc));
- }
- }
- else {
- // check duplicate static names
- if (staticSlotName) {
- if (seenSlotNames.has(staticSlotName)) {
- context.onError(createCompilerError(38 /* ErrorCodes.X_V_SLOT_DUPLICATE_SLOT_NAMES */, dirLoc));
- continue;
- }
- seenSlotNames.add(staticSlotName);
- if (staticSlotName === 'default') {
- hasNamedDefaultSlot = true;
- }
- }
- slotsProperties.push(createObjectProperty(slotName, slotFunction));
- }
- }
- if (!onComponentSlot) {
- const buildDefaultSlotProperty = (props, children) => {
- const fn = buildSlotFn(props, children, loc);
- if (context.compatConfig) {
- fn.isNonScopedSlot = true;
- }
- return createObjectProperty(`default`, fn);
- };
- if (!hasTemplateSlots) {
- // implicit default slot (on component)
- slotsProperties.push(buildDefaultSlotProperty(undefined, children));
- }
- else if (implicitDefaultChildren.length &&
- // #3766
- // with whitespace: 'preserve', whitespaces between slots will end up in
- // implicitDefaultChildren. Ignore if all implicit children are whitespaces.
- implicitDefaultChildren.some(node => isNonWhitespaceContent(node))) {
- // implicit default slot (mixed with named slots)
- if (hasNamedDefaultSlot) {
- context.onError(createCompilerError(39 /* ErrorCodes.X_V_SLOT_EXTRANEOUS_DEFAULT_SLOT_CHILDREN */, implicitDefaultChildren[0].loc));
- }
- else {
- slotsProperties.push(buildDefaultSlotProperty(undefined, implicitDefaultChildren));
- }
- }
- }
- const slotFlag = hasDynamicSlots
- ? 2 /* SlotFlags.DYNAMIC */
- : hasForwardedSlots(node.children)
- ? 3 /* SlotFlags.FORWARDED */
- : 1 /* SlotFlags.STABLE */;
- let slots = createObjectExpression(slotsProperties.concat(createObjectProperty(`_`,
- // 2 = compiled but dynamic = can skip normalization, but must run diff
- // 1 = compiled and static = can skip normalization AND diff as optimized
- createSimpleExpression(slotFlag + (``), false))), loc);
- if (dynamicSlots.length) {
- slots = createCallExpression(context.helper(CREATE_SLOTS), [
- slots,
- createArrayExpression(dynamicSlots)
- ]);
- }
- return {
- slots,
- hasDynamicSlots
- };
- }
- function buildDynamicSlot(name, fn, index) {
- const props = [
- createObjectProperty(`name`, name),
- createObjectProperty(`fn`, fn)
- ];
- if (index != null) {
- props.push(createObjectProperty(`key`, createSimpleExpression(String(index), true)));
- }
- return createObjectExpression(props);
- }
- function hasForwardedSlots(children) {
- for (let i = 0; i < children.length; i++) {
- const child = children[i];
- switch (child.type) {
- case 1 /* NodeTypes.ELEMENT */:
- if (child.tagType === 2 /* ElementTypes.SLOT */ ||
- hasForwardedSlots(child.children)) {
- return true;
- }
- break;
- case 9 /* NodeTypes.IF */:
- if (hasForwardedSlots(child.branches))
- return true;
- break;
- case 10 /* NodeTypes.IF_BRANCH */:
- case 11 /* NodeTypes.FOR */:
- if (hasForwardedSlots(child.children))
- return true;
- break;
- }
- }
- return false;
- }
- function isNonWhitespaceContent(node) {
- if (node.type !== 2 /* NodeTypes.TEXT */ && node.type !== 12 /* NodeTypes.TEXT_CALL */)
- return true;
- return node.type === 2 /* NodeTypes.TEXT */
- ? !!node.content.trim()
- : isNonWhitespaceContent(node.content);
- }
- // some directive transforms (e.g. v-model) may return a symbol for runtime
- // import, which should be used instead of a resolveDirective call.
- const directiveImportMap = new WeakMap();
- // generate a JavaScript AST for this element's codegen
- const transformElement = (node, context) => {
- // perform the work on exit, after all child expressions have been
- // processed and merged.
- return function postTransformElement() {
- node = context.currentNode;
- if (!(node.type === 1 /* NodeTypes.ELEMENT */ &&
- (node.tagType === 0 /* ElementTypes.ELEMENT */ ||
- node.tagType === 1 /* ElementTypes.COMPONENT */))) {
- return;
- }
- const { tag, props } = node;
- const isComponent = node.tagType === 1 /* ElementTypes.COMPONENT */;
- // The goal of the transform is to create a codegenNode implementing the
- // VNodeCall interface.
- let vnodeTag = isComponent
- ? resolveComponentType(node, context)
- : `"${tag}"`;
- const isDynamicComponent = shared.isObject(vnodeTag) && vnodeTag.callee === RESOLVE_DYNAMIC_COMPONENT;
- let vnodeProps;
- let vnodeChildren;
- let vnodePatchFlag;
- let patchFlag = 0;
- let vnodeDynamicProps;
- let dynamicPropNames;
- let vnodeDirectives;
- let shouldUseBlock =
- // dynamic component may resolve to plain elements
- isDynamicComponent ||
- vnodeTag === TELEPORT ||
- vnodeTag === SUSPENSE ||
- (!isComponent &&
- // <svg> and <foreignObject> must be forced into blocks so that block
- // updates inside get proper isSVG flag at runtime. (#639, #643)
- // This is technically web-specific, but splitting the logic out of core
- // leads to too much unnecessary complexity.
- (tag === 'svg' || tag === 'foreignObject'));
- // props
- if (props.length > 0) {
- const propsBuildResult = buildProps(node, context, undefined, isComponent, isDynamicComponent);
- vnodeProps = propsBuildResult.props;
- patchFlag = propsBuildResult.patchFlag;
- dynamicPropNames = propsBuildResult.dynamicPropNames;
- const directives = propsBuildResult.directives;
- vnodeDirectives =
- directives && directives.length
- ? createArrayExpression(directives.map(dir => buildDirectiveArgs(dir, context)))
- : undefined;
- if (propsBuildResult.shouldUseBlock) {
- shouldUseBlock = true;
- }
- }
- // children
- if (node.children.length > 0) {
- if (vnodeTag === KEEP_ALIVE) {
- // Although a built-in component, we compile KeepAlive with raw children
- // instead of slot functions so that it can be used inside Transition
- // or other Transition-wrapping HOCs.
- // To ensure correct updates with block optimizations, we need to:
- // 1. Force keep-alive into a block. This avoids its children being
- // collected by a parent block.
- shouldUseBlock = true;
- // 2. Force keep-alive to always be updated, since it uses raw children.
- patchFlag |= 1024 /* PatchFlags.DYNAMIC_SLOTS */;
- }
- const shouldBuildAsSlots = isComponent &&
- // Teleport is not a real component and has dedicated runtime handling
- vnodeTag !== TELEPORT &&
- // explained above.
- vnodeTag !== KEEP_ALIVE;
- if (shouldBuildAsSlots) {
- const { slots, hasDynamicSlots } = buildSlots(node, context);
- vnodeChildren = slots;
- if (hasDynamicSlots) {
- patchFlag |= 1024 /* PatchFlags.DYNAMIC_SLOTS */;
- }
- }
- else if (node.children.length === 1 && vnodeTag !== TELEPORT) {
- const child = node.children[0];
- const type = child.type;
- // check for dynamic text children
- const hasDynamicTextChild = type === 5 /* NodeTypes.INTERPOLATION */ ||
- type === 8 /* NodeTypes.COMPOUND_EXPRESSION */;
- if (hasDynamicTextChild &&
- getConstantType(child, context) === 0 /* ConstantTypes.NOT_CONSTANT */) {
- patchFlag |= 1 /* PatchFlags.TEXT */;
- }
- // pass directly if the only child is a text node
- // (plain / interpolation / expression)
- if (hasDynamicTextChild || type === 2 /* NodeTypes.TEXT */) {
- vnodeChildren = child;
- }
- else {
- vnodeChildren = node.children;
- }
- }
- else {
- vnodeChildren = node.children;
- }
- }
- // patchFlag & dynamicPropNames
- if (patchFlag !== 0) {
- {
- vnodePatchFlag = String(patchFlag);
- }
- if (dynamicPropNames && dynamicPropNames.length) {
- vnodeDynamicProps = stringifyDynamicPropNames(dynamicPropNames);
- }
- }
- node.codegenNode = createVNodeCall(context, vnodeTag, vnodeProps, vnodeChildren, vnodePatchFlag, vnodeDynamicProps, vnodeDirectives, !!shouldUseBlock, false /* disableTracking */, isComponent, node.loc);
- };
- };
- function resolveComponentType(node, context, ssr = false) {
- let { tag } = node;
- // 1. dynamic component
- const isExplicitDynamic = isComponentTag(tag);
- const isProp = findProp(node, 'is');
- if (isProp) {
- if (isExplicitDynamic ||
- (isCompatEnabled("COMPILER_IS_ON_ELEMENT" /* CompilerDeprecationTypes.COMPILER_IS_ON_ELEMENT */, context))) {
- const exp = isProp.type === 6 /* NodeTypes.ATTRIBUTE */
- ? isProp.value && createSimpleExpression(isProp.value.content, true)
- : isProp.exp;
- if (exp) {
- return createCallExpression(context.helper(RESOLVE_DYNAMIC_COMPONENT), [
- exp
- ]);
- }
- }
- else if (isProp.type === 6 /* NodeTypes.ATTRIBUTE */ &&
- isProp.value.content.startsWith('vue:')) {
- // <button is="vue:xxx">
- // if not <component>, only is value that starts with "vue:" will be
- // treated as component by the parse phase and reach here, unless it's
- // compat mode where all is values are considered components
- tag = isProp.value.content.slice(4);
- }
- }
- // 1.5 v-is (TODO: Deprecate)
- const isDir = !isExplicitDynamic && findDir(node, 'is');
- if (isDir && isDir.exp) {
- return createCallExpression(context.helper(RESOLVE_DYNAMIC_COMPONENT), [
- isDir.exp
- ]);
- }
- // 2. built-in components (Teleport, Transition, KeepAlive, Suspense...)
- const builtIn = isCoreComponent(tag) || context.isBuiltInComponent(tag);
- if (builtIn) {
- // built-ins are simply fallthroughs / have special handling during ssr
- // so we don't need to import their runtime equivalents
- if (!ssr)
- context.helper(builtIn);
- return builtIn;
- }
- // 3. user component (from setup bindings)
- // this is skipped in browser build since browser builds do not perform
- // binding analysis.
- {
- const fromSetup = resolveSetupReference(tag, context);
- if (fromSetup) {
- return fromSetup;
- }
- const dotIndex = tag.indexOf('.');
- if (dotIndex > 0) {
- const ns = resolveSetupReference(tag.slice(0, dotIndex), context);
- if (ns) {
- return ns + tag.slice(dotIndex);
- }
- }
- }
- // 4. Self referencing component (inferred from filename)
- if (context.selfName &&
- shared.capitalize(shared.camelize(tag)) === context.selfName) {
- context.helper(RESOLVE_COMPONENT);
- // codegen.ts has special check for __self postfix when generating
- // component imports, which will pass additional `maybeSelfReference` flag
- // to `resolveComponent`.
- context.components.add(tag + `__self`);
- return toValidAssetId(tag, `component`);
- }
- // 5. user component (resolve)
- context.helper(RESOLVE_COMPONENT);
- context.components.add(tag);
- return toValidAssetId(tag, `component`);
- }
- function resolveSetupReference(name, context) {
- const bindings = context.bindingMetadata;
- if (!bindings || bindings.__isScriptSetup === false) {
- return;
- }
- const camelName = shared.camelize(name);
- const PascalName = shared.capitalize(camelName);
- const checkType = (type) => {
- if (bindings[name] === type) {
- return name;
- }
- if (bindings[camelName] === type) {
- return camelName;
- }
- if (bindings[PascalName] === type) {
- return PascalName;
- }
- };
- const fromConst = checkType("setup-const" /* BindingTypes.SETUP_CONST */) ||
- checkType("setup-reactive-const" /* BindingTypes.SETUP_REACTIVE_CONST */);
- if (fromConst) {
- return context.inline
- ? // in inline mode, const setup bindings (e.g. imports) can be used as-is
- fromConst
- : `$setup[${JSON.stringify(fromConst)}]`;
- }
- const fromMaybeRef = checkType("setup-let" /* BindingTypes.SETUP_LET */) ||
- checkType("setup-ref" /* BindingTypes.SETUP_REF */) ||
- checkType("setup-maybe-ref" /* BindingTypes.SETUP_MAYBE_REF */);
- if (fromMaybeRef) {
- return context.inline
- ? // setup scope bindings that may be refs need to be unrefed
- `${context.helperString(UNREF)}(${fromMaybeRef})`
- : `$setup[${JSON.stringify(fromMaybeRef)}]`;
- }
- }
- function buildProps(node, context, props = node.props, isComponent, isDynamicComponent, ssr = false) {
- const { tag, loc: elementLoc, children } = node;
- let properties = [];
- const mergeArgs = [];
- const runtimeDirectives = [];
- const hasChildren = children.length > 0;
- let shouldUseBlock = false;
- // patchFlag analysis
- let patchFlag = 0;
- let hasRef = false;
- let hasClassBinding = false;
- let hasStyleBinding = false;
- let hasHydrationEventBinding = false;
- let hasDynamicKeys = false;
- let hasVnodeHook = false;
- const dynamicPropNames = [];
- const pushMergeArg = (arg) => {
- if (properties.length) {
- mergeArgs.push(createObjectExpression(dedupeProperties(properties), elementLoc));
- properties = [];
- }
- if (arg)
- mergeArgs.push(arg);
- };
- const analyzePatchFlag = ({ key, value }) => {
- if (isStaticExp(key)) {
- const name = key.content;
- const isEventHandler = shared.isOn(name);
- if (isEventHandler &&
- (!isComponent || isDynamicComponent) &&
- // omit the flag for click handlers because hydration gives click
- // dedicated fast path.
- name.toLowerCase() !== 'onclick' &&
- // omit v-model handlers
- name !== 'onUpdate:modelValue' &&
- // omit onVnodeXXX hooks
- !shared.isReservedProp(name)) {
- hasHydrationEventBinding = true;
- }
- if (isEventHandler && shared.isReservedProp(name)) {
- hasVnodeHook = true;
- }
- if (value.type === 20 /* NodeTypes.JS_CACHE_EXPRESSION */ ||
- ((value.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */ ||
- value.type === 8 /* NodeTypes.COMPOUND_EXPRESSION */) &&
- getConstantType(value, context) > 0)) {
- // skip if the prop is a cached handler or has constant value
- return;
- }
- if (name === 'ref') {
- hasRef = true;
- }
- else if (name === 'class') {
- hasClassBinding = true;
- }
- else if (name === 'style') {
- hasStyleBinding = true;
- }
- else if (name !== 'key' && !dynamicPropNames.includes(name)) {
- dynamicPropNames.push(name);
- }
- // treat the dynamic class and style binding of the component as dynamic props
- if (isComponent &&
- (name === 'class' || name === 'style') &&
- !dynamicPropNames.includes(name)) {
- dynamicPropNames.push(name);
- }
- }
- else {
- hasDynamicKeys = true;
- }
- };
- for (let i = 0; i < props.length; i++) {
- // static attribute
- const prop = props[i];
- if (prop.type === 6 /* NodeTypes.ATTRIBUTE */) {
- const { loc, name, value } = prop;
- let isStatic = true;
- if (name === 'ref') {
- hasRef = true;
- if (context.scopes.vFor > 0) {
- properties.push(createObjectProperty(createSimpleExpression('ref_for', true), createSimpleExpression('true')));
- }
- // in inline mode there is no setupState object, so we can't use string
- // keys to set the ref. Instead, we need to transform it to pass the
- // actual ref instead.
- if (value && context.inline) {
- const binding = context.bindingMetadata[value.content];
- if (binding === "setup-let" /* BindingTypes.SETUP_LET */ ||
- binding === "setup-ref" /* BindingTypes.SETUP_REF */ ||
- binding === "setup-maybe-ref" /* BindingTypes.SETUP_MAYBE_REF */) {
- isStatic = false;
- properties.push(createObjectProperty(createSimpleExpression('ref_key', true), createSimpleExpression(value.content, true, value.loc)));
- }
- }
- }
- // skip is on <component>, or is="vue:xxx"
- if (name === 'is' &&
- (isComponentTag(tag) ||
- (value && value.content.startsWith('vue:')) ||
- (isCompatEnabled("COMPILER_IS_ON_ELEMENT" /* CompilerDeprecationTypes.COMPILER_IS_ON_ELEMENT */, context)))) {
- continue;
- }
- properties.push(createObjectProperty(createSimpleExpression(name, true, getInnerRange(loc, 0, name.length)), createSimpleExpression(value ? value.content : '', isStatic, value ? value.loc : loc)));
- }
- else {
- // directives
- const { name, arg, exp, loc } = prop;
- const isVBind = name === 'bind';
- const isVOn = name === 'on';
- // skip v-slot - it is handled by its dedicated transform.
- if (name === 'slot') {
- if (!isComponent) {
- context.onError(createCompilerError(40 /* ErrorCodes.X_V_SLOT_MISPLACED */, loc));
- }
- continue;
- }
- // skip v-once/v-memo - they are handled by dedicated transforms.
- if (name === 'once' || name === 'memo') {
- continue;
- }
- // skip v-is and :is on <component>
- if (name === 'is' ||
- (isVBind &&
- isStaticArgOf(arg, 'is') &&
- (isComponentTag(tag) ||
- (isCompatEnabled("COMPILER_IS_ON_ELEMENT" /* CompilerDeprecationTypes.COMPILER_IS_ON_ELEMENT */, context))))) {
- continue;
- }
- // skip v-on in SSR compilation
- if (isVOn && ssr) {
- continue;
- }
- if (
- // #938: elements with dynamic keys should be forced into blocks
- (isVBind && isStaticArgOf(arg, 'key')) ||
- // inline before-update hooks need to force block so that it is invoked
- // before children
- (isVOn && hasChildren && isStaticArgOf(arg, 'vue:before-update'))) {
- shouldUseBlock = true;
- }
- if (isVBind && isStaticArgOf(arg, 'ref') && context.scopes.vFor > 0) {
- properties.push(createObjectProperty(createSimpleExpression('ref_for', true), createSimpleExpression('true')));
- }
- // special case for v-bind and v-on with no argument
- if (!arg && (isVBind || isVOn)) {
- hasDynamicKeys = true;
- if (exp) {
- if (isVBind) {
- // have to merge early for compat build check
- pushMergeArg();
- {
- if (isCompatEnabled("COMPILER_V_BIND_OBJECT_ORDER" /* CompilerDeprecationTypes.COMPILER_V_BIND_OBJECT_ORDER */, context)) {
- mergeArgs.unshift(exp);
- continue;
- }
- }
- mergeArgs.push(exp);
- }
- else {
- // v-on="obj" -> toHandlers(obj)
- pushMergeArg({
- type: 14 /* NodeTypes.JS_CALL_EXPRESSION */,
- loc,
- callee: context.helper(TO_HANDLERS),
- arguments: isComponent ? [exp] : [exp, `true`]
- });
- }
- }
- else {
- context.onError(createCompilerError(isVBind
- ? 34 /* ErrorCodes.X_V_BIND_NO_EXPRESSION */
- : 35 /* ErrorCodes.X_V_ON_NO_EXPRESSION */, loc));
- }
- continue;
- }
- const directiveTransform = context.directiveTransforms[name];
- if (directiveTransform) {
- // has built-in directive transform.
- const { props, needRuntime } = directiveTransform(prop, node, context);
- !ssr && props.forEach(analyzePatchFlag);
- if (isVOn && arg && !isStaticExp(arg)) {
- pushMergeArg(createObjectExpression(props, elementLoc));
- }
- else {
- properties.push(...props);
- }
- if (needRuntime) {
- runtimeDirectives.push(prop);
- if (shared.isSymbol(needRuntime)) {
- directiveImportMap.set(prop, needRuntime);
- }
- }
- }
- else if (!shared.isBuiltInDirective(name)) {
- // no built-in transform, this is a user custom directive.
- runtimeDirectives.push(prop);
- // custom dirs may use beforeUpdate so they need to force blocks
- // to ensure before-update gets called before children update
- if (hasChildren) {
- shouldUseBlock = true;
- }
- }
- }
- }
- let propsExpression = undefined;
- // has v-bind="object" or v-on="object", wrap with mergeProps
- if (mergeArgs.length) {
- // close up any not-yet-merged props
- pushMergeArg();
- if (mergeArgs.length > 1) {
- propsExpression = createCallExpression(context.helper(MERGE_PROPS), mergeArgs, elementLoc);
- }
- else {
- // single v-bind with nothing else - no need for a mergeProps call
- propsExpression = mergeArgs[0];
- }
- }
- else if (properties.length) {
- propsExpression = createObjectExpression(dedupeProperties(properties), elementLoc);
- }
- // patchFlag analysis
- if (hasDynamicKeys) {
- patchFlag |= 16 /* PatchFlags.FULL_PROPS */;
- }
- else {
- if (hasClassBinding && !isComponent) {
- patchFlag |= 2 /* PatchFlags.CLASS */;
- }
- if (hasStyleBinding && !isComponent) {
- patchFlag |= 4 /* PatchFlags.STYLE */;
- }
- if (dynamicPropNames.length) {
- patchFlag |= 8 /* PatchFlags.PROPS */;
- }
- if (hasHydrationEventBinding) {
- patchFlag |= 32 /* PatchFlags.HYDRATE_EVENTS */;
- }
- }
- if (!shouldUseBlock &&
- (patchFlag === 0 || patchFlag === 32 /* PatchFlags.HYDRATE_EVENTS */) &&
- (hasRef || hasVnodeHook || runtimeDirectives.length > 0)) {
- patchFlag |= 512 /* PatchFlags.NEED_PATCH */;
- }
- // pre-normalize props, SSR is skipped for now
- if (!context.inSSR && propsExpression) {
- switch (propsExpression.type) {
- case 15 /* NodeTypes.JS_OBJECT_EXPRESSION */:
- // means that there is no v-bind,
- // but still need to deal with dynamic key binding
- let classKeyIndex = -1;
- let styleKeyIndex = -1;
- let hasDynamicKey = false;
- for (let i = 0; i < propsExpression.properties.length; i++) {
- const key = propsExpression.properties[i].key;
- if (isStaticExp(key)) {
- if (key.content === 'class') {
- classKeyIndex = i;
- }
- else if (key.content === 'style') {
- styleKeyIndex = i;
- }
- }
- else if (!key.isHandlerKey) {
- hasDynamicKey = true;
- }
- }
- const classProp = propsExpression.properties[classKeyIndex];
- const styleProp = propsExpression.properties[styleKeyIndex];
- // no dynamic key
- if (!hasDynamicKey) {
- if (classProp && !isStaticExp(classProp.value)) {
- classProp.value = createCallExpression(context.helper(NORMALIZE_CLASS), [classProp.value]);
- }
- if (styleProp &&
- // the static style is compiled into an object,
- // so use `hasStyleBinding` to ensure that it is a dynamic style binding
- (hasStyleBinding ||
- (styleProp.value.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */ &&
- styleProp.value.content.trim()[0] === `[`) ||
- // v-bind:style and style both exist,
- // v-bind:style with static literal object
- styleProp.value.type === 17 /* NodeTypes.JS_ARRAY_EXPRESSION */)) {
- styleProp.value = createCallExpression(context.helper(NORMALIZE_STYLE), [styleProp.value]);
- }
- }
- else {
- // dynamic key binding, wrap with `normalizeProps`
- propsExpression = createCallExpression(context.helper(NORMALIZE_PROPS), [propsExpression]);
- }
- break;
- case 14 /* NodeTypes.JS_CALL_EXPRESSION */:
- // mergeProps call, do nothing
- break;
- default:
- // single v-bind
- propsExpression = createCallExpression(context.helper(NORMALIZE_PROPS), [
- createCallExpression(context.helper(GUARD_REACTIVE_PROPS), [
- propsExpression
- ])
- ]);
- break;
- }
- }
- return {
- props: propsExpression,
- directives: runtimeDirectives,
- patchFlag,
- dynamicPropNames,
- shouldUseBlock
- };
- }
- // Dedupe props in an object literal.
- // Literal duplicated attributes would have been warned during the parse phase,
- // however, it's possible to encounter duplicated `onXXX` handlers with different
- // modifiers. We also need to merge static and dynamic class / style attributes.
- // - onXXX handlers / style: merge into array
- // - class: merge into single expression with concatenation
- function dedupeProperties(properties) {
- const knownProps = new Map();
- const deduped = [];
- for (let i = 0; i < properties.length; i++) {
- const prop = properties[i];
- // dynamic keys are always allowed
- if (prop.key.type === 8 /* NodeTypes.COMPOUND_EXPRESSION */ || !prop.key.isStatic) {
- deduped.push(prop);
- continue;
- }
- const name = prop.key.content;
- const existing = knownProps.get(name);
- if (existing) {
- if (name === 'style' || name === 'class' || shared.isOn(name)) {
- mergeAsArray(existing, prop);
- }
- // unexpected duplicate, should have emitted error during parse
- }
- else {
- knownProps.set(name, prop);
- deduped.push(prop);
- }
- }
- return deduped;
- }
- function mergeAsArray(existing, incoming) {
- if (existing.value.type === 17 /* NodeTypes.JS_ARRAY_EXPRESSION */) {
- existing.value.elements.push(incoming.value);
- }
- else {
- existing.value = createArrayExpression([existing.value, incoming.value], existing.loc);
- }
- }
- function buildDirectiveArgs(dir, context) {
- const dirArgs = [];
- const runtime = directiveImportMap.get(dir);
- if (runtime) {
- // built-in directive with runtime
- dirArgs.push(context.helperString(runtime));
- }
- else {
- // user directive.
- // see if we have directives exposed via <script setup>
- const fromSetup = resolveSetupReference('v-' + dir.name, context);
- if (fromSetup) {
- dirArgs.push(fromSetup);
- }
- else {
- // inject statement for resolving directive
- context.helper(RESOLVE_DIRECTIVE);
- context.directives.add(dir.name);
- dirArgs.push(toValidAssetId(dir.name, `directive`));
- }
- }
- const { loc } = dir;
- if (dir.exp)
- dirArgs.push(dir.exp);
- if (dir.arg) {
- if (!dir.exp) {
- dirArgs.push(`void 0`);
- }
- dirArgs.push(dir.arg);
- }
- if (Object.keys(dir.modifiers).length) {
- if (!dir.arg) {
- if (!dir.exp) {
- dirArgs.push(`void 0`);
- }
- dirArgs.push(`void 0`);
- }
- const trueExpression = createSimpleExpression(`true`, false, loc);
- dirArgs.push(createObjectExpression(dir.modifiers.map(modifier => createObjectProperty(modifier, trueExpression)), loc));
- }
- return createArrayExpression(dirArgs, dir.loc);
- }
- function stringifyDynamicPropNames(props) {
- let propsNamesString = `[`;
- for (let i = 0, l = props.length; i < l; i++) {
- propsNamesString += JSON.stringify(props[i]);
- if (i < l - 1)
- propsNamesString += ', ';
- }
- return propsNamesString + `]`;
- }
- function isComponentTag(tag) {
- return tag === 'component' || tag === 'Component';
- }
- const cacheStringFunction = (fn) => {
- const cache = Object.create(null);
- return ((str) => {
- const hit = cache[str];
- return hit || (cache[str] = fn(str));
- });
- };
- const camelizeRE = /-(\w)/g;
- /**
- * @private
- */
- const camelize = cacheStringFunction((str) => {
- return str.replace(camelizeRE, (_, c) => (c ? c.toUpperCase() : ''));
- });
- const transformSlotOutlet = (node, context) => {
- if (isSlotOutlet(node)) {
- const { children, loc } = node;
- const { slotName, slotProps } = processSlotOutlet(node, context);
- const slotArgs = [
- context.prefixIdentifiers ? `_ctx.$slots` : `$slots`,
- slotName,
- '{}',
- 'undefined',
- 'true'
- ];
- let expectedLen = 2;
- if (slotProps) {
- slotArgs[2] = slotProps;
- expectedLen = 3;
- }
- if (children.length) {
- slotArgs[3] = createFunctionExpression([], children, false, false, loc);
- expectedLen = 4;
- }
- if (context.scopeId && !context.slotted) {
- expectedLen = 5;
- }
- slotArgs.splice(expectedLen); // remove unused arguments
- node.codegenNode = createCallExpression(context.helper(RENDER_SLOT), slotArgs, loc);
- }
- };
- function processSlotOutlet(node, context) {
- let slotName = `"default"`;
- let slotProps = undefined;
- const nonNameProps = [];
- for (let i = 0; i < node.props.length; i++) {
- const p = node.props[i];
- if (p.type === 6 /* NodeTypes.ATTRIBUTE */) {
- if (p.value) {
- if (p.name === 'name') {
- slotName = JSON.stringify(p.value.content);
- }
- else {
- p.name = camelize(p.name);
- nonNameProps.push(p);
- }
- }
- }
- else {
- if (p.name === 'bind' && isStaticArgOf(p.arg, 'name')) {
- if (p.exp)
- slotName = p.exp;
- }
- else {
- if (p.name === 'bind' && p.arg && isStaticExp(p.arg)) {
- p.arg.content = camelize(p.arg.content);
- }
- nonNameProps.push(p);
- }
- }
- }
- if (nonNameProps.length > 0) {
- const { props, directives } = buildProps(node, context, nonNameProps, false, false);
- slotProps = props;
- if (directives.length) {
- context.onError(createCompilerError(36 /* ErrorCodes.X_V_SLOT_UNEXPECTED_DIRECTIVE_ON_SLOT_OUTLET */, directives[0].loc));
- }
- }
- return {
- slotName,
- slotProps
- };
- }
- const fnExpRE = /^\s*([\w$_]+|(async\s*)?\([^)]*?\))\s*(:[^=]+)?=>|^\s*(async\s+)?function(?:\s+[\w$]+)?\s*\(/;
- const transformOn = (dir, node, context, augmentor) => {
- const { loc, modifiers, arg } = dir;
- if (!dir.exp && !modifiers.length) {
- context.onError(createCompilerError(35 /* ErrorCodes.X_V_ON_NO_EXPRESSION */, loc));
- }
- let eventName;
- if (arg.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */) {
- if (arg.isStatic) {
- let rawName = arg.content;
- // TODO deprecate @vnodeXXX usage
- if (rawName.startsWith('vue:')) {
- rawName = `vnode-${rawName.slice(4)}`;
- }
- const eventString = node.tagType !== 0 /* ElementTypes.ELEMENT */ ||
- rawName.startsWith('vnode') ||
- !/[A-Z]/.test(rawName)
- ? // for non-element and vnode lifecycle event listeners, auto convert
- // it to camelCase. See issue #2249
- shared.toHandlerKey(shared.camelize(rawName))
- : // preserve case for plain element listeners that have uppercase
- // letters, as these may be custom elements' custom events
- `on:${rawName}`;
- eventName = createSimpleExpression(eventString, true, arg.loc);
- }
- else {
- // #2388
- eventName = createCompoundExpression([
- `${context.helperString(TO_HANDLER_KEY)}(`,
- arg,
- `)`
- ]);
- }
- }
- else {
- // already a compound expression.
- eventName = arg;
- eventName.children.unshift(`${context.helperString(TO_HANDLER_KEY)}(`);
- eventName.children.push(`)`);
- }
- // handler processing
- let exp = dir.exp;
- if (exp && !exp.content.trim()) {
- exp = undefined;
- }
- let shouldCache = context.cacheHandlers && !exp && !context.inVOnce;
- if (exp) {
- const isMemberExp = isMemberExpression(exp.content, context);
- const isInlineStatement = !(isMemberExp || fnExpRE.test(exp.content));
- const hasMultipleStatements = exp.content.includes(`;`);
- // process the expression since it's been skipped
- if (context.prefixIdentifiers) {
- isInlineStatement && context.addIdentifiers(`$event`);
- exp = dir.exp = processExpression(exp, context, false, hasMultipleStatements);
- isInlineStatement && context.removeIdentifiers(`$event`);
- // with scope analysis, the function is hoistable if it has no reference
- // to scope variables.
- shouldCache =
- context.cacheHandlers &&
- // unnecessary to cache inside v-once
- !context.inVOnce &&
- // runtime constants don't need to be cached
- // (this is analyzed by compileScript in SFC <script setup>)
- !(exp.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */ && exp.constType > 0) &&
- // #1541 bail if this is a member exp handler passed to a component -
- // we need to use the original function to preserve arity,
- // e.g. <transition> relies on checking cb.length to determine
- // transition end handling. Inline function is ok since its arity
- // is preserved even when cached.
- !(isMemberExp && node.tagType === 1 /* ElementTypes.COMPONENT */) &&
- // bail if the function references closure variables (v-for, v-slot)
- // it must be passed fresh to avoid stale values.
- !hasScopeRef(exp, context.identifiers);
- // If the expression is optimizable and is a member expression pointing
- // to a function, turn it into invocation (and wrap in an arrow function
- // below) so that it always accesses the latest value when called - thus
- // avoiding the need to be patched.
- if (shouldCache && isMemberExp) {
- if (exp.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */) {
- exp.content = `${exp.content} && ${exp.content}(...args)`;
- }
- else {
- exp.children = [...exp.children, ` && `, ...exp.children, `(...args)`];
- }
- }
- }
- if (isInlineStatement || (shouldCache && isMemberExp)) {
- // wrap inline statement in a function expression
- exp = createCompoundExpression([
- `${isInlineStatement
- ? context.isTS
- ? `($event: any)`
- : `$event`
- : `${context.isTS ? `\n//@ts-ignore\n` : ``}(...args)`} => ${hasMultipleStatements ? `{` : `(`}`,
- exp,
- hasMultipleStatements ? `}` : `)`
- ]);
- }
- }
- let ret = {
- props: [
- createObjectProperty(eventName, exp || createSimpleExpression(`() => {}`, false, loc))
- ]
- };
- // apply extended compiler augmentor
- if (augmentor) {
- ret = augmentor(ret);
- }
- if (shouldCache) {
- // cache handlers so that it's always the same handler being passed down.
- // this avoids unnecessary re-renders when users use inline handlers on
- // components.
- ret.props[0].value = context.cache(ret.props[0].value);
- }
- // mark the key as handler for props normalization check
- ret.props.forEach(p => (p.key.isHandlerKey = true));
- return ret;
- };
- // v-bind without arg is handled directly in ./transformElements.ts due to it affecting
- // codegen for the entire props object. This transform here is only for v-bind
- // *with* args.
- const transformBind = (dir, _node, context) => {
- const { exp, modifiers, loc } = dir;
- const arg = dir.arg;
- if (arg.type !== 4 /* NodeTypes.SIMPLE_EXPRESSION */) {
- arg.children.unshift(`(`);
- arg.children.push(`) || ""`);
- }
- else if (!arg.isStatic) {
- arg.content = `${arg.content} || ""`;
- }
- // .sync is replaced by v-model:arg
- if (modifiers.includes('camel')) {
- if (arg.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */) {
- if (arg.isStatic) {
- arg.content = shared.camelize(arg.content);
- }
- else {
- arg.content = `${context.helperString(CAMELIZE)}(${arg.content})`;
- }
- }
- else {
- arg.children.unshift(`${context.helperString(CAMELIZE)}(`);
- arg.children.push(`)`);
- }
- }
- if (!context.inSSR) {
- if (modifiers.includes('prop')) {
- injectPrefix(arg, '.');
- }
- if (modifiers.includes('attr')) {
- injectPrefix(arg, '^');
- }
- }
- if (!exp ||
- (exp.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */ && !exp.content.trim())) {
- context.onError(createCompilerError(34 /* ErrorCodes.X_V_BIND_NO_EXPRESSION */, loc));
- return {
- props: [createObjectProperty(arg, createSimpleExpression('', true, loc))]
- };
- }
- return {
- props: [createObjectProperty(arg, exp)]
- };
- };
- const injectPrefix = (arg, prefix) => {
- if (arg.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */) {
- if (arg.isStatic) {
- arg.content = prefix + arg.content;
- }
- else {
- arg.content = `\`${prefix}\${${arg.content}}\``;
- }
- }
- else {
- arg.children.unshift(`'${prefix}' + (`);
- arg.children.push(`)`);
- }
- };
- // Merge adjacent text nodes and expressions into a single expression
- // e.g. <div>abc {{ d }} {{ e }}</div> should have a single expression node as child.
- const transformText = (node, context) => {
- if (node.type === 0 /* NodeTypes.ROOT */ ||
- node.type === 1 /* NodeTypes.ELEMENT */ ||
- node.type === 11 /* NodeTypes.FOR */ ||
- node.type === 10 /* NodeTypes.IF_BRANCH */) {
- // perform the transform on node exit so that all expressions have already
- // been processed.
- return () => {
- const children = node.children;
- let currentContainer = undefined;
- let hasText = false;
- for (let i = 0; i < children.length; i++) {
- const child = children[i];
- if (isText(child)) {
- hasText = true;
- for (let j = i + 1; j < children.length; j++) {
- const next = children[j];
- if (isText(next)) {
- if (!currentContainer) {
- currentContainer = children[i] = createCompoundExpression([child], child.loc);
- }
- // merge adjacent text node into current
- currentContainer.children.push(` + `, next);
- children.splice(j, 1);
- j--;
- }
- else {
- currentContainer = undefined;
- break;
- }
- }
- }
- }
- if (!hasText ||
- // if this is a plain element with a single text child, leave it
- // as-is since the runtime has dedicated fast path for this by directly
- // setting textContent of the element.
- // for component root it's always normalized anyway.
- (children.length === 1 &&
- (node.type === 0 /* NodeTypes.ROOT */ ||
- (node.type === 1 /* NodeTypes.ELEMENT */ &&
- node.tagType === 0 /* ElementTypes.ELEMENT */ &&
- // #3756
- // custom directives can potentially add DOM elements arbitrarily,
- // we need to avoid setting textContent of the element at runtime
- // to avoid accidentally overwriting the DOM elements added
- // by the user through custom directives.
- !node.props.find(p => p.type === 7 /* NodeTypes.DIRECTIVE */ &&
- !context.directiveTransforms[p.name]) &&
- // in compat mode, <template> tags with no special directives
- // will be rendered as a fragment so its children must be
- // converted into vnodes.
- !(node.tag === 'template'))))) {
- return;
- }
- // pre-convert text nodes into createTextVNode(text) calls to avoid
- // runtime normalization.
- for (let i = 0; i < children.length; i++) {
- const child = children[i];
- if (isText(child) || child.type === 8 /* NodeTypes.COMPOUND_EXPRESSION */) {
- const callArgs = [];
- // createTextVNode defaults to single whitespace, so if it is a
- // single space the code could be an empty call to save bytes.
- if (child.type !== 2 /* NodeTypes.TEXT */ || child.content !== ' ') {
- callArgs.push(child);
- }
- // mark dynamic text with flag so it gets patched inside a block
- if (!context.ssr &&
- getConstantType(child, context) === 0 /* ConstantTypes.NOT_CONSTANT */) {
- callArgs.push(1 /* PatchFlags.TEXT */ +
- (``));
- }
- children[i] = {
- type: 12 /* NodeTypes.TEXT_CALL */,
- content: child,
- loc: child.loc,
- codegenNode: createCallExpression(context.helper(CREATE_TEXT), callArgs)
- };
- }
- }
- };
- }
- };
- const seen = new WeakSet();
- const transformOnce = (node, context) => {
- if (node.type === 1 /* NodeTypes.ELEMENT */ && findDir(node, 'once', true)) {
- if (seen.has(node) || context.inVOnce) {
- return;
- }
- seen.add(node);
- context.inVOnce = true;
- context.helper(SET_BLOCK_TRACKING);
- return () => {
- context.inVOnce = false;
- const cur = context.currentNode;
- if (cur.codegenNode) {
- cur.codegenNode = context.cache(cur.codegenNode, true /* isVNode */);
- }
- };
- }
- };
- const transformModel = (dir, node, context) => {
- const { exp, arg } = dir;
- if (!exp) {
- context.onError(createCompilerError(41 /* ErrorCodes.X_V_MODEL_NO_EXPRESSION */, dir.loc));
- return createTransformProps();
- }
- const rawExp = exp.loc.source;
- const expString = exp.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */ ? exp.content : rawExp;
- // im SFC <script setup> inline mode, the exp may have been transformed into
- // _unref(exp)
- const bindingType = context.bindingMetadata[rawExp];
- // check props
- if (bindingType === "props" /* BindingTypes.PROPS */ ||
- bindingType === "props-aliased" /* BindingTypes.PROPS_ALIASED */) {
- context.onError(createCompilerError(44 /* ErrorCodes.X_V_MODEL_ON_PROPS */, exp.loc));
- return createTransformProps();
- }
- const maybeRef = context.inline &&
- (bindingType === "setup-let" /* BindingTypes.SETUP_LET */ ||
- bindingType === "setup-ref" /* BindingTypes.SETUP_REF */ ||
- bindingType === "setup-maybe-ref" /* BindingTypes.SETUP_MAYBE_REF */);
- if (!expString.trim() ||
- (!isMemberExpression(expString, context) && !maybeRef)) {
- context.onError(createCompilerError(42 /* ErrorCodes.X_V_MODEL_MALFORMED_EXPRESSION */, exp.loc));
- return createTransformProps();
- }
- if (context.prefixIdentifiers &&
- isSimpleIdentifier(expString) &&
- context.identifiers[expString]) {
- context.onError(createCompilerError(43 /* ErrorCodes.X_V_MODEL_ON_SCOPE_VARIABLE */, exp.loc));
- return createTransformProps();
- }
- const propName = arg ? arg : createSimpleExpression('modelValue', true);
- const eventName = arg
- ? isStaticExp(arg)
- ? `onUpdate:${arg.content}`
- : createCompoundExpression(['"onUpdate:" + ', arg])
- : `onUpdate:modelValue`;
- let assignmentExp;
- const eventArg = context.isTS ? `($event: any)` : `$event`;
- if (maybeRef) {
- if (bindingType === "setup-ref" /* BindingTypes.SETUP_REF */) {
- // v-model used on known ref.
- assignmentExp = createCompoundExpression([
- `${eventArg} => ((`,
- createSimpleExpression(rawExp, false, exp.loc),
- `).value = $event)`
- ]);
- }
- else {
- // v-model used on a potentially ref binding in <script setup> inline mode.
- // the assignment needs to check whether the binding is actually a ref.
- const altAssignment = bindingType === "setup-let" /* BindingTypes.SETUP_LET */ ? `${rawExp} = $event` : `null`;
- assignmentExp = createCompoundExpression([
- `${eventArg} => (${context.helperString(IS_REF)}(${rawExp}) ? (`,
- createSimpleExpression(rawExp, false, exp.loc),
- `).value = $event : ${altAssignment})`
- ]);
- }
- }
- else {
- assignmentExp = createCompoundExpression([
- `${eventArg} => ((`,
- exp,
- `) = $event)`
- ]);
- }
- const props = [
- // modelValue: foo
- createObjectProperty(propName, dir.exp),
- // "onUpdate:modelValue": $event => (foo = $event)
- createObjectProperty(eventName, assignmentExp)
- ];
- // cache v-model handler if applicable (when it doesn't refer any scope vars)
- if (context.prefixIdentifiers &&
- !context.inVOnce &&
- context.cacheHandlers &&
- !hasScopeRef(exp, context.identifiers)) {
- props[1].value = context.cache(props[1].value);
- }
- // modelModifiers: { foo: true, "bar-baz": true }
- if (dir.modifiers.length && node.tagType === 1 /* ElementTypes.COMPONENT */) {
- const modifiers = dir.modifiers
- .map(m => (isSimpleIdentifier(m) ? m : JSON.stringify(m)) + `: true`)
- .join(`, `);
- const modifiersKey = arg
- ? isStaticExp(arg)
- ? `${arg.content}Modifiers`
- : createCompoundExpression([arg, ' + "Modifiers"'])
- : `modelModifiers`;
- props.push(createObjectProperty(modifiersKey, createSimpleExpression(`{ ${modifiers} }`, false, dir.loc, 2 /* ConstantTypes.CAN_HOIST */)));
- }
- return createTransformProps(props);
- };
- function createTransformProps(props = []) {
- return { props };
- }
- const validDivisionCharRE = /[\w).+\-_$\]]/;
- const transformFilter = (node, context) => {
- if (!isCompatEnabled("COMPILER_FILTER" /* CompilerDeprecationTypes.COMPILER_FILTERS */, context)) {
- return;
- }
- if (node.type === 5 /* NodeTypes.INTERPOLATION */) {
- // filter rewrite is applied before expression transform so only
- // simple expressions are possible at this stage
- rewriteFilter(node.content, context);
- }
- if (node.type === 1 /* NodeTypes.ELEMENT */) {
- node.props.forEach((prop) => {
- if (prop.type === 7 /* NodeTypes.DIRECTIVE */ &&
- prop.name !== 'for' &&
- prop.exp) {
- rewriteFilter(prop.exp, context);
- }
- });
- }
- };
- function rewriteFilter(node, context) {
- if (node.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */) {
- parseFilter(node, context);
- }
- else {
- for (let i = 0; i < node.children.length; i++) {
- const child = node.children[i];
- if (typeof child !== 'object')
- continue;
- if (child.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */) {
- parseFilter(child, context);
- }
- else if (child.type === 8 /* NodeTypes.COMPOUND_EXPRESSION */) {
- rewriteFilter(node, context);
- }
- else if (child.type === 5 /* NodeTypes.INTERPOLATION */) {
- rewriteFilter(child.content, context);
- }
- }
- }
- }
- function parseFilter(node, context) {
- const exp = node.content;
- let inSingle = false;
- let inDouble = false;
- let inTemplateString = false;
- let inRegex = false;
- let curly = 0;
- let square = 0;
- let paren = 0;
- let lastFilterIndex = 0;
- let c, prev, i, expression, filters = [];
- for (i = 0; i < exp.length; i++) {
- prev = c;
- c = exp.charCodeAt(i);
- if (inSingle) {
- if (c === 0x27 && prev !== 0x5c)
- inSingle = false;
- }
- else if (inDouble) {
- if (c === 0x22 && prev !== 0x5c)
- inDouble = false;
- }
- else if (inTemplateString) {
- if (c === 0x60 && prev !== 0x5c)
- inTemplateString = false;
- }
- else if (inRegex) {
- if (c === 0x2f && prev !== 0x5c)
- inRegex = false;
- }
- else if (c === 0x7c && // pipe
- exp.charCodeAt(i + 1) !== 0x7c &&
- exp.charCodeAt(i - 1) !== 0x7c &&
- !curly &&
- !square &&
- !paren) {
- if (expression === undefined) {
- // first filter, end of expression
- lastFilterIndex = i + 1;
- expression = exp.slice(0, i).trim();
- }
- else {
- pushFilter();
- }
- }
- else {
- switch (c) {
- case 0x22:
- inDouble = true;
- break; // "
- case 0x27:
- inSingle = true;
- break; // '
- case 0x60:
- inTemplateString = true;
- break; // `
- case 0x28:
- paren++;
- break; // (
- case 0x29:
- paren--;
- break; // )
- case 0x5b:
- square++;
- break; // [
- case 0x5d:
- square--;
- break; // ]
- case 0x7b:
- curly++;
- break; // {
- case 0x7d:
- curly--;
- break; // }
- }
- if (c === 0x2f) {
- // /
- let j = i - 1;
- let p;
- // find first non-whitespace prev char
- for (; j >= 0; j--) {
- p = exp.charAt(j);
- if (p !== ' ')
- break;
- }
- if (!p || !validDivisionCharRE.test(p)) {
- inRegex = true;
- }
- }
- }
- }
- if (expression === undefined) {
- expression = exp.slice(0, i).trim();
- }
- else if (lastFilterIndex !== 0) {
- pushFilter();
- }
- function pushFilter() {
- filters.push(exp.slice(lastFilterIndex, i).trim());
- lastFilterIndex = i + 1;
- }
- if (filters.length) {
- for (i = 0; i < filters.length; i++) {
- expression = wrapFilter(expression, filters[i], context);
- }
- node.content = expression;
- }
- }
- function wrapFilter(exp, filter, context) {
- context.helper(RESOLVE_FILTER);
- const i = filter.indexOf('(');
- if (i < 0) {
- context.filters.add(filter);
- return `${toValidAssetId(filter, 'filter')}(${exp})`;
- }
- else {
- const name = filter.slice(0, i);
- const args = filter.slice(i + 1);
- context.filters.add(name);
- return `${toValidAssetId(name, 'filter')}(${exp}${args !== ')' ? ',' + args : args}`;
- }
- }
- const seen$1 = new WeakSet();
- const transformMemo = (node, context) => {
- if (node.type === 1 /* NodeTypes.ELEMENT */) {
- const dir = findDir(node, 'memo');
- if (!dir || seen$1.has(node)) {
- return;
- }
- seen$1.add(node);
- return () => {
- const codegenNode = node.codegenNode ||
- context.currentNode.codegenNode;
- if (codegenNode && codegenNode.type === 13 /* NodeTypes.VNODE_CALL */) {
- // non-component sub tree should be turned into a block
- if (node.tagType !== 1 /* ElementTypes.COMPONENT */) {
- makeBlock(codegenNode, context);
- }
- node.codegenNode = createCallExpression(context.helper(WITH_MEMO), [
- dir.exp,
- createFunctionExpression(undefined, codegenNode),
- `_cache`,
- String(context.cached++)
- ]);
- }
- };
- }
- };
- function getBaseTransformPreset(prefixIdentifiers) {
- return [
- [
- transformOnce,
- transformIf,
- transformMemo,
- transformFor,
- ...([transformFilter] ),
- ...(prefixIdentifiers
- ? [
- // order is important
- trackVForSlotScopes,
- transformExpression
- ]
- : []),
- transformSlotOutlet,
- transformElement,
- trackSlotScopes,
- transformText
- ],
- {
- on: transformOn,
- bind: transformBind,
- model: transformModel
- }
- ];
- }
- // we name it `baseCompile` so that higher order compilers like
- // @vue/compiler-dom can export `compile` while re-exporting everything else.
- function baseCompile(template, options = {}) {
- const onError = options.onError || defaultOnError;
- const isModuleMode = options.mode === 'module';
- const prefixIdentifiers = (options.prefixIdentifiers === true || isModuleMode);
- if (!prefixIdentifiers && options.cacheHandlers) {
- onError(createCompilerError(49 /* ErrorCodes.X_CACHE_HANDLER_NOT_SUPPORTED */));
- }
- if (options.scopeId && !isModuleMode) {
- onError(createCompilerError(50 /* ErrorCodes.X_SCOPE_ID_NOT_SUPPORTED */));
- }
- const ast = shared.isString(template) ? baseParse(template, options) : template;
- const [nodeTransforms, directiveTransforms] = getBaseTransformPreset(prefixIdentifiers);
- if (options.isTS) {
- const { expressionPlugins } = options;
- if (!expressionPlugins || !expressionPlugins.includes('typescript')) {
- options.expressionPlugins = [...(expressionPlugins || []), 'typescript'];
- }
- }
- transform(ast, shared.extend({}, options, {
- prefixIdentifiers,
- nodeTransforms: [
- ...nodeTransforms,
- ...(options.nodeTransforms || []) // user transforms
- ],
- directiveTransforms: shared.extend({}, directiveTransforms, options.directiveTransforms || {} // user transforms
- )
- }));
- return generate(ast, shared.extend({}, options, {
- prefixIdentifiers
- }));
- }
- const noopDirectiveTransform = () => ({ props: [] });
- exports.generateCodeFrame = shared.generateCodeFrame;
- exports.BASE_TRANSITION = BASE_TRANSITION;
- exports.CAMELIZE = CAMELIZE;
- exports.CAPITALIZE = CAPITALIZE;
- exports.CREATE_BLOCK = CREATE_BLOCK;
- exports.CREATE_COMMENT = CREATE_COMMENT;
- exports.CREATE_ELEMENT_BLOCK = CREATE_ELEMENT_BLOCK;
- exports.CREATE_ELEMENT_VNODE = CREATE_ELEMENT_VNODE;
- exports.CREATE_SLOTS = CREATE_SLOTS;
- exports.CREATE_STATIC = CREATE_STATIC;
- exports.CREATE_TEXT = CREATE_TEXT;
- exports.CREATE_VNODE = CREATE_VNODE;
- exports.FRAGMENT = FRAGMENT;
- exports.GUARD_REACTIVE_PROPS = GUARD_REACTIVE_PROPS;
- exports.IS_MEMO_SAME = IS_MEMO_SAME;
- exports.IS_REF = IS_REF;
- exports.KEEP_ALIVE = KEEP_ALIVE;
- exports.MERGE_PROPS = MERGE_PROPS;
- exports.NORMALIZE_CLASS = NORMALIZE_CLASS;
- exports.NORMALIZE_PROPS = NORMALIZE_PROPS;
- exports.NORMALIZE_STYLE = NORMALIZE_STYLE;
- exports.OPEN_BLOCK = OPEN_BLOCK;
- exports.POP_SCOPE_ID = POP_SCOPE_ID;
- exports.PUSH_SCOPE_ID = PUSH_SCOPE_ID;
- exports.RENDER_LIST = RENDER_LIST;
- exports.RENDER_SLOT = RENDER_SLOT;
- exports.RESOLVE_COMPONENT = RESOLVE_COMPONENT;
- exports.RESOLVE_DIRECTIVE = RESOLVE_DIRECTIVE;
- exports.RESOLVE_DYNAMIC_COMPONENT = RESOLVE_DYNAMIC_COMPONENT;
- exports.RESOLVE_FILTER = RESOLVE_FILTER;
- exports.SET_BLOCK_TRACKING = SET_BLOCK_TRACKING;
- exports.SUSPENSE = SUSPENSE;
- exports.TELEPORT = TELEPORT;
- exports.TO_DISPLAY_STRING = TO_DISPLAY_STRING;
- exports.TO_HANDLERS = TO_HANDLERS;
- exports.TO_HANDLER_KEY = TO_HANDLER_KEY;
- exports.UNREF = UNREF;
- exports.WITH_CTX = WITH_CTX;
- exports.WITH_DIRECTIVES = WITH_DIRECTIVES;
- exports.WITH_MEMO = WITH_MEMO;
- exports.advancePositionWithClone = advancePositionWithClone;
- exports.advancePositionWithMutation = advancePositionWithMutation;
- exports.assert = assert;
- exports.baseCompile = baseCompile;
- exports.baseParse = baseParse;
- exports.buildDirectiveArgs = buildDirectiveArgs;
- exports.buildProps = buildProps;
- exports.buildSlots = buildSlots;
- exports.checkCompatEnabled = checkCompatEnabled;
- exports.createArrayExpression = createArrayExpression;
- exports.createAssignmentExpression = createAssignmentExpression;
- exports.createBlockStatement = createBlockStatement;
- exports.createCacheExpression = createCacheExpression;
- exports.createCallExpression = createCallExpression;
- exports.createCompilerError = createCompilerError;
- exports.createCompoundExpression = createCompoundExpression;
- exports.createConditionalExpression = createConditionalExpression;
- exports.createForLoopParams = createForLoopParams;
- exports.createFunctionExpression = createFunctionExpression;
- exports.createIfStatement = createIfStatement;
- exports.createInterpolation = createInterpolation;
- exports.createObjectExpression = createObjectExpression;
- exports.createObjectProperty = createObjectProperty;
- exports.createReturnStatement = createReturnStatement;
- exports.createRoot = createRoot;
- exports.createSequenceExpression = createSequenceExpression;
- exports.createSimpleExpression = createSimpleExpression;
- exports.createStructuralDirectiveTransform = createStructuralDirectiveTransform;
- exports.createTemplateLiteral = createTemplateLiteral;
- exports.createTransformContext = createTransformContext;
- exports.createVNodeCall = createVNodeCall;
- exports.extractIdentifiers = extractIdentifiers;
- exports.findDir = findDir;
- exports.findProp = findProp;
- exports.generate = generate;
- exports.getBaseTransformPreset = getBaseTransformPreset;
- exports.getConstantType = getConstantType;
- exports.getInnerRange = getInnerRange;
- exports.getMemoedVNodeCall = getMemoedVNodeCall;
- exports.getVNodeBlockHelper = getVNodeBlockHelper;
- exports.getVNodeHelper = getVNodeHelper;
- exports.hasDynamicKeyVBind = hasDynamicKeyVBind;
- exports.hasScopeRef = hasScopeRef;
- exports.helperNameMap = helperNameMap;
- exports.injectProp = injectProp;
- exports.isBuiltInType = isBuiltInType;
- exports.isCoreComponent = isCoreComponent;
- exports.isFunctionType = isFunctionType;
- exports.isInDestructureAssignment = isInDestructureAssignment;
- exports.isMemberExpression = isMemberExpression;
- exports.isMemberExpressionBrowser = isMemberExpressionBrowser;
- exports.isMemberExpressionNode = isMemberExpressionNode;
- exports.isReferencedIdentifier = isReferencedIdentifier;
- exports.isSimpleIdentifier = isSimpleIdentifier;
- exports.isSlotOutlet = isSlotOutlet;
- exports.isStaticArgOf = isStaticArgOf;
- exports.isStaticExp = isStaticExp;
- exports.isStaticProperty = isStaticProperty;
- exports.isStaticPropertyKey = isStaticPropertyKey;
- exports.isTemplateNode = isTemplateNode;
- exports.isText = isText;
- exports.isVSlot = isVSlot;
- exports.locStub = locStub;
- exports.makeBlock = makeBlock;
- exports.noopDirectiveTransform = noopDirectiveTransform;
- exports.processExpression = processExpression;
- exports.processFor = processFor;
- exports.processIf = processIf;
- exports.processSlotOutlet = processSlotOutlet;
- exports.registerRuntimeHelpers = registerRuntimeHelpers;
- exports.resolveComponentType = resolveComponentType;
- exports.stringifyExpression = stringifyExpression;
- exports.toValidAssetId = toValidAssetId;
- exports.trackSlotScopes = trackSlotScopes;
- exports.trackVForSlotScopes = trackVForSlotScopes;
- exports.transform = transform;
- exports.transformBind = transformBind;
- exports.transformElement = transformElement;
- exports.transformExpression = transformExpression;
- exports.transformModel = transformModel;
- exports.transformOn = transformOn;
- exports.traverseNode = traverseNode;
- exports.walkBlockDeclarations = walkBlockDeclarations;
- exports.walkFunctionParams = walkFunctionParams;
- exports.walkIdentifiers = walkIdentifiers;
- exports.warnDeprecation = warnDeprecation;
|