Compilation.js 172 KB

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