Compilation.js 181 KB

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