Compilation.js 172 KB

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