Compilation.js 175 KB

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