Compilation.js 204 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const util = require("util");
  7. const asyncLib = require("neo-async");
  8. const {
  9. AsyncParallelHook,
  10. AsyncSeriesBailHook,
  11. AsyncSeriesHook,
  12. AsyncSeriesWaterfallHook,
  13. HookMap,
  14. SyncBailHook,
  15. SyncHook,
  16. SyncWaterfallHook
  17. } = require("tapable");
  18. const { CachedSource } = require("webpack-sources");
  19. const { MultiItemCache } = require("./CacheFacade");
  20. const Chunk = require("./Chunk");
  21. const ChunkGraph = require("./ChunkGraph");
  22. const ChunkGroup = require("./ChunkGroup");
  23. const ChunkTemplate = require("./ChunkTemplate");
  24. const CodeGenerationResults = require("./CodeGenerationResults");
  25. const Dependency = require("./Dependency");
  26. const DependencyTemplates = require("./DependencyTemplates");
  27. const Entrypoint = require("./Entrypoint");
  28. const ErrorHelpers = require("./ErrorHelpers");
  29. const FileSystemInfo = require("./FileSystemInfo");
  30. const LazyBarrelController = require("./LazyBarrel");
  31. const MainTemplate = require("./MainTemplate");
  32. const Module = require("./Module");
  33. const ModuleGraph = require("./ModuleGraph");
  34. const ModuleProfile = require("./ModuleProfile");
  35. const ModuleTemplate = require("./ModuleTemplate");
  36. const { WEBPACK_MODULE_TYPE_RUNTIME } = require("./ModuleTypeConstants");
  37. const RuntimeGlobals = require("./RuntimeGlobals");
  38. const RuntimeTemplate = require("./RuntimeTemplate");
  39. const Stats = require("./Stats");
  40. const buildChunkGraph = require("./buildChunkGraph");
  41. const {
  42. makeWebpackError,
  43. tryRunOrWebpackError
  44. } = require("./errors/HookWebpackError");
  45. const WebpackError = require("./errors/WebpackError");
  46. const { LogType, Logger } = require("./logging/Logger");
  47. const StatsFactory = require("./stats/StatsFactory");
  48. const StatsPrinter = require("./stats/StatsPrinter");
  49. const { equals: arrayEquals } = require("./util/ArrayHelpers");
  50. const AsyncQueue = require("./util/AsyncQueue");
  51. const LazySet = require("./util/LazySet");
  52. const { getOrInsert } = require("./util/MapHelpers");
  53. const WeakTupleMap = require("./util/WeakTupleMap");
  54. const { cachedCleverMerge } = require("./util/cleverMerge");
  55. const {
  56. compareErrors,
  57. compareIds,
  58. compareModulesByIdentifier,
  59. compareSelect,
  60. concatComparators
  61. } = require("./util/comparators");
  62. const createHash = require("./util/createHash");
  63. const {
  64. arrayToSetDeprecation,
  65. createFakeHook,
  66. soonFrozenObjectDeprecation
  67. } = require("./util/deprecation");
  68. const memoize = require("./util/memoize");
  69. const processAsyncTree = require("./util/processAsyncTree");
  70. const { getRuntimeKey } = require("./util/runtime");
  71. const { isSourceEqual } = require("./util/source");
  72. const getModuleStoreError = memoize(() => require("./errors/ModuleStoreError"));
  73. const getModuleRestoreError = memoize(() =>
  74. require("./errors/ModuleRestoreError")
  75. );
  76. const getModuleNotFoundError = memoize(() =>
  77. require("./errors/ModuleNotFoundError")
  78. );
  79. const getModuleHashingError = memoize(() =>
  80. require("./errors/ModuleHashingError")
  81. );
  82. const getModuleDependencyWarning = memoize(() =>
  83. require("./errors/ModuleDependencyWarning")
  84. );
  85. const getModuleDependencyError = memoize(() =>
  86. require("./errors/ModuleDependencyError")
  87. );
  88. const getCodeGenerationError = memoize(() =>
  89. require("./errors/CodeGenerationError")
  90. );
  91. const getChunkRenderError = memoize(() => require("./errors/ChunkRenderError"));
  92. const getBuildCycleError = memoize(() => require("./errors/BuildCycleError"));
  93. /** @import { Source } from "webpack-sources" */
  94. /**
  95. * @import {
  96. * OutputNormalized as OutputOptions,
  97. * HashFunction,
  98. * HashDigest,
  99. * HashDigestLength,
  100. * StatsOptions,
  101. * Plugins,
  102. * ResolveOptions
  103. * } from "../declarations/WebpackOptions"
  104. */
  105. /**
  106. * @import {
  107. * WebpackOptionsNormalizedWithDefaults as WebpackOptions,
  108. * OutputNormalizedWithDefaults as OutputOptionsWithDefaults
  109. * } from "./config/defaults"
  110. */
  111. /** @import AsyncDependenciesBlock from "./AsyncDependenciesBlock" */
  112. /** @import Cache from "./Cache" */
  113. /** @import CacheFacade from "./CacheFacade" */
  114. /** @import { ChunkName, ChunkId } from "./Chunk" */
  115. /** @import { ChunkGroupOptions } from "./ChunkGroup" */
  116. /**
  117. * @import Compiler, {
  118. * CompilationParams,
  119. * MemCache,
  120. * WeakReferences,
  121. * ModuleMemCachesItem,
  122. * Records
  123. * } from "./Compiler"
  124. */
  125. /** @import DependenciesBlock from "./DependenciesBlock" */
  126. /** @import { DependencyLocation, ReferencedExports } from "./Dependency" */
  127. /** @typedef {import("./Entrypoint").EntryOptions} EntryOptions */
  128. /**
  129. * @import {
  130. * NameForCondition,
  131. * BuildInfo,
  132. * ValueCacheVersions,
  133. * RuntimeRequirements,
  134. * SourceTypes,
  135. * SourceType,
  136. * FactoryMeta,
  137. * CodeGenerationResult
  138. * } from "./Module"
  139. */
  140. /**
  141. * @import NormalModule, {
  142. * NormalModuleCompilationHooks,
  143. * AnyLoaderContext,
  144. * ParserOptions,
  145. * GeneratorOptions
  146. * } from "./NormalModule"
  147. */
  148. /**
  149. * @import ModuleFactory, {
  150. * ModuleFactoryCreateDataContextInfo,
  151. * ModuleFactoryResult
  152. * } from "./ModuleFactory"
  153. */
  154. /** @import { ModuleId } from "./ChunkGraph" */
  155. /** @import ModuleGraphConnection from "./ModuleGraphConnection" */
  156. /** @import RequestShortener from "./RequestShortener" */
  157. /** @import RuntimeModule from "./RuntimeModule" */
  158. /** @import { RenderManifestEntry, RenderManifestOptions } from "./Template" */
  159. /**
  160. * One language's source embedded in another's output.
  161. * @typedef {object} EmbeddedSourceInfo
  162. * @property {SourceType} type the embedded source's type, e.g. `"css"` / `"html"`
  163. * @property {SourceType} hostType the type of the source it is embedded in, e.g. `"javascript"`
  164. * @property {Module} module the module being generated
  165. * @property {string=} as which of that language's productions this is, where more than one can be embedded — a `style=""` holds `"block-contents"`, an inline `<style>` a whole `"stylesheet"`. Absent where the language has only one
  166. */
  167. /**
  168. * @import {
  169. * StatsAsset,
  170. * StatsError,
  171. * StatsModule
  172. * } from "./stats/DefaultStatsFactoryPlugin"
  173. */
  174. /** @import Hash from "./util/Hash" */
  175. /**
  176. * Defines the shared type used by this module.
  177. * @template T
  178. * @typedef {import("tapable").AsArray<T>} AsArray<T>
  179. */
  180. /**
  181. * Defines the shared type used by this module.
  182. * @template T
  183. * @typedef {import("./util/deprecation").FakeHook<T>} FakeHook<T>
  184. */
  185. /** @import { RuntimeSpec } from "./util/runtime" */
  186. /** @import { InputFileSystem } from "./util/fs" */
  187. /**
  188. * Defines the callback callback.
  189. * @callback Callback
  190. * @param {(WebpackError | null)=} err
  191. * @returns {void}
  192. */
  193. /**
  194. * Defines the module callback callback.
  195. * @callback ModuleCallback
  196. * @param {WebpackError | null=} err
  197. * @param {Module | null=} result
  198. * @returns {void}
  199. */
  200. /**
  201. * Defines the module factory result callback callback.
  202. * @callback ModuleFactoryResultCallback
  203. * @param {WebpackError | null=} err
  204. * @param {ModuleFactoryResult | null=} result
  205. * @returns {void}
  206. */
  207. /**
  208. * Defines the module or module factory result callback callback.
  209. * @callback ModuleOrModuleFactoryResultCallback
  210. * @param {WebpackError | null=} err
  211. * @param {Module | ModuleFactoryResult | null=} result
  212. * @returns {void}
  213. */
  214. /**
  215. * Defines the execute module callback callback.
  216. * @callback ExecuteModuleCallback
  217. * @param {WebpackError | null=} err
  218. * @param {ExecuteModuleResult | null=} result
  219. * @returns {void}
  220. */
  221. /** @typedef {new (...args: EXPECTED_ANY[]) => Dependency} DependencyConstructor */
  222. /** @typedef {Record<string, Source>} CompilationAssets */
  223. /**
  224. * Defines the available modules chunk group mapping type used by this module.
  225. * @typedef {object} AvailableModulesChunkGroupMapping
  226. * @property {ChunkGroup} chunkGroup
  227. * @property {Set<Module>} availableModules
  228. * @property {boolean} needCopy
  229. */
  230. /**
  231. * Defines the dependencies block like type used by this module.
  232. * @typedef {object} DependenciesBlockLike
  233. * @property {Dependency[]} dependencies
  234. * @property {AsyncDependenciesBlock[]} blocks
  235. */
  236. /** @typedef {Set<Chunk>} Chunks */
  237. /**
  238. * Defines the chunk path data type used by this module.
  239. * @typedef {object} ChunkPathData
  240. * @property {string | number} id
  241. * @property {string=} name
  242. * @property {string} hash
  243. * @property {HashWithLengthFunction=} hashWithLength
  244. * @property {HashWithDigestFunction=} hashWithDigest builds `[chunkhash:<digest>]` per chunk in the runtime chunk-filename map
  245. * @property {(Record<string, string>)=} contentHash
  246. * @property {(Record<string, HashWithLengthFunction>)=} contentHashWithLength
  247. * @property {(Record<string, HashWithDigestFunction>)=} contentHashWithDigest builds `[contenthash:<digest>]` per chunk in the runtime chunk-filename map
  248. */
  249. /**
  250. * Defines the chunk hash context type used by this module.
  251. * @typedef {object} ChunkHashContext
  252. * @property {CodeGenerationResults} codeGenerationResults results of code generation
  253. * @property {RuntimeTemplate} runtimeTemplate the runtime template
  254. * @property {ModuleGraph} moduleGraph the module graph
  255. * @property {ChunkGraph} chunkGraph the chunk graph
  256. */
  257. /**
  258. * Defines the runtime requirements context type used by this module.
  259. * @typedef {object} RuntimeRequirementsContext
  260. * @property {ChunkGraph} chunkGraph the chunk graph
  261. * @property {CodeGenerationResults} codeGenerationResults the code generation results
  262. */
  263. /**
  264. * Defines the execute module options type used by this module.
  265. * @typedef {object} ExecuteModuleOptions
  266. * @property {EntryOptions=} entryOptions
  267. */
  268. /** @typedef {LazySet<string>} FileSystemDependencies */
  269. /** @typedef {EXPECTED_ANY} ExecuteModuleExports */
  270. /**
  271. * Defines the execute module result type used by this module.
  272. * @typedef {object} ExecuteModuleResult
  273. * @property {ExecuteModuleExports} exports
  274. * @property {boolean} cacheable
  275. * @property {string[]} notCacheableReasons reasons why the executed modules are not cacheable
  276. * @property {ExecuteModuleAssets} assets
  277. * @property {FileSystemDependencies} fileDependencies
  278. * @property {FileSystemDependencies} contextDependencies
  279. * @property {FileSystemDependencies} missingDependencies
  280. * @property {FileSystemDependencies} buildDependencies
  281. */
  282. /**
  283. * Defines the execute module object type used by this module.
  284. * @typedef {object} ExecuteModuleObject
  285. * @property {string=} id module id
  286. * @property {ExecuteModuleExports} exports exports
  287. * @property {boolean} loaded is loaded
  288. * @property {Error=} error error
  289. */
  290. /**
  291. * Defines the execute module argument type used by this module.
  292. * @typedef {object} ExecuteModuleArgument
  293. * @property {Module} module
  294. * @property {ExecuteModuleObject=} moduleObject
  295. * @property {CodeGenerationResult} codeGenerationResult
  296. */
  297. /** @typedef {((id: string) => ExecuteModuleExports) & { i?: ((options: ExecuteOptions) => void)[], c?: Record<string, ExecuteModuleObject>, p?: string }} WebpackRequire */
  298. /**
  299. * Defines the execute options type used by this module.
  300. * @typedef {object} ExecuteOptions
  301. * @property {string=} id module id
  302. * @property {ExecuteModuleObject} module module
  303. * @property {WebpackRequire} require require function
  304. */
  305. /** @typedef {Map<string, { source: Source, info: AssetInfo | undefined }>} ExecuteModuleAssets */
  306. /**
  307. * Defines the execute module context type used by this module.
  308. * @typedef {object} ExecuteModuleContext
  309. * @property {ExecuteModuleAssets} assets
  310. * @property {Chunk} chunk
  311. * @property {ChunkGraph} chunkGraph
  312. * @property {WebpackRequire=} __webpack_require__
  313. */
  314. /**
  315. * Defines the entry data type used by this module.
  316. * @typedef {object} EntryData
  317. * @property {Dependency[]} dependencies dependencies of the entrypoint that should be evaluated at startup
  318. * @property {Dependency[]} includeDependencies dependencies of the entrypoint that should be included but not evaluated
  319. * @property {EntryOptions} options options of the entrypoint
  320. */
  321. /**
  322. * Defines the log entry type used by this module.
  323. * @typedef {object} LogEntry
  324. * @property {keyof LogType} type
  325. * @property {EXPECTED_ANY[]=} args
  326. * @property {number} time
  327. * @property {string[]=} trace
  328. */
  329. /**
  330. * Defines the known asset info type used by this module.
  331. * @typedef {object} KnownAssetInfo
  332. * @property {boolean=} immutable true, if the asset can be long term cached forever (contains a hash)
  333. * @property {boolean=} minimized whether the asset is minimized
  334. * @property {string | string[]=} fullhash the value(s) of the full hash used for this asset
  335. * @property {string | string[]=} chunkhash the value(s) of the chunk hash used for this asset
  336. * @property {string | string[]=} modulehash the value(s) of the module hash used for this asset
  337. * @property {string | string[]=} contenthash the value(s) of the content hash used for this asset
  338. * @property {Record<string, string>=} contenthashDigest maps a `[contenthash:<digest>]` value to its digest, so `RealContentHashPlugin` re-encodes the recomputed hash in it
  339. * @property {string=} sourceFilename when asset was created from a source file (potentially transformed), the original filename relative to compilation context
  340. * @property {number=} size size in bytes, only set after asset has been emitted
  341. * @property {boolean=} development true, when asset is only used for development and doesn't count towards user-facing assets
  342. * @property {boolean=} hotModuleReplacement true, when asset ships data for updating an existing application (HMR)
  343. * @property {boolean=} javascriptModule true, when asset is javascript and an ESM
  344. * @property {boolean=} manifest true, when file is a manifest
  345. * @property {Record<string, null | string | string[]>=} related object of pointers to other assets, keyed by type of relation (only points from parent to child)
  346. */
  347. /** @typedef {KnownAssetInfo & Record<string, EXPECTED_ANY>} AssetInfo */
  348. /** @typedef {{ path: string, info: AssetInfo }} InterpolatedPathAndAssetInfo */
  349. /**
  350. * Defines the asset type used by this module.
  351. * @typedef {object} Asset
  352. * @property {string} name the filename of the asset
  353. * @property {Source} source source of the asset
  354. * @property {AssetInfo} info info about the asset
  355. */
  356. /** @typedef {(length: number) => string} HashWithLengthFunction */
  357. /** @typedef {(digest: string, length?: number) => string} HashWithDigestFunction */
  358. /**
  359. * Defines the module path data type used by this module.
  360. * @typedef {object} ModulePathData
  361. * @property {string | number} id
  362. * @property {string} hash
  363. * @property {HashWithLengthFunction=} hashWithLength
  364. */
  365. /** @typedef {(id: string | number) => string | number} PrepareIdFunction */
  366. /**
  367. * Defines the path data type used by this module.
  368. * @typedef {object} PathData
  369. * @property {ChunkGraph=} chunkGraph
  370. * @property {string=} hash
  371. * @property {string=} fullHash untruncated compilation hash, for re-encoding `[fullhash:<digest>]`
  372. * @property {string=} fullHashDigest digest `fullHash` is encoded in (defaults to `hashDigest`)
  373. * @property {HashWithLengthFunction=} hashWithLength
  374. * @property {HashWithDigestFunction=} hashWithDigest builds `[fullhash:<digest>]`/`[hash:<digest>]` in the runtime chunk-filename context, where it throws because a runtime `getFullHash()` expression cannot be re-encoded
  375. * @property {(Chunk | ChunkPathData)=} chunk
  376. * @property {(Module | ModulePathData)=} module
  377. * @property {RuntimeSpec=} runtime
  378. * @property {string=} filename
  379. * @property {string=} basename
  380. * @property {string=} query
  381. * @property {string=} contentHashType
  382. * @property {string=} contentHash
  383. * @property {string=} contentHashFull untruncated module/asset content hash, for re-encoding `[contenthash:<digest>]` from full entropy
  384. * @property {HashWithLengthFunction=} contentHashWithLength
  385. * @property {string=} hashDigest digest the stored hashes are encoded in (for `[hash:<digest>]`)
  386. * @property {boolean=} realContentHash whether `optimization.realContentHash` recomputes content hashes (records an inline `[contenthash:<digest>]` so it re-encodes in that digest)
  387. * @property {boolean=} hashAsFullHash treat `[hash]` as `[fullhash]` rather than the module hash (CSS local idents)
  388. * @property {boolean=} noChunkHash
  389. * @property {string=} url
  390. * @property {string=} local
  391. * @property {string=} uniqueName
  392. * @property {PrepareIdFunction=} prepareId
  393. */
  394. /**
  395. * Path data narrowed for the chunk filename / chunk asset interpolation context,
  396. * where `chunk` is always provided. Use as the type parameter to `TemplatePathFn`
  397. * for callbacks that receive a chunk context (for example `output.filename`,
  398. * `output.chunkFilename`, `output.cssFilename`, `output.cssChunkFilename`,
  399. * `optimization.splitChunks.cacheGroups[*].filename`).
  400. * @typedef {PathData & { chunk: Chunk | ChunkPathData }} PathDataChunk
  401. */
  402. /**
  403. * Path data narrowed for the module asset interpolation context, where `module`
  404. * and `chunkGraph` are always provided. Use as the type parameter to
  405. * `TemplatePathFn` for callbacks that receive a module context (for example
  406. * `output.assetModuleFilename`, the per-module `generator.filename` /
  407. * `generator.outputPath`, and `module.parser.css.localIdentName`).
  408. * @typedef {PathData & { module: Module | ModulePathData, chunkGraph: ChunkGraph }} PathDataModule
  409. */
  410. /** @typedef {"module" | "chunk" | "root-of-chunk" | "nested"} ExcludeModulesType */
  411. /**
  412. * Defines the known normalized stats options type used by this module.
  413. * @typedef {object} KnownNormalizedStatsOptions
  414. * @property {string} context
  415. * @property {RequestShortener} requestShortener
  416. * @property {string | false} chunksSort
  417. * @property {string | false} modulesSort
  418. * @property {string | false} chunkModulesSort
  419. * @property {string | false} nestedModulesSort
  420. * @property {string | false} assetsSort
  421. * @property {boolean} ids
  422. * @property {boolean} cachedAssets
  423. * @property {boolean} groupAssetsByEmitStatus
  424. * @property {boolean} groupAssetsByPath
  425. * @property {boolean} groupAssetsByExtension
  426. * @property {number} assetsSpace
  427. * @property {((value: string, asset: StatsAsset) => boolean)[]} excludeAssets
  428. * @property {((name: string, module: StatsModule, type: ExcludeModulesType) => boolean)[]} excludeModules
  429. * @property {((warning: StatsError, textValue: string) => boolean)[]} warningsFilter
  430. * @property {boolean} cachedModules
  431. * @property {boolean} orphanModules
  432. * @property {boolean} dependentModules
  433. * @property {boolean} runtimeModules
  434. * @property {boolean} groupModulesByCacheStatus
  435. * @property {boolean} groupModulesByLayer
  436. * @property {boolean} groupModulesByAttributes
  437. * @property {boolean} groupModulesByPath
  438. * @property {boolean} groupModulesByExtension
  439. * @property {boolean} groupModulesByType
  440. * @property {boolean | "auto"} entrypoints
  441. * @property {boolean} chunkGroups
  442. * @property {boolean} chunkGroupAuxiliary
  443. * @property {boolean} chunkGroupChildren
  444. * @property {number} chunkGroupMaxAssets
  445. * @property {number} modulesSpace
  446. * @property {number} chunkModulesSpace
  447. * @property {number} nestedModulesSpace
  448. * @property {false | "none" | "error" | "warn" | "info" | "log" | "verbose"} logging
  449. * @property {((value: string) => boolean)[]} loggingDebug
  450. * @property {boolean} loggingTrace
  451. * @property {EXPECTED_ANY} _env
  452. */
  453. /** @typedef {KnownNormalizedStatsOptions & Omit<StatsOptions, keyof KnownNormalizedStatsOptions> & Record<string, EXPECTED_ANY>} NormalizedStatsOptions */
  454. /**
  455. * Defines the known create stats options context type used by this module.
  456. * @typedef {object} KnownCreateStatsOptionsContext
  457. * @property {boolean=} forToString
  458. */
  459. /** @typedef {KnownCreateStatsOptionsContext & Record<string, EXPECTED_ANY>} CreateStatsOptionsContext */
  460. /** @typedef {{ module: Module, hash: string, runtime: RuntimeSpec, runtimes: RuntimeSpec[] }} CodeGenerationJob */
  461. /** @typedef {CodeGenerationJob[]} CodeGenerationJobs */
  462. /** @typedef {{ javascript: ModuleTemplate }} ModuleTemplates */
  463. /** @typedef {Set<Module>} NotCodeGeneratedModules */
  464. /** @type {AssetInfo} */
  465. const EMPTY_ASSET_INFO = Object.freeze({});
  466. const esmDependencyCategory = "esm";
  467. // TODO webpack 6: remove
  468. const deprecatedNormalModuleLoaderHook = util.deprecate(
  469. /**
  470. * Handles the callback logic for this hook.
  471. * @param {Compilation} compilation compilation
  472. * @returns {NormalModuleCompilationHooks["loader"]} hooks
  473. */
  474. (compilation) =>
  475. require("./NormalModule").getCompilationHooks(compilation).loader,
  476. "Compilation.hooks.normalModuleLoader was moved to NormalModule.getCompilationHooks(compilation).loader",
  477. "DEP_WEBPACK_COMPILATION_NORMAL_MODULE_LOADER_HOOK"
  478. );
  479. // TODO webpack 6: remove
  480. /**
  481. * Define removed module templates.
  482. * @param {ModuleTemplates | undefined} moduleTemplates module templates
  483. */
  484. const defineRemovedModuleTemplates = (moduleTemplates) => {
  485. Object.defineProperties(moduleTemplates, {
  486. asset: {
  487. enumerable: false,
  488. configurable: false,
  489. get: () => {
  490. throw new WebpackError(
  491. "Compilation.moduleTemplates.asset has been removed"
  492. );
  493. }
  494. },
  495. webassembly: {
  496. enumerable: false,
  497. configurable: false,
  498. get: () => {
  499. throw new WebpackError(
  500. "Compilation.moduleTemplates.webassembly has been removed"
  501. );
  502. }
  503. }
  504. });
  505. moduleTemplates = undefined;
  506. };
  507. const byId = compareSelect((c) => c.id, compareIds);
  508. const byNameOrHash = concatComparators(
  509. compareSelect((c) => c.name, compareIds),
  510. compareSelect((c) => c.fullHash, compareIds)
  511. );
  512. /**
  513. * Defines the known unsafe cache data type used by this module.
  514. * @typedef {object} KnownUnsafeCacheData
  515. * @property {FactoryMeta=} factoryMeta factory meta
  516. * @property {ResolveOptions=} resolveOptions resolve options
  517. * @property {ParserOptions=} parserOptions
  518. * @property {GeneratorOptions=} generatorOptions
  519. */
  520. /** @typedef {KnownUnsafeCacheData & Record<string, EXPECTED_ANY>} UnsafeCacheData */
  521. /**
  522. * Defines the module with restore from unsafe cache type used by this module.
  523. * @typedef {Module & { restoreFromUnsafeCache?: (unsafeCacheData: UnsafeCacheData, moduleFactory: ModuleFactory, compilationParams: CompilationParams) => void }} ModuleWithRestoreFromUnsafeCache
  524. */
  525. /** @typedef {(module: Module) => boolean} UnsafeCachePredicate */
  526. /** @type {WeakMap<Dependency, ModuleWithRestoreFromUnsafeCache | null>} */
  527. const unsafeCacheDependencies = new WeakMap();
  528. /** @type {WeakMap<ModuleWithRestoreFromUnsafeCache, UnsafeCacheData>} */
  529. const unsafeCacheData = new WeakMap();
  530. /** @typedef {EXPECTED_OBJECT} DependencyReportCacheToken */
  531. /**
  532. * Renewed when the module or a transitively referenced module is rebuilt.
  533. * @type {WeakMap<Module, DependencyReportCacheToken>}
  534. */
  535. const dependencyReportCacheTokens = new WeakMap();
  536. /**
  537. * Modules known to have no dependency errors/warnings, per cache token.
  538. * @type {WeakMap<DependencyReportCacheToken, WeakSet<Module>>}
  539. */
  540. const modulesWithoutProblems = new WeakMap();
  541. /**
  542. * Reduce affect type.
  543. * @param {Readonly<ModuleGraphConnection[]>} connections connections
  544. * @returns {symbol | boolean} result
  545. */
  546. const reduceAffectType = (connections) => {
  547. let affected = false;
  548. for (const { dependency } of connections) {
  549. if (!dependency) continue;
  550. const type = dependency.couldAffectReferencingModule();
  551. if (type === Dependency.TRANSITIVE) return Dependency.TRANSITIVE;
  552. if (type === false) continue;
  553. affected = true;
  554. }
  555. return affected;
  556. };
  557. /** @typedef {{ id: ModuleId, modules?: Map<Module, ModuleId>, blocks?: (ChunkId | null)[], sourceTypes?: SourceTypes }} References */
  558. /** @typedef {Map<Module, WeakTupleMap<EXPECTED_ANY[], EXPECTED_ANY>>} ModuleMemCaches */
  559. /** @typedef {{ chunk: Chunk, load: () => Promise<EXPECTED_ANY>, create: (loaded: EXPECTED_ANY) => RuntimeModule, chunkGraph: ChunkGraph }} PendingRuntimeModule */
  560. class Compilation {
  561. /**
  562. * Creates an instance of Compilation.
  563. * @param {Compiler} compiler the compiler which created the compilation
  564. * @param {CompilationParams} params the compilation parameters
  565. */
  566. constructor(compiler, params) {
  567. /** @type {boolean} */
  568. this._backCompat = compiler._backCompat;
  569. const getNormalModuleLoader = () => deprecatedNormalModuleLoaderHook(this);
  570. /** @typedef {{ additionalAssets?: boolean | ((assets: CompilationAssets) => void) }} ProcessAssetsAdditionalOptions */
  571. /** @type {AsyncSeriesHook<[CompilationAssets], ProcessAssetsAdditionalOptions>} */
  572. const processAssetsHook = new AsyncSeriesHook(["assets"]);
  573. /** @type {Set<string>} */
  574. let savedAssets = new Set();
  575. /**
  576. * Returns new assets.
  577. * @param {CompilationAssets} assets assets
  578. * @returns {CompilationAssets} new assets
  579. */
  580. const popNewAssets = (assets) => {
  581. /** @type {undefined | CompilationAssets} */
  582. let newAssets;
  583. for (const file of Object.keys(assets)) {
  584. if (savedAssets.has(file)) continue;
  585. if (newAssets === undefined) {
  586. newAssets = Object.create(null);
  587. }
  588. /** @type {CompilationAssets} */
  589. (newAssets)[file] = assets[file];
  590. savedAssets.add(file);
  591. }
  592. return /** @type {CompilationAssets} */ (newAssets);
  593. };
  594. processAssetsHook.intercept({
  595. name: "Compilation",
  596. call: () => {
  597. savedAssets = new Set(Object.keys(this.assets));
  598. },
  599. register: (tap) => {
  600. const { type, name } = tap;
  601. const { fn, additionalAssets, ...remainingTap } = tap;
  602. const additionalAssetsFn =
  603. additionalAssets === true ? fn : additionalAssets;
  604. /** @typedef {WeakSet<CompilationAssets>} ProcessedAssets */
  605. /** @type {ProcessedAssets | undefined} */
  606. const processedAssets = additionalAssetsFn ? new WeakSet() : undefined;
  607. /**
  608. * Gets available assets.
  609. * @param {CompilationAssets} assets to be processed by additionalAssetsFn
  610. * @returns {CompilationAssets} available assets
  611. */
  612. const getAvailableAssets = (assets) => {
  613. /** @type {CompilationAssets} */
  614. const availableAssets = {};
  615. for (const file of Object.keys(assets)) {
  616. // https://github.com/webpack-contrib/compression-webpack-plugin/issues/390
  617. if (this.assets[file]) {
  618. availableAssets[file] = assets[file];
  619. }
  620. }
  621. return availableAssets;
  622. };
  623. switch (type) {
  624. case "sync":
  625. if (additionalAssetsFn) {
  626. this.hooks.processAdditionalAssets.tap(name, (assets) => {
  627. if (
  628. /** @type {ProcessedAssets} */
  629. (processedAssets).has(this.assets)
  630. ) {
  631. additionalAssetsFn(getAvailableAssets(assets));
  632. }
  633. });
  634. }
  635. return {
  636. ...remainingTap,
  637. type: "async",
  638. /**
  639. * Processes the provided asset.
  640. * @param {CompilationAssets} assets assets
  641. * @param {(err?: Error | null, result?: void) => void} callback callback
  642. * @returns {void}
  643. */
  644. fn: (assets, callback) => {
  645. try {
  646. fn(assets);
  647. } catch (err) {
  648. return callback(/** @type {Error} */ (err));
  649. }
  650. if (processedAssets !== undefined) {
  651. processedAssets.add(this.assets);
  652. }
  653. const newAssets = popNewAssets(assets);
  654. if (newAssets !== undefined) {
  655. this.hooks.processAdditionalAssets.callAsync(
  656. newAssets,
  657. callback
  658. );
  659. return;
  660. }
  661. callback();
  662. }
  663. };
  664. case "async":
  665. if (additionalAssetsFn) {
  666. this.hooks.processAdditionalAssets.tapAsync(
  667. name,
  668. (assets, callback) => {
  669. if (
  670. /** @type {ProcessedAssets} */
  671. (processedAssets).has(this.assets)
  672. ) {
  673. return additionalAssetsFn(
  674. getAvailableAssets(assets),
  675. callback
  676. );
  677. }
  678. callback();
  679. }
  680. );
  681. }
  682. return {
  683. ...remainingTap,
  684. /**
  685. * Processes the provided asset.
  686. * @param {CompilationAssets} assets assets
  687. * @param {(err?: Error | null, result?: void) => void} callback callback
  688. * @returns {void}
  689. */
  690. fn: (assets, callback) => {
  691. fn(
  692. assets,
  693. /**
  694. * Handles the callback logic for this hook.
  695. * @param {Error} err err
  696. * @returns {void}
  697. */
  698. (err) => {
  699. if (err) return callback(err);
  700. if (processedAssets !== undefined) {
  701. processedAssets.add(this.assets);
  702. }
  703. const newAssets = popNewAssets(assets);
  704. if (newAssets !== undefined) {
  705. this.hooks.processAdditionalAssets.callAsync(
  706. newAssets,
  707. callback
  708. );
  709. return;
  710. }
  711. callback();
  712. }
  713. );
  714. }
  715. };
  716. case "promise":
  717. if (additionalAssetsFn) {
  718. this.hooks.processAdditionalAssets.tapPromise(name, (assets) => {
  719. if (
  720. /** @type {ProcessedAssets} */
  721. (processedAssets).has(this.assets)
  722. ) {
  723. return additionalAssetsFn(getAvailableAssets(assets));
  724. }
  725. return Promise.resolve();
  726. });
  727. }
  728. return {
  729. ...remainingTap,
  730. /**
  731. * Returns result.
  732. * @param {CompilationAssets} assets assets
  733. * @returns {Promise<CompilationAssets>} result
  734. */
  735. fn: (assets) => {
  736. const p = fn(assets);
  737. if (!p || !p.then) return p;
  738. return p.then(() => {
  739. if (processedAssets !== undefined) {
  740. processedAssets.add(this.assets);
  741. }
  742. const newAssets = popNewAssets(assets);
  743. if (newAssets !== undefined) {
  744. return this.hooks.processAdditionalAssets.promise(
  745. newAssets
  746. );
  747. }
  748. });
  749. }
  750. };
  751. }
  752. }
  753. });
  754. /** @type {SyncHook<[CompilationAssets]>} */
  755. const afterProcessAssetsHook = new SyncHook(["assets"]);
  756. /**
  757. * Creates a process assets hook.
  758. * @template T
  759. * @param {string} name name of the hook
  760. * @param {number} stage new stage
  761. * @param {() => AsArray<T>} getArgs get old hook function args
  762. * @param {string=} code deprecation code (not deprecated when unset)
  763. * @returns {FakeHook<Pick<AsyncSeriesHook<T>, "tap" | "tapAsync" | "tapPromise" | "name">> | undefined} fake hook which redirects
  764. */
  765. const createProcessAssetsHook = (name, stage, getArgs, code) => {
  766. if (!this._backCompat && code) return;
  767. /**
  768. * Returns error message.
  769. * @param {string} reason reason
  770. * @returns {string} error message
  771. */
  772. const errorMessage = (
  773. reason
  774. ) => `Can't automatically convert plugin using Compilation.hooks.${name} to Compilation.hooks.processAssets because ${reason}.
  775. BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a single Compilation.hooks.processAssets hook.`;
  776. /**
  777. * Normalizes tap options for migrated process-assets hooks.
  778. * @param {string | (import("tapable").TapOptions & { name: string } & ProcessAssetsAdditionalOptions)} options hook options
  779. * @returns {import("tapable").TapOptions & { name: string } & ProcessAssetsAdditionalOptions} modified options
  780. */
  781. const getOptions = (options) => {
  782. if (typeof options === "string") options = { name: options };
  783. if (options.stage) {
  784. throw new Error(errorMessage("it's using the 'stage' option"));
  785. }
  786. return { ...options, stage };
  787. };
  788. return createFakeHook(
  789. {
  790. name,
  791. /** @type {AsyncSeriesHook<T>["intercept"]} */
  792. intercept(_interceptor) {
  793. throw new Error(errorMessage("it's using 'intercept'"));
  794. },
  795. /** @type {AsyncSeriesHook<T>["tap"]} */
  796. tap: (options, fn) => {
  797. processAssetsHook.tap(getOptions(options), () => fn(...getArgs()));
  798. },
  799. /** @type {AsyncSeriesHook<T>["tapAsync"]} */
  800. tapAsync: (options, fn) => {
  801. processAssetsHook.tapAsync(
  802. getOptions(options),
  803. (assets, callback) =>
  804. /** @type {EXPECTED_ANY} */ (fn)(...getArgs(), callback)
  805. );
  806. },
  807. /** @type {AsyncSeriesHook<T>["tapPromise"]} */
  808. tapPromise: (options, fn) => {
  809. processAssetsHook.tapPromise(getOptions(options), () =>
  810. fn(...getArgs())
  811. );
  812. }
  813. },
  814. `${name} is deprecated (use Compilation.hooks.processAssets instead and use one of Compilation.PROCESS_ASSETS_STAGE_* as stage option)`,
  815. code
  816. );
  817. };
  818. this.hooks = Object.freeze({
  819. /** @type {SyncHook<[Module]>} */
  820. buildModule: new SyncHook(["module"]),
  821. /** @type {SyncHook<[Module]>} */
  822. rebuildModule: new SyncHook(["module"]),
  823. /** @type {SyncHook<[Module, WebpackError]>} */
  824. failedModule: new SyncHook(["module", "error"]),
  825. /** @type {SyncHook<[Module]>} */
  826. succeedModule: new SyncHook(["module"]),
  827. /** @type {SyncHook<[Module]>} */
  828. stillValidModule: new SyncHook(["module"]),
  829. /** @type {SyncHook<[Dependency, EntryOptions]>} */
  830. addEntry: new SyncHook(["entry", "options"]),
  831. /** @type {SyncHook<[Dependency, EntryOptions, Error]>} */
  832. failedEntry: new SyncHook(["entry", "options", "error"]),
  833. /** @type {SyncHook<[Dependency, EntryOptions, Module]>} */
  834. succeedEntry: new SyncHook(["entry", "options", "module"]),
  835. /** @type {SyncWaterfallHook<[ReferencedExports, Dependency, RuntimeSpec]>} */
  836. dependencyReferencedExports: new SyncWaterfallHook([
  837. "referencedExports",
  838. "dependency",
  839. "runtime"
  840. ]),
  841. /**
  842. * @type {SyncHook<[ExecuteModuleArgument, ExecuteModuleContext]>}
  843. * @since 5.32.0
  844. */
  845. executeModule: new SyncHook(["options", "context"]),
  846. /**
  847. * @type {AsyncParallelHook<[ExecuteModuleArgument, ExecuteModuleContext]>}
  848. * @since 5.33.0
  849. */
  850. prepareModuleExecution: new AsyncParallelHook(["options", "context"]),
  851. /** @type {AsyncSeriesHook<[Iterable<Module>]>} */
  852. finishModules: new AsyncSeriesHook(["modules"]),
  853. /** @type {AsyncSeriesHook<[Module]>} */
  854. finishRebuildingModule: new AsyncSeriesHook(["module"]),
  855. /** @type {SyncHook<[]>} */
  856. unseal: new SyncHook([]),
  857. /** @type {SyncHook<[]>} */
  858. seal: new SyncHook([]),
  859. /** @type {SyncHook<[]>} */
  860. beforeChunks: new SyncHook([]),
  861. /**
  862. * The `afterChunks` hook is called directly after the chunks and module graph have
  863. * been created and before the chunks and modules have been optimized. This hook is useful to
  864. * inspect, analyze, and/or modify the chunk graph.
  865. * @type {SyncHook<[Iterable<Chunk>]>}
  866. */
  867. afterChunks: new SyncHook(["chunks"]),
  868. /** @type {SyncBailHook<[Iterable<Module>], boolean | void>} */
  869. optimizeDependencies: new SyncBailHook(["modules"]),
  870. /** @type {SyncHook<[Iterable<Module>]>} */
  871. afterOptimizeDependencies: new SyncHook(["modules"]),
  872. /** @type {SyncHook<[]>} */
  873. optimize: new SyncHook([]),
  874. /** @type {SyncBailHook<[Iterable<Module>], boolean | void>} */
  875. optimizeModules: new SyncBailHook(["modules"]),
  876. /** @type {SyncHook<[Iterable<Module>]>} */
  877. afterOptimizeModules: new SyncHook(["modules"]),
  878. /** @type {SyncBailHook<[Iterable<Chunk>, ChunkGroup[]], boolean | void>} */
  879. optimizeChunks: new SyncBailHook(["chunks", "chunkGroups"]),
  880. /** @type {SyncHook<[Iterable<Chunk>, ChunkGroup[]]>} */
  881. afterOptimizeChunks: new SyncHook(["chunks", "chunkGroups"]),
  882. /** @type {AsyncSeriesHook<[Iterable<Chunk>, Iterable<Module>]>} */
  883. optimizeTree: new AsyncSeriesHook(["chunks", "modules"]),
  884. /** @type {SyncHook<[Iterable<Chunk>, Iterable<Module>]>} */
  885. afterOptimizeTree: new SyncHook(["chunks", "modules"]),
  886. /** @type {AsyncSeriesBailHook<[Iterable<Chunk>, Iterable<Module>], void>} */
  887. optimizeChunkModules: new AsyncSeriesBailHook(["chunks", "modules"]),
  888. /** @type {SyncHook<[Iterable<Chunk>, Iterable<Module>]>} */
  889. afterOptimizeChunkModules: new SyncHook(["chunks", "modules"]),
  890. /** @type {SyncBailHook<[], boolean | void>} */
  891. shouldRecord: new SyncBailHook([]),
  892. /** @type {SyncHook<[Chunk, RuntimeRequirements, RuntimeRequirementsContext]>} */
  893. additionalChunkRuntimeRequirements: new SyncHook([
  894. "chunk",
  895. "runtimeRequirements",
  896. "context"
  897. ]),
  898. /** @type {HookMap<SyncBailHook<[Chunk, RuntimeRequirements, RuntimeRequirementsContext], void>>} */
  899. runtimeRequirementInChunk: new HookMap(
  900. () => new SyncBailHook(["chunk", "runtimeRequirements", "context"])
  901. ),
  902. /** @type {SyncHook<[Module, RuntimeRequirements, RuntimeRequirementsContext]>} */
  903. additionalModuleRuntimeRequirements: new SyncHook([
  904. "module",
  905. "runtimeRequirements",
  906. "context"
  907. ]),
  908. /** @type {HookMap<SyncBailHook<[Module, RuntimeRequirements, RuntimeRequirementsContext], void>>} */
  909. runtimeRequirementInModule: new HookMap(
  910. () => new SyncBailHook(["module", "runtimeRequirements", "context"])
  911. ),
  912. /** @type {SyncHook<[Chunk, RuntimeRequirements, RuntimeRequirementsContext]>} */
  913. additionalTreeRuntimeRequirements: new SyncHook([
  914. "chunk",
  915. "runtimeRequirements",
  916. "context"
  917. ]),
  918. /** @type {HookMap<SyncBailHook<[Chunk, RuntimeRequirements, RuntimeRequirementsContext], void>>} */
  919. runtimeRequirementInTree: new HookMap(
  920. () => new SyncBailHook(["chunk", "runtimeRequirements", "context"])
  921. ),
  922. /** @type {SyncHook<[RuntimeModule, Chunk]>} */
  923. runtimeModule: new SyncHook(["module", "chunk"]),
  924. /** @type {SyncHook<[Iterable<Module>, Records]>} */
  925. reviveModules: new SyncHook(["modules", "records"]),
  926. /** @type {SyncHook<[Iterable<Module>]>} */
  927. beforeModuleIds: new SyncHook(["modules"]),
  928. /** @type {SyncHook<[Iterable<Module>]>} */
  929. moduleIds: new SyncHook(["modules"]),
  930. /** @type {SyncHook<[Iterable<Module>]>} */
  931. optimizeModuleIds: new SyncHook(["modules"]),
  932. /** @type {SyncHook<[Iterable<Module>]>} */
  933. afterOptimizeModuleIds: new SyncHook(["modules"]),
  934. /** @type {SyncHook<[Iterable<Chunk>, Records]>} */
  935. reviveChunks: new SyncHook(["chunks", "records"]),
  936. /** @type {SyncHook<[Iterable<Chunk>]>} */
  937. beforeChunkIds: new SyncHook(["chunks"]),
  938. /** @type {SyncHook<[Iterable<Chunk>]>} */
  939. chunkIds: new SyncHook(["chunks"]),
  940. /** @type {SyncHook<[Iterable<Chunk>]>} */
  941. optimizeChunkIds: new SyncHook(["chunks"]),
  942. /** @type {SyncHook<[Iterable<Chunk>]>} */
  943. afterOptimizeChunkIds: new SyncHook(["chunks"]),
  944. /** @type {SyncHook<[Iterable<Module>, Records]>} */
  945. recordModules: new SyncHook(["modules", "records"]),
  946. /** @type {SyncHook<[Iterable<Chunk>, Records]>} */
  947. recordChunks: new SyncHook(["chunks", "records"]),
  948. /** @type {SyncHook<[Iterable<Module>]>} */
  949. optimizeCodeGeneration: new SyncHook(["modules"]),
  950. /** @type {SyncHook<[]>} */
  951. beforeModuleHash: new SyncHook([]),
  952. /** @type {SyncHook<[]>} */
  953. afterModuleHash: new SyncHook([]),
  954. /** @type {SyncHook<[]>} */
  955. beforeCodeGeneration: new SyncHook([]),
  956. /** @type {SyncHook<[]>} */
  957. afterCodeGeneration: new SyncHook([]),
  958. /** @type {SyncHook<[]>} */
  959. beforeRuntimeRequirements: new SyncHook([]),
  960. /** @type {SyncHook<[]>} */
  961. afterRuntimeRequirements: new SyncHook([]),
  962. /** @type {SyncHook<[]>} */
  963. beforeHash: new SyncHook([]),
  964. /** @type {SyncHook<[Chunk]>} */
  965. contentHash: new SyncHook(["chunk"]),
  966. /** @type {SyncHook<[]>} */
  967. afterHash: new SyncHook([]),
  968. /** @type {SyncHook<[Records]>} */
  969. recordHash: new SyncHook(["records"]),
  970. /** @type {SyncHook<[Compilation, Records]>} */
  971. record: new SyncHook(["compilation", "records"]),
  972. /** @type {SyncHook<[]>} */
  973. beforeModuleAssets: new SyncHook([]),
  974. /** @type {SyncBailHook<[], boolean | void>} */
  975. shouldGenerateChunkAssets: new SyncBailHook([]),
  976. /** @type {SyncHook<[]>} */
  977. beforeChunkAssets: new SyncHook([]),
  978. // TODO webpack 6 remove
  979. /** @deprecated */
  980. additionalChunkAssets:
  981. /** @type {FakeHook<Pick<AsyncSeriesHook<[Chunks]>, "tap" | "tapAsync" | "tapPromise" | "name">>} */
  982. (
  983. createProcessAssetsHook(
  984. "additionalChunkAssets",
  985. Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL,
  986. () => [this.chunks],
  987. "DEP_WEBPACK_COMPILATION_ADDITIONAL_CHUNK_ASSETS"
  988. )
  989. ),
  990. // TODO webpack 6 deprecate
  991. /** @deprecated */
  992. additionalAssets:
  993. /** @type {FakeHook<Pick<AsyncSeriesHook<[]>, "tap" | "tapAsync" | "tapPromise" | "name">>} */
  994. (
  995. createProcessAssetsHook(
  996. "additionalAssets",
  997. Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL,
  998. () => []
  999. )
  1000. ),
  1001. // TODO webpack 6 remove
  1002. /** @deprecated */
  1003. optimizeChunkAssets:
  1004. /** @type {FakeHook<Pick<AsyncSeriesHook<[Chunks]>, "tap" | "tapAsync" | "tapPromise" | "name">>} */
  1005. (
  1006. createProcessAssetsHook(
  1007. "optimizeChunkAssets",
  1008. Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE,
  1009. () => [this.chunks],
  1010. "DEP_WEBPACK_COMPILATION_OPTIMIZE_CHUNK_ASSETS"
  1011. )
  1012. ),
  1013. // TODO webpack 6 remove
  1014. /** @deprecated */
  1015. afterOptimizeChunkAssets:
  1016. /** @type {FakeHook<Pick<AsyncSeriesHook<[Chunks]>, "tap" | "tapAsync" | "tapPromise" | "name">>} */
  1017. (
  1018. createProcessAssetsHook(
  1019. "afterOptimizeChunkAssets",
  1020. Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE + 1,
  1021. () => [this.chunks],
  1022. "DEP_WEBPACK_COMPILATION_AFTER_OPTIMIZE_CHUNK_ASSETS"
  1023. )
  1024. ),
  1025. // TODO webpack 6 deprecate
  1026. /** @deprecated */
  1027. optimizeAssets: processAssetsHook,
  1028. // TODO webpack 6 deprecate
  1029. /** @deprecated */
  1030. afterOptimizeAssets: afterProcessAssetsHook,
  1031. processAssets: processAssetsHook,
  1032. afterProcessAssets: afterProcessAssetsHook,
  1033. /**
  1034. * @type {AsyncSeriesHook<[CompilationAssets]>}
  1035. * @since 5.8.0
  1036. */
  1037. processAdditionalAssets: new AsyncSeriesHook(["assets"]),
  1038. /** @type {SyncBailHook<[], boolean | void>} */
  1039. needAdditionalSeal: new SyncBailHook([]),
  1040. /** @type {AsyncSeriesHook<[]>} */
  1041. afterSeal: new AsyncSeriesHook([]),
  1042. /** @type {SyncWaterfallHook<[RenderManifestEntry[], RenderManifestOptions]>} */
  1043. renderManifest: new SyncWaterfallHook(["result", "options"]),
  1044. /**
  1045. * Called with source written in one language that a module emits inside
  1046. * another — CSS or HTML reaching the bundle as a JavaScript string
  1047. * literal today — before it is embedded; return the (possibly
  1048. * transformed) source, e.g. a minified one. `info.type` says which
  1049. * language it is, so one tap serves every pair; no asset carries this
  1050. * source, so an asset-level minimizer cannot reach it.
  1051. * @type {AsyncSeriesWaterfallHook<[Source, EmbeddedSourceInfo]>}
  1052. * @since 5.110.0
  1053. */
  1054. renderEmbeddedSource: new AsyncSeriesWaterfallHook(["source", "info"]),
  1055. /**
  1056. * Called while hashing a module that embeds such a source. Module hashes
  1057. * are taken before code generation, so a `renderEmbeddedSource` tap must
  1058. * write whatever it varies on into the hash, or the codegen cache
  1059. * replays output from before its options changed.
  1060. * @type {SyncHook<[Module, Hash]>}
  1061. * @since 5.110.0
  1062. */
  1063. embeddedSourceHash: new SyncHook(["module", "hash"]),
  1064. /** @type {SyncHook<[Hash]>} */
  1065. fullHash: new SyncHook(["hash"]),
  1066. /** @type {SyncHook<[Chunk, Hash, ChunkHashContext]>} */
  1067. chunkHash: new SyncHook(["chunk", "chunkHash", "ChunkHashContext"]),
  1068. /** @type {SyncHook<[Module, string]>} */
  1069. moduleAsset: new SyncHook(["module", "filename"]),
  1070. /** @type {SyncHook<[Chunk, string]>} */
  1071. chunkAsset: new SyncHook(["chunk", "filename"]),
  1072. /** @type {SyncWaterfallHook<[string, PathData, AssetInfo | undefined]>} */
  1073. assetPath: new SyncWaterfallHook(["path", "options", "assetInfo"]),
  1074. /** @type {SyncBailHook<[], boolean | void>} */
  1075. needAdditionalPass: new SyncBailHook([]),
  1076. /** @type {SyncHook<[Compiler, string, number]>} */
  1077. childCompiler: new SyncHook([
  1078. "childCompiler",
  1079. "compilerName",
  1080. "compilerIndex"
  1081. ]),
  1082. /** @type {SyncBailHook<[string, LogEntry], boolean | void>} */
  1083. log: new SyncBailHook(["origin", "logEntry"]),
  1084. /** @type {SyncWaterfallHook<[Error[]]>} */
  1085. processWarnings: new SyncWaterfallHook(["warnings"]),
  1086. /** @type {SyncWaterfallHook<[Error[]]>} */
  1087. processErrors: new SyncWaterfallHook(["errors"]),
  1088. /** @type {HookMap<SyncHook<[Partial<NormalizedStatsOptions>, CreateStatsOptionsContext]>>} */
  1089. statsPreset: new HookMap(() => new SyncHook(["options", "context"])),
  1090. /** @type {SyncHook<[Partial<NormalizedStatsOptions>, CreateStatsOptionsContext]>} */
  1091. statsNormalize: new SyncHook(["options", "context"]),
  1092. /** @type {SyncHook<[StatsFactory, NormalizedStatsOptions]>} */
  1093. statsFactory: new SyncHook(["statsFactory", "options"]),
  1094. /** @type {SyncHook<[StatsPrinter, NormalizedStatsOptions]>} */
  1095. statsPrinter: new SyncHook(["statsPrinter", "options"]),
  1096. /**
  1097. * Gets normal module loader.
  1098. * @deprecated
  1099. * @returns {SyncHook<[AnyLoaderContext, NormalModule]>} normal module loader hook
  1100. */
  1101. get normalModuleLoader() {
  1102. return getNormalModuleLoader();
  1103. }
  1104. });
  1105. /** @type {string=} */
  1106. this.name = undefined;
  1107. /** @type {number | undefined} */
  1108. this.startTime = undefined;
  1109. /** @type {number | undefined} */
  1110. this.endTime = undefined;
  1111. /** @type {Compiler} */
  1112. this.compiler = compiler;
  1113. this.resolverFactory = compiler.resolverFactory;
  1114. /** @type {InputFileSystem} */
  1115. this.inputFileSystem =
  1116. /** @type {InputFileSystem} */
  1117. (compiler.inputFileSystem);
  1118. /** @type {FileSystemInfo} */
  1119. this.fileSystemInfo = new FileSystemInfo(this.inputFileSystem, {
  1120. unmanagedPaths: compiler.unmanagedPaths,
  1121. managedPaths: compiler.managedPaths,
  1122. immutablePaths: compiler.immutablePaths,
  1123. logger: this.getLogger("webpack.FileSystemInfo"),
  1124. hashFunction: compiler.options.output.hashFunction
  1125. });
  1126. if (compiler.fileTimestamps) {
  1127. this.fileSystemInfo.addFileTimestamps(compiler.fileTimestamps, true);
  1128. }
  1129. if (compiler.contextTimestamps) {
  1130. this.fileSystemInfo.addContextTimestamps(
  1131. compiler.contextTimestamps,
  1132. true
  1133. );
  1134. }
  1135. /** @type {ValueCacheVersions} */
  1136. this.valueCacheVersions = new Map();
  1137. /** @type {RequestShortener} */
  1138. this.requestShortener = compiler.requestShortener;
  1139. /** @type {string} */
  1140. this.compilerPath = compiler.compilerPath;
  1141. this.logger = this.getLogger("webpack.Compilation");
  1142. const options = /** @type {WebpackOptions} */ (compiler.options);
  1143. this.options = options;
  1144. this.outputOptions =
  1145. /** @type {OutputOptionsWithDefaults} */
  1146. (options && options.output);
  1147. /** @type {boolean} */
  1148. this.bail = (options && options.bail) || false;
  1149. /** @type {boolean} */
  1150. this.profile = (options && options.profile) || false;
  1151. /** @type {CompilationParams} */
  1152. this.params = params;
  1153. /** @type {MainTemplate} */
  1154. this.mainTemplate = new MainTemplate(this.outputOptions, this);
  1155. /** @type {ChunkTemplate} */
  1156. this.chunkTemplate = new ChunkTemplate(this.outputOptions, this);
  1157. /** @type {RuntimeTemplate} */
  1158. this.runtimeTemplate = new RuntimeTemplate(
  1159. this,
  1160. this.outputOptions,
  1161. this.requestShortener
  1162. );
  1163. /** @type {ModuleTemplates} */
  1164. this.moduleTemplates = {
  1165. javascript: new ModuleTemplate(this.runtimeTemplate, this)
  1166. };
  1167. defineRemovedModuleTemplates(this.moduleTemplates);
  1168. // We need to think how implement types here
  1169. /** @type {ModuleMemCaches | undefined} */
  1170. this.moduleMemCaches = undefined;
  1171. /** @type {ModuleMemCaches | undefined} */
  1172. this.moduleMemCaches2 = undefined;
  1173. /** @type {ModuleGraph} */
  1174. this.moduleGraph = new ModuleGraph();
  1175. /** @type {ChunkGraph} */
  1176. this.chunkGraph = new ChunkGraph(
  1177. this.moduleGraph,
  1178. this.outputOptions.hashFunction
  1179. );
  1180. /** @type {CodeGenerationResults | undefined} */
  1181. this.codeGenerationResults = undefined;
  1182. /**
  1183. * What `renderEmbeddedSource` returned, by module and by language pair and
  1184. * text. Never shared between modules: a returned source may carry a map,
  1185. * which names the module it came from.
  1186. * @type {Map<Module, Map<string, Source>>}
  1187. * @private
  1188. */
  1189. this._embeddedSources = new Map();
  1190. /**
  1191. * Embedded source seen this pass that the hook has not been run over yet.
  1192. * @type {Map<Module, Map<string, { source: Source, info: EmbeddedSourceInfo, jobModule: Module }>>}
  1193. * @private
  1194. */
  1195. this._pendingEmbeddedSources = new Map();
  1196. /**
  1197. * The module whose code generation is currently running — the outer one
  1198. * when a generator runs nested, as `ConcatenatedModule` does.
  1199. * @type {Module | undefined}
  1200. * @private
  1201. */
  1202. this._generatingModule = undefined;
  1203. /** @type {AsyncQueue<Module, Module, Module>} */
  1204. this.processDependenciesQueue = new AsyncQueue({
  1205. name: "processDependencies",
  1206. parallelism: options.parallelism || 100,
  1207. processor: this._processModuleDependencies.bind(this)
  1208. });
  1209. /** @type {AsyncQueue<Module, string, Module>} */
  1210. this.addModuleQueue = new AsyncQueue({
  1211. name: "addModule",
  1212. parent: this.processDependenciesQueue,
  1213. getKey: (module) => module.identifier(),
  1214. processor: this._addModule.bind(this)
  1215. });
  1216. /** @type {AsyncQueue<FactorizeModuleOptions, string, Module | ModuleFactoryResult>} */
  1217. this.factorizeQueue = new AsyncQueue({
  1218. name: "factorize",
  1219. parent: this.addModuleQueue,
  1220. processor: this._factorizeModule.bind(this)
  1221. });
  1222. /** @type {AsyncQueue<Module, Module, Module>} */
  1223. this.buildQueue = new AsyncQueue({
  1224. name: "build",
  1225. parent: this.factorizeQueue,
  1226. processor: this._buildModule.bind(this)
  1227. });
  1228. /** @type {AsyncQueue<Module, Module, Module>} */
  1229. this.rebuildQueue = new AsyncQueue({
  1230. name: "rebuild",
  1231. parallelism: options.parallelism || 100,
  1232. processor: this._rebuildModule.bind(this)
  1233. });
  1234. /**
  1235. * Modules in value are building during the build of Module in key.
  1236. * Means value blocking key from finishing.
  1237. * Needed to detect build cycles.
  1238. * @type {WeakMap<Module, Set<Module>>}
  1239. */
  1240. this.creatingModuleDuringBuild = new WeakMap();
  1241. /** @type {Map<Exclude<ChunkName, null>, EntryData>} */
  1242. this.entries = new Map();
  1243. /** @type {EntryData} */
  1244. this.globalEntry = {
  1245. dependencies: [],
  1246. includeDependencies: [],
  1247. options: {
  1248. name: undefined
  1249. }
  1250. };
  1251. /** @type {Map<string, Entrypoint>} */
  1252. this.entrypoints = new Map();
  1253. /** @type {Entrypoint[]} */
  1254. this.asyncEntrypoints = [];
  1255. /** @type {Chunks} */
  1256. this.chunks = new Set();
  1257. /** @type {ChunkGroup[]} */
  1258. this.chunkGroups = [];
  1259. /** @type {Map<string, ChunkGroup>} */
  1260. this.namedChunkGroups = new Map();
  1261. /** @type {Map<string, Chunk>} */
  1262. this.namedChunks = new Map();
  1263. /** @type {Set<Module>} */
  1264. this.modules = new Set();
  1265. if (this._backCompat) {
  1266. arrayToSetDeprecation(this.chunks, "Compilation.chunks");
  1267. arrayToSetDeprecation(this.modules, "Compilation.modules");
  1268. }
  1269. /**
  1270. * @private
  1271. * @type {Map<string, Module>}
  1272. */
  1273. this._modules = new Map();
  1274. /** @type {Records | null} */
  1275. this.records = null;
  1276. /** @type {string[]} */
  1277. this.additionalChunkAssets = [];
  1278. /** @type {CompilationAssets} */
  1279. this.assets = {};
  1280. /** @type {Map<string, AssetInfo>} */
  1281. this.assetsInfo = new Map();
  1282. /** @type {Map<string, Map<string, Set<string>>>} */
  1283. this._assetsRelatedIn = new Map();
  1284. /** @type {Map<string, Set<Chunk>> | undefined} */
  1285. this._assetToChunkIndex = undefined;
  1286. /** @type {Map<string, Set<Chunk>> | undefined} */
  1287. this._assetToChunkAuxiliaryIndex = undefined;
  1288. /** @type {Error[]} */
  1289. this.errors = [];
  1290. /** @type {Error[]} */
  1291. this.warnings = [];
  1292. // Hints reported with `performance.hints: "stats"` — surfaced in stats
  1293. // only, so they neither fail the build nor count as warnings.
  1294. /** @type {Error[]} */
  1295. this.hints = [];
  1296. /** @type {Compilation[]} */
  1297. this.children = [];
  1298. /** @type {Map<string, LogEntry[]>} */
  1299. this.logging = new Map();
  1300. /** @type {Map<DependencyConstructor, ModuleFactory>} */
  1301. this.dependencyFactories = new Map();
  1302. /** @type {DependencyTemplates} */
  1303. this.dependencyTemplates = new DependencyTemplates(
  1304. this.outputOptions.hashFunction
  1305. );
  1306. /** @type {Record<string, number>} */
  1307. this.childrenCounters = {};
  1308. /** @type {Set<number> | null} */
  1309. this.usedChunkIds = null;
  1310. /** @type {Set<number> | null} */
  1311. this.usedModuleIds = null;
  1312. /** @type {boolean} */
  1313. this.needAdditionalPass = false;
  1314. /** @type {Set<ModuleWithRestoreFromUnsafeCache>} */
  1315. this._restoredUnsafeCacheModuleEntries = new Set();
  1316. /** @type {Map<string, ModuleWithRestoreFromUnsafeCache>} */
  1317. this._restoredUnsafeCacheEntries = new Map();
  1318. /** @type {WeakSet<Module>} */
  1319. this.builtModules = new WeakSet();
  1320. /** @type {WeakSet<Module>} */
  1321. this.codeGeneratedModules = new WeakSet();
  1322. /** @type {WeakSet<Module>} */
  1323. this.buildTimeExecutedModules = new WeakSet();
  1324. /** @type {Set<string>} */
  1325. this.emittedAssets = new Set();
  1326. /** @type {Set<string>} */
  1327. this.comparedForEmitAssets = new Set();
  1328. /** @type {FileSystemDependencies} */
  1329. this.fileDependencies = new LazySet();
  1330. /** @type {FileSystemDependencies} */
  1331. this.contextDependencies = new LazySet();
  1332. /** @type {FileSystemDependencies} */
  1333. this.missingDependencies = new LazySet();
  1334. /** @type {FileSystemDependencies} */
  1335. this.buildDependencies = new LazySet();
  1336. // TODO webpack 6 remove
  1337. /**
  1338. * @deprecated
  1339. * @type {{ add: (item: string) => FileSystemDependencies }}
  1340. */
  1341. this.compilationDependencies = {
  1342. add: util.deprecate(
  1343. /**
  1344. * Handles the add callback for this hook.
  1345. * @param {string} item item
  1346. * @returns {FileSystemDependencies} file dependencies
  1347. */
  1348. (item) => this.fileDependencies.add(item),
  1349. "Compilation.compilationDependencies is deprecated (used Compilation.fileDependencies instead)",
  1350. "DEP_WEBPACK_COMPILATION_COMPILATION_DEPENDENCIES"
  1351. )
  1352. };
  1353. /** @type {CacheFacade} */
  1354. this._modulesCache = this.getCache("Compilation/modules");
  1355. /** @type {CacheFacade} */
  1356. this._assetsCache = this.getCache("Compilation/assets");
  1357. /** @type {CacheFacade} */
  1358. this._codeGenerationCache = this.getCache("Compilation/codeGeneration");
  1359. /** @type {PendingRuntimeModule[] | undefined} */
  1360. this._pendingRuntimeModules = undefined;
  1361. const unsafeCache = options.module.unsafeCache;
  1362. /** @type {boolean} */
  1363. this._unsafeCache = Boolean(unsafeCache);
  1364. /** @type {UnsafeCachePredicate} */
  1365. this._unsafeCachePredicate =
  1366. typeof unsafeCache === "function" ? unsafeCache : () => true;
  1367. /** @type {LazyBarrelController} */
  1368. this._lazyBarrelController = new LazyBarrelController(this);
  1369. }
  1370. getStats() {
  1371. return new Stats(this);
  1372. }
  1373. /**
  1374. * Creates a stats options.
  1375. * @param {string | boolean | StatsOptions | undefined} optionsOrPreset stats option value
  1376. * @param {CreateStatsOptionsContext=} context context
  1377. * @returns {NormalizedStatsOptions} normalized options
  1378. */
  1379. createStatsOptions(optionsOrPreset, context = {}) {
  1380. if (typeof optionsOrPreset === "boolean") {
  1381. optionsOrPreset = {
  1382. preset: optionsOrPreset === false ? "none" : "normal"
  1383. };
  1384. } else if (typeof optionsOrPreset === "string") {
  1385. optionsOrPreset = { preset: optionsOrPreset };
  1386. }
  1387. if (typeof optionsOrPreset === "object" && optionsOrPreset !== null) {
  1388. // We use this method of shallow cloning this object to include
  1389. // properties in the prototype chain
  1390. /** @type {Partial<NormalizedStatsOptions>} */
  1391. const options = {};
  1392. for (const key in optionsOrPreset) {
  1393. options[key] = optionsOrPreset[/** @type {keyof StatsOptions} */ (key)];
  1394. }
  1395. if (options.preset !== undefined) {
  1396. this.hooks.statsPreset.for(options.preset).call(options, context);
  1397. }
  1398. this.hooks.statsNormalize.call(options, context);
  1399. return /** @type {NormalizedStatsOptions} */ (options);
  1400. }
  1401. /** @type {Partial<NormalizedStatsOptions>} */
  1402. const options = {};
  1403. this.hooks.statsNormalize.call(options, context);
  1404. return /** @type {NormalizedStatsOptions} */ (options);
  1405. }
  1406. /**
  1407. * Creates a stats factory.
  1408. * @param {NormalizedStatsOptions} options options
  1409. * @returns {StatsFactory} the stats factory
  1410. */
  1411. createStatsFactory(options) {
  1412. const statsFactory = new StatsFactory();
  1413. this.hooks.statsFactory.call(statsFactory, options);
  1414. return statsFactory;
  1415. }
  1416. /**
  1417. * Creates a stats printer.
  1418. * @param {NormalizedStatsOptions} options options
  1419. * @returns {StatsPrinter} the stats printer
  1420. */
  1421. createStatsPrinter(options) {
  1422. const statsPrinter = new StatsPrinter();
  1423. this.hooks.statsPrinter.call(statsPrinter, options);
  1424. return statsPrinter;
  1425. }
  1426. /**
  1427. * Returns the cache facade instance.
  1428. * @param {string} name cache name
  1429. * @returns {CacheFacade} the cache facade instance
  1430. */
  1431. getCache(name) {
  1432. return this.compiler.getCache(name);
  1433. }
  1434. /**
  1435. * Returns a logger with that name.
  1436. * @param {string | (() => string)} name name of the logger, or function called once to get the logger name
  1437. * @returns {Logger} a logger with that name
  1438. */
  1439. getLogger(name) {
  1440. if (!name) {
  1441. throw new TypeError("Compilation.getLogger(name) called without a name");
  1442. }
  1443. /** @type {LogEntry[] | undefined} */
  1444. let logEntries;
  1445. return new Logger(
  1446. (type, args) => {
  1447. if (typeof name === "function") {
  1448. name = name();
  1449. if (!name) {
  1450. throw new TypeError(
  1451. "Compilation.getLogger(name) called with a function not returning a name"
  1452. );
  1453. }
  1454. }
  1455. /** @type {LogEntry["trace"]} */
  1456. let trace;
  1457. switch (type) {
  1458. case LogType.warn:
  1459. case LogType.error:
  1460. case LogType.trace:
  1461. trace = ErrorHelpers.cutOffLoaderExecution(
  1462. /** @type {string} */ (new Error("Trace").stack)
  1463. )
  1464. .split("\n")
  1465. .slice(3);
  1466. break;
  1467. }
  1468. /** @type {LogEntry} */
  1469. const logEntry = {
  1470. time: Date.now(),
  1471. type,
  1472. args,
  1473. trace
  1474. };
  1475. /* eslint-disable no-console */
  1476. if (this.hooks.log.call(name, logEntry) === undefined) {
  1477. if (
  1478. logEntry.type === LogType.profileEnd &&
  1479. typeof console.profileEnd === "function"
  1480. ) {
  1481. console.profileEnd(
  1482. `[${name}] ${
  1483. /** @type {NonNullable<LogEntry["args"]>} */ (logEntry.args)[0]
  1484. }`
  1485. );
  1486. }
  1487. if (logEntries === undefined) {
  1488. logEntries = this.logging.get(name);
  1489. if (logEntries === undefined) {
  1490. logEntries = [];
  1491. this.logging.set(name, logEntries);
  1492. }
  1493. }
  1494. logEntries.push(logEntry);
  1495. if (
  1496. logEntry.type === LogType.profile &&
  1497. typeof console.profile === "function"
  1498. ) {
  1499. console.profile(
  1500. `[${name}] ${
  1501. /** @type {NonNullable<LogEntry["args"]>} */
  1502. (logEntry.args)[0]
  1503. }`
  1504. );
  1505. }
  1506. /* eslint-enable no-console */
  1507. }
  1508. },
  1509. (childName) => {
  1510. if (typeof name === "function") {
  1511. if (typeof childName === "function") {
  1512. return this.getLogger(() => {
  1513. if (typeof name === "function") {
  1514. name = name();
  1515. if (!name) {
  1516. throw new TypeError(
  1517. "Compilation.getLogger(name) called with a function not returning a name"
  1518. );
  1519. }
  1520. }
  1521. if (typeof childName === "function") {
  1522. childName = childName();
  1523. if (!childName) {
  1524. throw new TypeError(
  1525. "Logger.getChildLogger(name) called with a function not returning a name"
  1526. );
  1527. }
  1528. }
  1529. return `${name}/${childName}`;
  1530. });
  1531. }
  1532. return this.getLogger(() => {
  1533. if (typeof name === "function") {
  1534. name = name();
  1535. if (!name) {
  1536. throw new TypeError(
  1537. "Compilation.getLogger(name) called with a function not returning a name"
  1538. );
  1539. }
  1540. }
  1541. return `${name}/${childName}`;
  1542. });
  1543. }
  1544. if (typeof childName === "function") {
  1545. return this.getLogger(() => {
  1546. if (typeof childName === "function") {
  1547. childName = childName();
  1548. if (!childName) {
  1549. throw new TypeError(
  1550. "Logger.getChildLogger(name) called with a function not returning a name"
  1551. );
  1552. }
  1553. }
  1554. return `${name}/${childName}`;
  1555. });
  1556. }
  1557. return this.getLogger(`${name}/${childName}`);
  1558. }
  1559. );
  1560. }
  1561. /**
  1562. * Adds the provided module to the compilation.
  1563. * @param {Module} module module to be added that was created
  1564. * @param {ModuleCallback} callback returns the module in the compilation,
  1565. * it could be the passed one (if new), or an already existing in the compilation
  1566. * @returns {void}
  1567. */
  1568. addModule(module, callback) {
  1569. this.addModuleQueue.add(module, callback);
  1570. }
  1571. /**
  1572. * Adds the provided module to the compilation.
  1573. * @param {Module} module module to be added that was created
  1574. * @param {ModuleCallback} callback returns the module in the compilation,
  1575. * it could be the passed one (if new), or an already existing in the compilation
  1576. * @returns {void}
  1577. */
  1578. _addModule(module, callback) {
  1579. const identifier = module.identifier();
  1580. const alreadyAddedModule = this._modules.get(identifier);
  1581. if (alreadyAddedModule) {
  1582. return callback(null, alreadyAddedModule);
  1583. }
  1584. const currentProfile = this.profile
  1585. ? this.moduleGraph.getProfile(module)
  1586. : undefined;
  1587. if (currentProfile !== undefined) {
  1588. currentProfile.markRestoringStart();
  1589. }
  1590. this._modulesCache.get(identifier, null, (err, cacheModule) => {
  1591. if (err) return callback(new (getModuleRestoreError())(module, err));
  1592. if (currentProfile !== undefined) {
  1593. currentProfile.markRestoringEnd();
  1594. currentProfile.markIntegrationStart();
  1595. }
  1596. if (cacheModule) {
  1597. cacheModule.updateCacheModule(module);
  1598. module = cacheModule;
  1599. }
  1600. this._modules.set(identifier, module);
  1601. this.modules.add(module);
  1602. if (this._backCompat) {
  1603. ModuleGraph.setModuleGraphForModule(module, this.moduleGraph);
  1604. }
  1605. if (currentProfile !== undefined) {
  1606. currentProfile.markIntegrationEnd();
  1607. }
  1608. callback(null, module);
  1609. });
  1610. }
  1611. /**
  1612. * Fetches a module from a compilation by its identifier
  1613. * @param {Module} module the module provided
  1614. * @returns {Module} the module requested
  1615. */
  1616. getModule(module) {
  1617. const identifier = module.identifier();
  1618. return /** @type {Module} */ (this._modules.get(identifier));
  1619. }
  1620. /**
  1621. * Attempts to search for a module by its identifier
  1622. * @param {string} identifier identifier (usually path) for module
  1623. * @returns {Module | undefined} attempt to search for module and return it, else undefined
  1624. */
  1625. findModule(identifier) {
  1626. return this._modules.get(identifier);
  1627. }
  1628. /**
  1629. * Schedules a build of the module object
  1630. * @param {Module} module module to be built
  1631. * @param {ModuleCallback} callback the callback
  1632. * @returns {void}
  1633. */
  1634. buildModule(module, callback) {
  1635. this.buildQueue.add(module, callback);
  1636. }
  1637. /**
  1638. * Builds the module object
  1639. * @param {Module} module module to be built
  1640. * @param {ModuleCallback} callback the callback
  1641. * @returns {void}
  1642. */
  1643. _buildModule(module, callback) {
  1644. const currentProfile = this.profile
  1645. ? this.moduleGraph.getProfile(module)
  1646. : undefined;
  1647. if (currentProfile !== undefined) {
  1648. currentProfile.markBuildingStart();
  1649. }
  1650. module.needBuild(
  1651. {
  1652. compilation: this,
  1653. fileSystemInfo: this.fileSystemInfo,
  1654. valueCacheVersions: this.valueCacheVersions
  1655. },
  1656. (err, needBuild) => {
  1657. if (err) return callback(err);
  1658. if (!needBuild) {
  1659. if (currentProfile !== undefined) {
  1660. currentProfile.markBuildingEnd();
  1661. }
  1662. this.hooks.stillValidModule.call(module);
  1663. return callback();
  1664. }
  1665. this.hooks.buildModule.call(module);
  1666. this.builtModules.add(module);
  1667. module.build(
  1668. this.options,
  1669. this,
  1670. this.resolverFactory.get("normal", module.resolveOptions),
  1671. /** @type {InputFileSystem} */
  1672. (this.inputFileSystem),
  1673. (err) => {
  1674. if (currentProfile !== undefined) {
  1675. currentProfile.markBuildingEnd();
  1676. }
  1677. if (err) {
  1678. this.hooks.failedModule.call(module, err);
  1679. return callback(err);
  1680. }
  1681. if (currentProfile !== undefined) {
  1682. currentProfile.markStoringStart();
  1683. }
  1684. this._modulesCache.store(
  1685. module.identifier(),
  1686. null,
  1687. module,
  1688. (err) => {
  1689. if (currentProfile !== undefined) {
  1690. currentProfile.markStoringEnd();
  1691. }
  1692. if (err) {
  1693. this.hooks.failedModule.call(
  1694. module,
  1695. /** @type {WebpackError} */ (err)
  1696. );
  1697. return callback(new (getModuleStoreError())(module, err));
  1698. }
  1699. this.hooks.succeedModule.call(module);
  1700. return callback();
  1701. }
  1702. );
  1703. }
  1704. );
  1705. }
  1706. );
  1707. }
  1708. /**
  1709. * Process module dependencies.
  1710. * @param {Module} module to be processed for deps
  1711. * @param {ModuleCallback} callback callback to be triggered
  1712. * @returns {void}
  1713. */
  1714. processModuleDependencies(module, callback) {
  1715. this.processDependenciesQueue.add(module, callback);
  1716. }
  1717. /**
  1718. * Process module dependencies non recursive.
  1719. * @param {Module} module to be processed for deps
  1720. * @returns {void}
  1721. */
  1722. processModuleDependenciesNonRecursive(module) {
  1723. /**
  1724. * Process dependencies block.
  1725. * @param {DependenciesBlock} block block
  1726. */
  1727. const processDependenciesBlock = (block) => {
  1728. if (block.dependencies) {
  1729. let i = 0;
  1730. for (const dep of block.dependencies) {
  1731. this.moduleGraph.setParents(dep, block, module, i++);
  1732. }
  1733. }
  1734. if (block.blocks) {
  1735. for (const b of block.blocks) processDependenciesBlock(b);
  1736. }
  1737. };
  1738. processDependenciesBlock(module);
  1739. }
  1740. /**
  1741. * Process module dependencies.
  1742. * @param {Module} module to be processed for deps
  1743. * @param {ModuleCallback} callback callback to be triggered
  1744. * @returns {void}
  1745. */
  1746. _processModuleDependencies(module, callback) {
  1747. /** @type {{ factory: ModuleFactory, dependencies: Dependency[], context: string | undefined, originModule: Module | null }[]} */
  1748. const sortedDependencies = [];
  1749. /** @type {boolean} */
  1750. const hasLowPriorityDependencies = module.dependencies.some(
  1751. Dependency.isLowPriorityDependency
  1752. );
  1753. // lazy barrel: defer re-export targets of side-effect-free modules
  1754. const hasLazyBarrel = this._lazyBarrelController.classify(module);
  1755. /** @type {DependenciesBlock} */
  1756. let currentBlock;
  1757. /** @type {Map<ModuleFactory, Map<string, Dependency[]>>} */
  1758. let dependencies;
  1759. /** @type {DependencyConstructor} */
  1760. let factoryCacheKey;
  1761. /** @type {ModuleFactory} */
  1762. let factoryCacheKey2;
  1763. /** @typedef {Map<string, Dependency[]>} FactoryCacheValue */
  1764. /** @type {FactoryCacheValue | undefined} */
  1765. let factoryCacheValue;
  1766. /** @type {string} */
  1767. let listCacheKey1;
  1768. /** @type {string} */
  1769. let listCacheKey2;
  1770. /** @type {Dependency[]} */
  1771. let listCacheValue;
  1772. let inProgressSorting = 1;
  1773. let inProgressTransitive = 1;
  1774. /**
  1775. * On dependencies sorted.
  1776. * @param {WebpackError=} err error
  1777. * @returns {void}
  1778. */
  1779. const onDependenciesSorted = (err) => {
  1780. if (err) return callback(err);
  1781. // early exit without changing parallelism back and forth
  1782. if (sortedDependencies.length === 0 && inProgressTransitive === 1) {
  1783. return callback();
  1784. }
  1785. // This is nested so we need to allow one additional task
  1786. this.processDependenciesQueue.increaseParallelism();
  1787. for (const item of sortedDependencies) {
  1788. inProgressTransitive++;
  1789. // eslint-disable-next-line no-loop-func
  1790. this.handleModuleCreation(item, (err) => {
  1791. // In V8, the Error objects keep a reference to the functions on the stack. These warnings &
  1792. // errors are created inside closures that keep a reference to the Compilation, so errors are
  1793. // leaking the Compilation object.
  1794. if (err && this.bail) {
  1795. if (inProgressTransitive <= 0) return;
  1796. inProgressTransitive = -1;
  1797. // eslint-disable-next-line no-self-assign
  1798. err.stack = err.stack;
  1799. onTransitiveTasksFinished(err);
  1800. return;
  1801. }
  1802. if (--inProgressTransitive === 0) onTransitiveTasksFinished();
  1803. });
  1804. }
  1805. if (--inProgressTransitive === 0) onTransitiveTasksFinished();
  1806. };
  1807. /**
  1808. * On transitive tasks finished.
  1809. * @param {WebpackError=} err error
  1810. * @returns {void}
  1811. */
  1812. const onTransitiveTasksFinished = (err) => {
  1813. if (err) return callback(err);
  1814. this.processDependenciesQueue.decreaseParallelism();
  1815. return callback();
  1816. };
  1817. /**
  1818. * Process dependency.
  1819. * @param {Dependency} dep dependency
  1820. * @param {number} index index in block
  1821. * @returns {void}
  1822. */
  1823. const processDependency = (dep, index) => {
  1824. this.moduleGraph.setParents(dep, currentBlock, module, index);
  1825. if (
  1826. hasLazyBarrel &&
  1827. // TODO remove in webpack 6
  1828. // It may be missing on custom dependency types not extending the base Dependency
  1829. "isLazy" in dep &&
  1830. dep.isLazy()
  1831. ) {
  1832. return;
  1833. }
  1834. if (this._unsafeCache) {
  1835. try {
  1836. const unsafeCachedModule = unsafeCacheDependencies.get(dep);
  1837. if (unsafeCachedModule === null) return;
  1838. if (unsafeCachedModule !== undefined) {
  1839. if (
  1840. this._restoredUnsafeCacheModuleEntries.has(unsafeCachedModule)
  1841. ) {
  1842. this._handleExistingModuleFromUnsafeCache(
  1843. module,
  1844. dep,
  1845. unsafeCachedModule
  1846. );
  1847. this._lazyBarrelController.unlazyForDependency(
  1848. unsafeCachedModule,
  1849. dep,
  1850. sortedDependencies
  1851. );
  1852. return;
  1853. }
  1854. const identifier = unsafeCachedModule.identifier();
  1855. const cachedModule =
  1856. this._restoredUnsafeCacheEntries.get(identifier);
  1857. if (cachedModule !== undefined) {
  1858. // update unsafe cache to new module
  1859. unsafeCacheDependencies.set(dep, cachedModule);
  1860. this._handleExistingModuleFromUnsafeCache(
  1861. module,
  1862. dep,
  1863. cachedModule
  1864. );
  1865. this._lazyBarrelController.unlazyForDependency(
  1866. cachedModule,
  1867. dep,
  1868. sortedDependencies
  1869. );
  1870. return;
  1871. }
  1872. inProgressSorting++;
  1873. this._modulesCache.get(identifier, null, (err, cachedModule) => {
  1874. if (err) {
  1875. if (inProgressSorting <= 0) return;
  1876. inProgressSorting = -1;
  1877. onDependenciesSorted(/** @type {WebpackError} */ (err));
  1878. return;
  1879. }
  1880. try {
  1881. if (!this._restoredUnsafeCacheEntries.has(identifier)) {
  1882. const data = unsafeCacheData.get(cachedModule);
  1883. if (data === undefined) {
  1884. processDependencyForResolving(dep);
  1885. if (--inProgressSorting === 0) onDependenciesSorted();
  1886. return;
  1887. }
  1888. if (cachedModule !== unsafeCachedModule) {
  1889. unsafeCacheDependencies.set(dep, cachedModule);
  1890. }
  1891. cachedModule.restoreFromUnsafeCache(
  1892. data,
  1893. this.params.normalModuleFactory,
  1894. this.params
  1895. );
  1896. this._restoredUnsafeCacheEntries.set(
  1897. identifier,
  1898. cachedModule
  1899. );
  1900. this._restoredUnsafeCacheModuleEntries.add(cachedModule);
  1901. if (!this.modules.has(cachedModule)) {
  1902. inProgressTransitive++;
  1903. this._handleNewModuleFromUnsafeCache(
  1904. module,
  1905. dep,
  1906. cachedModule,
  1907. (err) => {
  1908. if (err) {
  1909. if (inProgressTransitive <= 0) return;
  1910. inProgressTransitive = -1;
  1911. onTransitiveTasksFinished(err);
  1912. }
  1913. if (--inProgressTransitive === 0) {
  1914. return onTransitiveTasksFinished();
  1915. }
  1916. }
  1917. );
  1918. if (--inProgressSorting === 0) onDependenciesSorted();
  1919. return;
  1920. }
  1921. }
  1922. if (unsafeCachedModule !== cachedModule) {
  1923. unsafeCacheDependencies.set(dep, cachedModule);
  1924. }
  1925. this._handleExistingModuleFromUnsafeCache(
  1926. module,
  1927. dep,
  1928. cachedModule
  1929. ); // a3
  1930. this._lazyBarrelController.unlazyForDependency(
  1931. cachedModule,
  1932. dep,
  1933. sortedDependencies
  1934. );
  1935. } catch (err) {
  1936. if (inProgressSorting <= 0) return;
  1937. inProgressSorting = -1;
  1938. onDependenciesSorted(/** @type {WebpackError} */ (err));
  1939. return;
  1940. }
  1941. if (--inProgressSorting === 0) onDependenciesSorted();
  1942. });
  1943. return;
  1944. }
  1945. } catch (err) {
  1946. // eslint-disable-next-line no-console
  1947. console.error(err);
  1948. }
  1949. }
  1950. processDependencyForResolving(dep);
  1951. };
  1952. /**
  1953. * Process dependency for resolving.
  1954. * @param {Dependency} dep dependency
  1955. * @returns {void}
  1956. */
  1957. const processDependencyForResolving = (dep) => {
  1958. const resourceIdent = dep.getResourceIdentifier();
  1959. if (resourceIdent !== undefined && resourceIdent !== null) {
  1960. const category = dep.category;
  1961. const constructor =
  1962. /** @type {DependencyConstructor} */
  1963. (dep.constructor);
  1964. if (factoryCacheKey === constructor) {
  1965. // Fast path 1: same constructor as prev item
  1966. if (listCacheKey1 === category && listCacheKey2 === resourceIdent) {
  1967. // Super fast path 1: also same resource
  1968. listCacheValue.push(dep);
  1969. return;
  1970. }
  1971. } else {
  1972. const factory = this.dependencyFactories.get(constructor);
  1973. if (factory === undefined) {
  1974. throw new Error(
  1975. `No module factory available for dependency type: ${constructor.name}`
  1976. );
  1977. }
  1978. if (factoryCacheKey2 === factory) {
  1979. // Fast path 2: same factory as prev item
  1980. factoryCacheKey = constructor;
  1981. if (listCacheKey1 === category && listCacheKey2 === resourceIdent) {
  1982. // Super fast path 2: also same resource
  1983. listCacheValue.push(dep);
  1984. return;
  1985. }
  1986. } else {
  1987. // Slow path
  1988. if (factoryCacheKey2 !== undefined) {
  1989. // Archive last cache entry
  1990. if (dependencies === undefined) dependencies = new Map();
  1991. dependencies.set(
  1992. factoryCacheKey2,
  1993. /** @type {FactoryCacheValue} */ (factoryCacheValue)
  1994. );
  1995. factoryCacheValue = dependencies.get(factory);
  1996. if (factoryCacheValue === undefined) {
  1997. factoryCacheValue = new Map();
  1998. }
  1999. } else {
  2000. factoryCacheValue = new Map();
  2001. }
  2002. factoryCacheKey = constructor;
  2003. factoryCacheKey2 = factory;
  2004. }
  2005. }
  2006. // Here webpack is using heuristic that assumes
  2007. // mostly esm dependencies would be used
  2008. // so we don't allocate extra string for them
  2009. const cacheKey =
  2010. category === esmDependencyCategory
  2011. ? resourceIdent
  2012. : `${category}${resourceIdent}`;
  2013. let list = /** @type {FactoryCacheValue} */ (factoryCacheValue).get(
  2014. cacheKey
  2015. );
  2016. if (list === undefined) {
  2017. /** @type {FactoryCacheValue} */
  2018. (factoryCacheValue).set(cacheKey, (list = []));
  2019. const newItem = {
  2020. factory: factoryCacheKey2,
  2021. dependencies: list,
  2022. context: dep.getContext(),
  2023. originModule: module
  2024. };
  2025. if (hasLowPriorityDependencies) {
  2026. let insertIndex = sortedDependencies.length;
  2027. while (insertIndex > 0) {
  2028. const item = sortedDependencies[insertIndex - 1];
  2029. const isAllLowPriorityDependencies = item.dependencies.every(
  2030. Dependency.isLowPriorityDependency
  2031. );
  2032. if (isAllLowPriorityDependencies) {
  2033. insertIndex--;
  2034. } else {
  2035. break;
  2036. }
  2037. }
  2038. sortedDependencies.splice(insertIndex, 0, newItem);
  2039. } else {
  2040. sortedDependencies.push(newItem);
  2041. }
  2042. }
  2043. list.push(dep);
  2044. listCacheKey1 = category;
  2045. listCacheKey2 = resourceIdent;
  2046. listCacheValue = list;
  2047. }
  2048. };
  2049. try {
  2050. /** @type {DependenciesBlock[]} */
  2051. const queue = [module];
  2052. do {
  2053. const block = /** @type {DependenciesBlock} */ (queue.pop());
  2054. if (block.dependencies) {
  2055. currentBlock = block;
  2056. let i = 0;
  2057. for (const dep of block.dependencies) processDependency(dep, i++);
  2058. }
  2059. if (block.blocks) {
  2060. for (const b of block.blocks) queue.push(b);
  2061. }
  2062. } while (queue.length !== 0);
  2063. } catch (err) {
  2064. return callback(/** @type {WebpackError} */ (err));
  2065. }
  2066. if (--inProgressSorting === 0) onDependenciesSorted();
  2067. }
  2068. /**
  2069. * Handle new module from unsafe cache.
  2070. * @private
  2071. * @param {Module} originModule original module
  2072. * @param {Dependency} dependency dependency
  2073. * @param {Module} module cached module
  2074. * @param {Callback} callback callback
  2075. */
  2076. _handleNewModuleFromUnsafeCache(originModule, dependency, module, callback) {
  2077. const moduleGraph = this.moduleGraph;
  2078. moduleGraph.setResolvedModule(originModule, dependency, module);
  2079. moduleGraph.setIssuerIfUnset(
  2080. module,
  2081. originModule !== undefined ? originModule : null
  2082. );
  2083. this._modules.set(module.identifier(), module);
  2084. this.modules.add(module);
  2085. if (this._backCompat) {
  2086. ModuleGraph.setModuleGraphForModule(module, this.moduleGraph);
  2087. }
  2088. this._handleModuleBuildAndDependencies(
  2089. originModule,
  2090. module,
  2091. true,
  2092. false,
  2093. [dependency],
  2094. callback
  2095. );
  2096. }
  2097. /**
  2098. * Handle existing module from unsafe cache.
  2099. * @private
  2100. * @param {Module} originModule original modules
  2101. * @param {Dependency} dependency dependency
  2102. * @param {Module} module cached module
  2103. */
  2104. _handleExistingModuleFromUnsafeCache(originModule, dependency, module) {
  2105. const moduleGraph = this.moduleGraph;
  2106. moduleGraph.setResolvedModule(originModule, dependency, module);
  2107. }
  2108. /**
  2109. * Processes the provided factorize module option.
  2110. * @param {FactorizeModuleOptions} options options
  2111. * @param {ModuleOrModuleFactoryResultCallback} callback callback
  2112. * @returns {void}
  2113. */
  2114. _factorizeModule(
  2115. {
  2116. currentProfile,
  2117. factory,
  2118. dependencies,
  2119. originModule,
  2120. factoryResult,
  2121. contextInfo,
  2122. context
  2123. },
  2124. callback
  2125. ) {
  2126. if (currentProfile !== undefined) {
  2127. currentProfile.markFactoryStart();
  2128. }
  2129. factory.create(
  2130. {
  2131. contextInfo: {
  2132. issuer: originModule
  2133. ? /** @type {NameForCondition} */ (originModule.nameForCondition())
  2134. : "",
  2135. issuerLayer: originModule ? originModule.layer : null,
  2136. compiler: this.compiler.name,
  2137. ...contextInfo
  2138. },
  2139. resolveOptions: originModule ? originModule.resolveOptions : undefined,
  2140. context:
  2141. context ||
  2142. (originModule
  2143. ? /** @type {string} */ (originModule.context)
  2144. : this.compiler.context),
  2145. dependencies
  2146. },
  2147. (err, result) => {
  2148. if (result) {
  2149. // TODO webpack 6: remove
  2150. // For backward-compat
  2151. if (result.module === undefined && result instanceof Module) {
  2152. result = {
  2153. module: result
  2154. };
  2155. }
  2156. if (!factoryResult) {
  2157. const {
  2158. fileDependencies,
  2159. contextDependencies,
  2160. missingDependencies
  2161. } = result;
  2162. if (fileDependencies) {
  2163. this.fileDependencies.addAll(fileDependencies);
  2164. }
  2165. if (contextDependencies) {
  2166. this.contextDependencies.addAll(contextDependencies);
  2167. }
  2168. if (missingDependencies) {
  2169. this.missingDependencies.addAll(missingDependencies);
  2170. }
  2171. }
  2172. }
  2173. if (err) {
  2174. const notFoundError = new (getModuleNotFoundError())(
  2175. originModule,
  2176. err,
  2177. /** @type {DependencyLocation} */
  2178. (dependencies.map((d) => d.loc).find(Boolean))
  2179. );
  2180. return callback(notFoundError, factoryResult ? result : undefined);
  2181. }
  2182. if (!result) {
  2183. return callback();
  2184. }
  2185. if (currentProfile !== undefined) {
  2186. currentProfile.markFactoryEnd();
  2187. }
  2188. callback(null, factoryResult ? result : result.module);
  2189. }
  2190. );
  2191. }
  2192. /**
  2193. * Processes the provided module callback.
  2194. * @overload
  2195. * @param {FactorizeModuleOptions & { factoryResult?: false }} options options
  2196. * @param {ModuleCallback} callback callback
  2197. * @returns {void}
  2198. */
  2199. /**
  2200. * Processes the provided module factory result callback.
  2201. * @overload
  2202. * @param {FactorizeModuleOptions & { factoryResult: true }} options options
  2203. * @param {ModuleFactoryResultCallback} callback callback
  2204. * @returns {void}
  2205. */
  2206. /**
  2207. * Processes the provided |.
  2208. * @param {FactorizeModuleOptions & { factoryResult?: false } | FactorizeModuleOptions & { factoryResult: true }} options options
  2209. * @param {ModuleCallback | ModuleFactoryResultCallback} callback callback
  2210. */
  2211. factorizeModule(options, callback) {
  2212. this.factorizeQueue.add(
  2213. options,
  2214. /** @type {ModuleOrModuleFactoryResultCallback} */
  2215. (callback)
  2216. );
  2217. }
  2218. /**
  2219. * Defines the handle module creation options type used by this module.
  2220. * @typedef {object} HandleModuleCreationOptions
  2221. * @property {ModuleFactory} factory
  2222. * @property {Dependency[]} dependencies
  2223. * @property {Module | null} originModule
  2224. * @property {Partial<ModuleFactoryCreateDataContextInfo>=} contextInfo
  2225. * @property {string=} context
  2226. * @property {boolean=} recursive recurse into dependencies of the created module
  2227. * @property {boolean=} connectOrigin connect the resolved module with the origin module
  2228. * @property {boolean=} checkCycle check the cycle dependencies of the created module
  2229. */
  2230. /**
  2231. * Handle module creation.
  2232. * @param {HandleModuleCreationOptions} options options object
  2233. * @param {ModuleCallback} callback callback
  2234. * @returns {void}
  2235. */
  2236. handleModuleCreation(
  2237. {
  2238. factory,
  2239. dependencies,
  2240. originModule,
  2241. contextInfo,
  2242. context,
  2243. recursive = true,
  2244. connectOrigin = recursive,
  2245. checkCycle = !recursive
  2246. },
  2247. callback
  2248. ) {
  2249. const moduleGraph = this.moduleGraph;
  2250. const currentProfile = this.profile ? new ModuleProfile() : undefined;
  2251. this.factorizeModule(
  2252. {
  2253. currentProfile,
  2254. factory,
  2255. dependencies,
  2256. factoryResult: true,
  2257. originModule,
  2258. contextInfo,
  2259. context
  2260. },
  2261. (err, factoryResult) => {
  2262. const applyFactoryResultDependencies = () => {
  2263. const { fileDependencies, contextDependencies, missingDependencies } =
  2264. /** @type {ModuleFactoryResult} */ (factoryResult);
  2265. if (fileDependencies) {
  2266. this.fileDependencies.addAll(fileDependencies);
  2267. }
  2268. if (contextDependencies) {
  2269. this.contextDependencies.addAll(contextDependencies);
  2270. }
  2271. if (missingDependencies) {
  2272. this.missingDependencies.addAll(missingDependencies);
  2273. }
  2274. };
  2275. if (err) {
  2276. if (factoryResult) applyFactoryResultDependencies();
  2277. if (dependencies.every((d) => d.optional)) {
  2278. this.warnings.push(err);
  2279. return callback();
  2280. }
  2281. this.errors.push(err);
  2282. return callback(err);
  2283. }
  2284. const newModule =
  2285. /** @type {ModuleFactoryResult} */
  2286. (factoryResult).module;
  2287. if (!newModule) {
  2288. applyFactoryResultDependencies();
  2289. return callback();
  2290. }
  2291. if (currentProfile !== undefined) {
  2292. moduleGraph.setProfile(newModule, currentProfile);
  2293. }
  2294. this.addModule(newModule, (err, _module) => {
  2295. if (err) {
  2296. applyFactoryResultDependencies();
  2297. if (!err.module) {
  2298. err.module = _module;
  2299. }
  2300. this.errors.push(err);
  2301. return callback(err);
  2302. }
  2303. const module =
  2304. /** @type {ModuleWithRestoreFromUnsafeCache} */
  2305. (_module);
  2306. if (
  2307. this._unsafeCache &&
  2308. /** @type {ModuleFactoryResult} */
  2309. (factoryResult).cacheable !== false &&
  2310. module.restoreFromUnsafeCache &&
  2311. this._unsafeCachePredicate(module)
  2312. ) {
  2313. const unsafeCacheableModule =
  2314. /** @type {ModuleWithRestoreFromUnsafeCache} */
  2315. (module);
  2316. for (const dependency of dependencies) {
  2317. moduleGraph.setResolvedModule(
  2318. connectOrigin ? originModule : null,
  2319. dependency,
  2320. unsafeCacheableModule
  2321. );
  2322. unsafeCacheDependencies.set(dependency, unsafeCacheableModule);
  2323. }
  2324. if (!unsafeCacheData.has(unsafeCacheableModule)) {
  2325. unsafeCacheData.set(
  2326. unsafeCacheableModule,
  2327. unsafeCacheableModule.getUnsafeCacheData()
  2328. );
  2329. }
  2330. } else {
  2331. applyFactoryResultDependencies();
  2332. for (const dependency of dependencies) {
  2333. moduleGraph.setResolvedModule(
  2334. connectOrigin ? originModule : null,
  2335. dependency,
  2336. module
  2337. );
  2338. }
  2339. }
  2340. moduleGraph.setIssuerIfUnset(
  2341. module,
  2342. originModule !== undefined ? originModule : null
  2343. );
  2344. if (module !== newModule && currentProfile !== undefined) {
  2345. const otherProfile = moduleGraph.getProfile(module);
  2346. if (otherProfile !== undefined) {
  2347. currentProfile.mergeInto(otherProfile);
  2348. } else {
  2349. moduleGraph.setProfile(module, currentProfile);
  2350. }
  2351. }
  2352. this._handleModuleBuildAndDependencies(
  2353. originModule,
  2354. module,
  2355. recursive,
  2356. checkCycle,
  2357. dependencies,
  2358. callback
  2359. );
  2360. });
  2361. }
  2362. );
  2363. }
  2364. /**
  2365. * Handle module build and dependencies.
  2366. * @private
  2367. * @param {Module | null} originModule original module
  2368. * @param {Module} module module
  2369. * @param {boolean} recursive true if make it recursive, otherwise false
  2370. * @param {boolean} checkCycle true if need to check cycle, otherwise false
  2371. * @param {Dependency[]} dependencies the dependencies that resolved to the module (lazy barrel)
  2372. * @param {ModuleCallback} callback callback
  2373. * @returns {void}
  2374. */
  2375. _handleModuleBuildAndDependencies(
  2376. originModule,
  2377. module,
  2378. recursive,
  2379. checkCycle,
  2380. dependencies,
  2381. callback
  2382. ) {
  2383. // Check for cycles when build is trigger inside another build
  2384. /** @type {Set<Module> | undefined} */
  2385. let creatingModuleDuringBuildSet;
  2386. if (
  2387. checkCycle &&
  2388. this.buildQueue.isProcessing(/** @type {Module} */ (originModule))
  2389. ) {
  2390. // Track build dependency
  2391. creatingModuleDuringBuildSet = this.creatingModuleDuringBuild.get(
  2392. /** @type {Module} */
  2393. (originModule)
  2394. );
  2395. if (creatingModuleDuringBuildSet === undefined) {
  2396. /** @type {Set<Module>} */
  2397. creatingModuleDuringBuildSet = new Set();
  2398. this.creatingModuleDuringBuild.set(
  2399. /** @type {Module} */
  2400. (originModule),
  2401. creatingModuleDuringBuildSet
  2402. );
  2403. }
  2404. creatingModuleDuringBuildSet.add(module);
  2405. // When building is blocked by another module
  2406. // search for a cycle, cancel the cycle by throwing
  2407. // an error (otherwise this would deadlock)
  2408. const blockReasons = this.creatingModuleDuringBuild.get(module);
  2409. if (blockReasons !== undefined) {
  2410. const set = new Set(blockReasons);
  2411. for (const item of set) {
  2412. const blockReasons = this.creatingModuleDuringBuild.get(item);
  2413. if (blockReasons !== undefined) {
  2414. for (const m of blockReasons) {
  2415. if (m === module) {
  2416. return callback(new (getBuildCycleError())(module));
  2417. }
  2418. set.add(m);
  2419. }
  2420. }
  2421. }
  2422. }
  2423. }
  2424. this.buildModule(module, (err) => {
  2425. if (creatingModuleDuringBuildSet !== undefined) {
  2426. creatingModuleDuringBuildSet.delete(module);
  2427. }
  2428. if (err) {
  2429. if (!err.module) {
  2430. err.module = module;
  2431. }
  2432. this.errors.push(err);
  2433. return callback(err);
  2434. }
  2435. if (!recursive) {
  2436. this.processModuleDependenciesNonRecursive(module);
  2437. callback(null, module);
  2438. return;
  2439. }
  2440. // lazy barrel:
  2441. // 1. first call: barrel module is not classified yet, so this records the requested
  2442. // ids and returns undefined; the targets get built below when
  2443. // `processModuleDependencies` runs `_lazyBarrelController.classify` and replays them.
  2444. // 2. later call: barrel module is already built, so `processModuleDependencies` won't
  2445. // re-walk it; the newly requested targets must be built here.
  2446. const unlazyItems = this._lazyBarrelController.request(
  2447. module,
  2448. dependencies
  2449. );
  2450. if (unlazyItems !== undefined) {
  2451. let inProgress = unlazyItems.length + 1; // +1 = the module's own dep processing
  2452. let errored = false;
  2453. /**
  2454. * @param {(WebpackError | null)=} err error
  2455. * @returns {void}
  2456. */
  2457. const onJobDone = (err) => {
  2458. if (errored) return;
  2459. if (err) {
  2460. errored = true;
  2461. return callback(err);
  2462. }
  2463. if (--inProgress === 0) callback(null, module);
  2464. };
  2465. for (const item of unlazyItems) {
  2466. this.handleModuleCreation(item, (err) => {
  2467. onJobDone(err && this.bail ? err : null);
  2468. });
  2469. }
  2470. if (this.processDependenciesQueue.isProcessing(module)) {
  2471. onJobDone();
  2472. } else {
  2473. this.processModuleDependencies(module, onJobDone);
  2474. }
  2475. } else {
  2476. // This avoids deadlocks for circular dependencies
  2477. if (this.processDependenciesQueue.isProcessing(module)) {
  2478. return callback(null, module);
  2479. }
  2480. this.processModuleDependencies(module, (err) => {
  2481. if (err) {
  2482. return callback(err);
  2483. }
  2484. callback(null, module);
  2485. });
  2486. }
  2487. });
  2488. }
  2489. /**
  2490. * Adds the provided string to the compilation.
  2491. * @param {string} context context string path
  2492. * @param {Dependency} dependency dependency used to create Module chain
  2493. * @param {ModuleCallback} callback callback for when module chain is complete
  2494. * @returns {void} will throw if dependency instance is not a valid Dependency
  2495. */
  2496. addModuleChain(context, dependency, callback) {
  2497. return this.addModuleTree({ context, dependency }, callback);
  2498. }
  2499. /**
  2500. * Adds the provided object to the compilation.
  2501. * @param {object} options options
  2502. * @param {string} options.context context string path
  2503. * @param {Dependency} options.dependency dependency used to create Module chain
  2504. * @param {Partial<ModuleFactoryCreateDataContextInfo>=} options.contextInfo additional context info for the root module
  2505. * @param {ModuleCallback} callback callback for when module chain is complete
  2506. * @returns {void} will throw if dependency instance is not a valid Dependency
  2507. */
  2508. addModuleTree({ context, dependency, contextInfo }, callback) {
  2509. if (
  2510. typeof dependency !== "object" ||
  2511. dependency === null ||
  2512. !dependency.constructor
  2513. ) {
  2514. return callback(
  2515. new WebpackError("Parameter 'dependency' must be a Dependency")
  2516. );
  2517. }
  2518. const Dep =
  2519. /** @type {DependencyConstructor} */
  2520. (dependency.constructor);
  2521. const moduleFactory = this.dependencyFactories.get(Dep);
  2522. if (!moduleFactory) {
  2523. return callback(
  2524. new WebpackError(
  2525. `No dependency factory available for this dependency type: ${dependency.constructor.name}`
  2526. )
  2527. );
  2528. }
  2529. this.handleModuleCreation(
  2530. {
  2531. factory: moduleFactory,
  2532. dependencies: [dependency],
  2533. originModule: null,
  2534. contextInfo,
  2535. context
  2536. },
  2537. (err, result) => {
  2538. if (err && this.bail) {
  2539. callback(err);
  2540. this.buildQueue.stop();
  2541. this.rebuildQueue.stop();
  2542. this.processDependenciesQueue.stop();
  2543. this.factorizeQueue.stop();
  2544. } else if (!err && result) {
  2545. callback(null, result);
  2546. } else {
  2547. callback();
  2548. }
  2549. }
  2550. );
  2551. }
  2552. /**
  2553. * Adds the provided string to the compilation.
  2554. * @param {string} context context path for entry
  2555. * @param {Dependency} entry entry dependency that should be followed
  2556. * @param {string | EntryOptions} optionsOrName options or deprecated name of entry
  2557. * @param {ModuleCallback} callback callback function
  2558. * @returns {void} returns
  2559. */
  2560. addEntry(context, entry, optionsOrName, callback) {
  2561. // TODO webpack 6 remove
  2562. const options =
  2563. typeof optionsOrName === "object"
  2564. ? optionsOrName
  2565. : { name: optionsOrName };
  2566. this._addEntryItem(context, entry, "dependencies", options, callback);
  2567. }
  2568. /**
  2569. * Adds the provided string to the compilation.
  2570. * @param {string} context context path for entry
  2571. * @param {Dependency} dependency dependency that should be followed
  2572. * @param {EntryOptions} options options
  2573. * @param {ModuleCallback} callback callback function
  2574. * @returns {void} returns
  2575. */
  2576. addInclude(context, dependency, options, callback) {
  2577. this._addEntryItem(
  2578. context,
  2579. dependency,
  2580. "includeDependencies",
  2581. options,
  2582. callback
  2583. );
  2584. }
  2585. /**
  2586. * Adds the provided string to the compilation.
  2587. * @param {string} context context path for entry
  2588. * @param {Dependency} entry entry dependency that should be followed
  2589. * @param {"dependencies" | "includeDependencies"} target type of entry
  2590. * @param {EntryOptions} options options
  2591. * @param {ModuleCallback} callback callback function
  2592. * @returns {void} returns
  2593. */
  2594. _addEntryItem(context, entry, target, options, callback) {
  2595. const { name } = options;
  2596. /** @type {EntryData | undefined} */
  2597. let entryData =
  2598. name !== undefined ? this.entries.get(name) : this.globalEntry;
  2599. if (entryData === undefined) {
  2600. entryData = {
  2601. dependencies: [],
  2602. includeDependencies: [],
  2603. options: {
  2604. name: undefined,
  2605. ...options
  2606. }
  2607. };
  2608. entryData[target].push(entry);
  2609. this.entries.set(
  2610. /** @type {NonNullable<EntryOptions["name"]>} */
  2611. (name),
  2612. entryData
  2613. );
  2614. } else {
  2615. entryData[target].push(entry);
  2616. for (const key_ of Object.keys(options)) {
  2617. const key = /** @type {keyof EntryOptions} */ (key_);
  2618. if (options[key] === undefined) continue;
  2619. if (entryData.options[key] === options[key]) continue;
  2620. if (
  2621. Array.isArray(entryData.options[key]) &&
  2622. Array.isArray(options[key]) &&
  2623. arrayEquals(entryData.options[key], options[key])
  2624. ) {
  2625. continue;
  2626. }
  2627. if (entryData.options[key] === undefined) {
  2628. /** @type {EntryOptions[keyof EntryOptions]} */
  2629. (entryData.options[key]) = options[key];
  2630. } else {
  2631. return callback(
  2632. new WebpackError(
  2633. `Conflicting entry option ${key} = ${entryData.options[key]} vs ${options[key]}`
  2634. )
  2635. );
  2636. }
  2637. }
  2638. }
  2639. this.hooks.addEntry.call(entry, options);
  2640. this.addModuleTree(
  2641. {
  2642. context,
  2643. dependency: entry,
  2644. contextInfo: entryData.options.layer
  2645. ? { issuerLayer: entryData.options.layer }
  2646. : undefined
  2647. },
  2648. (err, module) => {
  2649. if (err) {
  2650. this.hooks.failedEntry.call(entry, options, err);
  2651. return callback(err);
  2652. }
  2653. this.hooks.succeedEntry.call(
  2654. entry,
  2655. options,
  2656. /** @type {Module} */
  2657. (module)
  2658. );
  2659. return callback(null, module);
  2660. }
  2661. );
  2662. }
  2663. /**
  2664. * Processes the provided module.
  2665. * @param {Module} module module to be rebuilt
  2666. * @param {ModuleCallback} callback callback when module finishes rebuilding
  2667. * @returns {void}
  2668. */
  2669. rebuildModule(module, callback) {
  2670. this.rebuildQueue.add(module, callback);
  2671. }
  2672. /**
  2673. * Processes the provided module.
  2674. * @param {Module} module module to be rebuilt
  2675. * @param {ModuleCallback} callback callback when module finishes rebuilding
  2676. * @returns {void}
  2677. */
  2678. _rebuildModule(module, callback) {
  2679. this.hooks.rebuildModule.call(module);
  2680. const oldDependencies = [...module.dependencies];
  2681. const oldBlocks = [...module.blocks];
  2682. module.invalidateBuild();
  2683. this.buildQueue.invalidate(module);
  2684. this.buildModule(module, (err) => {
  2685. if (err) {
  2686. return this.hooks.finishRebuildingModule.callAsync(module, (err2) => {
  2687. if (err2) {
  2688. callback(
  2689. makeWebpackError(err2, "Compilation.hooks.finishRebuildingModule")
  2690. );
  2691. return;
  2692. }
  2693. callback(err);
  2694. });
  2695. }
  2696. this.processDependenciesQueue.invalidate(module);
  2697. this.moduleGraph.unfreeze();
  2698. this.processModuleDependencies(module, (err) => {
  2699. if (err) return callback(err);
  2700. this.removeReasonsOfDependencyBlock(module, {
  2701. dependencies: oldDependencies,
  2702. blocks: oldBlocks
  2703. });
  2704. this.hooks.finishRebuildingModule.callAsync(module, (err2) => {
  2705. if (err2) {
  2706. callback(
  2707. makeWebpackError(err2, "Compilation.hooks.finishRebuildingModule")
  2708. );
  2709. return;
  2710. }
  2711. callback(null, module);
  2712. });
  2713. });
  2714. });
  2715. }
  2716. /**
  2717. * Compute affected modules.
  2718. * @private
  2719. * @param {Set<Module>} modules modules
  2720. */
  2721. _computeAffectedModules(modules) {
  2722. const moduleMemCacheCache = this.compiler.moduleMemCaches;
  2723. if (!moduleMemCacheCache) return;
  2724. if (!this.moduleMemCaches) {
  2725. this.moduleMemCaches = new Map();
  2726. this.moduleGraph.setModuleMemCaches(this.moduleMemCaches);
  2727. }
  2728. const { moduleGraph, moduleMemCaches } = this;
  2729. /** @type {Set<Module>} */
  2730. const affectedModules = new Set();
  2731. /** @type {Set<Module>} */
  2732. const infectedModules = new Set();
  2733. let statNew = 0;
  2734. let statChanged = 0;
  2735. let statUnchanged = 0;
  2736. let statReferencesChanged = 0;
  2737. let statWithoutBuild = 0;
  2738. /**
  2739. * Compute references.
  2740. * @param {Module} module module
  2741. * @returns {WeakReferences | undefined} references
  2742. */
  2743. const computeReferences = (module) => {
  2744. /** @type {WeakReferences | undefined} */
  2745. let references;
  2746. for (const connection of moduleGraph.getOutgoingConnections(module)) {
  2747. const d = connection.dependency;
  2748. const m = connection.module;
  2749. if (!d || !m || unsafeCacheDependencies.has(d)) continue;
  2750. if (references === undefined) references = new WeakMap();
  2751. references.set(d, m);
  2752. }
  2753. return references;
  2754. };
  2755. /**
  2756. * Compares references.
  2757. * @param {Module} module the module
  2758. * @param {WeakReferences | undefined} references references
  2759. * @returns {boolean} true, when the references differ
  2760. */
  2761. const compareReferences = (module, references) => {
  2762. if (references === undefined) return true;
  2763. for (const connection of moduleGraph.getOutgoingConnections(module)) {
  2764. const d = connection.dependency;
  2765. if (!d) continue;
  2766. const entry = references.get(d);
  2767. if (entry === undefined) continue;
  2768. if (entry !== connection.module) return false;
  2769. }
  2770. return true;
  2771. };
  2772. const modulesWithoutCache = new Set(modules);
  2773. for (const [module, cachedMemCache] of moduleMemCacheCache) {
  2774. if (modulesWithoutCache.has(module)) {
  2775. const buildInfo = module.buildInfo;
  2776. if (buildInfo) {
  2777. if (cachedMemCache.buildInfo !== buildInfo) {
  2778. // use a new one
  2779. /** @type {MemCache} */
  2780. const memCache = new WeakTupleMap();
  2781. moduleMemCaches.set(module, memCache);
  2782. affectedModules.add(module);
  2783. cachedMemCache.buildInfo = buildInfo;
  2784. cachedMemCache.references = computeReferences(module);
  2785. cachedMemCache.memCache = memCache;
  2786. statChanged++;
  2787. } else if (!compareReferences(module, cachedMemCache.references)) {
  2788. // use a new one
  2789. /** @type {MemCache} */
  2790. const memCache = new WeakTupleMap();
  2791. moduleMemCaches.set(module, memCache);
  2792. affectedModules.add(module);
  2793. cachedMemCache.references = computeReferences(module);
  2794. cachedMemCache.memCache = memCache;
  2795. statReferencesChanged++;
  2796. } else {
  2797. // keep the old mem cache
  2798. moduleMemCaches.set(module, cachedMemCache.memCache);
  2799. statUnchanged++;
  2800. }
  2801. } else {
  2802. infectedModules.add(module);
  2803. moduleMemCacheCache.delete(module);
  2804. statWithoutBuild++;
  2805. }
  2806. modulesWithoutCache.delete(module);
  2807. } else {
  2808. moduleMemCacheCache.delete(module);
  2809. }
  2810. }
  2811. for (const module of modulesWithoutCache) {
  2812. const buildInfo = module.buildInfo;
  2813. if (buildInfo) {
  2814. // create a new entry
  2815. const memCache = new WeakTupleMap();
  2816. moduleMemCacheCache.set(module, {
  2817. buildInfo,
  2818. references: computeReferences(module),
  2819. memCache
  2820. });
  2821. moduleMemCaches.set(module, memCache);
  2822. affectedModules.add(module);
  2823. statNew++;
  2824. } else {
  2825. infectedModules.add(module);
  2826. statWithoutBuild++;
  2827. }
  2828. }
  2829. /** @type {Set<Module>} */
  2830. const directOnlyInfectedModules = new Set();
  2831. for (const module of infectedModules) {
  2832. for (const [
  2833. referencingModule,
  2834. connections
  2835. ] of moduleGraph.getIncomingConnectionsByOriginModule(module)) {
  2836. if (!referencingModule) continue;
  2837. if (infectedModules.has(referencingModule)) continue;
  2838. const type = reduceAffectType(connections);
  2839. if (!type) continue;
  2840. if (type === true) {
  2841. directOnlyInfectedModules.add(referencingModule);
  2842. } else {
  2843. infectedModules.add(referencingModule);
  2844. }
  2845. }
  2846. }
  2847. for (const module of directOnlyInfectedModules) infectedModules.add(module);
  2848. /** @type {Set<Module>} */
  2849. const directOnlyAffectModules = new Set();
  2850. for (const module of affectedModules) {
  2851. for (const [
  2852. referencingModule,
  2853. connections
  2854. ] of moduleGraph.getIncomingConnectionsByOriginModule(module)) {
  2855. if (!referencingModule) continue;
  2856. if (infectedModules.has(referencingModule)) continue;
  2857. if (affectedModules.has(referencingModule)) continue;
  2858. const type = reduceAffectType(connections);
  2859. if (!type) continue;
  2860. if (type === true) {
  2861. directOnlyAffectModules.add(referencingModule);
  2862. } else {
  2863. affectedModules.add(referencingModule);
  2864. }
  2865. /** @type {MemCache} */
  2866. const memCache = new WeakTupleMap();
  2867. const cache =
  2868. /** @type {ModuleMemCachesItem} */
  2869. (moduleMemCacheCache.get(referencingModule));
  2870. cache.memCache = memCache;
  2871. moduleMemCaches.set(referencingModule, memCache);
  2872. }
  2873. }
  2874. for (const module of directOnlyAffectModules) affectedModules.add(module);
  2875. this.logger.log(
  2876. `${Math.round(
  2877. (100 * (affectedModules.size + infectedModules.size)) /
  2878. this.modules.size
  2879. )}% (${affectedModules.size} affected + ${
  2880. infectedModules.size
  2881. } infected of ${
  2882. this.modules.size
  2883. }) modules flagged as affected (${statNew} new modules, ${statChanged} changed, ${statReferencesChanged} references changed, ${statUnchanged} unchanged, ${statWithoutBuild} were not built)`
  2884. );
  2885. }
  2886. _computeAffectedModulesWithChunkGraph() {
  2887. const { moduleMemCaches } = this;
  2888. if (!moduleMemCaches) return;
  2889. const moduleMemCaches2 = (this.moduleMemCaches2 = new Map());
  2890. const { moduleGraph, chunkGraph } = this;
  2891. const key = "memCache2";
  2892. let statUnchanged = 0;
  2893. let statChanged = 0;
  2894. let statNew = 0;
  2895. /**
  2896. * Compute references.
  2897. * @param {Module} module module
  2898. * @returns {References} references
  2899. */
  2900. const computeReferences = (module) => {
  2901. const id = /** @type {ModuleId} */ (chunkGraph.getModuleId(module));
  2902. /** @type {Map<Module, ModuleId> | undefined} */
  2903. let modules;
  2904. /** @type {(ChunkId | null)[] | undefined} */
  2905. let blocks;
  2906. const outgoing = moduleGraph.getOutgoingConnectionsByModule(module);
  2907. if (outgoing !== undefined) {
  2908. for (const m of outgoing.keys()) {
  2909. if (!m) continue;
  2910. if (modules === undefined) modules = new Map();
  2911. modules.set(m, /** @type {ModuleId} */ (chunkGraph.getModuleId(m)));
  2912. }
  2913. }
  2914. if (module.blocks.length > 0) {
  2915. blocks = [];
  2916. const queue = [...module.blocks];
  2917. for (const block of queue) {
  2918. const chunkGroup = chunkGraph.getBlockChunkGroup(block);
  2919. if (chunkGroup) {
  2920. for (const chunk of chunkGroup.chunks) {
  2921. blocks.push(chunk.id);
  2922. }
  2923. } else {
  2924. blocks.push(null);
  2925. }
  2926. // eslint-disable-next-line prefer-spread
  2927. queue.push.apply(queue, block.blocks);
  2928. }
  2929. }
  2930. return {
  2931. id,
  2932. modules,
  2933. blocks,
  2934. sourceTypes: module.getReferencedSourceTypes()
  2935. };
  2936. };
  2937. /**
  2938. * Compares references.
  2939. * @param {Module} module module
  2940. * @param {object} references references
  2941. * @param {string | number} references.id id
  2942. * @param {Map<Module, string | number | undefined>=} references.modules modules
  2943. * @param {(string | number | null)[]=} references.blocks blocks
  2944. * @param {SourceTypes=} references.sourceTypes connection-dependent source types
  2945. * @returns {boolean} ok?
  2946. */
  2947. const compareReferences = (
  2948. module,
  2949. { id, modules, blocks, sourceTypes }
  2950. ) => {
  2951. if (id !== chunkGraph.getModuleId(module)) return false;
  2952. if (modules !== undefined) {
  2953. for (const [module, id] of modules) {
  2954. if (chunkGraph.getModuleId(module) !== id) return false;
  2955. }
  2956. }
  2957. if (blocks !== undefined) {
  2958. const queue = [...module.blocks];
  2959. let i = 0;
  2960. for (const block of queue) {
  2961. const chunkGroup = chunkGraph.getBlockChunkGroup(block);
  2962. if (chunkGroup) {
  2963. for (const chunk of chunkGroup.chunks) {
  2964. if (i >= blocks.length || blocks[i++] !== chunk.id) return false;
  2965. }
  2966. } else if (i >= blocks.length || blocks[i++] !== null) {
  2967. return false;
  2968. }
  2969. // eslint-disable-next-line prefer-spread
  2970. queue.push.apply(queue, block.blocks);
  2971. }
  2972. if (i !== blocks.length) return false;
  2973. }
  2974. // getReferencedSourceTypes() returns interned type sets, compare by reference. #20800
  2975. if (
  2976. sourceTypes !== undefined &&
  2977. module.getReferencedSourceTypes() !== sourceTypes
  2978. ) {
  2979. return false;
  2980. }
  2981. return true;
  2982. };
  2983. for (const [module, memCache] of moduleMemCaches) {
  2984. /** @type {{ references: References, memCache: MemCache } | undefined} */
  2985. const cache = memCache.get(key);
  2986. if (cache === undefined) {
  2987. /** @type {WeakTupleMap<Module[], RuntimeRequirements | null> | undefined} */
  2988. const memCache2 = new WeakTupleMap();
  2989. memCache.set(key, {
  2990. references: computeReferences(module),
  2991. memCache: memCache2
  2992. });
  2993. moduleMemCaches2.set(module, memCache2);
  2994. statNew++;
  2995. } else if (!compareReferences(module, cache.references)) {
  2996. /** @type {WeakTupleMap<Module[], RuntimeRequirements | null> | undefined} */
  2997. const memCache = new WeakTupleMap();
  2998. cache.references = computeReferences(module);
  2999. cache.memCache = memCache;
  3000. moduleMemCaches2.set(module, memCache);
  3001. statChanged++;
  3002. } else {
  3003. moduleMemCaches2.set(module, cache.memCache);
  3004. statUnchanged++;
  3005. }
  3006. }
  3007. this.logger.log(
  3008. `${Math.round(
  3009. (100 * statChanged) / (statNew + statChanged + statUnchanged)
  3010. )}% modules flagged as affected by chunk graph (${statNew} new modules, ${statChanged} changed, ${statUnchanged} unchanged)`
  3011. );
  3012. }
  3013. /**
  3014. * Assigns a fresh dependency report cache token to every module whose
  3015. * dependency errors/warnings could have changed since the previous
  3016. * compilation: built modules and their (transitive) parents.
  3017. * @private
  3018. * @param {Set<Module>} modules modules
  3019. * @returns {void}
  3020. */
  3021. _flagModulesForDependencyReporting(modules) {
  3022. /** @type {DependencyReportCacheToken} */
  3023. const token = {};
  3024. const { moduleGraph, builtModules } = this;
  3025. /** @type {Set<Module>} */
  3026. const updatedModules = new Set();
  3027. for (const module of modules) {
  3028. if (
  3029. builtModules.has(module) ||
  3030. !dependencyReportCacheTokens.has(module)
  3031. ) {
  3032. updatedModules.add(module);
  3033. }
  3034. }
  3035. // skip the parent walk when everything is updated anyway (initial build)
  3036. if (updatedModules.size !== modules.size) {
  3037. /** @type {Set<Module>} */
  3038. const directOnlyUpdatedModules = new Set();
  3039. for (const module of updatedModules) {
  3040. for (const [
  3041. referencingModule,
  3042. connections
  3043. ] of moduleGraph.getIncomingConnectionsByOriginModule(module)) {
  3044. if (!referencingModule) continue;
  3045. if (updatedModules.has(referencingModule)) continue;
  3046. const type = reduceAffectType(connections);
  3047. if (!type) continue;
  3048. if (type === true) {
  3049. directOnlyUpdatedModules.add(referencingModule);
  3050. } else {
  3051. updatedModules.add(referencingModule);
  3052. }
  3053. }
  3054. }
  3055. for (const module of directOnlyUpdatedModules) {
  3056. updatedModules.add(module);
  3057. }
  3058. }
  3059. for (const module of updatedModules) {
  3060. dependencyReportCacheTokens.set(module, token);
  3061. }
  3062. }
  3063. /**
  3064. * Processes the provided callback.
  3065. * @param {Callback} callback callback
  3066. */
  3067. finish(callback) {
  3068. this.factorizeQueue.clear();
  3069. if (this.profile) {
  3070. this.logger.time("finish module profiles");
  3071. const ParallelismFactorCalculator = require("./util/ParallelismFactorCalculator");
  3072. const p = new ParallelismFactorCalculator();
  3073. const moduleGraph = this.moduleGraph;
  3074. /** @type {Map<Module, ModuleProfile>} */
  3075. const modulesWithProfiles = new Map();
  3076. for (const module of this.modules) {
  3077. const profile = moduleGraph.getProfile(module);
  3078. if (!profile) continue;
  3079. modulesWithProfiles.set(module, profile);
  3080. p.range(
  3081. profile.buildingStartTime,
  3082. profile.buildingEndTime,
  3083. (f) => (profile.buildingParallelismFactor = f)
  3084. );
  3085. p.range(
  3086. profile.factoryStartTime,
  3087. profile.factoryEndTime,
  3088. (f) => (profile.factoryParallelismFactor = f)
  3089. );
  3090. p.range(
  3091. profile.integrationStartTime,
  3092. profile.integrationEndTime,
  3093. (f) => (profile.integrationParallelismFactor = f)
  3094. );
  3095. p.range(
  3096. profile.storingStartTime,
  3097. profile.storingEndTime,
  3098. (f) => (profile.storingParallelismFactor = f)
  3099. );
  3100. p.range(
  3101. profile.restoringStartTime,
  3102. profile.restoringEndTime,
  3103. (f) => (profile.restoringParallelismFactor = f)
  3104. );
  3105. if (profile.additionalFactoryTimes) {
  3106. for (const { start, end } of profile.additionalFactoryTimes) {
  3107. const influence = (end - start) / profile.additionalFactories;
  3108. p.range(
  3109. start,
  3110. end,
  3111. (f) =>
  3112. (profile.additionalFactoriesParallelismFactor += f * influence)
  3113. );
  3114. }
  3115. }
  3116. }
  3117. p.calculate();
  3118. const logger = this.getLogger("webpack.Compilation.ModuleProfile");
  3119. // Avoid coverage problems due indirect changes
  3120. /**
  3121. * Processes the provided value.
  3122. * @param {number} value value
  3123. * @param {string} msg message
  3124. */
  3125. /* istanbul ignore next */
  3126. const logByValue = (value, msg) => {
  3127. if (value > 1000) {
  3128. logger.error(msg);
  3129. } else if (value > 500) {
  3130. logger.warn(msg);
  3131. } else if (value > 200) {
  3132. logger.info(msg);
  3133. } else if (value > 30) {
  3134. logger.log(msg);
  3135. } else {
  3136. logger.debug(msg);
  3137. }
  3138. };
  3139. /**
  3140. * Log normal summary.
  3141. * @param {string} category a category
  3142. * @param {(profile: ModuleProfile) => number} getDuration get duration callback
  3143. * @param {(profile: ModuleProfile) => number} getParallelism get parallelism callback
  3144. */
  3145. const logNormalSummary = (category, getDuration, getParallelism) => {
  3146. let sum = 0;
  3147. let max = 0;
  3148. for (const [module, profile] of modulesWithProfiles) {
  3149. const p = getParallelism(profile);
  3150. const d = getDuration(profile);
  3151. if (d === 0 || p === 0) continue;
  3152. const t = d / p;
  3153. sum += t;
  3154. if (t <= 10) continue;
  3155. logByValue(
  3156. t,
  3157. ` | ${Math.round(t)} ms${
  3158. p >= 1.1 ? ` (parallelism ${Math.round(p * 10) / 10})` : ""
  3159. } ${category} > ${module.readableIdentifier(this.requestShortener)}`
  3160. );
  3161. max = Math.max(max, t);
  3162. }
  3163. if (sum <= 10) return;
  3164. logByValue(
  3165. Math.max(sum / 10, max),
  3166. `${Math.round(sum)} ms ${category}`
  3167. );
  3168. };
  3169. /**
  3170. * Log by loaders summary.
  3171. * @param {string} category a category
  3172. * @param {(profile: ModuleProfile) => number} getDuration get duration callback
  3173. * @param {(profile: ModuleProfile) => number} getParallelism get parallelism callback
  3174. */
  3175. const logByLoadersSummary = (category, getDuration, getParallelism) => {
  3176. /** @type {Map<string, { module: Module, profile: ModuleProfile }[]>} */
  3177. const map = new Map();
  3178. for (const [module, profile] of modulesWithProfiles) {
  3179. const list = getOrInsert(
  3180. map,
  3181. `${module.type}!${module.identifier().replace(/(!|^)[^!]*$/, "")}`,
  3182. () => []
  3183. );
  3184. list.push({ module, profile });
  3185. }
  3186. let sum = 0;
  3187. let max = 0;
  3188. for (const [key, modules] of map) {
  3189. let innerSum = 0;
  3190. let innerMax = 0;
  3191. for (const { module, profile } of modules) {
  3192. const p = getParallelism(profile);
  3193. const d = getDuration(profile);
  3194. if (d === 0 || p === 0) continue;
  3195. const t = d / p;
  3196. innerSum += t;
  3197. /* istanbul ignore next -- @preserve: only slow (>10ms) modules are logged, timing-dependent */
  3198. if (t > 10) {
  3199. logByValue(
  3200. t,
  3201. ` | | ${Math.round(t)} ms${
  3202. p >= 1.1 ? ` (parallelism ${Math.round(p * 10) / 10})` : ""
  3203. } ${category} > ${module.readableIdentifier(
  3204. this.requestShortener
  3205. )}`
  3206. );
  3207. innerMax = Math.max(innerMax, t);
  3208. }
  3209. }
  3210. sum += innerSum;
  3211. if (innerSum <= 10) continue;
  3212. const idx = key.indexOf("!");
  3213. const loaders = key.slice(idx + 1);
  3214. const moduleType = key.slice(0, idx);
  3215. const t = Math.max(innerSum / 10, innerMax);
  3216. logByValue(
  3217. t,
  3218. ` | ${Math.round(innerSum)} ms ${category} > ${
  3219. loaders
  3220. ? `${
  3221. modules.length
  3222. } x ${moduleType} with ${this.requestShortener.shorten(
  3223. loaders
  3224. )}`
  3225. : `${modules.length} x ${moduleType}`
  3226. }`
  3227. );
  3228. max = Math.max(max, t);
  3229. }
  3230. if (sum <= 10) return;
  3231. logByValue(
  3232. Math.max(sum / 10, max),
  3233. `${Math.round(sum)} ms ${category}`
  3234. );
  3235. };
  3236. logNormalSummary(
  3237. "resolve to new modules",
  3238. (p) => p.factory,
  3239. (p) => p.factoryParallelismFactor
  3240. );
  3241. logNormalSummary(
  3242. "resolve to existing modules",
  3243. (p) => p.additionalFactories,
  3244. (p) => p.additionalFactoriesParallelismFactor
  3245. );
  3246. logNormalSummary(
  3247. "integrate modules",
  3248. (p) => p.restoring,
  3249. (p) => p.restoringParallelismFactor
  3250. );
  3251. logByLoadersSummary(
  3252. "build modules",
  3253. (p) => p.building,
  3254. (p) => p.buildingParallelismFactor
  3255. );
  3256. logNormalSummary(
  3257. "store modules",
  3258. (p) => p.storing,
  3259. (p) => p.storingParallelismFactor
  3260. );
  3261. logNormalSummary(
  3262. "restore modules",
  3263. (p) => p.restoring,
  3264. (p) => p.restoringParallelismFactor
  3265. );
  3266. this.logger.timeEnd("finish module profiles");
  3267. }
  3268. this.logger.time("compute affected modules");
  3269. this._computeAffectedModules(this.modules);
  3270. this.logger.timeEnd("compute affected modules");
  3271. this.logger.time("finish modules");
  3272. const { modules, moduleMemCaches } = this;
  3273. this.hooks.finishModules.callAsync(modules, (err) => {
  3274. this.logger.timeEnd("finish modules");
  3275. if (err) return callback(/** @type {WebpackError} */ (err));
  3276. // extract warnings and errors from modules
  3277. this.moduleGraph.freeze("dependency errors");
  3278. this.logger.time("report dependency errors and warnings");
  3279. // moduleMemCaches has its own invalidation (incl. reference changes),
  3280. // so cache tokens are only used without it
  3281. const useReportCacheTokens = moduleMemCaches === undefined;
  3282. if (useReportCacheTokens) {
  3283. this._flagModulesForDependencyReporting(modules);
  3284. }
  3285. for (const module of modules) {
  3286. const memCache = moduleMemCaches && moduleMemCaches.get(module);
  3287. if (memCache && memCache.get("noWarningsOrErrors")) continue;
  3288. let token;
  3289. if (useReportCacheTokens) {
  3290. token = dependencyReportCacheTokens.get(module);
  3291. const cleanModules = modulesWithoutProblems.get(
  3292. /** @type {DependencyReportCacheToken} */ (token)
  3293. );
  3294. if (cleanModules !== undefined && cleanModules.has(module)) continue;
  3295. }
  3296. let hasProblems = this.reportDependencyErrorsAndWarnings(module, [
  3297. module
  3298. ]);
  3299. const errors = /** @type {WebpackError[]} */ (module.getErrors());
  3300. if (errors !== undefined) {
  3301. for (const error of errors) {
  3302. if (!error.module) {
  3303. error.module = module;
  3304. }
  3305. this.errors.push(error);
  3306. hasProblems = true;
  3307. }
  3308. }
  3309. const warnings = /** @type {WebpackError[]} */ (module.getWarnings());
  3310. if (warnings !== undefined) {
  3311. for (const warning of warnings) {
  3312. if (!warning.module) {
  3313. warning.module = module;
  3314. }
  3315. this.warnings.push(warning);
  3316. hasProblems = true;
  3317. }
  3318. }
  3319. if (!hasProblems) {
  3320. if (memCache) memCache.set("noWarningsOrErrors", true);
  3321. if (useReportCacheTokens) {
  3322. let cleanModules = modulesWithoutProblems.get(
  3323. /** @type {DependencyReportCacheToken} */ (token)
  3324. );
  3325. if (cleanModules === undefined) {
  3326. modulesWithoutProblems.set(
  3327. /** @type {DependencyReportCacheToken} */ (token),
  3328. (cleanModules = new WeakSet())
  3329. );
  3330. }
  3331. cleanModules.add(module);
  3332. }
  3333. }
  3334. }
  3335. this.moduleGraph.unfreeze();
  3336. this.logger.timeEnd("report dependency errors and warnings");
  3337. callback();
  3338. });
  3339. }
  3340. unseal() {
  3341. this.hooks.unseal.call();
  3342. this.chunks.clear();
  3343. this.chunkGroups.length = 0;
  3344. this.namedChunks.clear();
  3345. this.namedChunkGroups.clear();
  3346. this.entrypoints.clear();
  3347. this.additionalChunkAssets.length = 0;
  3348. this.assets = {};
  3349. this.assetsInfo.clear();
  3350. this._assetToChunkIndex = undefined;
  3351. this._assetToChunkAuxiliaryIndex = undefined;
  3352. this.moduleGraph.removeAllModuleAttributes();
  3353. this.moduleGraph.unfreeze();
  3354. this.moduleMemCaches2 = undefined;
  3355. }
  3356. /**
  3357. * Processes the provided callback.
  3358. * @param {Callback} callback signals when the call finishes
  3359. * @returns {void}
  3360. */
  3361. seal(callback) {
  3362. /**
  3363. * Processes the provided err.
  3364. * @param {WebpackError=} err err
  3365. * @returns {void}
  3366. */
  3367. const finalCallback = (err) => {
  3368. this.factorizeQueue.clear();
  3369. this.buildQueue.clear();
  3370. this.rebuildQueue.clear();
  3371. this.processDependenciesQueue.clear();
  3372. this.addModuleQueue.clear();
  3373. // lazy barrel only acts during make; release its bookkeeping now
  3374. this._lazyBarrelController.clear();
  3375. // unsafe-cache restore tables are only read during make; release them
  3376. // so they stop pinning restored modules for the rest of the compilation
  3377. this._restoredUnsafeCacheModuleEntries.clear();
  3378. this._restoredUnsafeCacheEntries.clear();
  3379. return callback(err);
  3380. };
  3381. if (this._backCompat) {
  3382. for (const module of this.modules) {
  3383. ChunkGraph.setChunkGraphForModule(module, this.chunkGraph);
  3384. }
  3385. }
  3386. this.hooks.seal.call();
  3387. this.logger.time("optimize dependencies");
  3388. while (this.hooks.optimizeDependencies.call(this.modules)) {
  3389. /* empty */
  3390. }
  3391. this.hooks.afterOptimizeDependencies.call(this.modules);
  3392. this.logger.timeEnd("optimize dependencies");
  3393. this.logger.time("create chunks");
  3394. this.hooks.beforeChunks.call();
  3395. this.moduleGraph.freeze("seal");
  3396. /** @type {Map<Entrypoint, Module[]>} */
  3397. const chunkGraphInit = new Map();
  3398. for (const [name, { dependencies, includeDependencies, options }] of this
  3399. .entries) {
  3400. const chunk = this.addChunk(name);
  3401. if (options.filename) {
  3402. chunk.filenameTemplate = options.filename;
  3403. }
  3404. const entrypoint = new Entrypoint(options);
  3405. if (!options.dependOn && !options.runtime) {
  3406. entrypoint.setRuntimeChunk(chunk);
  3407. }
  3408. entrypoint.setEntrypointChunk(chunk);
  3409. this.namedChunkGroups.set(name, entrypoint);
  3410. this.entrypoints.set(name, entrypoint);
  3411. this.chunkGroups.push(entrypoint);
  3412. if (entrypoint.pushChunk(chunk)) {
  3413. chunk.addGroup(entrypoint);
  3414. }
  3415. /** @type {Set<Module>} */
  3416. const entryModules = new Set();
  3417. for (const dep of [...this.globalEntry.dependencies, ...dependencies]) {
  3418. entrypoint.addOrigin(
  3419. null,
  3420. { name },
  3421. /** @type {Dependency & { request: string }} */
  3422. (dep).request
  3423. );
  3424. const module = this.moduleGraph.getModule(dep);
  3425. if (module) {
  3426. this.chunkGraph.connectChunkAndEntryModule(chunk, module, entrypoint);
  3427. entryModules.add(module);
  3428. const modulesList = chunkGraphInit.get(entrypoint);
  3429. if (modulesList === undefined) {
  3430. chunkGraphInit.set(entrypoint, [module]);
  3431. } else {
  3432. modulesList.push(module);
  3433. }
  3434. }
  3435. }
  3436. this.assignDepths(entryModules);
  3437. /**
  3438. * Returns sorted deps.
  3439. * @param {Dependency[]} deps deps
  3440. * @returns {Module[]} sorted deps
  3441. */
  3442. const mapAndSort = (deps) =>
  3443. /** @type {Module[]} */
  3444. (
  3445. deps.map((dep) => this.moduleGraph.getModule(dep)).filter(Boolean)
  3446. ).sort(compareModulesByIdentifier);
  3447. const includedModules = [
  3448. ...mapAndSort(this.globalEntry.includeDependencies),
  3449. ...mapAndSort(includeDependencies)
  3450. ];
  3451. let modulesList = chunkGraphInit.get(entrypoint);
  3452. if (modulesList === undefined) {
  3453. chunkGraphInit.set(entrypoint, (modulesList = []));
  3454. }
  3455. for (const module of includedModules) {
  3456. this.assignDepths([module]);
  3457. modulesList.push(module);
  3458. }
  3459. }
  3460. /** @type {Set<Chunk>} */
  3461. const runtimeChunks = new Set();
  3462. outer: for (const [
  3463. name,
  3464. {
  3465. options: { dependOn, runtime }
  3466. }
  3467. ] of this.entries) {
  3468. if (dependOn && runtime) {
  3469. const err =
  3470. new WebpackError(`Entrypoint '${name}' has 'dependOn' and 'runtime' specified. This is not valid.
  3471. Entrypoints that depend on other entrypoints do not have their own runtime.
  3472. They will use the runtime(s) from referenced entrypoints instead.
  3473. Remove the 'runtime' option from the entrypoint.`);
  3474. const entry = /** @type {Entrypoint} */ (this.entrypoints.get(name));
  3475. err.chunk = entry.getEntrypointChunk();
  3476. this.errors.push(err);
  3477. }
  3478. if (dependOn) {
  3479. const entry = /** @type {Entrypoint} */ (this.entrypoints.get(name));
  3480. const referencedChunks = entry
  3481. .getEntrypointChunk()
  3482. .getAllReferencedChunks();
  3483. for (const dep of dependOn) {
  3484. const dependency = this.entrypoints.get(dep);
  3485. if (!dependency) {
  3486. throw new Error(
  3487. `Entry ${name} depends on ${dep}, but this entry was not found`
  3488. );
  3489. }
  3490. if (referencedChunks.has(dependency.getEntrypointChunk())) {
  3491. const err = new WebpackError(
  3492. `Entrypoints '${name}' and '${dep}' use 'dependOn' to depend on each other in a circular way.`
  3493. );
  3494. const entryChunk = entry.getEntrypointChunk();
  3495. err.chunk = entryChunk;
  3496. this.errors.push(err);
  3497. entry.setRuntimeChunk(entryChunk);
  3498. continue outer;
  3499. }
  3500. entry.addDependOn(dependency);
  3501. if (dependency.addChild(entry)) {
  3502. entry.addParent(dependency);
  3503. }
  3504. }
  3505. } else if (runtime) {
  3506. const entry = /** @type {Entrypoint} */ (this.entrypoints.get(name));
  3507. let chunk = this.namedChunks.get(runtime);
  3508. if (chunk) {
  3509. if (!runtimeChunks.has(chunk)) {
  3510. const err =
  3511. new WebpackError(`Entrypoint '${name}' has a 'runtime' option which points to another entrypoint named '${runtime}'.
  3512. It's not valid to use other entrypoints as runtime chunk.
  3513. Did you mean to use 'dependOn: ${JSON.stringify(
  3514. runtime
  3515. )}' instead to allow using entrypoint '${name}' within the runtime of entrypoint '${runtime}'? For this '${runtime}' must always be loaded when '${name}' is used.
  3516. Or do you want to use the entrypoints '${name}' and '${runtime}' independently on the same page with a shared runtime? In this case give them both the same value for the 'runtime' option. It must be a name not already used by an entrypoint.`);
  3517. const entryChunk =
  3518. /** @type {Chunk} */
  3519. (entry.getEntrypointChunk());
  3520. err.chunk = entryChunk;
  3521. this.errors.push(err);
  3522. entry.setRuntimeChunk(entryChunk);
  3523. continue;
  3524. }
  3525. } else {
  3526. chunk = this.addChunk(runtime);
  3527. chunk.preventIntegration = true;
  3528. runtimeChunks.add(chunk);
  3529. }
  3530. entry.unshiftChunk(chunk);
  3531. chunk.addGroup(entry);
  3532. entry.setRuntimeChunk(chunk);
  3533. }
  3534. }
  3535. buildChunkGraph(this, chunkGraphInit);
  3536. this.hooks.afterChunks.call(this.chunks);
  3537. this.logger.timeEnd("create chunks");
  3538. this.logger.time("optimize");
  3539. this.hooks.optimize.call();
  3540. while (this.hooks.optimizeModules.call(this.modules)) {
  3541. /* empty */
  3542. }
  3543. this.hooks.afterOptimizeModules.call(this.modules);
  3544. while (this.hooks.optimizeChunks.call(this.chunks, this.chunkGroups)) {
  3545. /* empty */
  3546. }
  3547. this.hooks.afterOptimizeChunks.call(this.chunks, this.chunkGroups);
  3548. this.hooks.optimizeTree.callAsync(this.chunks, this.modules, (err) => {
  3549. if (err) {
  3550. return finalCallback(
  3551. makeWebpackError(err, "Compilation.hooks.optimizeTree")
  3552. );
  3553. }
  3554. this.hooks.afterOptimizeTree.call(this.chunks, this.modules);
  3555. this.hooks.optimizeChunkModules.callAsync(
  3556. this.chunks,
  3557. this.modules,
  3558. (err) => {
  3559. if (err) {
  3560. return finalCallback(
  3561. makeWebpackError(err, "Compilation.hooks.optimizeChunkModules")
  3562. );
  3563. }
  3564. this.hooks.afterOptimizeChunkModules.call(this.chunks, this.modules);
  3565. const shouldRecord = this.hooks.shouldRecord.call() !== false;
  3566. this.hooks.reviveModules.call(
  3567. this.modules,
  3568. /** @type {Records} */
  3569. (this.records)
  3570. );
  3571. this.hooks.beforeModuleIds.call(this.modules);
  3572. this.hooks.moduleIds.call(this.modules);
  3573. this.hooks.optimizeModuleIds.call(this.modules);
  3574. this.hooks.afterOptimizeModuleIds.call(this.modules);
  3575. this.hooks.reviveChunks.call(
  3576. this.chunks,
  3577. /** @type {Records} */
  3578. (this.records)
  3579. );
  3580. this.hooks.beforeChunkIds.call(this.chunks);
  3581. this.hooks.chunkIds.call(this.chunks);
  3582. this.hooks.optimizeChunkIds.call(this.chunks);
  3583. this.hooks.afterOptimizeChunkIds.call(this.chunks);
  3584. this.assignRuntimeIds();
  3585. this.logger.time("compute affected modules with chunk graph");
  3586. this._computeAffectedModulesWithChunkGraph();
  3587. this.logger.timeEnd("compute affected modules with chunk graph");
  3588. this.sortItemsWithChunkIds();
  3589. if (shouldRecord) {
  3590. this.hooks.recordModules.call(
  3591. this.modules,
  3592. /** @type {Records} */
  3593. (this.records)
  3594. );
  3595. this.hooks.recordChunks.call(
  3596. this.chunks,
  3597. /** @type {Records} */
  3598. (this.records)
  3599. );
  3600. }
  3601. this.hooks.optimizeCodeGeneration.call(this.modules);
  3602. this.logger.timeEnd("optimize");
  3603. this.logger.time("module hashing");
  3604. this.hooks.beforeModuleHash.call();
  3605. this.createModuleHashes();
  3606. this.hooks.afterModuleHash.call();
  3607. this.logger.timeEnd("module hashing");
  3608. this.logger.time("code generation");
  3609. this.hooks.beforeCodeGeneration.call();
  3610. this.codeGeneration((err) => {
  3611. if (err) {
  3612. return finalCallback(err);
  3613. }
  3614. this.hooks.afterCodeGeneration.call();
  3615. this.logger.timeEnd("code generation");
  3616. this.logger.time("runtime requirements");
  3617. this.hooks.beforeRuntimeRequirements.call();
  3618. this.processRuntimeRequirements();
  3619. this._attachPendingRuntimeModules((err) => {
  3620. if (err) {
  3621. return finalCallback(err);
  3622. }
  3623. this.hooks.afterRuntimeRequirements.call();
  3624. this.logger.timeEnd("runtime requirements");
  3625. this.logger.time("hashing");
  3626. this.hooks.beforeHash.call();
  3627. const codeGenerationJobs = this.createHash();
  3628. this.hooks.afterHash.call();
  3629. this.logger.timeEnd("hashing");
  3630. this._runCodeGenerationJobs(codeGenerationJobs, (err) => {
  3631. if (err) {
  3632. return finalCallback(err);
  3633. }
  3634. if (shouldRecord) {
  3635. this.logger.time("record hash");
  3636. this.hooks.recordHash.call(
  3637. /** @type {Records} */
  3638. (this.records)
  3639. );
  3640. this.logger.timeEnd("record hash");
  3641. }
  3642. this.logger.time("module assets");
  3643. this.clearAssets();
  3644. this.hooks.beforeModuleAssets.call();
  3645. this.createModuleAssets();
  3646. this.logger.timeEnd("module assets");
  3647. const cont = () => {
  3648. this.logger.time("process assets");
  3649. this.hooks.processAssets.callAsync(this.assets, (err) => {
  3650. if (err) {
  3651. return finalCallback(
  3652. makeWebpackError(err, "Compilation.hooks.processAssets")
  3653. );
  3654. }
  3655. this.hooks.afterProcessAssets.call(this.assets);
  3656. this.logger.timeEnd("process assets");
  3657. this.assets =
  3658. /** @type {CompilationAssets} */
  3659. (
  3660. this._backCompat
  3661. ? soonFrozenObjectDeprecation(
  3662. this.assets,
  3663. "Compilation.assets",
  3664. "DEP_WEBPACK_COMPILATION_ASSETS",
  3665. `BREAKING CHANGE: No more changes should happen to Compilation.assets after sealing the Compilation.
  3666. Do changes to assets earlier, e. g. in Compilation.hooks.processAssets.
  3667. Make sure to select an appropriate stage from Compilation.PROCESS_ASSETS_STAGE_*.`
  3668. )
  3669. : Object.freeze(this.assets)
  3670. );
  3671. this.summarizeDependencies();
  3672. if (shouldRecord) {
  3673. this.hooks.record.call(
  3674. this,
  3675. /** @type {Records} */
  3676. (this.records)
  3677. );
  3678. }
  3679. if (this.hooks.needAdditionalSeal.call()) {
  3680. this.unseal();
  3681. return this.seal(callback);
  3682. }
  3683. return this.hooks.afterSeal.callAsync((err) => {
  3684. if (err) {
  3685. return finalCallback(
  3686. makeWebpackError(err, "Compilation.hooks.afterSeal")
  3687. );
  3688. }
  3689. this.fileSystemInfo.logStatistics();
  3690. finalCallback();
  3691. });
  3692. });
  3693. };
  3694. this.logger.time("create chunk assets");
  3695. if (this.hooks.shouldGenerateChunkAssets.call() !== false) {
  3696. this.hooks.beforeChunkAssets.call();
  3697. this.createChunkAssets((err) => {
  3698. this.logger.timeEnd("create chunk assets");
  3699. if (err) {
  3700. return finalCallback(err);
  3701. }
  3702. cont();
  3703. });
  3704. } else {
  3705. this.logger.timeEnd("create chunk assets");
  3706. cont();
  3707. }
  3708. });
  3709. });
  3710. });
  3711. }
  3712. );
  3713. });
  3714. }
  3715. /**
  3716. * Report dependency errors and warnings.
  3717. * @param {Module} module module to report from
  3718. * @param {DependenciesBlock[]} blocks blocks to report from
  3719. * @returns {boolean} true, when it has warnings or errors
  3720. */
  3721. reportDependencyErrorsAndWarnings(module, blocks) {
  3722. let hasProblems = false;
  3723. for (const block of blocks) {
  3724. const dependencies = block.dependencies;
  3725. for (const d of dependencies) {
  3726. const warnings = d.getWarnings(this.moduleGraph);
  3727. if (warnings) {
  3728. for (const w of warnings) {
  3729. // A consolidated dependency (e.g. CssIcssExportDependency) carries
  3730. // per-item locations on the error itself; fall back to the
  3731. // dependency loc for the usual one-loc-per-dependency case.
  3732. const warning = new (getModuleDependencyWarning())(
  3733. module,
  3734. w,
  3735. /** @type {EXPECTED_ANY} */ (w).loc || d.loc
  3736. );
  3737. this.warnings.push(warning);
  3738. hasProblems = true;
  3739. }
  3740. }
  3741. const errors = d.getErrors(this.moduleGraph);
  3742. if (errors) {
  3743. for (const e of errors) {
  3744. const error = new (getModuleDependencyError())(
  3745. module,
  3746. e,
  3747. /** @type {EXPECTED_ANY} */ (e).loc || d.loc
  3748. );
  3749. this.errors.push(error);
  3750. hasProblems = true;
  3751. }
  3752. }
  3753. }
  3754. if (this.reportDependencyErrorsAndWarnings(module, block.blocks)) {
  3755. hasProblems = true;
  3756. }
  3757. }
  3758. return hasProblems;
  3759. }
  3760. /**
  3761. * Generates code and runtime requirements for this module.
  3762. * @param {Callback} callback callback
  3763. */
  3764. codeGeneration(callback) {
  3765. const { chunkGraph } = this;
  3766. this.codeGenerationResults = new CodeGenerationResults(
  3767. this.outputOptions.hashFunction
  3768. );
  3769. /** @type {CodeGenerationJobs} */
  3770. const jobs = [];
  3771. for (const module of this.modules) {
  3772. const runtimes = chunkGraph.getModuleRuntimes(module);
  3773. if (runtimes.size === 1) {
  3774. for (const runtime of runtimes) {
  3775. const hash = chunkGraph.getModuleHash(module, runtime);
  3776. jobs.push({ module, hash, runtime, runtimes: [runtime] });
  3777. }
  3778. } else if (runtimes.size > 1) {
  3779. /** @type {Map<string, { runtimes: RuntimeSpec[] }>} */
  3780. const map = new Map();
  3781. for (const runtime of runtimes) {
  3782. const hash = chunkGraph.getModuleHash(module, runtime);
  3783. const job = map.get(hash);
  3784. if (job === undefined) {
  3785. const newJob = { module, hash, runtime, runtimes: [runtime] };
  3786. jobs.push(newJob);
  3787. map.set(hash, newJob);
  3788. } else {
  3789. job.runtimes.push(runtime);
  3790. }
  3791. }
  3792. }
  3793. }
  3794. this._runCodeGenerationJobs(jobs, callback);
  3795. }
  3796. /**
  3797. * Offer source one language embeds in another to `renderEmbeddedSource`. The
  3798. * hook is async and generation is not, so the first pass returns the source
  3799. * untouched and records it; `_resolveEmbeddedSources` awaits the hook and
  3800. * generates those modules again, when the resolved source is waiting here.
  3801. * @param {Source} source the embedded source
  3802. * @param {EmbeddedSourceInfo} info what it is and where it is going
  3803. * @returns {Source} the resolved source, or `source` until it is resolved
  3804. */
  3805. _resolveEmbeddedSource(source, info) {
  3806. // Untapped, nothing can change: skip reading the text and the second pass.
  3807. if (this.hooks.renderEmbeddedSource.taps.length === 0) return source;
  3808. const text = /** @type {string} */ (source.source());
  3809. // Everything the hook is handed is in the key: a tap answers per language
  3810. // pair, so identical text offered as two of them is two questions.
  3811. const key = `${info.type}�${info.hostType}�${text}`;
  3812. const resolved = this._embeddedSources.get(info.module);
  3813. if (resolved !== undefined) {
  3814. const hit = resolved.get(key);
  3815. if (hit !== undefined) return hit;
  3816. }
  3817. getOrInsert(this._pendingEmbeddedSources, info.module, () => new Map()).set(
  3818. key,
  3819. { source, info, jobModule: this._generatingModule || info.module }
  3820. );
  3821. return source;
  3822. }
  3823. /**
  3824. * Run `renderEmbeddedSource` over everything the last pass recorded, then
  3825. * generate those modules again so the resolved source is the one embedded.
  3826. * @private
  3827. * @param {CodeGenerationJobs} jobs the jobs the last pass ran
  3828. * @param {Callback} callback callback
  3829. * @returns {void}
  3830. */
  3831. _resolveEmbeddedSources(jobs, callback) {
  3832. if (this._pendingEmbeddedSources.size === 0) return callback();
  3833. /** @type {{ key: string, source: Source, info: EmbeddedSourceInfo, jobModule: Module }[]} */
  3834. const pending = [];
  3835. for (const byKey of this._pendingEmbeddedSources.values()) {
  3836. for (const [key, entry] of byKey) {
  3837. pending.push({ key, ...entry });
  3838. }
  3839. }
  3840. this._pendingEmbeddedSources.clear();
  3841. asyncLib.each(
  3842. pending,
  3843. ({ key, source, info }, cb) => {
  3844. this.hooks.renderEmbeddedSource.callAsync(
  3845. source,
  3846. info,
  3847. /**
  3848. * @param {(Error | null)=} err error
  3849. * @param {Source=} result the resolved source
  3850. * @returns {void}
  3851. */
  3852. (err, result) => {
  3853. if (err) return cb(err);
  3854. getOrInsert(
  3855. this._embeddedSources,
  3856. info.module,
  3857. () => new Map()
  3858. ).set(key, result || source);
  3859. cb();
  3860. }
  3861. );
  3862. },
  3863. (err) => {
  3864. if (err) return callback(/** @type {WebpackError} */ (err));
  3865. const affected = new Set(pending.map(({ jobModule }) => jobModule));
  3866. const redo = jobs.filter(({ module }) => affected.has(module));
  3867. // Generated directly rather than through the codegen cache: the module
  3868. // hash is unchanged, so the cache would hand back the first pass again.
  3869. const results =
  3870. /** @type {CodeGenerationResults} */
  3871. (this.codeGenerationResults);
  3872. for (const { module, runtime, runtimes } of redo) {
  3873. /** @type {CodeGenerationResult} */
  3874. let result;
  3875. try {
  3876. this._generatingModule = module;
  3877. result = module.codeGeneration({
  3878. chunkGraph: this.chunkGraph,
  3879. moduleGraph: this.moduleGraph,
  3880. dependencyTemplates: this.dependencyTemplates,
  3881. runtimeTemplate: this.runtimeTemplate,
  3882. runtime,
  3883. runtimes,
  3884. codeGenerationResults: results,
  3885. compilation: this
  3886. });
  3887. } catch (err) {
  3888. // Reported and carried on with, as the first pass does: a throw
  3889. // here would leave the build with no error to show for it.
  3890. this.errors.push(
  3891. new (getCodeGenerationError())(module, /** @type {Error} */ (err))
  3892. );
  3893. result = {
  3894. sources: new Map(),
  3895. runtimeRequirements: null,
  3896. data: undefined
  3897. };
  3898. } finally {
  3899. this._generatingModule = undefined;
  3900. }
  3901. for (const r of runtimes) results.add(module, r, result);
  3902. }
  3903. // A tap that changed the source again is resolved on the next round.
  3904. this._resolveEmbeddedSources(redo, callback);
  3905. }
  3906. );
  3907. }
  3908. /**
  3909. * Run code generation jobs.
  3910. * @private
  3911. * @param {CodeGenerationJobs} jobs code generation jobs
  3912. * @param {Callback} callback callback
  3913. * @returns {void}
  3914. */
  3915. _runCodeGenerationJobs(jobs, callback) {
  3916. if (jobs.length === 0) {
  3917. return callback();
  3918. }
  3919. // `jobs` is reassigned per iteration; embedded source is resolved over all.
  3920. // Untapped nothing is recorded, so the array is not held past its iteration.
  3921. const allJobs =
  3922. this.hooks.renderEmbeddedSource.taps.length === 0 ? undefined : jobs;
  3923. let statModulesFromCache = 0;
  3924. let statModulesGenerated = 0;
  3925. const { chunkGraph, moduleGraph, dependencyTemplates, runtimeTemplate } =
  3926. this;
  3927. const results =
  3928. /** @type {CodeGenerationResults} */
  3929. (this.codeGenerationResults);
  3930. /** @type {WebpackError[]} */
  3931. const errors = [];
  3932. /** @type {NotCodeGeneratedModules | undefined} */
  3933. let notCodeGeneratedModules;
  3934. const runIteration = () => {
  3935. /** @type {CodeGenerationJobs} */
  3936. let delayedJobs = [];
  3937. /** @type {Set<Module>} */
  3938. let delayedModules = new Set();
  3939. asyncLib.eachLimit(
  3940. jobs,
  3941. this.options.parallelism,
  3942. (job, callback) => {
  3943. const { module } = job;
  3944. const { codeGenerationDependencies } = module;
  3945. if (
  3946. codeGenerationDependencies !== undefined &&
  3947. (notCodeGeneratedModules === undefined ||
  3948. codeGenerationDependencies.some((dep) => {
  3949. const referencedModule = /** @type {Module} */ (
  3950. moduleGraph.getModule(dep)
  3951. );
  3952. return /** @type {NotCodeGeneratedModules} */ (
  3953. notCodeGeneratedModules
  3954. ).has(referencedModule);
  3955. }))
  3956. ) {
  3957. delayedJobs.push(job);
  3958. delayedModules.add(module);
  3959. return callback();
  3960. }
  3961. const { hash, runtime, runtimes } = job;
  3962. this._codeGenerationModule(
  3963. module,
  3964. runtime,
  3965. runtimes,
  3966. hash,
  3967. dependencyTemplates,
  3968. chunkGraph,
  3969. moduleGraph,
  3970. runtimeTemplate,
  3971. errors,
  3972. results,
  3973. (err, codeGenerated) => {
  3974. if (codeGenerated) statModulesGenerated++;
  3975. else statModulesFromCache++;
  3976. callback(err);
  3977. }
  3978. );
  3979. },
  3980. (err) => {
  3981. if (err) return callback(/** @type {WebpackError} */ (err));
  3982. if (delayedJobs.length > 0) {
  3983. if (delayedJobs.length === jobs.length) {
  3984. return callback(
  3985. /** @type {WebpackError} */ (
  3986. new Error(
  3987. `Unable to make progress during code generation because of circular code generation dependency: ${Array.from(
  3988. delayedModules,
  3989. (m) => m.identifier()
  3990. ).join(", ")}`
  3991. )
  3992. )
  3993. );
  3994. }
  3995. jobs = delayedJobs;
  3996. delayedJobs = [];
  3997. notCodeGeneratedModules = delayedModules;
  3998. delayedModules = new Set();
  3999. return runIteration();
  4000. }
  4001. if (errors.length > 0) {
  4002. errors.sort(
  4003. compareSelect((err) => err.module, compareModulesByIdentifier)
  4004. );
  4005. for (const error of errors) {
  4006. this.errors.push(error);
  4007. }
  4008. }
  4009. this.logger.log(
  4010. `${Math.round(
  4011. (100 * statModulesGenerated) /
  4012. (statModulesGenerated + statModulesFromCache)
  4013. )}% code generated (${statModulesGenerated} generated, ${statModulesFromCache} from cache)`
  4014. );
  4015. this._resolveEmbeddedSources(allJobs || jobs, (err) => {
  4016. this._embeddedSources.clear();
  4017. this._pendingEmbeddedSources.clear();
  4018. callback(err);
  4019. });
  4020. }
  4021. );
  4022. };
  4023. runIteration();
  4024. }
  4025. /**
  4026. * Code generation module.
  4027. * @param {Module} module module
  4028. * @param {RuntimeSpec} runtime runtime
  4029. * @param {RuntimeSpec[]} runtimes runtimes
  4030. * @param {string} hash hash
  4031. * @param {DependencyTemplates} dependencyTemplates dependencyTemplates
  4032. * @param {ChunkGraph} chunkGraph chunkGraph
  4033. * @param {ModuleGraph} moduleGraph moduleGraph
  4034. * @param {RuntimeTemplate} runtimeTemplate runtimeTemplate
  4035. * @param {WebpackError[]} errors errors
  4036. * @param {CodeGenerationResults} results results
  4037. * @param {(err?: WebpackError | null, result?: boolean) => void} callback callback
  4038. * @returns {void}
  4039. */
  4040. _codeGenerationModule(
  4041. module,
  4042. runtime,
  4043. runtimes,
  4044. hash,
  4045. dependencyTemplates,
  4046. chunkGraph,
  4047. moduleGraph,
  4048. runtimeTemplate,
  4049. errors,
  4050. results,
  4051. callback
  4052. ) {
  4053. let codeGenerated = false;
  4054. // without a cache backend, skip building the cache keys — the module
  4055. // identifier strings are large (concatenated modules join all inner ids)
  4056. if (!this._codeGenerationCache.isEnabled()) {
  4057. /** @type {CodeGenerationResult} */
  4058. let result;
  4059. try {
  4060. codeGenerated = true;
  4061. this.codeGeneratedModules.add(module);
  4062. this._generatingModule = module;
  4063. result = module.codeGeneration({
  4064. chunkGraph,
  4065. moduleGraph,
  4066. dependencyTemplates,
  4067. runtimeTemplate,
  4068. runtime,
  4069. runtimes,
  4070. codeGenerationResults: results,
  4071. compilation: this
  4072. });
  4073. } catch (err) {
  4074. errors.push(
  4075. new (getCodeGenerationError())(module, /** @type {Error} */ (err))
  4076. );
  4077. result = {
  4078. sources: new Map(),
  4079. runtimeRequirements: null,
  4080. data: undefined
  4081. };
  4082. } finally {
  4083. this._generatingModule = undefined;
  4084. }
  4085. for (const runtime of runtimes) {
  4086. results.add(module, runtime, result);
  4087. }
  4088. return callback(null, codeGenerated);
  4089. }
  4090. const cache = new MultiItemCache(
  4091. runtimes.map((runtime) =>
  4092. this._codeGenerationCache.getItemCache(
  4093. `${module.identifier()}|${getRuntimeKey(runtime)}`,
  4094. `${hash}|${dependencyTemplates.getHash()}`
  4095. )
  4096. )
  4097. );
  4098. cache.get((err, cachedResult) => {
  4099. if (err) return callback(/** @type {WebpackError} */ (err));
  4100. /** @type {CodeGenerationResult} */
  4101. let result;
  4102. if (!cachedResult) {
  4103. try {
  4104. codeGenerated = true;
  4105. this.codeGeneratedModules.add(module);
  4106. this._generatingModule = module;
  4107. result = module.codeGeneration({
  4108. chunkGraph,
  4109. moduleGraph,
  4110. dependencyTemplates,
  4111. runtimeTemplate,
  4112. runtime,
  4113. runtimes,
  4114. codeGenerationResults: results,
  4115. compilation: this
  4116. });
  4117. } catch (err) {
  4118. errors.push(
  4119. new (getCodeGenerationError())(module, /** @type {Error} */ (err))
  4120. );
  4121. result = cachedResult = {
  4122. sources: new Map(),
  4123. runtimeRequirements: null,
  4124. data: undefined
  4125. };
  4126. } finally {
  4127. this._generatingModule = undefined;
  4128. }
  4129. } else {
  4130. result = cachedResult;
  4131. }
  4132. for (const runtime of runtimes) {
  4133. results.add(module, runtime, result);
  4134. }
  4135. if (!cachedResult) {
  4136. cache.store(result, (err) =>
  4137. callback(/** @type {WebpackError} */ (err), codeGenerated)
  4138. );
  4139. } else {
  4140. callback(null, codeGenerated);
  4141. }
  4142. });
  4143. }
  4144. _getChunkGraphEntries() {
  4145. /** @type {Set<Chunk>} */
  4146. const treeEntries = new Set();
  4147. for (const ep of this.entrypoints.values()) {
  4148. const chunk = ep.getRuntimeChunk();
  4149. if (chunk) treeEntries.add(chunk);
  4150. }
  4151. for (const ep of this.asyncEntrypoints) {
  4152. const chunk = ep.getRuntimeChunk();
  4153. if (chunk) treeEntries.add(chunk);
  4154. }
  4155. return treeEntries;
  4156. }
  4157. /**
  4158. * Process runtime requirements.
  4159. * @param {object} options options
  4160. * @param {ChunkGraph=} options.chunkGraph the chunk graph
  4161. * @param {Iterable<Module>=} options.modules modules
  4162. * @param {Iterable<Chunk>=} options.chunks chunks
  4163. * @param {CodeGenerationResults=} options.codeGenerationResults codeGenerationResults
  4164. * @param {Iterable<Chunk>=} options.chunkGraphEntries chunkGraphEntries
  4165. * @returns {void}
  4166. */
  4167. processRuntimeRequirements({
  4168. chunkGraph = this.chunkGraph,
  4169. modules = this.modules,
  4170. chunks = this.chunks,
  4171. codeGenerationResults = /** @type {CodeGenerationResults} */ (
  4172. this.codeGenerationResults
  4173. ),
  4174. chunkGraphEntries = this._getChunkGraphEntries()
  4175. } = {}) {
  4176. const context = { chunkGraph, codeGenerationResults };
  4177. const { moduleMemCaches2 } = this;
  4178. this.logger.time("runtime requirements.modules");
  4179. const additionalModuleRuntimeRequirements =
  4180. this.hooks.additionalModuleRuntimeRequirements;
  4181. const runtimeRequirementInModule = this.hooks.runtimeRequirementInModule;
  4182. for (const module of modules) {
  4183. if (chunkGraph.getNumberOfModuleChunks(module) > 0) {
  4184. const memCache = moduleMemCaches2 && moduleMemCaches2.get(module);
  4185. for (const runtime of chunkGraph.getModuleRuntimes(module)) {
  4186. if (memCache) {
  4187. const cached = memCache.get(
  4188. `moduleRuntimeRequirements-${getRuntimeKey(runtime)}`
  4189. );
  4190. if (cached !== undefined) {
  4191. if (cached !== null) {
  4192. chunkGraph.addModuleRuntimeRequirements(
  4193. module,
  4194. runtime,
  4195. /** @type {RuntimeRequirements} */
  4196. (cached),
  4197. false
  4198. );
  4199. }
  4200. continue;
  4201. }
  4202. }
  4203. /** @type {RuntimeRequirements} */
  4204. let set;
  4205. const runtimeRequirements =
  4206. codeGenerationResults.getRuntimeRequirements(module, runtime);
  4207. if (runtimeRequirements && runtimeRequirements.size > 0) {
  4208. set = new Set(runtimeRequirements);
  4209. } else if (additionalModuleRuntimeRequirements.isUsed()) {
  4210. set = new Set();
  4211. } else {
  4212. if (memCache) {
  4213. memCache.set(
  4214. `moduleRuntimeRequirements-${getRuntimeKey(runtime)}`,
  4215. null
  4216. );
  4217. }
  4218. continue;
  4219. }
  4220. additionalModuleRuntimeRequirements.call(module, set, context);
  4221. for (const r of set) {
  4222. const hook = runtimeRequirementInModule.get(r);
  4223. if (hook !== undefined) hook.call(module, set, context);
  4224. }
  4225. if (set.size === 0) {
  4226. if (memCache) {
  4227. memCache.set(
  4228. `moduleRuntimeRequirements-${getRuntimeKey(runtime)}`,
  4229. null
  4230. );
  4231. }
  4232. } else if (memCache) {
  4233. memCache.set(
  4234. `moduleRuntimeRequirements-${getRuntimeKey(runtime)}`,
  4235. set
  4236. );
  4237. chunkGraph.addModuleRuntimeRequirements(
  4238. module,
  4239. runtime,
  4240. set,
  4241. false
  4242. );
  4243. } else {
  4244. chunkGraph.addModuleRuntimeRequirements(module, runtime, set);
  4245. }
  4246. }
  4247. }
  4248. }
  4249. this.logger.timeEnd("runtime requirements.modules");
  4250. this.logger.time("runtime requirements.chunks");
  4251. for (const chunk of chunks) {
  4252. /** @type {RuntimeRequirements} */
  4253. const set = new Set();
  4254. for (const module of chunkGraph.getChunkModulesIterable(chunk)) {
  4255. const runtimeRequirements = chunkGraph.getModuleRuntimeRequirements(
  4256. module,
  4257. chunk.runtime
  4258. );
  4259. for (const r of runtimeRequirements) set.add(r);
  4260. }
  4261. this.hooks.additionalChunkRuntimeRequirements.call(chunk, set, context);
  4262. for (const r of set) {
  4263. this.hooks.runtimeRequirementInChunk.for(r).call(chunk, set, context);
  4264. }
  4265. chunkGraph.addChunkRuntimeRequirements(chunk, set);
  4266. }
  4267. this.logger.timeEnd("runtime requirements.chunks");
  4268. this.logger.time("runtime requirements.entries");
  4269. for (const treeEntry of chunkGraphEntries) {
  4270. /** @type {RuntimeRequirements} */
  4271. const set = new Set();
  4272. for (const chunk of treeEntry.getAllReferencedChunks()) {
  4273. const runtimeRequirements =
  4274. chunkGraph.getChunkRuntimeRequirements(chunk);
  4275. for (const r of runtimeRequirements) set.add(r);
  4276. }
  4277. this.hooks.additionalTreeRuntimeRequirements.call(
  4278. treeEntry,
  4279. set,
  4280. context
  4281. );
  4282. for (const r of set) {
  4283. this.hooks.runtimeRequirementInTree
  4284. .for(r)
  4285. .call(treeEntry, set, context);
  4286. }
  4287. chunkGraph.addTreeRuntimeRequirements(treeEntry, set);
  4288. }
  4289. this.logger.timeEnd("runtime requirements.entries");
  4290. }
  4291. /**
  4292. * Queues a runtime module whose implementation is loaded on demand, for
  4293. * `_attachPendingRuntimeModules` to await and build once the requirement pass
  4294. * is over. `runtimeRequirementInTree` is a sync hook, so a tap cannot await
  4295. * the load itself; anything the tap reads off the requirement set must be
  4296. * captured before queueing, since `create` runs later.
  4297. * @param {Chunk} chunk target chunk
  4298. * @param {() => Promise<EXPECTED_ANY>} load resolves the runtime module implementation
  4299. * @param {(loaded: EXPECTED_ANY) => RuntimeModule} create builds the runtime module from it
  4300. * @param {ChunkGraph} chunkGraph the chunk graph
  4301. * @returns {void}
  4302. */
  4303. addLazyRuntimeModule(chunk, load, create, chunkGraph = this.chunkGraph) {
  4304. if (this._pendingRuntimeModules === undefined) {
  4305. this._pendingRuntimeModules = [];
  4306. }
  4307. this._pendingRuntimeModules.push({ chunk, load, create, chunkGraph });
  4308. }
  4309. /**
  4310. * Awaits and attaches everything `addLazyRuntimeModule` queued. The only
  4311. * place a deferred runtime module implementation is loaded.
  4312. * @param {Callback} callback signals when the call finishes
  4313. * @returns {void}
  4314. */
  4315. _attachPendingRuntimeModules(callback) {
  4316. const pending = this._pendingRuntimeModules;
  4317. if (pending === undefined) return callback(null);
  4318. this._pendingRuntimeModules = undefined;
  4319. Promise.all(pending.map(({ load }) => load()))
  4320. .then((loaded) => {
  4321. for (let i = 0; i < pending.length; i++) {
  4322. const { chunk, create, chunkGraph } = pending[i];
  4323. this.addRuntimeModule(chunk, create(loaded[i]), chunkGraph);
  4324. }
  4325. })
  4326. // a `runtimeModule` tap may have queued more
  4327. .then(() => this._attachPendingRuntimeModules(callback), callback);
  4328. }
  4329. // TODO webpack 6 make chunkGraph argument non-optional
  4330. /**
  4331. * Adds runtime module.
  4332. * @param {Chunk} chunk target chunk
  4333. * @param {RuntimeModule} module runtime module
  4334. * @param {ChunkGraph} chunkGraph the chunk graph
  4335. * @returns {void}
  4336. */
  4337. addRuntimeModule(chunk, module, chunkGraph = this.chunkGraph) {
  4338. // Deprecated ModuleGraph association
  4339. if (this._backCompat) {
  4340. ModuleGraph.setModuleGraphForModule(module, this.moduleGraph);
  4341. }
  4342. // add it to the list
  4343. this.modules.add(module);
  4344. this._modules.set(module.identifier(), module);
  4345. // connect to the chunk graph
  4346. chunkGraph.connectChunkAndModule(chunk, module);
  4347. chunkGraph.connectChunkAndRuntimeModule(chunk, module);
  4348. if (module.fullHash) {
  4349. chunkGraph.addFullHashModuleToChunk(chunk, module);
  4350. } else if (module.dependentHash) {
  4351. chunkGraph.addDependentHashModuleToChunk(chunk, module);
  4352. }
  4353. // attach runtime module
  4354. module.attach(this, chunk, chunkGraph);
  4355. // Setup internals
  4356. const exportsInfo = this.moduleGraph.getExportsInfo(module);
  4357. exportsInfo.setHasProvideInfo();
  4358. if (typeof chunk.runtime === "string") {
  4359. exportsInfo.setUsedForSideEffectsOnly(chunk.runtime);
  4360. } else if (chunk.runtime === undefined) {
  4361. exportsInfo.setUsedForSideEffectsOnly(undefined);
  4362. } else {
  4363. for (const runtime of chunk.runtime) {
  4364. exportsInfo.setUsedForSideEffectsOnly(runtime);
  4365. }
  4366. }
  4367. chunkGraph.addModuleRuntimeRequirements(
  4368. module,
  4369. chunk.runtime,
  4370. new Set([RuntimeGlobals.requireScope])
  4371. );
  4372. // runtime modules don't need ids
  4373. chunkGraph.setModuleId(module, "");
  4374. // Call hook
  4375. this.hooks.runtimeModule.call(module, chunk);
  4376. }
  4377. /**
  4378. * If `module` is passed, `loc` and `request` must also be passed.
  4379. * @param {string | ChunkGroupOptions} groupOptions options for the chunk group
  4380. * @param {Module=} module the module the references the chunk group
  4381. * @param {DependencyLocation=} loc the location from with the chunk group is referenced (inside of module)
  4382. * @param {string=} request the request from which the chunk group is referenced
  4383. * @returns {ChunkGroup} the new or existing chunk group
  4384. */
  4385. addChunkInGroup(groupOptions, module, loc, request) {
  4386. if (typeof groupOptions === "string") {
  4387. groupOptions = { name: groupOptions };
  4388. }
  4389. const name = groupOptions.name;
  4390. if (name) {
  4391. const chunkGroup = this.namedChunkGroups.get(name);
  4392. if (chunkGroup !== undefined) {
  4393. if (module) {
  4394. chunkGroup.addOrigin(
  4395. module,
  4396. /** @type {DependencyLocation} */
  4397. (loc),
  4398. /** @type {string} */
  4399. (request)
  4400. );
  4401. }
  4402. return chunkGroup;
  4403. }
  4404. }
  4405. const chunkGroup = new ChunkGroup(groupOptions);
  4406. if (module) {
  4407. chunkGroup.addOrigin(
  4408. module,
  4409. /** @type {DependencyLocation} */
  4410. (loc),
  4411. /** @type {string} */
  4412. (request)
  4413. );
  4414. }
  4415. const chunk = this.addChunk(name);
  4416. if (chunkGroup.pushChunk(chunk)) {
  4417. chunk.addGroup(chunkGroup);
  4418. }
  4419. this.chunkGroups.push(chunkGroup);
  4420. if (name) {
  4421. this.namedChunkGroups.set(name, chunkGroup);
  4422. }
  4423. return chunkGroup;
  4424. }
  4425. /**
  4426. * Adds the provided async entrypoint to this chunk group.
  4427. * @param {EntryOptions} options options for the entrypoint
  4428. * @param {Module} module the module the references the chunk group
  4429. * @param {DependencyLocation} loc the location from with the chunk group is referenced (inside of module)
  4430. * @param {string} request the request from which the chunk group is referenced
  4431. * @returns {Entrypoint} the new or existing entrypoint
  4432. */
  4433. addAsyncEntrypoint(options, module, loc, request) {
  4434. const name = options.name;
  4435. if (name) {
  4436. const entrypoint = this.namedChunkGroups.get(name);
  4437. if (entrypoint instanceof Entrypoint) {
  4438. if (module) {
  4439. entrypoint.addOrigin(module, loc, request);
  4440. }
  4441. return entrypoint;
  4442. } else if (entrypoint) {
  4443. throw new Error(
  4444. `Cannot add an async entrypoint with the name '${name}', because there is already an chunk group with this name`
  4445. );
  4446. }
  4447. }
  4448. const chunk = this.addChunk(name);
  4449. if (options.filename) {
  4450. chunk.filenameTemplate = options.filename;
  4451. }
  4452. const entrypoint = new Entrypoint(options, false);
  4453. entrypoint.setRuntimeChunk(chunk);
  4454. entrypoint.setEntrypointChunk(chunk);
  4455. if (name) {
  4456. this.namedChunkGroups.set(name, entrypoint);
  4457. }
  4458. this.chunkGroups.push(entrypoint);
  4459. this.asyncEntrypoints.push(entrypoint);
  4460. if (entrypoint.pushChunk(chunk)) {
  4461. chunk.addGroup(entrypoint);
  4462. }
  4463. if (module) {
  4464. entrypoint.addOrigin(module, loc, request);
  4465. }
  4466. return entrypoint;
  4467. }
  4468. /**
  4469. * This method first looks to see if a name is provided for a new chunk,
  4470. * and first looks to see if any named chunks already exist and reuse that chunk instead.
  4471. * @param {ChunkName=} name optional chunk name to be provided
  4472. * @returns {Chunk} create a chunk (invoked during seal event)
  4473. */
  4474. addChunk(name) {
  4475. if (name) {
  4476. const chunk = this.namedChunks.get(name);
  4477. if (chunk !== undefined) {
  4478. return chunk;
  4479. }
  4480. }
  4481. const chunk = new Chunk(name, this._backCompat);
  4482. this.chunks.add(chunk);
  4483. if (this._backCompat) {
  4484. ChunkGraph.setChunkGraphForChunk(chunk, this.chunkGraph);
  4485. }
  4486. if (name) {
  4487. this.namedChunks.set(name, chunk);
  4488. }
  4489. return chunk;
  4490. }
  4491. /**
  4492. * Processes the provided module.
  4493. * @deprecated
  4494. * @param {Module} module module to assign depth
  4495. * @returns {void}
  4496. */
  4497. assignDepth(module) {
  4498. const moduleGraph = this.moduleGraph;
  4499. const queue = new Set([module]);
  4500. /** @type {number} */
  4501. let depth;
  4502. moduleGraph.setDepth(module, 0);
  4503. /**
  4504. * Processes the provided module.
  4505. * @param {Module} module module for processing
  4506. * @returns {void}
  4507. */
  4508. const processModule = (module) => {
  4509. if (!moduleGraph.setDepthIfLower(module, depth)) return;
  4510. queue.add(module);
  4511. };
  4512. for (module of queue) {
  4513. queue.delete(module);
  4514. depth = /** @type {number} */ (moduleGraph.getDepth(module)) + 1;
  4515. for (const connection of moduleGraph.getOutgoingConnections(module)) {
  4516. const refModule = connection.module;
  4517. if (refModule) {
  4518. processModule(refModule);
  4519. }
  4520. }
  4521. }
  4522. }
  4523. /**
  4524. * Assigns depth values to the provided modules.
  4525. * @param {Module[] | Set<Module>} modules modules to assign depth
  4526. * @returns {void}
  4527. */
  4528. assignDepths(modules) {
  4529. const moduleGraph = this.moduleGraph;
  4530. /** @type {Set<Module>} */
  4531. const queue = new Set(modules);
  4532. // Track these in local variables so that queue only has one data type
  4533. let nextDepthAt = queue.size;
  4534. let depth = 0;
  4535. let i = 0;
  4536. for (const module of queue) {
  4537. moduleGraph.setDepth(module, depth);
  4538. // Some of these results come from cache, which speeds this up
  4539. const connections = moduleGraph.getOutgoingConnectionsByModule(module);
  4540. // connections will be undefined if there are no outgoing connections
  4541. if (connections) {
  4542. for (const refModule of connections.keys()) {
  4543. if (refModule) queue.add(refModule);
  4544. }
  4545. }
  4546. i++;
  4547. // Since this is a breadth-first search, all modules added to the queue
  4548. // while at depth N will be depth N+1
  4549. if (i >= nextDepthAt) {
  4550. depth++;
  4551. nextDepthAt = queue.size;
  4552. }
  4553. }
  4554. }
  4555. /**
  4556. * Gets dependency referenced exports.
  4557. * @param {Dependency} dependency the dependency
  4558. * @param {RuntimeSpec} runtime the runtime
  4559. * @returns {ReferencedExports} referenced exports
  4560. */
  4561. getDependencyReferencedExports(dependency, runtime) {
  4562. const referencedExports = dependency.getReferencedExports(
  4563. this.moduleGraph,
  4564. runtime
  4565. );
  4566. return this.hooks.dependencyReferencedExports.call(
  4567. referencedExports,
  4568. dependency,
  4569. runtime
  4570. );
  4571. }
  4572. /**
  4573. * Removes reasons of dependency block.
  4574. * @param {Module} module module relationship for removal
  4575. * @param {DependenciesBlockLike} block dependencies block
  4576. * @returns {void}
  4577. */
  4578. removeReasonsOfDependencyBlock(module, block) {
  4579. if (block.blocks) {
  4580. for (const b of block.blocks) {
  4581. this.removeReasonsOfDependencyBlock(module, b);
  4582. }
  4583. }
  4584. if (block.dependencies) {
  4585. for (const dep of block.dependencies) {
  4586. const originalModule = this.moduleGraph.getModule(dep);
  4587. if (originalModule) {
  4588. this.moduleGraph.removeConnection(dep);
  4589. if (this.chunkGraph) {
  4590. for (const chunk of this.chunkGraph.getModuleChunks(
  4591. originalModule
  4592. )) {
  4593. this.patchChunksAfterReasonRemoval(originalModule, chunk);
  4594. }
  4595. }
  4596. }
  4597. }
  4598. }
  4599. }
  4600. /**
  4601. * Patch chunks after reason removal.
  4602. * @param {Module} module module to patch tie
  4603. * @param {Chunk} chunk chunk to patch tie
  4604. * @returns {void}
  4605. */
  4606. patchChunksAfterReasonRemoval(module, chunk) {
  4607. if (!module.hasReasons(this.moduleGraph, chunk.runtime)) {
  4608. this.removeReasonsOfDependencyBlock(module, module);
  4609. }
  4610. if (
  4611. !module.hasReasonForChunk(chunk, this.moduleGraph, this.chunkGraph) &&
  4612. this.chunkGraph.isModuleInChunk(module, chunk)
  4613. ) {
  4614. this.chunkGraph.disconnectChunkAndModule(chunk, module);
  4615. this.removeChunkFromDependencies(module, chunk);
  4616. }
  4617. }
  4618. /**
  4619. * Removes chunk from dependencies.
  4620. * @param {DependenciesBlock} block block tie for Chunk
  4621. * @param {Chunk} chunk chunk to remove from dep
  4622. * @returns {void}
  4623. */
  4624. removeChunkFromDependencies(block, chunk) {
  4625. /**
  4626. * Iterator dependency.
  4627. * @param {Dependency} d dependency to (maybe) patch up
  4628. */
  4629. const iteratorDependency = (d) => {
  4630. const depModule = this.moduleGraph.getModule(d);
  4631. if (!depModule) {
  4632. return;
  4633. }
  4634. this.patchChunksAfterReasonRemoval(depModule, chunk);
  4635. };
  4636. const blocks = block.blocks;
  4637. for (const asyncBlock of blocks) {
  4638. const chunkGroup =
  4639. /** @type {ChunkGroup} */
  4640. (this.chunkGraph.getBlockChunkGroup(asyncBlock));
  4641. // Grab all chunks from the first Block's AsyncDepBlock
  4642. const chunks = chunkGroup.chunks;
  4643. // For each chunk in chunkGroup
  4644. for (const iteratedChunk of chunks) {
  4645. chunkGroup.removeChunk(iteratedChunk);
  4646. // Recurse
  4647. this.removeChunkFromDependencies(block, iteratedChunk);
  4648. }
  4649. }
  4650. if (block.dependencies) {
  4651. for (const dep of block.dependencies) iteratorDependency(dep);
  4652. }
  4653. }
  4654. assignRuntimeIds() {
  4655. const { chunkGraph } = this;
  4656. /**
  4657. * Process entrypoint.
  4658. * @param {Entrypoint} ep an entrypoint
  4659. */
  4660. const processEntrypoint = (ep) => {
  4661. const runtime = /** @type {string} */ (ep.options.runtime || ep.name);
  4662. const chunk = /** @type {Chunk} */ (ep.getRuntimeChunk());
  4663. chunkGraph.setRuntimeId(runtime, /** @type {ChunkId} */ (chunk.id));
  4664. };
  4665. for (const ep of this.entrypoints.values()) {
  4666. processEntrypoint(ep);
  4667. }
  4668. for (const ep of this.asyncEntrypoints) {
  4669. processEntrypoint(ep);
  4670. }
  4671. }
  4672. sortItemsWithChunkIds() {
  4673. for (const chunkGroup of this.chunkGroups) {
  4674. chunkGroup.sortItems();
  4675. }
  4676. this.errors.sort(compareErrors);
  4677. this.warnings.sort(compareErrors);
  4678. // `hints` is sorted where stats read it — producers tap `afterSeal` and
  4679. // `afterEmit`, so they append after this point.
  4680. this.children.sort(byNameOrHash);
  4681. }
  4682. summarizeDependencies() {
  4683. for (const child of this.children) {
  4684. this.fileDependencies.addAll(child.fileDependencies);
  4685. this.contextDependencies.addAll(child.contextDependencies);
  4686. this.missingDependencies.addAll(child.missingDependencies);
  4687. this.buildDependencies.addAll(child.buildDependencies);
  4688. }
  4689. for (const module of this.modules) {
  4690. module.addCacheDependencies(
  4691. this.fileDependencies,
  4692. this.contextDependencies,
  4693. this.missingDependencies,
  4694. this.buildDependencies
  4695. );
  4696. }
  4697. }
  4698. createModuleHashes() {
  4699. let statModulesHashed = 0;
  4700. let statModulesFromCache = 0;
  4701. const { chunkGraph, runtimeTemplate, moduleMemCaches2 } = this;
  4702. const { hashFunction, hashDigest, hashDigestLength } = this.outputOptions;
  4703. /** @type {WebpackError[]} */
  4704. const errors = [];
  4705. for (const module of this.modules) {
  4706. const memCache = moduleMemCaches2 && moduleMemCaches2.get(module);
  4707. for (const runtime of chunkGraph.getModuleRuntimes(module)) {
  4708. const cacheKey = memCache
  4709. ? `moduleHash-${getRuntimeKey(runtime)}`
  4710. : undefined;
  4711. if (memCache) {
  4712. const digest =
  4713. /** @type {string} */
  4714. (memCache.get(/** @type {string} */ (cacheKey)));
  4715. if (digest !== undefined) {
  4716. chunkGraph.setModuleHashes(
  4717. module,
  4718. runtime,
  4719. digest,
  4720. digest.slice(0, hashDigestLength)
  4721. );
  4722. statModulesFromCache++;
  4723. continue;
  4724. }
  4725. }
  4726. statModulesHashed++;
  4727. const digest = this._createModuleHash(
  4728. module,
  4729. chunkGraph,
  4730. runtime,
  4731. hashFunction,
  4732. runtimeTemplate,
  4733. hashDigest,
  4734. hashDigestLength,
  4735. errors
  4736. );
  4737. if (memCache) {
  4738. memCache.set(/** @type {string} */ (cacheKey), digest);
  4739. }
  4740. }
  4741. }
  4742. if (errors.length > 0) {
  4743. errors.sort(
  4744. compareSelect((err) => err.module, compareModulesByIdentifier)
  4745. );
  4746. for (const error of errors) {
  4747. this.errors.push(error);
  4748. }
  4749. }
  4750. this.logger.log(
  4751. `${statModulesHashed} modules hashed, ${statModulesFromCache} from cache (${
  4752. Math.round(
  4753. (100 * (statModulesHashed + statModulesFromCache)) / this.modules.size
  4754. ) / 100
  4755. } variants per module in average)`
  4756. );
  4757. }
  4758. /**
  4759. * Create module hash.
  4760. * @private
  4761. * @param {Module} module module
  4762. * @param {ChunkGraph} chunkGraph the chunk graph
  4763. * @param {RuntimeSpec} runtime runtime
  4764. * @param {HashFunction} hashFunction hash function
  4765. * @param {RuntimeTemplate} runtimeTemplate runtime template
  4766. * @param {HashDigest} hashDigest hash digest
  4767. * @param {HashDigestLength} hashDigestLength hash digest length
  4768. * @param {WebpackError[]} errors errors
  4769. * @returns {string} module hash digest
  4770. */
  4771. _createModuleHash(
  4772. module,
  4773. chunkGraph,
  4774. runtime,
  4775. hashFunction,
  4776. runtimeTemplate,
  4777. hashDigest,
  4778. hashDigestLength,
  4779. errors
  4780. ) {
  4781. /** @type {string} */
  4782. let moduleHashDigest;
  4783. try {
  4784. const moduleHash = createHash(hashFunction);
  4785. module.updateHash(moduleHash, {
  4786. chunkGraph,
  4787. runtime,
  4788. runtimeTemplate
  4789. });
  4790. moduleHashDigest = moduleHash.digest(hashDigest);
  4791. } catch (err) {
  4792. errors.push(
  4793. new (getModuleHashingError())(module, /** @type {Error} */ (err))
  4794. );
  4795. moduleHashDigest = "XXXXXX";
  4796. }
  4797. chunkGraph.setModuleHashes(
  4798. module,
  4799. runtime,
  4800. moduleHashDigest,
  4801. moduleHashDigest.slice(0, hashDigestLength)
  4802. );
  4803. return moduleHashDigest;
  4804. }
  4805. createHash() {
  4806. this.logger.time("hashing: initialize hash");
  4807. const chunkGraph = /** @type {ChunkGraph} */ (this.chunkGraph);
  4808. const runtimeTemplate = this.runtimeTemplate;
  4809. const outputOptions = this.outputOptions;
  4810. const hashFunction = outputOptions.hashFunction;
  4811. const hashDigest = outputOptions.hashDigest;
  4812. const hashDigestLength = outputOptions.hashDigestLength;
  4813. const hash = createHash(hashFunction);
  4814. if (outputOptions.hashSalt) {
  4815. hash.update(outputOptions.hashSalt);
  4816. }
  4817. this.logger.timeEnd("hashing: initialize hash");
  4818. if (this.children.length > 0) {
  4819. this.logger.time("hashing: hash child compilations");
  4820. for (const child of this.children) {
  4821. hash.update(/** @type {string} */ (child.hash));
  4822. }
  4823. this.logger.timeEnd("hashing: hash child compilations");
  4824. }
  4825. if (this.warnings.length > 0) {
  4826. this.logger.time("hashing: hash warnings");
  4827. for (const warning of this.warnings) {
  4828. hash.update(`${warning.message}`);
  4829. }
  4830. this.logger.timeEnd("hashing: hash warnings");
  4831. }
  4832. if (this.errors.length > 0) {
  4833. this.logger.time("hashing: hash errors");
  4834. for (const error of this.errors) {
  4835. hash.update(`${error.message}`);
  4836. }
  4837. this.logger.timeEnd("hashing: hash errors");
  4838. }
  4839. this.logger.time("hashing: sort chunks");
  4840. /*
  4841. * Chunks are hashed in 4 categories, in this order:
  4842. * 1. Async chunks - no hash dependencies on other chunks
  4843. * 2. Non-entry initial chunks (e.g. shared split chunks) - no hash
  4844. * dependencies on other chunks, but runtime chunks may read their
  4845. * hashes via GetChunkFilenameRuntimeModule (dependentHash)
  4846. * 3. Runtime chunks - may use hashes of async and non-entry initial
  4847. * chunks (via GetChunkFilenameRuntimeModule). Ordered by references
  4848. * between each other (for async entrypoints)
  4849. * 4. Entry chunks - may depend on runtimeChunk.hash (via
  4850. * createChunkHashHandler for ESM/CJS entry importing runtime)
  4851. *
  4852. * This ordering ensures all hash dependencies flow in one direction:
  4853. * async/initial → runtime → entry, with no circular dependencies.
  4854. * Chunks within each category are sorted by id for determinism.
  4855. */
  4856. /** @type {Chunk[]} */
  4857. const unorderedRuntimeChunks = [];
  4858. /** @type {Chunk[]} */
  4859. const initialChunks = [];
  4860. /** @type {Chunk[]} */
  4861. const entryChunks = [];
  4862. /** @type {Chunk[]} */
  4863. const asyncChunks = [];
  4864. for (const c of this.chunks) {
  4865. if (c.hasRuntime()) {
  4866. unorderedRuntimeChunks.push(c);
  4867. } else if (chunkGraph.getNumberOfEntryModules(c) > 0) {
  4868. entryChunks.push(c);
  4869. } else if (c.canBeInitial()) {
  4870. initialChunks.push(c);
  4871. } else {
  4872. asyncChunks.push(c);
  4873. }
  4874. }
  4875. unorderedRuntimeChunks.sort(byId);
  4876. entryChunks.sort(byId);
  4877. initialChunks.sort(byId);
  4878. asyncChunks.sort(byId);
  4879. /** @typedef {{ chunk: Chunk, referencedBy: RuntimeChunkInfo[], remaining: number }} RuntimeChunkInfo */
  4880. /** @type {Map<Chunk, RuntimeChunkInfo>} */
  4881. const runtimeChunksMap = new Map();
  4882. for (const chunk of unorderedRuntimeChunks) {
  4883. runtimeChunksMap.set(chunk, {
  4884. chunk,
  4885. referencedBy: [],
  4886. remaining: 0
  4887. });
  4888. }
  4889. let remaining = 0;
  4890. for (const info of runtimeChunksMap.values()) {
  4891. for (const other of new Set(
  4892. [...info.chunk.getAllReferencedAsyncEntrypoints()].map(
  4893. (e) => e.chunks[e.chunks.length - 1]
  4894. )
  4895. )) {
  4896. const otherInfo = runtimeChunksMap.get(other);
  4897. // other may be a non-runtime chunk (e.g. worker chunk)
  4898. // when you have a worker chunk in your app.js (new Worker(...)) and as a separate entry point
  4899. if (otherInfo) {
  4900. otherInfo.referencedBy.push(info);
  4901. info.remaining++;
  4902. remaining++;
  4903. }
  4904. }
  4905. }
  4906. /** @type {Chunk[]} */
  4907. const runtimeChunks = [];
  4908. for (const info of runtimeChunksMap.values()) {
  4909. if (info.remaining === 0) {
  4910. runtimeChunks.push(info.chunk);
  4911. }
  4912. }
  4913. // If there are any references between chunks
  4914. // make sure to follow these chains
  4915. if (remaining > 0) {
  4916. /** @type {Chunk[]} */
  4917. const readyChunks = [];
  4918. for (const chunk of runtimeChunks) {
  4919. const hasFullHashModules =
  4920. chunkGraph.getNumberOfChunkFullHashModules(chunk) !== 0;
  4921. const info =
  4922. /** @type {RuntimeChunkInfo} */
  4923. (runtimeChunksMap.get(chunk));
  4924. for (const otherInfo of info.referencedBy) {
  4925. if (hasFullHashModules) {
  4926. chunkGraph.upgradeDependentToFullHashModules(otherInfo.chunk);
  4927. }
  4928. remaining--;
  4929. if (--otherInfo.remaining === 0) {
  4930. readyChunks.push(otherInfo.chunk);
  4931. }
  4932. }
  4933. if (readyChunks.length > 0) {
  4934. // This ensures deterministic ordering, since referencedBy is non-deterministic
  4935. readyChunks.sort(byId);
  4936. for (const c of readyChunks) runtimeChunks.push(c);
  4937. readyChunks.length = 0;
  4938. }
  4939. }
  4940. }
  4941. // If there are still remaining references we have cycles and want to create a warning
  4942. if (remaining > 0) {
  4943. /** @type {RuntimeChunkInfo[]} */
  4944. const circularRuntimeChunkInfo = [];
  4945. for (const info of runtimeChunksMap.values()) {
  4946. if (info.remaining !== 0) {
  4947. circularRuntimeChunkInfo.push(info);
  4948. }
  4949. }
  4950. circularRuntimeChunkInfo.sort(compareSelect((i) => i.chunk, byId));
  4951. const err =
  4952. new WebpackError(`Circular dependency between chunks with runtime (${Array.from(
  4953. circularRuntimeChunkInfo,
  4954. (c) => c.chunk.name || c.chunk.id
  4955. ).join(", ")})
  4956. This prevents using hashes of each other and should be avoided.`);
  4957. err.chunk = circularRuntimeChunkInfo[0].chunk;
  4958. this.warnings.push(err);
  4959. for (const i of circularRuntimeChunkInfo) runtimeChunks.push(i.chunk);
  4960. }
  4961. this.logger.timeEnd("hashing: sort chunks");
  4962. /** @type {Set<Chunk>} */
  4963. const fullHashChunks = new Set();
  4964. /** @type {CodeGenerationJobs} */
  4965. const codeGenerationJobs = [];
  4966. /** @type {Map<string, Map<Module, CodeGenerationJob>>} */
  4967. const codeGenerationJobsMap = new Map();
  4968. /** @type {WebpackError[]} */
  4969. const errors = [];
  4970. /**
  4971. * Processes the provided chunk.
  4972. * @param {Chunk} chunk chunk
  4973. */
  4974. const processChunk = (chunk) => {
  4975. // Last minute module hash generation for modules that depend on chunk hashes
  4976. this.logger.time("hashing: hash runtime modules");
  4977. const runtime = chunk.runtime;
  4978. for (const module of chunkGraph.getChunkModulesIterable(chunk)) {
  4979. if (!chunkGraph.hasModuleHashes(module, runtime)) {
  4980. const hash = this._createModuleHash(
  4981. module,
  4982. chunkGraph,
  4983. runtime,
  4984. hashFunction,
  4985. runtimeTemplate,
  4986. hashDigest,
  4987. hashDigestLength,
  4988. errors
  4989. );
  4990. let hashMap = codeGenerationJobsMap.get(hash);
  4991. if (hashMap) {
  4992. const moduleJob = hashMap.get(module);
  4993. if (moduleJob) {
  4994. moduleJob.runtimes.push(runtime);
  4995. continue;
  4996. }
  4997. } else {
  4998. hashMap = new Map();
  4999. codeGenerationJobsMap.set(hash, hashMap);
  5000. }
  5001. const job = {
  5002. module,
  5003. hash,
  5004. runtime,
  5005. runtimes: [runtime]
  5006. };
  5007. hashMap.set(module, job);
  5008. codeGenerationJobs.push(job);
  5009. }
  5010. }
  5011. this.logger.timeAggregate("hashing: hash runtime modules");
  5012. try {
  5013. this.logger.time("hashing: hash chunks");
  5014. const chunkHash = createHash(hashFunction);
  5015. if (outputOptions.hashSalt) {
  5016. chunkHash.update(outputOptions.hashSalt);
  5017. }
  5018. chunk.updateHash(chunkHash, chunkGraph);
  5019. this.hooks.chunkHash.call(chunk, chunkHash, {
  5020. chunkGraph,
  5021. codeGenerationResults:
  5022. /** @type {CodeGenerationResults} */
  5023. (this.codeGenerationResults),
  5024. moduleGraph: this.moduleGraph,
  5025. runtimeTemplate: this.runtimeTemplate
  5026. });
  5027. const chunkHashDigest = chunkHash.digest(hashDigest);
  5028. hash.update(chunkHashDigest);
  5029. chunk.hash = chunkHashDigest;
  5030. chunk.renderedHash = chunk.hash.slice(0, hashDigestLength);
  5031. const fullHashModules =
  5032. chunkGraph.getChunkFullHashModulesIterable(chunk);
  5033. if (fullHashModules) {
  5034. fullHashChunks.add(chunk);
  5035. } else {
  5036. this.hooks.contentHash.call(chunk);
  5037. }
  5038. } catch (err) {
  5039. this.errors.push(
  5040. new (getChunkRenderError())(chunk, "", /** @type {Error} */ (err))
  5041. );
  5042. }
  5043. this.logger.timeAggregate("hashing: hash chunks");
  5044. };
  5045. for (const chunk of asyncChunks) processChunk(chunk);
  5046. for (const chunk of initialChunks) processChunk(chunk);
  5047. for (const chunk of runtimeChunks) processChunk(chunk);
  5048. for (const chunk of entryChunks) processChunk(chunk);
  5049. if (errors.length > 0) {
  5050. errors.sort(
  5051. compareSelect((err) => err.module, compareModulesByIdentifier)
  5052. );
  5053. for (const error of errors) {
  5054. this.errors.push(error);
  5055. }
  5056. }
  5057. this.logger.timeAggregateEnd("hashing: hash runtime modules");
  5058. this.logger.timeAggregateEnd("hashing: hash chunks");
  5059. this.logger.time("hashing: hash digest");
  5060. this.hooks.fullHash.call(hash);
  5061. this.fullHash = hash.digest(hashDigest);
  5062. this.hash = this.fullHash.slice(0, hashDigestLength);
  5063. this.logger.timeEnd("hashing: hash digest");
  5064. this.logger.time("hashing: process full hash modules");
  5065. for (const chunk of fullHashChunks) {
  5066. for (const module of /** @type {Iterable<RuntimeModule>} */ (
  5067. chunkGraph.getChunkFullHashModulesIterable(chunk)
  5068. )) {
  5069. const moduleHash = createHash(hashFunction);
  5070. module.updateHash(moduleHash, {
  5071. chunkGraph,
  5072. runtime: chunk.runtime,
  5073. runtimeTemplate
  5074. });
  5075. const moduleHashDigest = moduleHash.digest(hashDigest);
  5076. const oldHash = chunkGraph.getModuleHash(module, chunk.runtime);
  5077. chunkGraph.setModuleHashes(
  5078. module,
  5079. chunk.runtime,
  5080. moduleHashDigest,
  5081. moduleHashDigest.slice(0, hashDigestLength)
  5082. );
  5083. /** @type {CodeGenerationJob} */
  5084. (
  5085. /** @type {Map<Module, CodeGenerationJob>} */
  5086. (codeGenerationJobsMap.get(oldHash)).get(module)
  5087. ).hash = moduleHashDigest;
  5088. }
  5089. const chunkHash = createHash(hashFunction);
  5090. chunkHash.update(/** @type {string} */ (chunk.hash));
  5091. chunkHash.update(this.hash);
  5092. const chunkHashDigest = chunkHash.digest(hashDigest);
  5093. chunk.hash = chunkHashDigest;
  5094. chunk.renderedHash = chunk.hash.slice(0, hashDigestLength);
  5095. this.hooks.contentHash.call(chunk);
  5096. }
  5097. this.logger.timeEnd("hashing: process full hash modules");
  5098. return codeGenerationJobs;
  5099. }
  5100. /**
  5101. * Processes the provided file.
  5102. * @param {string} file file name
  5103. * @param {Source} source asset source
  5104. * @param {AssetInfo} assetInfo extra asset information
  5105. * @returns {void}
  5106. */
  5107. emitAsset(file, source, assetInfo = {}) {
  5108. // A file may be attached to a chunk right after any emit (including the
  5109. // re-emit path for assets shared across chunks in createChunkAssets), so
  5110. // the lazily-built reverse index is stale after every emitAsset.
  5111. this._assetToChunkIndex = undefined;
  5112. this._assetToChunkAuxiliaryIndex = undefined;
  5113. if (this.assets[file]) {
  5114. if (!isSourceEqual(this.assets[file], source)) {
  5115. this.errors.push(
  5116. new WebpackError(
  5117. `Conflict: Multiple assets emit different content to the same filename ${file}${
  5118. assetInfo.sourceFilename
  5119. ? `. Original source ${assetInfo.sourceFilename}`
  5120. : ""
  5121. }`
  5122. )
  5123. );
  5124. this.assets[file] = source;
  5125. this._setAssetInfo(file, assetInfo);
  5126. return;
  5127. }
  5128. const oldInfo = this.assetsInfo.get(file);
  5129. const newInfo = { ...oldInfo, ...assetInfo };
  5130. this._setAssetInfo(file, newInfo, oldInfo);
  5131. return;
  5132. }
  5133. this.assets[file] = source;
  5134. this._setAssetInfo(file, assetInfo, undefined);
  5135. }
  5136. /**
  5137. * Processes the provided file.
  5138. * @private
  5139. * @param {string} file file name
  5140. * @param {AssetInfo=} newInfo new asset information
  5141. * @param {AssetInfo=} oldInfo old asset information
  5142. */
  5143. _setAssetInfo(file, newInfo, oldInfo = this.assetsInfo.get(file)) {
  5144. if (newInfo === undefined) {
  5145. this.assetsInfo.delete(file);
  5146. } else {
  5147. this.assetsInfo.set(file, newInfo);
  5148. }
  5149. const oldRelated = oldInfo && oldInfo.related;
  5150. const newRelated = newInfo && newInfo.related;
  5151. if (oldRelated) {
  5152. for (const key of Object.keys(oldRelated)) {
  5153. /**
  5154. * Processes the provided name.
  5155. * @param {string} name name
  5156. */
  5157. const remove = (name) => {
  5158. const relatedIn = this._assetsRelatedIn.get(name);
  5159. if (relatedIn === undefined) return;
  5160. const entry = relatedIn.get(key);
  5161. if (entry === undefined) return;
  5162. entry.delete(file);
  5163. if (entry.size !== 0) return;
  5164. relatedIn.delete(key);
  5165. if (relatedIn.size === 0) this._assetsRelatedIn.delete(name);
  5166. };
  5167. const entry = oldRelated[key];
  5168. if (Array.isArray(entry)) {
  5169. for (const name of entry) {
  5170. remove(name);
  5171. }
  5172. } else if (entry) {
  5173. remove(entry);
  5174. }
  5175. }
  5176. }
  5177. if (newRelated) {
  5178. for (const key of Object.keys(newRelated)) {
  5179. /**
  5180. * Processes the provided name.
  5181. * @param {string} name name
  5182. */
  5183. const add = (name) => {
  5184. let relatedIn = this._assetsRelatedIn.get(name);
  5185. if (relatedIn === undefined) {
  5186. this._assetsRelatedIn.set(name, (relatedIn = new Map()));
  5187. }
  5188. let entry = relatedIn.get(key);
  5189. if (entry === undefined) {
  5190. relatedIn.set(key, (entry = new Set()));
  5191. }
  5192. entry.add(file);
  5193. };
  5194. const entry = newRelated[key];
  5195. if (Array.isArray(entry)) {
  5196. for (const name of entry) {
  5197. add(name);
  5198. }
  5199. } else if (entry) {
  5200. add(entry);
  5201. }
  5202. }
  5203. }
  5204. }
  5205. /**
  5206. * Updates asset using the provided file.
  5207. * @param {string} file file name
  5208. * @param {Source | ((source: Source) => Source)} newSourceOrFunction new asset source or function converting old to new
  5209. * @param {(AssetInfo | ((assetInfo?: AssetInfo) => AssetInfo | undefined)) | undefined} assetInfoUpdateOrFunction new asset info or function converting old to new
  5210. */
  5211. updateAsset(
  5212. file,
  5213. newSourceOrFunction,
  5214. assetInfoUpdateOrFunction = undefined
  5215. ) {
  5216. if (!this.assets[file]) {
  5217. throw new Error(
  5218. `Called Compilation.updateAsset for not existing filename ${file}`
  5219. );
  5220. }
  5221. this.assets[file] =
  5222. typeof newSourceOrFunction === "function"
  5223. ? newSourceOrFunction(this.assets[file])
  5224. : newSourceOrFunction;
  5225. if (assetInfoUpdateOrFunction !== undefined) {
  5226. const oldInfo = this.assetsInfo.get(file) || EMPTY_ASSET_INFO;
  5227. if (typeof assetInfoUpdateOrFunction === "function") {
  5228. this._setAssetInfo(file, assetInfoUpdateOrFunction(oldInfo), oldInfo);
  5229. } else {
  5230. this._setAssetInfo(
  5231. file,
  5232. cachedCleverMerge(oldInfo, assetInfoUpdateOrFunction),
  5233. oldInfo
  5234. );
  5235. }
  5236. }
  5237. }
  5238. /**
  5239. * Processes the provided file.
  5240. * @param {string} file file name
  5241. * @param {string} newFile the new name of file
  5242. */
  5243. renameAsset(file, newFile) {
  5244. const source = this.assets[file];
  5245. if (!source) {
  5246. throw new Error(
  5247. `Called Compilation.renameAsset for not existing filename ${file}`
  5248. );
  5249. }
  5250. if (this.assets[newFile] && !isSourceEqual(this.assets[file], source)) {
  5251. this.errors.push(
  5252. new WebpackError(
  5253. `Conflict: Called Compilation.renameAsset for already existing filename ${newFile} with different content`
  5254. )
  5255. );
  5256. }
  5257. const assetInfo = this.assetsInfo.get(file);
  5258. // Update related in all other assets
  5259. const relatedInInfo = this._assetsRelatedIn.get(file);
  5260. if (relatedInInfo) {
  5261. for (const [key, assets] of relatedInInfo) {
  5262. for (const name of assets) {
  5263. const info = this.assetsInfo.get(name);
  5264. if (!info) continue;
  5265. const related = info.related;
  5266. if (!related) continue;
  5267. const entry = related[key];
  5268. /** @type {string | string[]} */
  5269. let newEntry;
  5270. if (Array.isArray(entry)) {
  5271. newEntry = entry.map((x) => (x === file ? newFile : x));
  5272. } else if (entry === file) {
  5273. newEntry = newFile;
  5274. } else {
  5275. continue;
  5276. }
  5277. this.assetsInfo.set(name, {
  5278. ...info,
  5279. related: {
  5280. ...related,
  5281. [key]: newEntry
  5282. }
  5283. });
  5284. }
  5285. }
  5286. }
  5287. this._setAssetInfo(file, undefined, assetInfo);
  5288. this._setAssetInfo(newFile, assetInfo);
  5289. delete this.assets[file];
  5290. this.assets[newFile] = source;
  5291. this._buildAssetToChunkIndex();
  5292. const index = /** @type {Map<string, Set<Chunk>>} */ (
  5293. this._assetToChunkIndex
  5294. );
  5295. const auxiliaryIndex = /** @type {Map<string, Set<Chunk>>} */ (
  5296. this._assetToChunkAuxiliaryIndex
  5297. );
  5298. const chunks = index.get(file);
  5299. const auxiliaryChunks = auxiliaryIndex.get(file);
  5300. if (chunks === undefined && auxiliaryChunks === undefined) {
  5301. // Not tracked in either index: chunk sets may have been mutated
  5302. // directly (bypassing emitAsset), so scan all chunks to stay correct.
  5303. for (const chunk of this.chunks) {
  5304. this._renameAssetInChunk(chunk, chunk.files, index, file, newFile);
  5305. this._renameAssetInChunk(
  5306. chunk,
  5307. chunk.auxiliaryFiles,
  5308. auxiliaryIndex,
  5309. file,
  5310. newFile
  5311. );
  5312. }
  5313. return;
  5314. }
  5315. if (chunks !== undefined) {
  5316. index.delete(file);
  5317. for (const chunk of chunks) {
  5318. this._renameAssetInChunk(chunk, chunk.files, index, file, newFile);
  5319. }
  5320. }
  5321. if (auxiliaryChunks !== undefined) {
  5322. auxiliaryIndex.delete(file);
  5323. for (const chunk of auxiliaryChunks) {
  5324. this._renameAssetInChunk(
  5325. chunk,
  5326. chunk.auxiliaryFiles,
  5327. auxiliaryIndex,
  5328. file,
  5329. newFile
  5330. );
  5331. }
  5332. }
  5333. }
  5334. // Lazily build the reverse index file -> chunks. emitAsset() invalidates
  5335. // it, so chunk.files / chunk.auxiliaryFiles entries added alongside a newly
  5336. // emitted asset are always picked up on the next rebuild.
  5337. /**
  5338. * @private
  5339. * @returns {void}
  5340. */
  5341. _buildAssetToChunkIndex() {
  5342. if (this._assetToChunkIndex !== undefined) return;
  5343. /** @type {Map<string, Set<Chunk>>} */
  5344. const filesIndex = new Map();
  5345. /** @type {Map<string, Set<Chunk>>} */
  5346. const auxiliaryIndex = new Map();
  5347. for (const chunk of this.chunks) {
  5348. for (const file of chunk.files) {
  5349. let set = filesIndex.get(file);
  5350. if (set === undefined) filesIndex.set(file, (set = new Set()));
  5351. set.add(chunk);
  5352. }
  5353. for (const file of chunk.auxiliaryFiles) {
  5354. let set = auxiliaryIndex.get(file);
  5355. if (set === undefined) auxiliaryIndex.set(file, (set = new Set()));
  5356. set.add(chunk);
  5357. }
  5358. }
  5359. this._assetToChunkIndex = filesIndex;
  5360. this._assetToChunkAuxiliaryIndex = auxiliaryIndex;
  5361. }
  5362. /**
  5363. * @private
  5364. * @param {Chunk} chunk the chunk owning the set
  5365. * @param {Set<string>} set chunk.files or chunk.auxiliaryFiles
  5366. * @param {Map<string, Set<Chunk>>} index matching reverse index
  5367. * @param {string} file old file name
  5368. * @param {string} newFile new file name
  5369. * @returns {void}
  5370. */
  5371. _renameAssetInChunk(chunk, set, index, file, newFile) {
  5372. // Only carry the rename to chunks that actually held the old name.
  5373. if (!set.delete(file)) return;
  5374. set.add(newFile);
  5375. let target = index.get(newFile);
  5376. if (target === undefined) index.set(newFile, (target = new Set()));
  5377. target.add(chunk);
  5378. }
  5379. /**
  5380. * Processes the provided file.
  5381. * @param {string} file file name
  5382. */
  5383. deleteAsset(file) {
  5384. if (!this.assets[file]) {
  5385. return;
  5386. }
  5387. delete this.assets[file];
  5388. const assetInfo = this.assetsInfo.get(file);
  5389. this._setAssetInfo(file, undefined, assetInfo);
  5390. const related = assetInfo && assetInfo.related;
  5391. if (related) {
  5392. for (const key of Object.keys(related)) {
  5393. /**
  5394. * Checks used and delete.
  5395. * @param {string} file file
  5396. */
  5397. const checkUsedAndDelete = (file) => {
  5398. if (!this._assetsRelatedIn.has(file)) {
  5399. this.deleteAsset(file);
  5400. }
  5401. };
  5402. const items = related[key];
  5403. if (Array.isArray(items)) {
  5404. for (const file of items) {
  5405. checkUsedAndDelete(file);
  5406. }
  5407. } else if (items) {
  5408. checkUsedAndDelete(items);
  5409. }
  5410. }
  5411. }
  5412. this._buildAssetToChunkIndex();
  5413. const index = /** @type {Map<string, Set<Chunk>>} */ (
  5414. this._assetToChunkIndex
  5415. );
  5416. const auxiliaryIndex = /** @type {Map<string, Set<Chunk>>} */ (
  5417. this._assetToChunkAuxiliaryIndex
  5418. );
  5419. const chunks = index.get(file);
  5420. const auxiliaryChunks = auxiliaryIndex.get(file);
  5421. if (chunks === undefined && auxiliaryChunks === undefined) {
  5422. // Not tracked in either index: chunk sets may have been mutated
  5423. // directly (bypassing emitAsset), so scan all chunks to stay correct.
  5424. for (const chunk of this.chunks) {
  5425. chunk.files.delete(file);
  5426. chunk.auxiliaryFiles.delete(file);
  5427. }
  5428. return;
  5429. }
  5430. if (chunks !== undefined) {
  5431. for (const chunk of chunks) chunk.files.delete(file);
  5432. index.delete(file);
  5433. }
  5434. if (auxiliaryChunks !== undefined) {
  5435. for (const chunk of auxiliaryChunks) chunk.auxiliaryFiles.delete(file);
  5436. auxiliaryIndex.delete(file);
  5437. }
  5438. }
  5439. getAssets() {
  5440. /** @type {Readonly<Asset>[]} */
  5441. const array = [];
  5442. for (const assetName of Object.keys(this.assets)) {
  5443. if (Object.prototype.hasOwnProperty.call(this.assets, assetName)) {
  5444. array.push({
  5445. name: assetName,
  5446. source: this.assets[assetName],
  5447. info: this.assetsInfo.get(assetName) || EMPTY_ASSET_INFO
  5448. });
  5449. }
  5450. }
  5451. return array;
  5452. }
  5453. /**
  5454. * Returns the asset or undefined when not found.
  5455. * @param {string} name the name of the asset
  5456. * @returns {Readonly<Asset> | undefined} the asset or undefined when not found
  5457. */
  5458. getAsset(name) {
  5459. if (!Object.prototype.hasOwnProperty.call(this.assets, name)) return;
  5460. return {
  5461. name,
  5462. source: this.assets[name],
  5463. info: this.assetsInfo.get(name) || EMPTY_ASSET_INFO
  5464. };
  5465. }
  5466. clearAssets() {
  5467. for (const chunk of this.chunks) {
  5468. chunk.files.clear();
  5469. chunk.auxiliaryFiles.clear();
  5470. }
  5471. this._assetToChunkIndex = undefined;
  5472. this._assetToChunkAuxiliaryIndex = undefined;
  5473. }
  5474. createModuleAssets() {
  5475. const { chunkGraph } = this;
  5476. for (const module of this.modules) {
  5477. const buildInfo = /** @type {BuildInfo} */ (module.buildInfo);
  5478. if (buildInfo.assets) {
  5479. const assetsInfo = buildInfo.assetsInfo;
  5480. for (const assetName of Object.keys(buildInfo.assets)) {
  5481. const fileName = this.getPath(assetName, {
  5482. chunkGraph: this.chunkGraph,
  5483. module
  5484. });
  5485. for (const chunk of chunkGraph.getModuleChunksIterable(module)) {
  5486. chunk.auxiliaryFiles.add(fileName);
  5487. }
  5488. this.emitAsset(
  5489. fileName,
  5490. buildInfo.assets[assetName],
  5491. assetsInfo ? assetsInfo.get(assetName) : undefined
  5492. );
  5493. this.hooks.moduleAsset.call(module, fileName);
  5494. }
  5495. }
  5496. }
  5497. }
  5498. /**
  5499. * Gets render manifest.
  5500. * @param {RenderManifestOptions} options options object
  5501. * @returns {RenderManifestEntry[]} manifest entries
  5502. */
  5503. getRenderManifest(options) {
  5504. return this.hooks.renderManifest.call([], options);
  5505. }
  5506. /**
  5507. * Creates a chunk assets.
  5508. * @param {Callback} callback signals when the call finishes
  5509. * @returns {void}
  5510. */
  5511. createChunkAssets(callback) {
  5512. const outputOptions = this.outputOptions;
  5513. /** @type {WeakMap<Source, CachedSource>} */
  5514. const cachedSourceMap = new WeakMap();
  5515. /** @type {Map<string, { hash: string, source: Source, chunk: Chunk }>} */
  5516. const alreadyWrittenFiles = new Map();
  5517. asyncLib.forEachLimit(
  5518. this.chunks,
  5519. 15,
  5520. (chunk, callback) => {
  5521. /** @type {RenderManifestEntry[]} */
  5522. let manifest;
  5523. try {
  5524. manifest = this.getRenderManifest({
  5525. chunk,
  5526. hash: /** @type {string} */ (this.hash),
  5527. fullHash: /** @type {string} */ (this.fullHash),
  5528. outputOptions,
  5529. codeGenerationResults:
  5530. /** @type {CodeGenerationResults} */
  5531. (this.codeGenerationResults),
  5532. moduleTemplates: this.moduleTemplates,
  5533. dependencyTemplates: this.dependencyTemplates,
  5534. chunkGraph: this.chunkGraph,
  5535. moduleGraph: this.moduleGraph,
  5536. runtimeTemplate: this.runtimeTemplate
  5537. });
  5538. } catch (err) {
  5539. this.errors.push(
  5540. new (getChunkRenderError())(chunk, "", /** @type {Error} */ (err))
  5541. );
  5542. return callback();
  5543. }
  5544. asyncLib.each(
  5545. manifest,
  5546. (fileManifest, callback) => {
  5547. const ident = fileManifest.identifier;
  5548. const usedHash = /** @type {string} */ (fileManifest.hash);
  5549. const assetCacheItem = this._assetsCache.getItemCache(
  5550. ident,
  5551. usedHash
  5552. );
  5553. assetCacheItem.get((err, sourceFromCache) => {
  5554. /** @type {string | import("./TemplatedPathPlugin").TemplatePathFn<EXPECTED_ANY>} */
  5555. let filenameTemplate;
  5556. /** @type {string} */
  5557. let file;
  5558. /** @type {AssetInfo} */
  5559. let assetInfo;
  5560. let inTry = true;
  5561. /**
  5562. * Error and callback.
  5563. * @param {Error} err error
  5564. * @returns {void}
  5565. */
  5566. const errorAndCallback = (err) => {
  5567. const filename =
  5568. file ||
  5569. (typeof file === "string"
  5570. ? file
  5571. : typeof filenameTemplate === "string"
  5572. ? filenameTemplate
  5573. : "");
  5574. this.errors.push(
  5575. new (getChunkRenderError())(chunk, filename, err)
  5576. );
  5577. inTry = false;
  5578. return callback();
  5579. };
  5580. try {
  5581. if ("filename" in fileManifest) {
  5582. file = fileManifest.filename;
  5583. assetInfo = fileManifest.info;
  5584. } else {
  5585. filenameTemplate = fileManifest.filenameTemplate;
  5586. const pathAndInfo = this.getPathWithInfo(
  5587. filenameTemplate,
  5588. fileManifest.pathOptions
  5589. );
  5590. file = pathAndInfo.path;
  5591. assetInfo = fileManifest.info
  5592. ? {
  5593. ...pathAndInfo.info,
  5594. ...fileManifest.info
  5595. }
  5596. : pathAndInfo.info;
  5597. }
  5598. if (err) {
  5599. return errorAndCallback(err);
  5600. }
  5601. let source = sourceFromCache;
  5602. // check if the same filename was already written by another chunk
  5603. const alreadyWritten = alreadyWrittenFiles.get(file);
  5604. if (alreadyWritten !== undefined) {
  5605. if (alreadyWritten.hash !== usedHash) {
  5606. inTry = false;
  5607. return callback(
  5608. new WebpackError(
  5609. `Conflict: Multiple chunks emit assets to the same filename ${file}` +
  5610. ` (chunks ${alreadyWritten.chunk.id} and ${chunk.id})`
  5611. )
  5612. );
  5613. }
  5614. source = alreadyWritten.source;
  5615. } else if (!source) {
  5616. // render the asset
  5617. source = fileManifest.render();
  5618. // Ensure that source is a cached source to avoid additional cost because of repeated access
  5619. if (!(source instanceof CachedSource)) {
  5620. const cacheEntry = cachedSourceMap.get(source);
  5621. if (cacheEntry) {
  5622. source = cacheEntry;
  5623. } else {
  5624. const cachedSource = new CachedSource(source);
  5625. cachedSourceMap.set(source, cachedSource);
  5626. source = cachedSource;
  5627. }
  5628. }
  5629. }
  5630. this.emitAsset(file, source, assetInfo);
  5631. if (fileManifest.auxiliary) {
  5632. chunk.auxiliaryFiles.add(file);
  5633. } else {
  5634. chunk.files.add(file);
  5635. }
  5636. this.hooks.chunkAsset.call(chunk, file);
  5637. alreadyWrittenFiles.set(file, {
  5638. hash: usedHash,
  5639. source,
  5640. chunk
  5641. });
  5642. if (source !== sourceFromCache) {
  5643. assetCacheItem.store(source, (err) => {
  5644. if (err) return errorAndCallback(err);
  5645. inTry = false;
  5646. return callback();
  5647. });
  5648. } else {
  5649. inTry = false;
  5650. callback();
  5651. }
  5652. } catch (err) {
  5653. if (!inTry) throw err;
  5654. errorAndCallback(/** @type {Error} */ (err));
  5655. }
  5656. });
  5657. },
  5658. callback
  5659. );
  5660. },
  5661. callback
  5662. );
  5663. }
  5664. /**
  5665. * Returns interpolated path.
  5666. * @template {PathData} [T=PathData]
  5667. * @param {string | import("./TemplatedPathPlugin").TemplatePathFn<T>} filename used to get asset path with hash
  5668. * @param {T=} data context data
  5669. * @returns {string} interpolated path
  5670. */
  5671. getPath(filename, data = /** @type {T} */ ({})) {
  5672. if (!data.hash) {
  5673. data = {
  5674. hash: this.hash,
  5675. ...data
  5676. };
  5677. }
  5678. return this.getAssetPath(filename, data);
  5679. }
  5680. /**
  5681. * Gets path with info.
  5682. * @template {PathData} [T=PathData]
  5683. * @param {string | import("./TemplatedPathPlugin").TemplatePathFn<T>} filename used to get asset path with hash
  5684. * @param {T=} data context data
  5685. * @returns {InterpolatedPathAndAssetInfo} interpolated path and asset info
  5686. */
  5687. getPathWithInfo(filename, data = /** @type {T} */ ({})) {
  5688. if (!data.hash) {
  5689. data = {
  5690. hash: this.hash,
  5691. ...data
  5692. };
  5693. }
  5694. return this.getAssetPathWithInfo(filename, data);
  5695. }
  5696. /**
  5697. * Returns interpolated path.
  5698. * @template {PathData} [T=PathData]
  5699. * @param {string | import("./TemplatedPathPlugin").TemplatePathFn<T>} filename used to get asset path with hash
  5700. * @param {T} data context data
  5701. * @returns {string} interpolated path
  5702. */
  5703. getAssetPath(filename, data) {
  5704. return this.hooks.assetPath.call(
  5705. typeof filename === "function" ? filename(data) : filename,
  5706. data,
  5707. undefined
  5708. );
  5709. }
  5710. /**
  5711. * Gets asset path with info.
  5712. * @template {PathData} [T=PathData]
  5713. * @param {string | import("./TemplatedPathPlugin").TemplatePathFn<T>} filename used to get asset path with hash
  5714. * @param {T} data context data
  5715. * @returns {InterpolatedPathAndAssetInfo} interpolated path and asset info
  5716. */
  5717. getAssetPathWithInfo(filename, data) {
  5718. const assetInfo = {};
  5719. // TODO webpack 5: refactor assetPath hook to receive { path, info } object
  5720. const newPath = this.hooks.assetPath.call(
  5721. typeof filename === "function" ? filename(data, assetInfo) : filename,
  5722. data,
  5723. assetInfo
  5724. );
  5725. return { path: newPath, info: assetInfo };
  5726. }
  5727. getWarnings() {
  5728. return this.hooks.processWarnings.call(this.warnings);
  5729. }
  5730. getErrors() {
  5731. return this.hooks.processErrors.call(this.errors);
  5732. }
  5733. /**
  5734. * This function allows you to run another instance of webpack inside of webpack however as
  5735. * a child with different settings and configurations (if desired) applied. It copies all hooks, plugins
  5736. * from parent (or top level compiler) and creates a child Compilation
  5737. * @param {string} name name of the child compiler
  5738. * @param {Partial<OutputOptions>=} outputOptions // Need to convert config schema to types for this
  5739. * @param {Plugins=} plugins webpack plugins that will be applied
  5740. * @returns {Compiler} creates a child Compiler instance
  5741. */
  5742. createChildCompiler(name, outputOptions, plugins) {
  5743. const idx = this.childrenCounters[name] || 0;
  5744. this.childrenCounters[name] = idx + 1;
  5745. return this.compiler.createChildCompiler(
  5746. this,
  5747. name,
  5748. idx,
  5749. outputOptions,
  5750. plugins
  5751. );
  5752. }
  5753. /**
  5754. * Processes the provided module.
  5755. * @param {Module} module the module
  5756. * @param {ExecuteModuleOptions} options options
  5757. * @param {ExecuteModuleCallback} callback callback
  5758. */
  5759. executeModule(module, options, callback) {
  5760. // Aggregate all referenced modules and ensure they are ready
  5761. const modules = new Set([module]);
  5762. processAsyncTree(
  5763. modules,
  5764. 10,
  5765. (module, push, callback) => {
  5766. this.buildQueue.waitFor(module, (err) => {
  5767. if (err) return callback(err);
  5768. this.processDependenciesQueue.waitFor(module, (err) => {
  5769. if (err) return callback(err);
  5770. for (const { module: m } of this.moduleGraph.getOutgoingConnections(
  5771. module
  5772. )) {
  5773. const size = modules.size;
  5774. modules.add(m);
  5775. if (modules.size !== size) push(m);
  5776. }
  5777. callback();
  5778. });
  5779. });
  5780. },
  5781. (err) => {
  5782. if (err) return callback(/** @type {WebpackError} */ (err));
  5783. // Create new chunk graph, chunk and entrypoint for the build time execution
  5784. const chunkGraph = new ChunkGraph(
  5785. this.moduleGraph,
  5786. this.outputOptions.hashFunction
  5787. );
  5788. chunkGraph.buildTimeExecution = true;
  5789. const runtime = "build time";
  5790. const { hashFunction, hashDigest, hashDigestLength } =
  5791. this.outputOptions;
  5792. const runtimeTemplate = this.runtimeTemplate;
  5793. const chunk = new Chunk("build time chunk", this._backCompat);
  5794. chunk.id = /** @type {ChunkId} */ (chunk.name);
  5795. chunk.ids = [chunk.id];
  5796. chunk.runtime = runtime;
  5797. const entrypoint = new Entrypoint({
  5798. runtime,
  5799. chunkLoading: false,
  5800. ...options.entryOptions
  5801. });
  5802. chunkGraph.connectChunkAndEntryModule(chunk, module, entrypoint);
  5803. if (entrypoint.pushChunk(chunk)) {
  5804. chunk.addGroup(entrypoint);
  5805. }
  5806. entrypoint.setRuntimeChunk(chunk);
  5807. entrypoint.setEntrypointChunk(chunk);
  5808. const chunks = new Set([chunk]);
  5809. // Assign ids to modules and modules to the chunk
  5810. for (const module of modules) {
  5811. const id = module.identifier();
  5812. chunkGraph.setModuleId(module, id);
  5813. chunkGraph.connectChunkAndModule(chunk, module);
  5814. }
  5815. /** @type {WebpackError[]} */
  5816. const errors = [];
  5817. // Hash modules
  5818. for (const module of modules) {
  5819. this._createModuleHash(
  5820. module,
  5821. chunkGraph,
  5822. runtime,
  5823. hashFunction,
  5824. runtimeTemplate,
  5825. hashDigest,
  5826. hashDigestLength,
  5827. errors
  5828. );
  5829. }
  5830. const codeGenerationResults = new CodeGenerationResults(
  5831. this.outputOptions.hashFunction
  5832. );
  5833. /**
  5834. * Processes the provided module.
  5835. * @param {Module} module the module
  5836. * @param {Callback} callback callback
  5837. * @returns {void}
  5838. */
  5839. const codeGen = (module, callback) => {
  5840. this._codeGenerationModule(
  5841. module,
  5842. runtime,
  5843. [runtime],
  5844. chunkGraph.getModuleHash(module, runtime),
  5845. this.dependencyTemplates,
  5846. chunkGraph,
  5847. this.moduleGraph,
  5848. runtimeTemplate,
  5849. errors,
  5850. codeGenerationResults,
  5851. (err, _codeGenerated) => {
  5852. callback(err);
  5853. }
  5854. );
  5855. };
  5856. const reportErrors = () => {
  5857. if (errors.length > 0) {
  5858. errors.sort(
  5859. compareSelect((err) => err.module, compareModulesByIdentifier)
  5860. );
  5861. for (const error of errors) {
  5862. this.errors.push(error);
  5863. }
  5864. errors.length = 0;
  5865. }
  5866. };
  5867. // Generate code for all aggregated modules
  5868. asyncLib.eachLimit(
  5869. /** @type {import("neo-async").IterableCollection<Module>} */ (
  5870. /** @type {unknown} */ (modules)
  5871. ),
  5872. 10,
  5873. codeGen,
  5874. (err) => {
  5875. if (err) return callback(err);
  5876. reportErrors();
  5877. // for backward-compat temporary set the chunk graph
  5878. // TODO webpack 6
  5879. const old = this.chunkGraph;
  5880. this.chunkGraph = chunkGraph;
  5881. this.processRuntimeRequirements({
  5882. chunkGraph,
  5883. modules,
  5884. chunks,
  5885. codeGenerationResults,
  5886. chunkGraphEntries: chunks
  5887. });
  5888. // restored before the deferred attach so no concurrent `make`
  5889. // task observes the build-time graph
  5890. this.chunkGraph = old;
  5891. this._attachPendingRuntimeModules((err) => {
  5892. if (err) return callback(err);
  5893. const runtimeModules =
  5894. chunkGraph.getChunkRuntimeModulesIterable(chunk);
  5895. // Hash runtime modules
  5896. for (const module of runtimeModules) {
  5897. modules.add(module);
  5898. this._createModuleHash(
  5899. module,
  5900. chunkGraph,
  5901. runtime,
  5902. hashFunction,
  5903. runtimeTemplate,
  5904. hashDigest,
  5905. hashDigestLength,
  5906. errors
  5907. );
  5908. }
  5909. // Generate code for all runtime modules
  5910. asyncLib.eachLimit(
  5911. /** @type {import("neo-async").IterableCollection<RuntimeModule>} */ (
  5912. runtimeModules
  5913. ),
  5914. 10,
  5915. codeGen,
  5916. (err) => {
  5917. if (err) return callback(err);
  5918. reportErrors();
  5919. /** @type {Map<Module, ExecuteModuleArgument>} */
  5920. const moduleArgumentsMap = new Map();
  5921. /** @type {Map<string, ExecuteModuleArgument>} */
  5922. const moduleArgumentsById = new Map();
  5923. /** @type {ExecuteModuleResult["fileDependencies"]} */
  5924. const fileDependencies = new LazySet();
  5925. /** @type {ExecuteModuleResult["contextDependencies"]} */
  5926. const contextDependencies = new LazySet();
  5927. /** @type {ExecuteModuleResult["missingDependencies"]} */
  5928. const missingDependencies = new LazySet();
  5929. /** @type {ExecuteModuleResult["buildDependencies"]} */
  5930. const buildDependencies = new LazySet();
  5931. /** @type {ExecuteModuleResult["assets"]} */
  5932. const assets = new Map();
  5933. let cacheable = true;
  5934. /** @type {ExecuteModuleResult["notCacheableReasons"]} */
  5935. const notCacheableReasons = [];
  5936. /** @type {ExecuteModuleContext} */
  5937. const context = {
  5938. assets,
  5939. __webpack_require__: undefined,
  5940. chunk,
  5941. chunkGraph
  5942. };
  5943. // Prepare execution
  5944. asyncLib.eachLimit(
  5945. modules,
  5946. 10,
  5947. (module, callback) => {
  5948. const codeGenerationResult = codeGenerationResults.get(
  5949. module,
  5950. runtime
  5951. );
  5952. /** @type {ExecuteModuleArgument} */
  5953. const moduleArgument = {
  5954. module,
  5955. codeGenerationResult,
  5956. moduleObject: undefined
  5957. };
  5958. moduleArgumentsMap.set(module, moduleArgument);
  5959. moduleArgumentsById.set(
  5960. module.identifier(),
  5961. moduleArgument
  5962. );
  5963. module.addCacheDependencies(
  5964. fileDependencies,
  5965. contextDependencies,
  5966. missingDependencies,
  5967. buildDependencies
  5968. );
  5969. const buildInfo = /** @type {BuildInfo} */ (
  5970. module.buildInfo
  5971. );
  5972. if (buildInfo.cacheable === false) {
  5973. cacheable = false;
  5974. if (buildInfo.notCacheableReasons) {
  5975. for (const reason of buildInfo.notCacheableReasons) {
  5976. if (!notCacheableReasons.includes(reason)) {
  5977. notCacheableReasons.push(reason);
  5978. }
  5979. }
  5980. }
  5981. }
  5982. if (module.buildInfo && module.buildInfo.assets) {
  5983. const { assets: moduleAssets, assetsInfo } =
  5984. module.buildInfo;
  5985. for (const assetName of Object.keys(moduleAssets)) {
  5986. assets.set(assetName, {
  5987. source: moduleAssets[assetName],
  5988. info: assetsInfo
  5989. ? assetsInfo.get(assetName)
  5990. : undefined
  5991. });
  5992. }
  5993. }
  5994. this.hooks.prepareModuleExecution.callAsync(
  5995. moduleArgument,
  5996. context,
  5997. callback
  5998. );
  5999. },
  6000. (err) => {
  6001. if (err) {
  6002. return callback(/** @type {WebpackError} */ (err));
  6003. }
  6004. /** @type {ExecuteModuleExports | undefined} */
  6005. let exports;
  6006. try {
  6007. const {
  6008. strictModuleErrorHandling,
  6009. strictModuleExceptionHandling
  6010. } = this.outputOptions;
  6011. /** @type {WebpackRequire} */
  6012. const __webpack_require__ = (id) => {
  6013. const cached = moduleCache[id];
  6014. if (cached !== undefined) {
  6015. if (cached.error) throw cached.error;
  6016. return cached.exports;
  6017. }
  6018. const moduleArgument = moduleArgumentsById.get(id);
  6019. return __webpack_require_module__(
  6020. /** @type {ExecuteModuleArgument} */
  6021. (moduleArgument),
  6022. id
  6023. );
  6024. };
  6025. const interceptModuleExecution = (__webpack_require__[
  6026. /** @type {"i"} */
  6027. (
  6028. RuntimeGlobals.interceptModuleExecution.replace(
  6029. `${RuntimeGlobals.require}.`,
  6030. ""
  6031. )
  6032. )
  6033. ] =
  6034. /** @type {NonNullable<WebpackRequire["i"]>} */ ([]));
  6035. const moduleCache = (__webpack_require__[
  6036. /** @type {"c"} */ (
  6037. RuntimeGlobals.moduleCache.replace(
  6038. `${RuntimeGlobals.require}.`,
  6039. ""
  6040. )
  6041. )
  6042. ] =
  6043. /** @type {NonNullable<WebpackRequire["c"]>} */ ({}));
  6044. context.__webpack_require__ = __webpack_require__;
  6045. /**
  6046. * Webpack require module.
  6047. * @param {ExecuteModuleArgument} moduleArgument the module argument
  6048. * @param {string=} id id
  6049. * @returns {ExecuteModuleExports} exports
  6050. */
  6051. const __webpack_require_module__ = (
  6052. moduleArgument,
  6053. id
  6054. ) => {
  6055. /** @type {ExecuteOptions} */
  6056. const execOptions = {
  6057. id,
  6058. module: {
  6059. id,
  6060. exports: {},
  6061. loaded: false,
  6062. error: undefined
  6063. },
  6064. require: __webpack_require__
  6065. };
  6066. for (const handler of interceptModuleExecution) {
  6067. handler(execOptions);
  6068. }
  6069. const module = moduleArgument.module;
  6070. this.buildTimeExecutedModules.add(module);
  6071. const moduleObject = execOptions.module;
  6072. moduleArgument.moduleObject = moduleObject;
  6073. try {
  6074. if (id) moduleCache[id] = moduleObject;
  6075. tryRunOrWebpackError(
  6076. () =>
  6077. this.hooks.executeModule.call(
  6078. moduleArgument,
  6079. context
  6080. ),
  6081. "Compilation.hooks.executeModule"
  6082. );
  6083. moduleObject.loaded = true;
  6084. return moduleObject.exports;
  6085. } catch (execErr) {
  6086. if (strictModuleExceptionHandling) {
  6087. if (id) delete moduleCache[id];
  6088. } else if (strictModuleErrorHandling) {
  6089. moduleObject.error =
  6090. /** @type {WebpackError} */
  6091. (execErr);
  6092. }
  6093. if (
  6094. !(/** @type {WebpackError} */ (execErr).module)
  6095. ) {
  6096. /** @type {WebpackError} */
  6097. (execErr).module = module;
  6098. }
  6099. throw execErr;
  6100. }
  6101. };
  6102. for (const runtimeModule of chunkGraph.getChunkRuntimeModulesInOrder(
  6103. chunk
  6104. )) {
  6105. __webpack_require_module__(
  6106. /** @type {ExecuteModuleArgument} */
  6107. (moduleArgumentsMap.get(runtimeModule))
  6108. );
  6109. }
  6110. exports = __webpack_require__(module.identifier());
  6111. } catch (execErr) {
  6112. const { message, stack, module } =
  6113. /** @type {WebpackError} */
  6114. (execErr);
  6115. const err = new WebpackError(
  6116. `Execution of module code from module graph (${
  6117. /** @type {Module} */
  6118. (module).readableIdentifier(this.requestShortener)
  6119. }) failed: ${message}`,
  6120. { cause: execErr }
  6121. );
  6122. err.stack = stack;
  6123. err.module = module;
  6124. return callback(err);
  6125. }
  6126. callback(null, {
  6127. exports,
  6128. assets,
  6129. cacheable,
  6130. notCacheableReasons,
  6131. fileDependencies,
  6132. contextDependencies,
  6133. missingDependencies,
  6134. buildDependencies
  6135. });
  6136. }
  6137. );
  6138. }
  6139. );
  6140. });
  6141. }
  6142. );
  6143. }
  6144. );
  6145. }
  6146. checkConstraints() {
  6147. const chunkGraph = this.chunkGraph;
  6148. /** @type {Set<ModuleId>} */
  6149. const usedIds = new Set();
  6150. for (const module of this.modules) {
  6151. if (module.type === WEBPACK_MODULE_TYPE_RUNTIME) continue;
  6152. const moduleId = chunkGraph.getModuleId(module);
  6153. if (moduleId === null) continue;
  6154. if (usedIds.has(moduleId)) {
  6155. throw new Error(`checkConstraints: duplicate module id ${moduleId}`);
  6156. }
  6157. usedIds.add(moduleId);
  6158. }
  6159. for (const chunk of this.chunks) {
  6160. for (const module of chunkGraph.getChunkModulesIterable(chunk)) {
  6161. if (!this.modules.has(module)) {
  6162. throw new Error(
  6163. "checkConstraints: module in chunk but not in compilation " +
  6164. ` ${chunk.debugId} ${module.debugId}`
  6165. );
  6166. }
  6167. }
  6168. for (const module of chunkGraph.getChunkEntryModulesIterable(chunk)) {
  6169. if (!this.modules.has(module)) {
  6170. throw new Error(
  6171. "checkConstraints: entry module in chunk but not in compilation " +
  6172. ` ${chunk.debugId} ${module.debugId}`
  6173. );
  6174. }
  6175. }
  6176. }
  6177. for (const chunkGroup of this.chunkGroups) {
  6178. chunkGroup.checkConstraints();
  6179. }
  6180. }
  6181. }
  6182. /**
  6183. * Defines the factorize module options type used by this module.
  6184. * @typedef {object} FactorizeModuleOptions
  6185. * @property {ModuleProfile=} currentProfile
  6186. * @property {ModuleFactory} factory
  6187. * @property {Dependency[]} dependencies
  6188. * @property {boolean=} factoryResult return full ModuleFactoryResult instead of only module
  6189. * @property {Module | null} originModule
  6190. * @property {Partial<ModuleFactoryCreateDataContextInfo>=} contextInfo
  6191. * @property {string=} context
  6192. */
  6193. /**
  6194. * Processes the provided factorize module option.
  6195. * @param {FactorizeModuleOptions} options options object
  6196. * @param {ModuleCallback | ModuleFactoryResultCallback} callback callback
  6197. * @returns {void}
  6198. */
  6199. // Hide from typescript
  6200. const compilationPrototype = Compilation.prototype;
  6201. // TODO webpack 6 remove
  6202. Object.defineProperty(compilationPrototype, "modifyHash", {
  6203. writable: false,
  6204. enumerable: false,
  6205. configurable: false,
  6206. value: () => {
  6207. throw new Error(
  6208. "Compilation.modifyHash was removed in favor of Compilation.hooks.fullHash"
  6209. );
  6210. }
  6211. });
  6212. // TODO webpack 6 remove
  6213. Object.defineProperty(compilationPrototype, "cache", {
  6214. enumerable: false,
  6215. configurable: false,
  6216. get: util.deprecate(
  6217. /**
  6218. * Returns the cache.
  6219. * @this {Compilation} the compilation
  6220. * @returns {Cache} the cache
  6221. */
  6222. function cache() {
  6223. return this.compiler.cache;
  6224. },
  6225. "Compilation.cache was removed in favor of Compilation.getCache()",
  6226. "DEP_WEBPACK_COMPILATION_CACHE"
  6227. ),
  6228. set: util.deprecate(
  6229. /**
  6230. * Handles the value callback for this hook.
  6231. * @param {EXPECTED_ANY} _v value
  6232. */
  6233. (_v) => {},
  6234. "Compilation.cache was removed in favor of Compilation.getCache()",
  6235. "DEP_WEBPACK_COMPILATION_CACHE"
  6236. )
  6237. });
  6238. /**
  6239. * Add additional assets to the compilation.
  6240. */
  6241. Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL = -2000;
  6242. /**
  6243. * Basic preprocessing of assets.
  6244. */
  6245. Compilation.PROCESS_ASSETS_STAGE_PRE_PROCESS = -1000;
  6246. /**
  6247. * Derive new assets from existing assets.
  6248. * Existing assets should not be treated as complete.
  6249. */
  6250. Compilation.PROCESS_ASSETS_STAGE_DERIVED = -200;
  6251. /**
  6252. * Add additional sections to existing assets, like a banner or initialization code.
  6253. */
  6254. Compilation.PROCESS_ASSETS_STAGE_ADDITIONS = -100;
  6255. /**
  6256. * Optimize existing assets in a general way.
  6257. */
  6258. Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE = 100;
  6259. /**
  6260. * Optimize the count of existing assets, e. g. by merging them.
  6261. * Only assets of the same type should be merged.
  6262. * For assets of different types see PROCESS_ASSETS_STAGE_OPTIMIZE_INLINE.
  6263. */
  6264. Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_COUNT = 200;
  6265. /**
  6266. * Optimize the compatibility of existing assets, e. g. add polyfills or vendor-prefixes.
  6267. */
  6268. Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_COMPATIBILITY = 300;
  6269. /**
  6270. * Optimize the size of existing assets, e. g. by minimizing or omitting whitespace.
  6271. */
  6272. Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_SIZE = 400;
  6273. /**
  6274. * Add development tooling to assets, e. g. by extracting a SourceMap.
  6275. */
  6276. Compilation.PROCESS_ASSETS_STAGE_DEV_TOOLING = 500;
  6277. /**
  6278. * Optimize the count of existing assets, e. g. by inlining assets of into other assets.
  6279. * Only assets of different types should be inlined.
  6280. * For assets of the same type see PROCESS_ASSETS_STAGE_OPTIMIZE_COUNT.
  6281. */
  6282. Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_INLINE = 700;
  6283. /**
  6284. * Summarize the list of existing assets
  6285. * e. g. creating an assets manifest of Service Workers.
  6286. */
  6287. Compilation.PROCESS_ASSETS_STAGE_SUMMARIZE = 1000;
  6288. /**
  6289. * Optimize the hashes of the assets, e. g. by generating real hashes of the asset content.
  6290. */
  6291. Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_HASH = 2500;
  6292. /**
  6293. * Optimize the transfer of existing assets, e. g. by preparing a compressed (gzip) file as separate asset.
  6294. */
  6295. Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_TRANSFER = 3000;
  6296. /**
  6297. * Analyse existing assets.
  6298. */
  6299. Compilation.PROCESS_ASSETS_STAGE_ANALYSE = 4000;
  6300. /**
  6301. * Creating assets for reporting purposes.
  6302. */
  6303. Compilation.PROCESS_ASSETS_STAGE_REPORT = 5000;
  6304. module.exports = Compilation;